all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Artur Malabarba <bruce.connor.am@gmail.com>
To: emacs-devel <emacs-devel@gnu.org>
Subject: Re: Lazy printing in tabulated-list-mode
Date: Thu, 30 Apr 2015 17:13:18 +0100	[thread overview]
Message-ID: <CAAdUY-LUd3bbxHkf1MSN7ekfJ+QqqXL8V0-Rvh5z8u3v5MrzwQ@mail.gmail.com> (raw)
In-Reply-To: <CAAdUY-JdsuV8i_zwZB9t+wEppTepz7EjBhqzEo8+5h28viNRtw@mail.gmail.com>

... because I wans't absolutely sure it would be well received or seen
as "a litle too much".

From: Artur Malabarba <bruce.connor.am@gmail.com>
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--cancel-timer, tabulated-list--print-in-buffer):
New functions.
(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
printing.
---
 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
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -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-init-header)
-  (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.
       (when package-menu-async
-        (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)))))

 ;;;###autoload
 (defalias 'package-list-packages 'list-packages)
diff --git a/lisp/emacs-lisp/tabulated-list.el
b/lisp/emacs-lisp/tabulated-list.el
index b12edc8..f9b5a8f 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -273,19 +273,61 @@ It runs `tabulated-list-revert-hook', then calls
`tabulated-list-print'."
     (or found
     (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
+    (save-excursion
+      (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
+            (run-with-idle-timer
+             0.5 nil #'tabulated-list--print-in-buffer
+             entries buffer t)))
+    entries))
+
+(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
+window."
+  (tabulated-list--cancel-timer)
   (let ((inhibit-read-only t)
     (entries (if (functionp tabulated-list-entries)
              (funcall tabulated-list-entries)
            tabulated-list-entries))
-    entry-id saved-pt saved-col)
+    entry-id saved-col)
     (and remember-pos
      (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
current line."
           (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))
-         (recenter)))
-      (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))
+                       (recenter)))
+            (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))
+        (redisplay))
+      (tabulated-list--print-in-buffer entries (current-buffer) lazy))))

 (defun tabulated-list-print-entry (id cols)
   "Insert a Tabulated List entry at point.
-- 
2.3.6



  reply	other threads:[~2015-04-30 16:13 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-30 16:11 Lazy printing in tabulated-list-mode Artur Malabarba
2015-04-30 16:13 ` Artur Malabarba [this message]
2015-05-01 13:43 ` Stefan Monnier
2015-05-01 14:03   ` Artur Malabarba
2015-05-01 17:27     ` Stefan Monnier
2015-05-01 18:11       ` Artur Malabarba
2015-05-01 18:12         ` Artur Malabarba
2015-05-01 18:31           ` Artur Malabarba
2015-05-01 20:46         ` Stefan Monnier
2015-05-02  9:38           ` Artur Malabarba
2015-05-03 16:21             ` Stefan Monnier
2015-05-03 17:02               ` Artur Malabarba
2015-05-04  0:19                 ` Stefan Monnier
2015-05-04  8:21                   ` Artur Malabarba
2015-05-04 10:46                     ` Artur Malabarba
2015-05-04 12:38                     ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAAdUY-LUd3bbxHkf1MSN7ekfJ+QqqXL8V0-Rvh5z8u3v5MrzwQ@mail.gmail.com \
    --to=bruce.connor.am@gmail.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.