[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