[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Lazy printing in tabulated-list-mode
Re: Lazy printing in tabulated-list-mode
Thu, 30 Apr 2015 17:13:18 +0100
... because I wans't absolutely sure it would be well received or seen
as "a litle too much".
From: Artur Malabarba <address@hidden>
Date: Thu, 30 Apr 2015 16:18:24 +0100
Subject: [PATCH] * lisp/emacs-lisp/tabulated-list.el: Implement lazy printing
(tabulated-list--timer): New variable.
(tabulated-list-print): Use them. Accept a second argument, lazy.
If it is non-nil, only the first page of entries is printed
immediately, the rest of the entries are printed on idle timers.
* lisp/emacs-lisp/package.el (package-menu--generate): Use it.
(list-packages): Reorder buffer switching to make use of lazy
lisp/emacs-lisp/package.el | 11 ++---
lisp/emacs-lisp/tabulated-list.el | 88 +++++++++++++++++++++++++++++++--------
2 files changed, 77 insertions(+), 22 deletions(-)
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index db61aba..21af0a3 100644
@@ -2648,7 +2648,7 @@ shown."
(define-key package-menu-mode-map "q" 'package-show-package-list)
(define-key package-menu-mode-map "q" 'quit-window))
- (tabulated-list-print remember-pos))
+ (tabulated-list-print remember-pos 'redisplay))
(defun package-menu--print-info (pkg)
"Return a package entry suitable for `tabulated-list-entries'.
@@ -3056,12 +3056,13 @@ The list is displayed in a buffer named `*Packages*'."
;; Fetch the remote list of packages.
(unless no-fetch (package-menu-refresh))
+ ;; The package menu buffer has keybindings. If the user types
+ ;; `M-x list-packages', that suggests it should become current.
+ (switch-to-buffer buf)
;; If we're not async, this would be redundant.
- (package-menu--generate nil t)))
- ;; The package menu buffer has keybindings. If the user types
- ;; `M-x list-packages', that suggests it should become current.
- (switch-to-buffer buf)))
+ (package-menu--generate nil t)))))
(defalias 'package-list-packages 'list-packages)
diff --git a/lisp/emacs-lisp/tabulated-list.el
index b12edc8..f9b5a8f 100644
@@ -273,19 +273,61 @@ It runs `tabulated-list-revert-hook', then calls
(error "No column named %s" name))))
-(defun tabulated-list-print (&optional remember-pos)
+(defvar-local tabulated-list--timer nil
+ "Timer being used for lazy printing.")
+(defun tabulated-list--cancel-timer ()
+ "Ensure that `tabulated-list--timer' is canceled and nil."
+ (when (timerp tabulated-list--timer)
+ (cancel-timer tabulated-list--timer)
+ (setq tabulated-list--timer nil)))
+(defun tabulated-list--print-in-buffer (entries buffer &optional lazy)
+ "Print list of ENTRIES at the end of BUFFER.
+If LAZY is non-nil, user input will interrupt the printing, in
+which case printing is resumed after some idle time. If LAZY is
+a number, just print that many entries and return.
+Return the list of entries left to print."
+ (with-current-buffer buffer
+ (goto-char (point-max))
+ (let ((inhibit-read-only t))
+ (while (and entries
+ (if (numberp lazy)
+ (< -1 (setq lazy (1- lazy)))
+ (or (not lazy)
+ (not (input-pending-p)))))
+ (apply tabulated-list-printer (pop entries)))))
+ (set-buffer-modified-p nil)
+ ;; If we're leaving before we finish printing, setup a timer.
+ (when (and entries (not (numberp lazy)))
+ (tabulated-list--cancel-timer) ; just in case
+ (setq tabulated-list--timer
+ 0.5 nil #'tabulated-list--print-in-buffer
+ entries buffer t)))
+(defun tabulated-list-print (&optional remember-pos lazy)
"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
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."
+to the entry with the same ID element as the current line.
+If REMEMBER-POS is nil and LAZY is non-nil, allow the printing to
+be interrupted by used input, in which case it is resumed after
+some idle time. If LAZY is the symbol redisplay, `redisplay' is
+called once after enough entries have been printed to fill a
(let ((inhibit-read-only t)
(entries (if (functionp tabulated-list-entries)
- entry-id saved-pt saved-col)
+ entry-id saved-col)
(setq entry-id (tabulated-list-get-id))
(setq saved-col (current-column)))
@@ -312,20 +354,32 @@ to the entry with the same ID element as the
(setq entries (nreverse entries)))
(unless (functionp tabulated-list-entries)
(setq tabulated-list-entries entries)))))
- ;; Print the resulting list.
- (dolist (elt entries)
- (and entry-id
- (equal entry-id (car elt))
- (setq saved-pt (point)))
- (apply tabulated-list-printer elt))
- (set-buffer-modified-p nil)
- ;; If REMEMBER-POS was specified, move to the "old" location.
- (if saved-pt
- (progn (goto-char saved-pt)
- (move-to-column saved-col)
- (when (eq (window-buffer) (current-buffer))
- (goto-char (point-min)))))
+ (if entry-id
+ ;; If remember-pos was given, we can't respect that and still
+ ;; print lazily, so we print the entire list.
+ (let (elt saved-pt)
+ (while (and (or (not lazy)
+ (not (input-pending-p)))
+ (setq elt (pop entries)))
+ (when (equal entry-id (car elt))
+ (setq saved-pt (point)))
+ (apply tabulated-list-printer elt))
+ ;; If REMEMBER-POS was specified, move to the "old" location.
+ (if saved-pt
+ (progn (goto-char saved-pt)
+ (move-to-column saved-col)
+ (when (eq (window-buffer) (current-buffer))
+ (goto-char (point-min))))
+ ;; Print the resulting list.
+ (when (eq lazy 'redisplay)
+ (setq entries (tabulated-list--print-in-buffer
+ ;; FIXME: `count-screen-lines' doesn't work
+ ;; here because the buffer is still empty.
+ entries (current-buffer) 50))
+ (tabulated-list--print-in-buffer entries (current-buffer) lazy))))
(defun tabulated-list-print-entry (id cols)
"Insert a Tabulated List entry at point.