summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/tabulated-list.el
diff options
context:
space:
mode:
authorArtur Malabarba <bruce.connor.am@gmail.com>2015-05-24 23:38:53 +0100
committerArtur Malabarba <bruce.connor.am@gmail.com>2015-05-24 23:45:46 +0100
commitc205098b6a8bd3b13256803f86f6863558a7a34e (patch)
treebd2c02bdb4f1a7822db9f753dccb84bb12287b9c /lisp/emacs-lisp/tabulated-list.el
parentd38350984e557aa492139ffecb9c1a910e763145 (diff)
downloademacs-c205098b6a8bd3b13256803f86f6863558a7a34e.tar.gz
emacs-c205098b6a8bd3b13256803f86f6863558a7a34e.tar.bz2
emacs-c205098b6a8bd3b13256803f86f6863558a7a34e.zip
* 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.
Diffstat (limited to 'lisp/emacs-lisp/tabulated-list.el')
-rw-r--r--lisp/emacs-lisp/tabulated-list.el54
1 files changed, 45 insertions, 9 deletions
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index 9d55ab8f533..58b8fd62d2f 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