@code{tabulated-list-format}).
@end defun
-@defun tabulated-list-print &optional remember-pos
+@defun 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
If the optional argument @var{remember-pos} is non-@code{nil}, 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 non-@code{nil}, 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
(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
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)
(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