emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/lentic 71017538d7 211/333: Multiple lentic-buffers are


From: ELPA Syncer
Subject: [elpa] externals/lentic 71017538d7 211/333: Multiple lentic-buffers are now possible.
Date: Tue, 27 Feb 2024 13:00:36 -0500 (EST)

branch: externals/lentic
commit 71017538d7da6707a8f26941cb771acdf4a469c0
Author: Phillip Lord <phillip.lord@newcastle.ac.uk>
Commit: Phillip Lord <phillip.lord@newcastle.ac.uk>

    Multiple lentic-buffers are now possible.
    
    Previously only two buffers could exist. Now this can be any number.
    This has been achieved by turning lentic-config and lentic-init into
    lists, replumbing all of the hooks to operate over these.
    
    lentic-clone has changed it's return value also (previously this was
    ignored, now it is used to percolate to further lentic-buffers).
---
 .ert-runner                           |   2 +-
 Cask                                  |   2 +-
 Makefile                              |   2 +-
 README.md                             |  20 +-
 examples/many-multi-block-comment.clj |  39 ++++
 examples/multi-block-comment-copy.clj |  40 ++++
 examples/multi-block-comment.clj      |  39 ++++
 examples/multi-lentic-copy.txt        |   4 +
 examples/multi-lentic.txt             |   4 +
 lentic-block.el                       | 117 +++++++-----
 lentic-delayed.el                     | 120 ------------
 lentic-dev.el                         |  27 ++-
 lentic-mode.el                        |  72 +++++--
 lentic.el                             | 351 ++++++++++++++++++++++------------
 lenticular.org                        |   6 -
 test/lentic-test.el                   |  81 +++++---
 16 files changed, 582 insertions(+), 344 deletions(-)

diff --git a/.ert-runner b/.ert-runner
index 0300cb2882..16731e3bee 100644
--- a/.ert-runner
+++ b/.ert-runner
@@ -1 +1 @@
---load lentic.el lentic-block.el lentic-latex-code lentic-asciidoc lentic-org 
lentic-delayed lentic-rot13 test/lentic-test.el
\ No newline at end of file
+--load lentic.el lentic-block.el lentic-latex-code.el lentic-asciidoc.el 
lentic-org.el lentic-rot13.el test/lentic-test.el
\ No newline at end of file
diff --git a/Cask b/Cask
index 11f9120e0d..e4db189fb1 100644
--- a/Cask
+++ b/Cask
@@ -1,6 +1,6 @@
 ;; -*- emacs-lisp -*-
 (source gnu)
-(source melpa-stable)
+(source melpa)
 (source marmalade)
 
 (package-file "lentic.el")
diff --git a/Makefile b/Makefile
index 930d0c9339..50a8a74a14 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ install:
        cask install
 
 test:
-       cask exec ert-runner
+       cask exec ert-runner $(TESTS)
 
 org:
        cask exec emacs --debug --script build.el -- gen-org
diff --git a/README.md b/README.md
index 8a0583c909..640ea82397 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,25 @@ completed the relevant paperwork with the FSF.
 
 ## ChangeLog
 
-### 0.7.1
+### 0.8
+
+This buffer introduces multiple lentic buffers. This is important because
+lentic has more than one use -- both for maintaining two syntactic views (for
+example for literate programming) and for maintaining two identical persistent
+views (for example, for editing a file in two places at once). It's now
+possible to do both of these at the same time.
+
+This necessitates a change to the return value of lentic-clone to enable the
+percolation of changes between several buffers. In this default usage of two
+lentic buffers this will have no effect.
+
+#### New Features
+
+- Multiple lentic buffers are now possible.
+
+#### Breaking Changes
+
+- The return value of lentic-clone has now changed.
 
 ### 0.7
 
diff --git a/examples/many-multi-block-comment.clj 
b/examples/many-multi-block-comment.clj
new file mode 100644
index 0000000000..50f27cb4f3
--- /dev/null
+++ b/examples/many-multi-block-comment.clj
@@ -0,0 +1,39 @@
+;; This buffer shows a "block-comment" where we wish to comment large blocks
+;; of the buffer between one lentic buffer and the other.
+
+;; In this case, we use latex tags to indicate the code blocks. Outside of
+;; these tags, we start every line with comments. Inside we do not (although
+;; we leave comments that are there.
+
+;; \begin{code}
+(println "It is now broken")
+;; \end{code}
+
+;; We can have multiple code blocks, of course, after the first.
+
+;; \begin{code}
+(println "hello")
+;; \end{code}
+
+;; And more
+
+;; \begin{code}
+(println "Hello")
+;; \end{code}
+
+;; And more
+
+;; \begin{code}
+(println "hello")
+;; \end{code}
+
+;; And we can put more comments after the final text. And finally, we finish
+;; with a file local variable to tell lentic what kind of text this is. Note
+;; that start characters which are comments in both clojure and latex. In real
+;; use dir-local variables work better.
+
+;; %%
+;; %% Local Variables:
+;; %% lentic-init: (lentic-clojure-latex-init lentic-default-init 
lentic-default-init lentic-default-init)
+;; %% End:
+;; %%
diff --git a/examples/multi-block-comment-copy.clj 
b/examples/multi-block-comment-copy.clj
new file mode 100644
index 0000000000..a14bf9fb51
--- /dev/null
+++ b/examples/multi-block-comment-copy.clj
@@ -0,0 +1,40 @@
+;; And this is all working too....
+;; This buffer shows a "block-comment" where we wish to comment large blocks
+;; of the buffer between one lentic buffer and the other.
+;; hello well this is all working
+;; In this case, we use latex tags to indicate the code blocks. Outside of
+;; these tags, we start every line with comments. Inside we do not (although
+;; we leave comments that are there.
+
+;; \begin{code}
+(println "It is now broken")
+;; \end{code}
+
+;; We can have multiple code blocks, of course, after the first.
+
+;; \begin{code}
+(println "hello")
+;; \end{code}
+
+;; And more
+
+;; \begin{code}
+(println "Hello")
+;; \end{code}
+
+;; And more
+
+;; \begin{code}
+(println "hello")
+;; \end{code}
+
+;; And we can put more comments after the final text. And finally, we finish
+;; with a file local variable to tell lentic what kind of text this is. Note
+;; that start characters which are comments in both clojure and latex. In real
+;; use dir-local variables work better.
+
+;; %%
+;; %% Local Variables:
+;; %% lentic-init: (lentic-default-init lentic-clojure-latex-init)
+;; %% End:
+;; %%
diff --git a/examples/multi-block-comment.clj b/examples/multi-block-comment.clj
new file mode 100644
index 0000000000..9dcd074d73
--- /dev/null
+++ b/examples/multi-block-comment.clj
@@ -0,0 +1,39 @@
+;; This buffer shows a "block-comment" where we wish to comment large blocks
+;; of the buffer between one lentic buffer and the other.
+
+;; In this case, we use latex tags to indicate the code blocks. Outside of
+;; these tags, we start every line with comments. Inside we do not (although
+;; we leave comments that are there.
+
+;; \begin{code}
+(println "It is now broken")
+;; \end{code}
+
+;; We can have multiple code blocks, of course, after the first.
+
+;; \begin{code}
+(println "hello")
+;; \end{code}
+
+;; And more
+
+;; \begin{code}
+(println "Hello")
+;; \end{code}
+
+;; And more
+
+;; \begin{code}
+(println "hello")
+;; \end{code}
+
+;; And we can put more comments after the final text. And finally, we finish
+;; with a file local variable to tell lentic what kind of text this is. Note
+;; that start characters which are comments in both clojure and latex. In real
+;; use dir-local variables work better.
+
+;; %%
+;; %% Local Variables:
+;; %% lentic-init: (lentic-clojure-latex-init lentic-default-init)
+;; %% End:
+;; %%
diff --git a/examples/multi-lentic-copy.txt b/examples/multi-lentic-copy.txt
new file mode 100644
index 0000000000..855842aa22
--- /dev/null
+++ b/examples/multi-lentic-copy.txt
@@ -0,0 +1,4 @@
+hello here we are and here and ehre
+Local Variables:
+lentic-init: (lentic-default-init lentic-default-init)
+End:
diff --git a/examples/multi-lentic.txt b/examples/multi-lentic.txt
new file mode 100644
index 0000000000..0471b9b68f
--- /dev/null
+++ b/examples/multi-lentic.txt
@@ -0,0 +1,4 @@
+
+Local Variables:
+lentic-init: (lentic-default-init lentic-default-init)
+End:
diff --git a/lentic-block.el b/lentic-block.el
index a69785cd13..06b4ca648a 100644
--- a/lentic-block.el
+++ b/lentic-block.el
@@ -341,34 +341,40 @@ between the two buffers; we don't care which one has 
comments."
                              "start")
                            (when stop-in-comment
                              "stop")))
-    ;; now clone the buffer
-    (call-next-method conf start stop length-before
-                      start-converted stop-converted)
-    ;; remove the line comments in the to buffer
-    ;; if the delimitors are unmatched, then we can do nothing other than 
clone.
-    (condition-case e
-        (lentic-blk-uncomment-buffer
-         conf
-         ;; the buffer at this point has been copied over, but is in an
-         ;; inconsistent state (because it may have comments that it should
-         ;; not). Still, the convertor should still work because it counts from
-         ;; the end
-         (lentic-convert
-          conf
-          ;; point-min if we know nothing else
-          (or start (point-min)))
-         (lentic-convert
-          conf
-          ;; if we have a stop
-          (if stop
-              ;; take stop (if we have got longer) or
-              ;; start length before (if we have got shorter)
-              (max stop
-                   (+ start length-before))
-            (point-max)))
-         (lentic-that conf))
-      (unmatched-delimiter-error
-       nil))))
+    ;; now clone the buffer, recording the return value unless either the
+    ;; start or the stop is in comment, in which case we need a nil.
+    (let* ((clone-return
+            (call-next-method conf start stop length-before
+                              start-converted stop-converted))
+           (clone-return
+            (unless (or start-in-comment stop-in-comment)
+              clone-return)))
+      ;; remove the line comments in the to buffer
+      ;; if the delimitors are unmatched, then we can do nothing other than 
clone.
+      (condition-case e
+          (lentic-blk-uncomment-buffer
+           conf
+           ;; the buffer at this point has been copied over, but is in an
+           ;; inconsistent state (because it may have comments that it should
+           ;; not). Still, the convertor should still work because it counts 
from
+           ;; the end
+           (lentic-convert
+            conf
+            ;; point-min if we know nothing else
+            (or start (point-min)))
+           (lentic-convert
+            conf
+            ;; if we have a stop
+            (if stop
+                ;; take stop (if we have got longer) or
+                ;; start length before (if we have got shorter)
+                (max stop
+                     (+ start length-before))
+              (point-max)))
+           (lentic-that conf))
+        (unmatched-delimiter-error
+         nil))
+      clone-return)))
 
 (defmethod lentic-invert
   ((conf lentic-commented-block-configuration))
@@ -395,7 +401,7 @@ between the two buffers; we don't care which one has 
comments."
 (defmethod lentic-clone
   ((conf lentic-uncommented-block-configuration)
    &optional start stop length-before start-converted stop-converted)
-  "Update the contents in the lentic with comments."
+  "Update the contents in the lentic without comments."
   ;;(lentic-log "blk-clone-comment conf):(%s)" conf)
   (let*
       ((start-at-bolp
@@ -412,30 +418,35 @@ between the two buffers; we don't care which one has 
comments."
         (lentic-log "In comment: %s"
                            (when start-at-bolp
                              "start")))
-    (call-next-method conf start stop length-before
-                      start-converted stop-converted)
-    (condition-case e
-        (lentic-blk-comment-buffer
-         conf
-         ;; the buffer at this point has been copied over, but is in an
-         ;; inconsistent state (because it may have comments that it should
-         ;; not). Still, the convertor should still work because it counts from
-         ;; the end
-         (lentic-convert
-          conf
-          ;; point-min if we know nothing else
-          (or start (point-min)))
-         (lentic-convert
-          conf
-          ;; if we have a stop
-          (if stop
-              ;; take stop (if we have got longer) or
-              ;; start length before (if we have got shorter)
-              (max stop
-                   (+ start length-before))
-            (point-max)))
-         (lentic-that conf))
-      (unmatched-delimiter-error nil))))
+    (let* ((clone-return
+           (call-next-method conf start stop length-before
+                             start-converted stop-converted))
+           (clone-return
+            (unless start-at-bolp
+              clone-return)))
+      (condition-case e
+          (lentic-blk-comment-buffer
+           conf
+           ;; the buffer at this point has been copied over, but is in an
+           ;; inconsistent state (because it may have comments that it should
+           ;; not). Still, the convertor should still work because it counts 
from
+           ;; the end
+           (lentic-convert
+            conf
+            ;; point-min if we know nothing else
+            (or start (point-min)))
+           (lentic-convert
+            conf
+            ;; if we have a stop
+            (if stop
+                ;; take stop (if we have got longer) or
+                ;; start length before (if we have got shorter)
+                (max stop
+                     (+ start length-before))
+              (point-max)))
+           (lentic-that conf))
+        (unmatched-delimiter-error nil))
+      clone-return)))
 
 (defmethod lentic-invert
   ((conf lentic-uncommented-block-configuration))
diff --git a/lentic-delayed.el b/lentic-delayed.el
deleted file mode 100644
index 60d1ddf1d1..0000000000
--- a/lentic-delayed.el
+++ /dev/null
@@ -1,120 +0,0 @@
-;; lentic-delayed.el --- lentics but slowly -*- lexical-binding: t -*-
-
-;;; Header:
-
-;; This file is not part of Emacs
-
-;; Author: Phillip Lord <phillip.lord@newcastle.ac.uk>
-;; Maintainer: Phillip Lord <phillip.lord@newcastle.ac.uk>
-
-;; The contents of this file are subject to the GPL License, Version 3.0.
-;;
-;; Copyright (C) 2014, 2015, Phillip Lord, Newcastle University
-;;
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This runs lentic updates in the idle cycle. It is not really necessary now,
-;; as lentic now percolates updates incrementally, rather than copying entire
-;; buffers with every keypress.
-
-;; However, incremental updates are a lot harder to implement than cloning the
-;; entire buffer, so this might still be useful.
-
-;;; Code:
-;; #+begin_src emacs-lisp
-(require 'lentic)
-(require 'dash)
-
-(defvar lentic-delayed-queue nil)
-(defvar lentic-delayed-timer nil)
-
-(defun lentic-delayed-ensure-timer ()
-  (unless lentic-delayed-timer
-    (setq lentic-delayed-timer
-          (run-with-idle-timer 0.2 t 'lentic-delayed-timer-function))))
-
-(defun lentic-delayed-timer-function ()
-  (let ((repeat t))
-    (while
-        (and repeat
-             lentic-delayed-queue)
-      (lentic-delayed-clone
-       (pop lentic-delayed-queue))
-      ;; redisplay and wait
-      (setq repeat (sit-for 0.1))))
-  ;; kill timer if we have finished
-  (unless lentic-delayed-queue
-    (when lentic-delayed-timer
-      (cancel-timer lentic-delayed-timer))
-    (setq lentic-delayed-timer nil)))
-
-(defclass lentic-delayed-configuration
-  (lentic-configuration)
-  ((delayed
-    :initarg :delayed))
-  "lentic in the idle cycle.")
-
-(defmethod lentic-this ((conf lentic-delayed-configuration))
-  (lentic-this (oref conf :delayed)))
-
-(defmethod lentic-that ((conf lentic-delayed-configuration))
-  (lentic-that (oref conf :delayed)))
-
-(defmethod lentic-create ((conf lentic-delayed-configuration))
-  (let ((buf (lentic-create (oref conf :delayed))))
-    ;; we should now have set up that-buffer and config, which will be the
-    ;; undelayed form -- so swap a new one in
-    (with-current-buffer
-        (lentic-that conf)
-      (setq lentic-config
-            (lentic-delayed-configuration
-             "inverted-delayed"
-             :delayed lentic-config)))
-    buf))
-
-
-(defmethod lentic-convert ((conf lentic-delayed-configuration)
-                           location)
-  (lentic-convert (oref conf :delayed) location))
-
-(defmethod lentic-clone ((conf lentic-delayed-configuration)
-                         &rest _rest)
-  (add-to-list 'lentic-delayed-queue
-               conf t)
-  (lentic-delayed-ensure-timer))
-
-(defmethod lentic-delayed-clone ((conf
-                                  lentic-delayed-configuration))
-  ;; inhibit-modification-hooks or we percolate back to the start
-  (let ((inhibit-modification-hooks t))
-    (lentic-clone (oref conf :delayed))
-    (lentic-update-point (oref conf :delayed))))
-
-;;;###autoload
-(defun lentic-delayed-init (delayed)
-  (unless lentic-config
-    (lentic-delayed-configuration
-     "delayed"
-     :delayed (funcall delayed))))
-
-;;;###autoload
-(defun lentic-delayed-default-init ()
-  (lentic-delayed-init
-   'lentic-default-init))
-
-(provide 'lentic-delayed)
-;;; lentic-delayed.el ends here
-;; #+end_src
diff --git a/lentic-dev.el b/lentic-dev.el
index efe5b7aaf2..0450e1fede 100644
--- a/lentic-dev.el
+++ b/lentic-dev.el
@@ -77,7 +77,31 @@ Using this function is the easiest way to test an new
 painful for debugging. Set variable `lentic-emergency' to
 true to disable command loop functionality."
   (interactive)
-  (lentic-post-command-hook-1))
+  (lentic-post-command-hook-1 (current-buffer) '()))
+
+;;;###autoload
+(defun lentic-dev-after-save-hook ()
+  (interactive)
+  (let ((lentic-emergency nil))
+    (lentic-mode-after-save-hook)))
+
+;;;###autoload
+(defun lentic-dev-mode-buffer-list-update-hook ()
+  (interactive)
+  (let ((lentic-emergency nil))
+    (lentic-mode-buffer-list-update-hook)))
+
+;;;###autoload
+(defun lentic-dev-kill-buffer-hook ()
+  (interactive)
+  (let ((lentic-emergency nil))
+    (lentic-kill-buffer-hook)))
+
+;;;###autoload
+(defun lentic-dev-kill-emacs-hook ()
+  (interactive)
+  (let ((lentic-emergency nil))
+    (lentic-kill-emacs-hook)))
 
 ;;;###autoload
 (defun lentic-dev-reinit ()
@@ -87,7 +111,6 @@ to make sure there is a new one."
   (interactive)
   (funcall lentic-init))
 
-
 ;; #+end_src
 
 ;; ** Font-Lock changes
diff --git a/lentic-mode.el b/lentic-mode.el
index f77356e5fc..2473507004 100644
--- a/lentic-mode.el
+++ b/lentic-mode.el
@@ -36,6 +36,36 @@
 (require 'lentic-doc)
 ;; #+end_src
 
+;; ** Utility
+(defun lentic-mode-lentic-list (buffer)
+  "Return a list of all lentics for BUFFER.
+Lentics are listed in an undefined order."
+  (lentic-mode--lentic-list-1 buffer nil))
+
+(defun lentic-mode--lentic-list-1 (buffer seen-buffer)
+  (when buffer
+    (with-current-buffer buffer
+      (lentic-when-lentic
+       (setq seen-buffer (cons buffer seen-buffer))
+       (-map
+        (lambda (config)
+          (unless (-contains? seen-buffer (lentic-that config))
+            (lentic-mode--lentic-list-1
+             (lentic-that config)
+             seen-buffer)))
+        (lentic-config))))))
+
+(defun lentic-mode-buffer-list (buffer &optional frame)
+  "Returns a list of all lentics for BUFFER.
+Lentics are listed in the same order as in fundamental
+`buffer-list'. or the frame local if FRAME is specified."
+  (let ((lentic-list
+         (lentic-mode-lentic-list buffer)))
+    (-filter
+     (lambda (b)
+       (-contains? lentic-list b))
+     (buffer-list frame))))
+
 ;; ** Window and Buffer Functions
 
 ;; #+begin_src emacs-lisp
@@ -51,7 +81,8 @@ then the current-buffer will be moved into that window. See 
also
          (point)))
     (lentic-mode-swap-buffer-windows
      (current-buffer)
-     (lentic-that lentic-config))
+     (lentic-that
+      (car lentic-config)))
     (set-window-start
      (selected-window)
      before-window-start)
@@ -65,7 +96,8 @@ See also `lentic-mode-move-lentic-window'."
   (interactive)
   (lentic-mode-swap-buffer-windows
    (current-buffer)
-   (lentic-that lentic-config))
+   (lentic-that
+    (car lentic-config)))
   (when (window-live-p
          (get-buffer-window
           (current-buffer)))
@@ -85,6 +117,7 @@ A and B are the buffers."
       (set-window-buffer
        window-b a))))
 
+;;;###autoload
 (defun lentic-mode-create-in-selected-window ()
   "Create a lentic buffer and move it to the current window."
   (interactive)
@@ -92,30 +125,30 @@ A and B are the buffers."
          (window-start (get-buffer-window)))
         (before-window-point
          (point)))
-    (lentic-ensure-init)
     (set-window-buffer
      (selected-window)
-     (lentic-create lentic-config))
+     (-take 1
+            (lentic-init-all-create lentic-config)))
     (set-window-start
      (selected-window)
      before-window-start)
     (goto-char before-window-point)))
 
+;;;###autoload
 (defun lentic-mode-split-window-below ()
   "Create a lentic buffer in a new window below."
   (interactive)
-  (lentic-ensure-init)
   (set-window-buffer
    (split-window-below)
-   (lentic-create lentic-config)))
+   (car (lentic-init-all-create))))
 
+;;;###autoload
 (defun lentic-mode-split-window-right ()
   "Create a lentic buffer in a new window right."
   (interactive)
-  (lentic-ensure-init)
   (set-window-buffer
    (split-window-right)
-   (lentic-create lentic-config)))
+   (car (lentic-init-all-create))))
 ;; #+end_src
 
 ;; ** Minor Mode
@@ -161,20 +194,27 @@ A and B are the buffers."
         (format " %s[%s]"
                 lentic-mode-line-lighter
                 (if lentic-config
-                    (lentic-mode-line-string lentic-config)
+                    (s-join ","
+                     (-map
+                      (lambda (conf)
+                        (lentic-mode-line-string conf))
+                      lentic-config))
                   "")))
   (force-mode-line-update))
 
 (defun lentic-mode-buffer-list-update-hook ()
-  (-map
-   (lambda (b)
-     (with-current-buffer
-         b
-       (lentic-mode-update-mode-line)))
-   (buffer-list)))
+  (if lentic-emergency
+      (setq lentic-mode-line
+            (format " %s[Emergency]" lentic-mode-line-lighter))
+    (-map
+     (lambda (b)
+       (with-current-buffer
+           b
+         (lentic-mode-update-mode-line)))
+     (buffer-list))))
 
 (add-hook 'buffer-list-update-hook
-         'lentic-mode-buffer-list-update-hook)
+          'lentic-mode-buffer-list-update-hook)
 
 ;;;###autoload
 (define-minor-mode lentic-mode
diff --git a/lentic.el b/lentic.el
index 026b39fac2..21cdb589d4 100644
--- a/lentic.el
+++ b/lentic.el
@@ -6,8 +6,8 @@
 
 ;; Author: Phillip Lord <phillip.lord@newcastle.ac.uk>
 ;; Maintainer: Phillip Lord <phillip.lord@newcastle.ac.uk>
-;; Version: 0.7.1
-;; Package-Requires: ((emacs "24.4")(m-buffer "0.8")(dash "2.5.0")(f "0.17.2"))
+;; Version: 0.8
+;; Package-Requires: ((emacs "24.4")(m-buffer "0.9")(dash "2.5.0")(f "0.17.2"))
 
 ;; The contents of this file are subject to the GPL License, Version 3.0.
 
@@ -175,6 +175,7 @@
 
 (require 'eieio)
 (require 'm-buffer)
+(require 'm-buffer-at)
 
 (defvar lentic-init 'lentic-default-init
   "Function that initializes a lentic.
@@ -200,9 +201,10 @@ of mode in the current buffer.")
   "A list of all functions that can be used as lentic-init
   functions.")
 
+(defvar lentic-counter 0)
 (defun lentic-config-name (buffer)
   "Given BUFFER, return a name for the configuration object."
-  (format "lentic: %s" buffer))
+  (format "lentic \"%s:%s\"" buffer (setq lentic-counter (+ 1 
lentic-counter))))
 ;; #+end_src
 
 ;; ** Base Configuration
@@ -214,7 +216,7 @@ of mode in the current buffer.")
 ;; #+begin_src emacs-lisp
 ;;
 ;; Base Configuration:
-;;
+
 (defclass lentic-configuration ()
   ((this-buffer
     :initarg :this-buffer)
@@ -252,6 +254,7 @@ by which linking happens.")
 (defgeneric lentic-convert (conf location))
 (defgeneric lentic-invert (conf that-buffer))
 
+
 (defmethod lentic-this ((conf lentic-configuration))
   (oref conf :this-buffer))
 
@@ -328,29 +331,37 @@ created."
   (let* ((this-buffer
           (lentic-this conf))
          (that-buffer
-          (get-buffer-create
+          (generate-new-buffer
            (format "*lentic: %s*"
                    (buffer-name
                     this-buffer))))
+         ;; TODO this is broken -- it's setting clojure mode when I don't want
+         ;; it for instance with tex
+         (sec-file (oref conf :lentic-file))
          (sec-mode
-          (or (oref conf :lentic-mode)
-              major-mode))
-         (sec-file (oref conf :lentic-file)))
+          (or
+           ;; the specified normal mode
+           (oref conf :lentic-mode)
+           ;; if we have a file try normal mode
+           (if sec-file
+               'normal-mode
+             ;; otherwise the same mode as the main file
+             major-mode))))
     (oset conf :creator t)
     ;; make sure this-buffer knows about that-buffer
     (oset conf :that-buffer that-buffer)
-    ;; insert the contents
-    (lentic-update-contents conf)
     ;; init that-buffer with mode, file and config
     ;; the mode must be init'd after adding content in case there are any
     ;; file-local variables need to be evaled
+    ;; insert the contents
+    (lentic-update-contents conf)
     (with-current-buffer that-buffer
       (when sec-mode
         (funcall sec-mode))
       (when sec-file
         (set-visited-file-name sec-file))
       (setq lentic-config
-            (lentic-invert conf)))
+            (list (lentic-invert conf))))
     that-buffer))
 
 (defmethod lentic-invert ((conf lentic-default-configuration))
@@ -370,7 +381,16 @@ the lentic."
                                 start-converted stop-converted)
   "Updates that-buffer to reflect the contents in this-buffer.
 
-Currently, this is just a clone all method but may use regions in future."
+Updates at least the region that has been given between start and
+stop in the this-buffer, into the region start-converted and
+stop-converted in that-buffer.
+
+Returns a list of the start location in that-buffer of the
+change, the stop location in that-buffer of the change and the
+length-before in that buffer of the region changed before the
+change, if and only if the changes are exactly that suggested by
+the START, STOP, _LENGTH-BEFORE, START-CONVERTED and
+STOP-CONVERTED. Otherwise, this should return nil."
   (let ((this-b (lentic-this conf))
         (that-b (lentic-that conf)))
     (with-current-buffer this-b
@@ -385,14 +405,17 @@ Currently, this is just a clone all method but may use 
regions in future."
               ;; lentic-convert is not reliable now, because the two
               ;; buffers do not share state until we have percolated it
               (let ((converted-start
-                     (or start-converted
-                         (point-min)))
+                     (max (point-min)
+                          (or start-converted
+                              (point-min))))
                     (converted-stop
-                     (or stop-converted
-                         (point-max))))
+                     (min (point-max)
+                          (or stop-converted
+                              (point-max)))))
+                ;; does this widen do anything?
                 (widen)
-                (delete-region (max (point-min) converted-start)
-                               (min (point-max) converted-stop))
+                (delete-region converted-start
+                               converted-stop)
                 (save-excursion
                   (goto-char converted-start)
                   ;; so this insertion is happening at the wrong place in block
@@ -403,7 +426,10 @@ Currently, this is just a clone all method but may use 
regions in future."
                      ;; hence the property
                      (lentic-insertion-string-transform
                       (buffer-substring-no-properties
-                       start stop)))))))))))))
+                       start stop))))
+                  (list converted-start
+                        (+ converted-start (- stop start))
+                        (- converted-stop converted-start)))))))))))
 
 ;;;###autoload
 (defun lentic-default-init ()
@@ -429,13 +455,44 @@ see `lentic-init' for details."
   (declare (debug t))
   `(when (and
           lentic-config
-          (lentic-that
-           lentic-config)
-          (buffer-live-p
-           (lentic-that
-            lentic-config)))
+          (-any?
+           (lambda (conf)
+             (-when-let
+                 (buf (lentic-that conf))
+               (buffer-live-p buf)))
+           lentic-config))
      ,@body))
 
+(defmacro lentic-when-with-current-buffer (buffer &rest body)
+  (declare (debug t)
+           (indent 1))
+  `(when (and buffer
+              (buffer-live-p buffer))
+     (with-current-buffer
+         buffer
+       ,@body)))
+
+(defun lentic-each (buffer fn &optional seen-buffer)
+  "Starting at buffer, call fn on every lentic-buffer in the
+excluding buffer. fn should take a single argument which is the
+buffer."
+  ;; when buffer is sane
+  (when (and buffer
+             (buffer-live-p buffer))
+    ;; and is lentic
+    (with-current-buffer buffer
+      (when lentic-config
+        (setq seen-buffer (cons buffer seen-buffer))
+        (-map
+         (lambda (conf)
+           (let ((that
+                  (lentic-that conf)))
+             (when (and (not (-contains? seen-buffer that))
+                        (buffer-live-p that))
+               (funcall fn that)
+               (lentic-each that fn seen-buffer))))
+         lentic-config)))))
+
 (defun lentic-ensure-hooks ()
   "Ensures that the hooks that this mode requires are in place."
   (add-hook 'post-command-hook
@@ -507,39 +564,43 @@ repeated errors.")
   (interactive)
   (setq lentic-emergency nil))
 
-(defvar lentic-saving-p nil)
-
 (defun lentic-after-save-hook ()
-  (lentic-when-lentic
-   ;; don't want to recurse!
-   (when (not lentic-saving-p)
-     (let ((lentic-saving-p t))
+  (unless lentic-emergency
+    (lentic-each
+     (current-buffer)
+     (lambda (buffer)
        (with-current-buffer
-           (lentic-that lentic-config)
-         (when (buffer-file-name)
-           (save-buffer)))))))
+           buffer
+         (save-buffer))))))
 
 (defvar lentic-kill-retain nil
   "If non-nil retain files even if requested to delete on exit.")
 
 (defun lentic-kill-buffer-hook ()
   (lentic-when-lentic
-    (progn
-      ;; remove files
-      (when
-          (and (oref lentic-config :delete-on-exit)
-               ;; might not exist if we not saved yet!
-               (file-exists-p buffer-file-name)
-               ;; if we are cloning in batch, we really do not want to kill
-               ;; everything at the end
-               (not noninteractive)
-               ;; or we have blocked this anyway
-               (not lentic-kill-retain))
-        (delete-file (buffer-file-name)))
-      ;; kill lentic-buffers
-      (when (oref lentic-config :creator)
-          (kill-buffer
-           (lentic-that lentic-config))))))
+   (when
+       (and
+        (--any?
+         (oref it :delete-on-exit)
+         lentic-config)
+        ;; might not exist if we not saved yet!
+        (file-exists-p buffer-file-name)
+        ;; if we are cloning in batch, we really do not want to kill
+        ;; everything at the end
+        (not noninteractive)
+        ;; or we have blocked this anyway
+        (not lentic-kill-retain))
+     (delete-file (buffer-file-name)))
+   ;; if we were the creator buffer, blitz the lentics (which causes their
+   ;; files to delete also).
+   (when
+       (--any?
+        (oref it :creator)
+        lentic-config)
+     (lentic-each
+      (current-buffer)
+      (lambda (buffer)
+        (kill-buffer buffer))))))
 
 (defun lentic-kill-emacs-hook ()
   (-map
@@ -547,55 +608,86 @@ repeated errors.")
      (with-current-buffer
          b
        (when
-           (and lentic-config
-                (oref lentic-config :delete-on-exit)
-                (file-exists-p buffer-file-name)
-                (not noninteractive))
-         (delete-file (buffer-file-name)))))
+           lentic-config
+         ;; delete if any delete-on-exit
+         (-map
+          (lambda (conf)
+            (and
+             (oref conf :delete-on-exit)
+             (file-exists-p buffer-file-name)
+             (not noninteractive)
+             (delete-file (buffer-file-name))))
+          lentic-config))))
    (buffer-list)))
 
 (defun lentic-post-command-hook ()
   "Update point according to config, with error handling."
-  ;;(message "Entering post-command-hook")
   (unless lentic-emergency
     (condition-case err
-        (lentic-post-command-hook-1)
+        (progn
+          (lentic-post-command-hook-1 (current-buffer)))
       (error
        (lentic-hook-fail err "post-command-hook")))))
 
-(defun lentic-post-command-hook-1 ()
+(defun lentic-post-command-hook-1 (buffer &optional seen-buffer)
   "Update point according to config."
-  (progn
-    (lentic-when-lentic
-     (lentic-update-point lentic-config))))
+  (lentic-when-with-current-buffer
+      buffer
+    ;; only if at least one config is live
+    (when lentic-config
+      ;; now we have seen this buffer don't look again
+      (setq seen-buffer (cons buffer seen-buffer))
+      ;; for all configurations
+      (-map
+       (lambda (config)
+         ;; check for the termination condition
+         (unless (-contains? seen-buffer (lentic-that config))
+           ;; then update and recurse
+           (lentic-update-point config)
+           (lentic-post-command-hook-1 (lentic-that config) seen-buffer)))
+       lentic-config))))
 
 (defun lentic-hook-fail (err hook)
   "Give an informative message when we have to fail.
 ERR is the error. HOOK is the hook type."
-  (message "lentic mode has failed on %s hook: %s "
+  (message "lentic mode has failed on \"%s\" hook: %s "
            hook (error-message-string err))
   (lentic-emergency)
   (with-output-to-temp-buffer "*lentic-fail*"
     (princ "There has been an error in lentic-mode.\n")
     (princ "The following is debugging information\n\n")
+    (princ (format "Hook: %s" hook))
     (princ (error-message-string err)))
   (select-window (get-buffer-window "*lentic-fail*")))
 
 (defun lentic-ensure-init ()
   "Ensure that the `lentic-init' has been run."
   (unless (and lentic-config
-               (slot-boundp
-                lentic-config :that-buffer)
-               (buffer-live-p (lentic-that
-                               lentic-config)))
+               (-any?
+                (lambda (conf)
+                  (and
+                   (slot-boundp conf :that-buffer)
+                   (buffer-live-p
+                    (lentic-that conf))))
+                lentic-config))
     (setq lentic-config
-          (funcall lentic-init))))
+          (-map
+           (lambda (init)
+             (funcall init))
+           (-list lentic-init)))))
 
-(defun lentic-init-create ()
-  "Create the lentic for current-buffer."
+(defun lentic-init-create (conf)
+  "Create the lentic for CONF."
   (lentic-ensure-init)
-  (lentic-create lentic-config))
+  (lentic-create conf))
 
+(defun lentic-init-all-create ()
+  "Create all lentics fo the current buffer."
+  (lentic-ensure-init)
+  (-map
+   (lambda (conf)
+     (lentic-create conf))
+   (-list lentic-config)))
 
 (defvar lentic-emergency-last-change nil)
 (make-variable-buffer-local 'lentic-emergency-last-change)
@@ -608,20 +700,35 @@ Errors are handled. REST is currently just ignored."
     (setq lentic-emergency-last-change (list start stop length-before)))
   (unless lentic-emergency
     (condition-case err
-        (lentic-after-change-function-1 start stop length-before)
+        (lentic-after-change-function-1
+         (current-buffer) start stop length-before)
       (error
        (lentic-hook-fail err "after change")))))
 
-(defun lentic-after-change-function-1 (start stop length-before)
+(defun lentic-after-change-function-1
+    (buffer start stop
+            length-before &optional seen-buffer)
   "run change update according to `lentic-config'.
 rest is currently just ignored."
-  (lentic-when-lentic
-   (lentic-log
-    "after-change (start, stop, length-before): %s,%s,%s"
-    start stop length-before)
-   (lentic-update-contents lentic-config
-                           start stop length-before)))
-
+  (when buffer
+    (with-current-buffer buffer
+      (lentic-when-lentic
+       (setq seen-buffer (cons buffer seen-buffer))
+       (-map
+        (lambda (config)
+          (unless (-contains? seen-buffer (lentic-that config))
+            (let ((updates
+                   (or
+                    (lentic-update-contents config
+                                            start stop length-before)
+                    '(nil nil nil))))
+              (lentic-after-change-function-1
+               (lentic-that config)
+               (nth 0 updates)
+               (nth 1 updates)
+               (nth 2 updates)
+               seen-buffer))))
+        lentic-config)))))
 
 ;; convert the start position and store it. we need to do this before
 ;; the change so that we can use the value during clone. after the
@@ -634,31 +741,38 @@ rest is currently just ignored."
            lentic-emergency
            (not lentic-emergency-debug))
     (condition-case err
-        (progn
-          (lentic-when-lentic
-           (oset lentic-config :last-change-start start)
-           (oset lentic-config
-                 :last-change-start-converted
-                 (lentic-convert
-                  lentic-config
-                  start))
-           (oset lentic-config :last-change-stop stop)
-           (oset lentic-config
-                 :last-change-stop-converted
-                 (lentic-convert
-                  lentic-config
-                  stop)))
-          (lentic-log
-           "before change:(start,stop,start-c,stop-c,command): %s,%s,%s,%s,%s"
-           start stop
-           (oref lentic-config
-                 :last-change-start-converted)
-           (oref lentic-config
-                 :last-change-stop-converted)
-           this-command))
+        (lentic-before-change-function-1 (current-buffer) start stop)
       (error
        (lentic-hook-fail err "before change")))))
 
+(defun lentic-before-change-function-1 (buffer start stop &optional 
seen-buffer)
+  (when buffer
+    (with-current-buffer buffer
+      (setq seen-buffer (cons buffer seen-buffer))
+      (lentic-when-lentic
+       (-map
+        (lambda (config)
+          (unless
+              (-contains? seen-buffer (lentic-that config))
+            (oset config :last-change-start start)
+            (oset config
+                  :last-change-start-converted
+                  (lentic-convert
+                   config
+                   start))
+            (oset config :last-change-stop stop)
+            (oset config
+                  :last-change-stop-converted
+                  (lentic-convert
+                   config
+                   stop))
+            (lentic-before-change-function-1
+             (lentic-that config)
+             (oref config :last-change-start-converted)
+             (oref config :last-change-stop-converted)
+             seen-buffer)))
+        lentic-config)))))
+
 (defun lentic-update-contents (conf &optional start stop length-before)
   "update the contents of that-buffer with the contents of this-buffer.
 update mechanism depends on conf."
@@ -675,16 +789,20 @@ update mechanism depends on conf."
     ;; Currently, the best solution I have for this is to fall-back to a full
     ;; clone.
     (let ((skewed
-           (when (and
-                  ;; we can't be skewed where we have no region!
-                  start stop length-before
-                  ;; skews only occur in insertions which result in a positive
-                  ;; length-before. This also picks up no-insertion changes
-                  (and (< 0 length-before)
-                       ;; = start stop means we have a deletion because
-                       ;; there is no range after. Deletions seem to be
-                       ;; safe.
-                       (not (= start stop))))
+           (when
+               (or
+                ;; previously this was not skewed if no region, but actually,
+                ;; if there is no region we need to copy everything, we can
+                ;; also do by declaring skew -- this is important for the
+                ;; multi-lentic situation
+                (not (or start stop length-before))
+                ;; skews only occur in insertions which result in a positive
+                ;; length-before. This also picks up no-insertion changes
+                (and (< 0 length-before)
+                     ;; = start stop means we have a deletion because
+                     ;; there is no range after. Deletions seem to be
+                     ;; safe.
+                     (not (= start stop))))
              (lentic-log "Skew detected: %s" this-command)
              t)))
       (m-buffer-with-markers
@@ -707,8 +825,6 @@ update mechanism depends on conf."
         (oset conf :last-change-start-converted nil)
         (oset conf :last-change-stop nil)
         (oset conf :last-change-stop-converted nil)
-        ;;(lentic-log
-        ;;"Update config: %s" lentic-config)
         (if skewed
             (lentic-clone conf)
           (lentic-clone conf start stop length-before
@@ -723,9 +839,8 @@ same top-left location. Update details depend on CONF."
     (let* ((from-point
             (lentic-convert
              conf
-             (with-current-buffer
-                 (lentic-this conf)
-               (point))))
+             (m-buffer-at-point
+              (lentic-this conf))))
            (from-window-start
             (lentic-convert
              conf
@@ -773,7 +888,8 @@ lentic is open already."
       (find-file-noselect filename)
     (setq lentic-init init)
     (with-current-buffer
-        (lentic-init-create)
+        (car
+         (lentic-init-all-create))
       (save-buffer)
       (kill-buffer))
     (kill-buffer)))
@@ -788,7 +904,8 @@ Return the lentic contents without properties."
         (find-file-noselect filename)
       (setq lentic-init init)
       (with-current-buffer
-          (lentic-init-create)
+          (car
+           (lentic-init-all-create))
         (setq retn
               (buffer-substring-no-properties
                (point-min)
diff --git a/lenticular.org b/lenticular.org
index 6a56c90f3b..92c9908676 100644
--- a/lenticular.org
+++ b/lenticular.org
@@ -86,12 +86,6 @@ Tools for developers of new configurations.
 
 #+include: "lentic-dev.org" :minlevel 2
 
-* Lentic Delayed
-
-A slightly useful package for cloning in the idle cycle.
-
-#+include: "lentic-delayed.org" :minlevel 2
-
 * Lentic Doc
 
 Lentic has a self-hosting documentation system which is defined here.
diff --git a/test/lentic-test.el b/test/lentic-test.el
index 31aaeb0337..14e8cf2364 100644
--- a/test/lentic-test.el
+++ b/test/lentic-test.el
@@ -2,7 +2,6 @@
 (require 'lentic-latex-code)
 (require 'lentic-asciidoc)
 (require 'lentic-org)
-(require 'lentic-delayed)
 (require 'lentic-rot13)
 (require 'f)
 
@@ -61,22 +60,32 @@
                    (buffer-string))))
       nil)))
 
+(defun lentic-test-clone-with-cleanup (file init)
+  (unwind-protect
+      (lentic-batch-clone-with-config (lentic-test-file file) init)
+    (let ((this (get-file-buffer (lentic-test-file file))))
+      (when this
+        (with-current-buffer this
+          (let ((this (lentic-that (car lentic-config))))
+            (kill-buffer that)))
+        (kill-buffer this)))))
+
 (defun lentic-test-clone-equal (init file cloned-file)
   (let ((cloned-file
          (f-read
           (lentic-test-file cloned-file)))
         (cloned-results
-         (lentic-batch-clone-with-config
-          (lentic-test-file file) init)))
+         (lentic-test-clone-with-cleanup
+          file init)))
     (lentic-test-equal-loudly cloned-file cloned-results)))
 
 (defun lentic-test-clone-equal-generate
   (init file cloned-file)
   "Generates the test file for `lentic-batch-clone-equal'."
   (f-write
-   (lentic-batch-clone-with-config
+   (lentic-test-clone-with-cleanup
     (lentic-test-file file) init)
-   'utf-8
+   o'utf-8
    (concat lentic-test-dir cloned-file))
   ;; return nil, so if we use this in a test by mistake, it will crash out.
   nil)
@@ -91,15 +100,16 @@
 (ert-deftest lentic-simple ()
   (should
    (equal "simple\n"
-          (lentic-batch-clone-with-config
-           (lentic-test-file "simple-contents.txt")
+          (lentic-test-clone-with-cleanup
+           "simple-contents.txt"
            'lentic-default-init))))
 
 (ert-deftest lentic-clojure-latex ()
   (should
    (lentic-test-clone-equal
     'lentic-clojure-latex-init
-    "block-comment.clj" "block-comment-out.tex")))
+    "block-comment.clj"
+    "block-comment-out.tex")))
 
 
 (ert-deftest lentic-asciidoc-clojure ()
@@ -146,8 +156,25 @@
   (should
    (lentic-test-clone-equal
     'lentic-rot13-init
-    "abc.txt" "rot13-abc.txt"))
-  )
+    "abc.txt" "rot13-abc.txt")))
+
+(ert-deftest three-way ()
+  (should
+   (with-current-buffer
+       (find-file-noselect
+        (lentic-test-file "block-comment.clj"))
+     (setq lentic-init
+           '(lentic-clojure-latex-init
+             lentic-default-init))
+     (lentic-init-all-create)
+     (let ((tex
+            (get-buffer "block-comment.tex"))
+           (clj
+            (get-buffer "*lentic: block-comment.clj*")))
+       (kill-buffer tex)
+       (kill-buffer clj)
+       (and clj tex)))))
+
 
 
 ;; incremental testing
@@ -172,10 +199,10 @@ results."
           (with-current-buffer
               (setq this
                     (find-file-noselect filename))
-            (setq lentic-init init)
+            (setq lentic-init (-list init))
             (progn
               (setq that
-                    (lentic-init-create))
+                    (car (lentic-init-all-create)))
               (funcall f-this)
               (with-current-buffer
                   that
@@ -196,8 +223,7 @@ results."
 
         ;; unwind forms
         (when this (kill-buffer this))
-        (when that (kill-buffer that))))
-    ))
+        (when that (kill-buffer that))))))
 
 (defun lentic-test-clone-and-change-equal
   (init file cloned-file
@@ -360,18 +386,21 @@ This mostly checks my test machinary."
     t)))
 
 ;; ** delayed init
-(ert-deftest lentic-simple-delayed ()
-  (should
-   (equal
-    (concat "x" abc-txt)
-    (lentic-test-clone-and-change-with-config
-     (lentic-test-file "abc.txt")
-     'lentic-delayed-default-init
-     (lambda ()
-       (goto-char (point-min))
-       (insert "x")
-       ;; run timer by ourselves.
-       (lentic-delayed-timer-function))))))
+
+;; Probably time to deprecate this package now
+
+;; (ert-deftest lentic-simple-delayed ()
+;;   (should
+;;    (equal
+;;     (concat "x" abc-txt)
+;;     (lentic-test-clone-and-change-with-config
+;;      (lentic-test-file "abc.txt")
+;;      'lentic-delayed-default-init
+;;      (lambda ()
+;;        (goto-char (point-min))
+;;        (insert "x")
+;;        ;; run timer by ourselves.
+;;        (lentic-delayed-timer-function))))))
 
 ;; tests for lots of types of change and whether they break the incremental
 ;; updates.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]