From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Artur Malabarba Newsgroups: gmane.emacs.devel Subject: Re: Lazy printing in tabulated-list-mode Date: Thu, 30 Apr 2015 17:13:18 +0100 Message-ID: References: Reply-To: bruce.connor.am@gmail.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Trace: ger.gmane.org 1430410431 12404 80.91.229.3 (30 Apr 2015 16:13:51 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 30 Apr 2015 16:13:51 +0000 (UTC) To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Apr 30 18:13:51 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Ynr5l-00011i-M8 for ged-emacs-devel@m.gmane.org; Thu, 30 Apr 2015 18:13:37 +0200 Original-Received: from localhost ([::1]:44880 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ynr5k-0001r0-TK for ged-emacs-devel@m.gmane.org; Thu, 30 Apr 2015 12:13:36 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:43145) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ynr5V-0001nC-2v for emacs-devel@gnu.org; Thu, 30 Apr 2015 12:13:22 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ynr5T-0000xr-OQ for emacs-devel@gnu.org; Thu, 30 Apr 2015 12:13:21 -0400 Original-Received: from mail-la0-x230.google.com ([2a00:1450:4010:c03::230]:36069) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ynr5T-0000xj-C1 for emacs-devel@gnu.org; Thu, 30 Apr 2015 12:13:19 -0400 Original-Received: by lagv1 with SMTP id v1so48072516lag.3 for ; Thu, 30 Apr 2015 09:13:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:reply-to:sender:in-reply-to:references:date:message-id :subject:from:to:content-type; bh=1Ju2f3iJTIsDKdhSx/ukujobSDmMzFT1psemiu9UA/I=; b=Z8TVjT9YVN9Gy2OeAu4+aixhCK9rucQW9dgu4iG1yi7ay34NchOtAhj+M3WmPoUWWQ 61mkC9Ry7Edh00TxZHjXiic8rGrwTBgJTmU7++t51w2yFP6TUBJedRy8uzqoZ7EW/Z5u rgq0KODOA8UPW/KPUytPw6/Y/yLUbmsuZOWQCzlaslh7m8OipGm150zM+m4a9gKAQD13 ihYT61i8S5B9wqzWWRRfaKEBXniL38FvWJlKKY5MH9J+WszsvjCcn0IJSWNi8l+SSx1L +34jg/oHtbPQp8D4mFF4YSSGcMSBI+LkmuobbfLbLiaPVa+o60aPMCT1ts0l8eKuktsB TgBg== X-Received: by 10.112.204.6 with SMTP id ku6mr4470635lbc.73.1430410398602; Thu, 30 Apr 2015 09:13:18 -0700 (PDT) Original-Received: by 10.25.150.1 with HTTP; Thu, 30 Apr 2015 09:13:18 -0700 (PDT) In-Reply-To: X-Google-Sender-Auth: Yj7a-0MlqqLy02rjkF-x1DYLlfw X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4010:c03::230 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:186067 Archived-At: ... because I wans't absolutely sure it would be well received or seen as "a litle too much". From: Artur Malabarba 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