diff options
author | Artur Malabarba <bruce.connor.am@gmail.com> | 2015-05-24 23:38:53 +0100 |
---|---|---|
committer | Artur Malabarba <bruce.connor.am@gmail.com> | 2015-05-24 23:45:46 +0100 |
commit | c205098b6a8bd3b13256803f86f6863558a7a34e (patch) | |
tree | bd2c02bdb4f1a7822db9f753dccb84bb12287b9c /lisp/emacs-lisp/tabulated-list.el | |
parent | d38350984e557aa492139ffecb9c1a910e763145 (diff) | |
download | emacs-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.el | 54 |
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 |