emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master c205098 2/2: * lisp/emacs-lisp/tabulated-list.el: N


From: Artur Malabarba
Subject: [Emacs-diffs] master c205098 2/2: * lisp/emacs-lisp/tabulated-list.el: New optional print method
Date: Sun, 24 May 2015 22:46:01 +0000

branch: master
commit c205098b6a8bd3b13256803f86f6863558a7a34e
Author: Artur Malabarba <address@hidden>
Commit: Artur Malabarba <address@hidden>

    * lisp/emacs-lisp/tabulated-list.el: New optional print method
    
    (tabulated-list-print): New optional argument, UPDATE.  If
    non-nil, the list is printed by only adding and deleting the
    changed entries, instead of erasing the whole buffer.  This method
    is much faster when few or no entries have changed.
    
    * doc/lispref/modes.texi (Tabulated List Mode): Document it.
    
    * etc/NEWS: Document it.
---
 doc/lispref/modes.texi            |    9 +++++-
 etc/NEWS                          |    6 ++++
 lisp/emacs-lisp/tabulated-list.el |   54 ++++++++++++++++++++++++++++++------
 3 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index c325506..a8b6bb1 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -1055,7 +1055,7 @@ the above variables (in particular, only after setting
 @code{tabulated-list-format}).
 @end defun
 
address@hidden tabulated-list-print &optional remember-pos
address@hidden tabulated-list-print &optional remember-pos update
 This function populates the current buffer with entries.  It should be
 called by the listing command.  It erases the buffer, sorts the entries
 specified by @code{tabulated-list-entries} according to
@@ -1065,6 +1065,13 @@ specified by @code{tabulated-list-entries} according to
 If the optional argument @var{remember-pos} is address@hidden, this
 function looks for the @var{id} element on the current line, if any, and
 tries to move to that entry after all the entries are (re)inserted.
+
+If the optional argument @var{update} is address@hidden, this function
+will only erase or add entries that have changed since the last print.
+This is several times faster if most entries haven't changed since the
+last time this function was called.  The only difference in outcome is
+that tags placed via @code{tabulated-list-put-tag} will not be removed
+from entries that haven't changed (normally all tags are removed).
 @end defun
 
 @node Generic Modes
diff --git a/etc/NEWS b/etc/NEWS
index 7ad85ba..b922a27 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -205,10 +205,16 @@ font, and (iii) the specified window.
    `message' and related functions from displaying messages the Echo
    Area.  The output is still logged to the *Messages* buffer.
 
++++
 ** It is now safe for a mode that derives `tabulated-list-mode' to not
 call `tabulated-list-init-header', in which case it will have no
 header.
 
++++
+** `tabulated-list-print' takes a second optional argument, update,
+which specifies an alternative printing method which is faster when
+few or no entries have changed.
+
 
 * Editing Changes in Emacs 25.1
 
diff --git a/lisp/emacs-lisp/tabulated-list.el 
b/lisp/emacs-lisp/tabulated-list.el
index 9d55ab8..58b8fd6 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -298,7 +298,7 @@ column.  Negate the predicate that would be returned if
           (lambda (a b) (not (funcall sorter a b)))
         sorter))))
 
-(defun tabulated-list-print (&optional remember-pos)
+(defun tabulated-list-print (&optional remember-pos update)
   "Populate the current Tabulated List mode buffer.
 This sorts the `tabulated-list-entries' list if sorting is
 specified by `tabulated-list-sort-key'.  It then erases the
@@ -306,7 +306,14 @@ buffer and inserts the entries with 
`tabulated-list-printer'.
 
 Optional argument REMEMBER-POS, if non-nil, means to move point
 to the entry with the same ID element as the current line and
-recenter window line accordingly."
+recenter window line accordingly.
+
+Non-nil UPDATE argument means to use an alternative printing
+method which is faster if most entries haven't changed since the
+last print.  The only difference in outcome is that tags will not
+be removed from entries that haven't changed (see
+`tabulated-list-put-tag').  Don't use this immediately after
+changing `tabulated-list-sort-key'."
   (let ((inhibit-read-only t)
        (entries (if (functionp tabulated-list-entries)
                     (funcall tabulated-list-entries)
@@ -319,18 +326,47 @@ recenter window line accordingly."
                  (count-screen-lines (window-start) (point))))
         (setq entry-id (tabulated-list-get-id))
         (setq saved-col (current-column)))
-    (erase-buffer)
-    (unless tabulated-list-use-header-line
-      (tabulated-list-print-fake-header))
     ;; Sort the entries, if necessary.
     (setq entries (sort entries sorter))
     (unless (functionp tabulated-list-entries)
       (setq tabulated-list-entries entries))
+    ;; Without a sorter, we have no way to just update.
+    (when (and update (not sorter))
+      (setq update nil))
+    (if update (goto-char (point-min))
+      ;; Redo the buffer, unless we're just updating.
+      (erase-buffer)
+      (unless tabulated-list-use-header-line
+        (tabulated-list-print-fake-header)))
+    ;; Finally, print the resulting list.
     (dolist (elt entries)
-      (and entry-id
-          (equal entry-id (car elt))
-          (setq saved-pt (point)))
-      (apply tabulated-list-printer elt))
+      (let ((id (car elt)))
+        (and entry-id
+             (equal entry-id id)
+             (setq entry-id nil
+                   saved-pt (point)))
+        ;; If the buffer this empty, simply print each elt.
+        (if (eobp)
+            (apply tabulated-list-printer elt)
+          (while (let ((local-id (tabulated-list-get-id)))
+                   ;; If we find id, then nothing to update.
+                   (cond ((equal id local-id)
+                          (forward-line 1)
+                          nil)
+                         ;; If this entry sorts after id (or it's the
+                         ;; end), then just insert id and move on.
+                         ((funcall sorter elt
+                                   ;; FIXME: Might be faster if
+                                   ;; don't construct this list.
+                                   (list local-id (tabulated-list-get-entry)))
+                          (apply tabulated-list-printer elt)
+                          nil)
+                         ;; We find an entry that sorts before id,
+                         ;; it needs to be deleted.
+                         (t t)))
+            (let ((old (point)))
+              (forward-line 1)
+              (delete-region old (point)))))))
     (set-buffer-modified-p nil)
     ;; If REMEMBER-POS was specified, move to the "old" location.
     (if saved-pt



reply via email to

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