From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: David Ponce Newsgroups: gmane.emacs.devel Subject: Re: recentf mode: point at first file / highlight (patch) Date: Sat, 25 Jun 2005 18:07:20 +0200 Message-ID: <42BD8138.8070804@wanadoo.fr> References: <43E9980B-D229-4D1A-BFF0-DA4F7E2FECE7@gmail.com> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: sea.gmane.org 1119716756 25255 80.91.229.2 (25 Jun 2005 16:25:56 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sat, 25 Jun 2005 16:25:56 +0000 (UTC) Cc: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Jun 25 18:25:50 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1DmDTD-0000AD-ON for ged-emacs-devel@m.gmane.org; Sat, 25 Jun 2005 18:25:28 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DmDaT-0004qn-PA for ged-emacs-devel@m.gmane.org; Sat, 25 Jun 2005 12:32:57 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DmDX9-0003Kk-OI for emacs-devel@gnu.org; Sat, 25 Jun 2005 12:29:32 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DmDWw-0003H1-TW for emacs-devel@gnu.org; Sat, 25 Jun 2005 12:29:21 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DmDWw-00036S-Ib for emacs-devel@gnu.org; Sat, 25 Jun 2005 12:29:18 -0400 Original-Received: from [193.252.22.24] (helo=smtp7.wanadoo.fr) by monty-python.gnu.org with esmtp (Exim 4.34) id 1DmDEA-0003RG-Mv for emacs-devel@gnu.org; Sat, 25 Jun 2005 12:09:55 -0400 Original-Received: from me-wanadoo.net (unknown [127.0.0.1]) by mwinf0709.wanadoo.fr (SMTP Server) with ESMTP id AE7CD1C000AF for ; Sat, 25 Jun 2005 18:05:58 +0200 (CEST) Original-Received: from [192.168.1.2] (AGrenoble-152-1-10-157.w82-122.abo.wanadoo.fr [82.122.8.157]) by mwinf0709.wanadoo.fr (SMTP Server) with ESMTP id 5D7901C0008D; Sat, 25 Jun 2005 18:05:57 +0200 (CEST) X-ME-UUID: 20050625160557382.5D7901C0008D@mwinf0709.wanadoo.fr User-Agent: Mozilla Thunderbird 1.0.2-1.3.3 (X11/20050513) X-Accept-Language: en-us, en Original-To: David Reitter In-Reply-To: <43E9980B-D229-4D1A-BFF0-DA4F7E2FECE7@gmail.com> X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:39503 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:39503 Hi David, > This patch makes recentf-open-files more comfortable: it positions the > point on the line showing the first file (instead of the first line, > which only contains explanations) and we turn on hl-line-mode. > Please consider applying. Thank you for your patch. It is a good idea to move the cursor to the first useful widget, however I think it is better to use `widget-move' to do that. Also I don't like much that hl-line-mode is automatically turned on in recentf dialog (I don't like the whole line highlighting). IMO, you can use the `recentf-dialog-mode-hook' to do that, if you like. Here is a more important patch to recentf I was working on, to improve dialogs L&F and ease of use. - In the open [more] files dialogs, `tree-widget' and `link' widgets are used to respectively represent sub-menus and single files. This gives the dialog a nicer and more convenient L&F (it is now possible to expand/collapse sub-menus). - The cursor is positioned to the first useful widget in dialogs. - The dialog code is cleaner and simpler. WDYT? If no objections I can commit it. Sincerely, David 2005-06-25 David Ponce * recentf.el: Require 'tree-widget instead of 'wid-edit. (recentf-cancel-dialog, recentf-open-more-files) (recentf-open-files-action): Doc fix. (recentf-dialog-goto-first): New function. (recentf-dialog-mode-map): Set parent keymap first. (recentf-dialog-mode): Define with define-derived-mode. Don't display continuation lines in dialogs. (recentf-edit-list): Rename from recentf-edit-selected-items. (recentf-edit-list-select): Rename from recentf-edit-list-action. Simplify. (recentf-edit-list-validate): New function. (recentf-edit-list): Update accordingly. (recentf-open-files-item-shift): Remove. (recentf-open-files-item): Convert menu elements into tree and link widgets. Don't create the widgets. (recentf-open-files): Update accordingly. (recentf-save-list): Untabify. Index: recentf.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/recentf.el,v retrieving revision 1.38 diff -c -r1.38 recentf.el *** recentf.el 14 Jun 2005 12:02:42 -0000 1.38 --- recentf.el 25 Jun 2005 15:54:05 -0000 *************** *** 28,45 **** ;;; Commentary: ;; This package maintains a menu for visiting files that were operated ! ;; on recently. When enabled a new "Open Recent" submenu is displayed ! ;; in the "Files" menu. The recent files list is automatically saved ! ;; across Emacs sessions. You can customize the number of recent ! ;; files displayed, the location of the menu and others options (see ! ;; the source code for details). ;;; History: ;; ;;; Code: (require 'easymenu) ! (require 'wid-edit) (require 'timer) ;;; Internal data --- 28,45 ---- ;;; Commentary: ;; This package maintains a menu for visiting files that were operated ! ;; on recently. When enabled a new "Open Recent" sub menu is ! ;; displayed in the "Files" menu. The recent files list is ! ;; automatically saved across Emacs sessions. You can customize the ! ;; number of recent files displayed, the location of the menu and ! ;; others options (see the source code for details). ;;; History: ;; ;;; Code: (require 'easymenu) ! (require 'tree-widget) (require 'timer) ;;; Internal data *************** *** 904,933 **** ;; (defun recentf-cancel-dialog (&rest ignore) "Cancel the current dialog. - Used internally by recentf dialogs. IGNORE arguments." (interactive) (kill-buffer (current-buffer)) (message "Dialog canceled")) (defvar recentf-dialog-mode-map (let ((km (make-sparse-keymap))) (define-key km "q" 'recentf-cancel-dialog) (define-key km [down-mouse-1] 'widget-button-click) - (set-keymap-parent km widget-keymap) km) "Keymap used in recentf dialogs.") ! (defun recentf-dialog-mode () "Major mode of recentf dialogs. \\{recentf-dialog-mode-map}" ! (interactive) ! (kill-all-local-variables) ! (setq major-mode 'recentf-dialog-mode) ! (setq mode-name "recentf-dialog") ! (use-local-map recentf-dialog-mode-map) ! (run-mode-hooks 'recentf-dialog-mode-hook)) ;;; Hooks ;; --- 904,957 ---- ;; (defun recentf-cancel-dialog (&rest ignore) "Cancel the current dialog. IGNORE arguments." (interactive) (kill-buffer (current-buffer)) (message "Dialog canceled")) + (defun recentf-dialog-goto-first (widget-type) + "Move the cursor to the first WIDGET-TYPE in current dialog. + Go to the beginning of buffer if not found." + (goto-char (point-min)) + (condition-case nil + (let (done) + (widget-move 1) + (while (not done) + (if (eq widget-type (widget-type (widget-at (point)))) + (setq done t) + (widget-move 1)))) + (goto-char (point-min)))) + (defvar recentf-dialog-mode-map (let ((km (make-sparse-keymap))) + (set-keymap-parent km widget-keymap) (define-key km "q" 'recentf-cancel-dialog) (define-key km [down-mouse-1] 'widget-button-click) km) "Keymap used in recentf dialogs.") ! (define-derived-mode recentf-dialog-mode nil "recentf-dialog" "Major mode of recentf dialogs. \\{recentf-dialog-mode-map}" ! :syntax-table nil ! :abbrev-table nil ! (setq truncate-lines t)) ! ! (defmacro recentf-dialog (name &rest forms) ! "Show a dialog buffer with NAME, setup with FORMS." ! (declare (indent 1) (debug t)) ! `(with-current-buffer (get-buffer-create ,name) ! ;; Cleanup buffer ! (let ((inhibit-read-only t) ! (ol (overlay-lists))) ! (mapc 'delete-overlay (car ol)) ! (mapc 'delete-overlay (cdr ol)) ! (erase-buffer)) ! (recentf-dialog-mode) ! ,@forms ! (widget-setup) ! (switch-to-buffer (current-buffer)))) ;;; Hooks ;; *************** *** 976,1138 **** ;;; Commands ;; ! (defvar recentf-edit-selected-items nil ! "List of files to be deleted from the recent list. ! Used internally by `recentf-edit-list'.") ! ! (defun recentf-edit-list-action (widget &rest ignore) ! "Checkbox WIDGET action that toogles a file selection. ! Used internally by `recentf-edit-list'. IGNORE other arguments." ! (let ((value (widget-get widget ':tag))) ! ;; if value is already in the selected items ! (if (memq value recentf-edit-selected-items) ! ;; then remove it ! (progn ! (setq recentf-edit-selected-items ! (delq value recentf-edit-selected-items)) ! (message "%s removed from selection" value)) ! ;; else add it ! (push value recentf-edit-selected-items) ! (message "%s added to selection" value)))) (defun recentf-edit-list () ! "Show a dialog buffer to edit the recent list. ! That is to select files to be deleted from the recent list." (interactive) ! (with-current-buffer ! (get-buffer-create (format "*%s - Edit list*" recentf-menu-title)) ! (switch-to-buffer (current-buffer)) ! ;; Cleanup buffer ! (let ((inhibit-read-only t) ! (ol (overlay-lists))) ! (erase-buffer) ! ;; Delete all the overlays. ! (mapc 'delete-overlay (car ol)) ! (mapc 'delete-overlay (cdr ol))) ! (recentf-dialog-mode) ! (setq recentf-edit-selected-items nil) ! ;; Insert the dialog header (widget-insert ! "\ ! Select the files to be deleted from the recent list.\n\n\ ! Click on Ok to update the list. \ ! Click on Cancel or type \"q\" to quit.\n") ;; Insert the list of files as checkboxes (dolist (item recentf-list) ! (widget-create ! 'checkbox ! :value nil ; unselected checkbox ! :format "\n %[%v%] %t" ! :tag item ! :notify 'recentf-edit-list-action)) (widget-insert "\n\n") - ;; Insert the Ok button (widget-create 'push-button ! :notify (lambda (&rest ignore) ! (if recentf-edit-selected-items ! (let ((i 0)) ! (kill-buffer (current-buffer)) ! (dolist (e recentf-edit-selected-items) ! (setq recentf-list (delq e recentf-list) ! i (1+ i))) ! (message "%S file(s) removed from the list" i) ! (recentf-clear-data)) ! (message "No file selected"))) ! "Ok") (widget-insert " ") - ;; Insert the Cancel button (widget-create 'push-button :notify 'recentf-cancel-dialog "Cancel") ! (widget-setup) ! (goto-char (point-min)))) (defun recentf-open-files-action (widget &rest ignore) ! "Button WIDGET action that open a file. ! Used internally by `recentf-open-files'. IGNORE other arguments." (kill-buffer (current-buffer)) (funcall recentf-menu-action (widget-value widget))) - (defvar recentf-open-files-item-shift "" - "Amount of space to shift right sub-menu items. - Used internally by `recentf-open-files'.") - (defun recentf-open-files-item (menu-element) ! "Insert an item widget for MENU-ELEMENT in the current dialog buffer. ! Used internally by `recentf-open-files'." ! (let ((item (car menu-element)) ! (file (cdr menu-element))) ! (if (consp file) ; This is a sub-menu ! (let* ((shift recentf-open-files-item-shift) ! (recentf-open-files-item-shift (concat shift " "))) ! (widget-create ! 'item ! :tag item ! :sample-face 'bold ! :format (concat shift "%{%t%}:\n")) ! (mapc 'recentf-open-files-item file) ! (widget-insert "\n")) ! (widget-create ! 'push-button ! :button-face 'default ! :tag item ! :help-echo (concat "Open " file) ! :format (concat recentf-open-files-item-shift "%[%t%]") ! :notify 'recentf-open-files-action ! file) ! (widget-insert "\n")))) (defun recentf-open-files (&optional files buffer-name) ! "Show a dialog buffer to open a recent file. ! If optional argument FILES is non-nil, it specifies the list of ! recently-opened files to choose from. It is the whole recent list ! otherwise. ! If optional argument BUFFER-NAME is non-nil, it specifies which buffer ! name to use for the interaction. It is \"*`recentf-menu-title'*\" by ! default." (interactive) ! (unless files ! (setq files recentf-list)) ! (unless buffer-name ! (setq buffer-name (format "*%s*" recentf-menu-title))) ! (with-current-buffer (get-buffer-create buffer-name) ! (switch-to-buffer (current-buffer)) ! ;; Cleanup buffer ! (let ((inhibit-read-only t) ! (ol (overlay-lists))) ! (erase-buffer) ! ;; Delete all the overlays. ! (mapc 'delete-overlay (car ol)) ! (mapc 'delete-overlay (cdr ol))) ! (recentf-dialog-mode) ! ;; Insert the dialog header ! (widget-insert "Click on a file to open it. ") ! (widget-insert "Click on Cancel or type \"q\" to quit.\n\n" ) ! ;; Insert the list of files as buttons ! (let ((recentf-open-files-item-shift "")) ! (mapc 'recentf-open-files-item ! (recentf-apply-menu-filter ! recentf-menu-filter ! (mapcar 'recentf-make-default-menu-element files)))) ! (widget-insert "\n") ! ;; Insert the Cancel button (widget-create 'push-button :notify 'recentf-cancel-dialog "Cancel") ! (widget-setup) ! (goto-char (point-min)))) (defun recentf-open-more-files () ! "Show a dialog buffer to open a recent file that is not in the menu." (interactive) (recentf-open-files (nthcdr recentf-max-menu-items recentf-list) (format "*%s - More*" recentf-menu-title))) (defconst recentf-save-file-header ";;; Automatically generated by `recentf' on %s.\n" "Header to be written into the `recentf-save-file'.") --- 1000,1126 ---- ;;; Commands ;; ! ! ;;; Edit list dialog ! ;; ! (defvar recentf-edit-list nil) ! ! (defun recentf-edit-list-select (widget &rest ignore) ! "Toggle a file selection based on the checkbox WIDGET state. IGNORE other arguments." ! (let ((value (widget-get widget :tag)) ! (check (widget-value widget))) ! (if check ! (add-to-list 'recentf-edit-list value) ! (setq recentf-edit-list (delq value recentf-edit-list))) ! (message "%s %sselected" value (if check "" "un")))) ! ! (defun recentf-edit-list-validate (&rest ignore) ! "Process the recent list when the edit list dialog is committed. ! IGNORE arguments." ! (if recentf-edit-list ! (let ((i 0)) ! (dolist (e recentf-edit-list) ! (setq recentf-list (delq e recentf-list) ! i (1+ i))) ! (kill-buffer (current-buffer)) ! (message "%S file(s) removed from the list" i) ! (recentf-clear-data)) ! (message "No file selected"))) (defun recentf-edit-list () ! "Show a dialog to delete selected files from the recent list." (interactive) ! (recentf-dialog (format "*%s - Edit list*" recentf-menu-title) ! (set (make-local-variable 'recentf-edit-list) nil) (widget-insert ! "Click on OK to delete selected files from the recent list. ! Click on Cancel or type `q' to cancel.\n") ;; Insert the list of files as checkboxes (dolist (item recentf-list) ! (widget-create 'checkbox ! :value nil ; unselected checkbox ! :format "\n %[%v%] %t" ! :tag item ! :notify 'recentf-edit-list-select)) (widget-insert "\n\n") (widget-create 'push-button ! :notify 'recentf-edit-list-validate ! :help-echo "Delete selected files from the recent list" ! "Ok") (widget-insert " ") (widget-create 'push-button :notify 'recentf-cancel-dialog "Cancel") ! (recentf-dialog-goto-first 'checkbox))) + ;;; Open file dialog + ;; (defun recentf-open-files-action (widget &rest ignore) ! "Open the file stored in WIDGET's value when notified. IGNORE other arguments." (kill-buffer (current-buffer)) (funcall recentf-menu-action (widget-value widget))) (defun recentf-open-files-item (menu-element) ! "Return a widget to display MENU-ELEMENT in a dialog buffer." ! (if (consp (cdr menu-element)) ! ;; Represent a sub-menu with a tree widget ! `(tree-widget ! :open t ! :match ignore ! :node (item :tag ,(car menu-element) ! :sample-face bold ! :format "%{%t%}:\n") ! ,@(mapcar 'recentf-open-files-item ! (cdr menu-element))) ! ;; Represent a single file with a link widget ! `(link :tag ,(car menu-element) ! :button-prefix "" ! :button-suffix "" ! :button-face default ! :format "%[%t%]\n" ! :help-echo ,(concat "Open " (cdr menu-element)) ! :action recentf-open-files-action ! ,(cdr menu-element)))) (defun recentf-open-files (&optional files buffer-name) ! "Show a dialog to open a recent file. ! If optional argument FILES is non-nil, it is a list of recently-opened ! files to choose from. It defaults to the whole recent list. ! If optional argument BUFFER-NAME is non-nil, it is a buffer name to ! use for the dialog. It defaults to \"*`recentf-menu-title'*\"." (interactive) ! (recentf-dialog (or buffer-name (format "*%s*" recentf-menu-title)) ! (widget-insert "Click on a file to open it. ! Click on Cancel or type `q' to cancel.\n" ) ! ;; Use a L&F that looks like the recentf menu. ! (tree-widget-set-theme "folder") ! (apply 'widget-create ! `(group ! :indent 2 ! :format "\n%v\n" ! ,@(mapcar 'recentf-open-files-item ! (recentf-apply-menu-filter ! recentf-menu-filter ! (mapcar 'recentf-make-default-menu-element ! (or files recentf-list)))))) (widget-create 'push-button :notify 'recentf-cancel-dialog "Cancel") ! (recentf-dialog-goto-first 'link))) (defun recentf-open-more-files () ! "Show a dialog to open a recent file that is not in the menu." (interactive) (recentf-open-files (nthcdr recentf-max-menu-items recentf-list) (format "*%s - More*" recentf-menu-title))) + ;;; Save/load/cleanup the recent list + ;; (defconst recentf-save-file-header ";;; Automatically generated by `recentf' on %s.\n" "Header to be written into the `recentf-save-file'.") *************** *** 1149,1164 **** (interactive) (condition-case error (with-temp-buffer ! (erase-buffer) ! (set-buffer-file-coding-system recentf-save-file-coding-system) ! (insert (format recentf-save-file-header (current-time-string))) ! (recentf-dump-variable 'recentf-list recentf-max-saved-items) ! (recentf-dump-variable 'recentf-filter-changer-state) ! (insert "\n \n;;; Local Variables:\n" ! (format ";;; coding: %s\n" recentf-save-file-coding-system) ! ";;; End:\n") ! (write-file (expand-file-name recentf-save-file)) ! nil) (error (warn "recentf mode: %s" (error-message-string error))))) --- 1137,1152 ---- (interactive) (condition-case error (with-temp-buffer ! (erase-buffer) ! (set-buffer-file-coding-system recentf-save-file-coding-system) ! (insert (format recentf-save-file-header (current-time-string))) ! (recentf-dump-variable 'recentf-list recentf-max-saved-items) ! (recentf-dump-variable 'recentf-filter-changer-state) ! (insert "\n \n;;; Local Variables:\n" ! (format ";;; coding: %s\n" recentf-save-file-coding-system) ! ";;; End:\n") ! (write-file (expand-file-name recentf-save-file)) ! nil) (error (warn "recentf mode: %s" (error-message-string error)))))