diff options
| author | David Ponce | 2005-06-26 07:42:38 +0000 |
|---|---|---|
| committer | David Ponce | 2005-06-26 07:42:38 +0000 |
| commit | 7b2ab96952f2fd9c1ffde2e40f59dad62c8047f6 (patch) | |
| tree | 43f8342ee13d34be835f178d427f75cd73f54e95 | |
| parent | ec9ac2bebb1f4dcbeb61d4a51403bf658a0f9a3c (diff) | |
| download | emacs-7b2ab96952f2fd9c1ffde2e40f59dad62c8047f6.tar.gz emacs-7b2ab96952f2fd9c1ffde2e40f59dad62c8047f6.zip | |
Require 'tree-widget instead of 'wid-edit.
(recentf-filename-handler): Fix widget :type.
(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.
| -rw-r--r-- | lisp/recentf.el | 285 |
1 files changed, 137 insertions, 148 deletions
diff --git a/lisp/recentf.el b/lisp/recentf.el index 1ea3ae6ecb2..64af3b1da3f 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el | |||
| @@ -28,18 +28,18 @@ | |||
| 28 | ;;; Commentary: | 28 | ;;; Commentary: |
| 29 | 29 | ||
| 30 | ;; This package maintains a menu for visiting files that were operated | 30 | ;; This package maintains a menu for visiting files that were operated |
| 31 | ;; on recently. When enabled a new "Open Recent" submenu is displayed | 31 | ;; on recently. When enabled a new "Open Recent" sub menu is |
| 32 | ;; in the "Files" menu. The recent files list is automatically saved | 32 | ;; displayed in the "Files" menu. The recent files list is |
| 33 | ;; across Emacs sessions. You can customize the number of recent | 33 | ;; automatically saved across Emacs sessions. You can customize the |
| 34 | ;; files displayed, the location of the menu and others options (see | 34 | ;; number of recent files displayed, the location of the menu and |
| 35 | ;; the source code for details). | 35 | ;; others options (see the source code for details). |
| 36 | 36 | ||
| 37 | ;;; History: | 37 | ;;; History: |
| 38 | ;; | 38 | ;; |
| 39 | 39 | ||
| 40 | ;;; Code: | 40 | ;;; Code: |
| 41 | (require 'easymenu) | 41 | (require 'easymenu) |
| 42 | (require 'wid-edit) | 42 | (require 'tree-widget) |
| 43 | (require 'timer) | 43 | (require 'timer) |
| 44 | 44 | ||
| 45 | ;;; Internal data | 45 | ;;; Internal data |
| @@ -259,7 +259,8 @@ If `file-name-history' is not empty, do nothing." | |||
| 259 | It is passed a filename to give a chance to transform it. | 259 | It is passed a filename to give a chance to transform it. |
| 260 | If it returns nil, the filename is left unchanged." | 260 | If it returns nil, the filename is left unchanged." |
| 261 | :group 'recentf | 261 | :group 'recentf |
| 262 | :type 'function) | 262 | :type '(choice (const :tag "None" nil) |
| 263 | function)) | ||
| 263 | 264 | ||
| 264 | ;;; Utilities | 265 | ;;; Utilities |
| 265 | ;; | 266 | ;; |
| @@ -904,30 +905,54 @@ unchanged." | |||
| 904 | ;; | 905 | ;; |
| 905 | (defun recentf-cancel-dialog (&rest ignore) | 906 | (defun recentf-cancel-dialog (&rest ignore) |
| 906 | "Cancel the current dialog. | 907 | "Cancel the current dialog. |
| 907 | Used internally by recentf dialogs. | ||
| 908 | IGNORE arguments." | 908 | IGNORE arguments." |
| 909 | (interactive) | 909 | (interactive) |
| 910 | (kill-buffer (current-buffer)) | 910 | (kill-buffer (current-buffer)) |
| 911 | (message "Dialog canceled")) | 911 | (message "Dialog canceled")) |
| 912 | 912 | ||
| 913 | (defun recentf-dialog-goto-first (widget-type) | ||
| 914 | "Move the cursor to the first WIDGET-TYPE in current dialog. | ||
| 915 | Go to the beginning of buffer if not found." | ||
| 916 | (goto-char (point-min)) | ||
| 917 | (condition-case nil | ||
| 918 | (let (done) | ||
| 919 | (widget-move 1) | ||
| 920 | (while (not done) | ||
| 921 | (if (eq widget-type (widget-type (widget-at (point)))) | ||
| 922 | (setq done t) | ||
| 923 | (widget-move 1)))) | ||
| 924 | (goto-char (point-min)))) | ||
| 925 | |||
| 913 | (defvar recentf-dialog-mode-map | 926 | (defvar recentf-dialog-mode-map |
| 914 | (let ((km (make-sparse-keymap))) | 927 | (let ((km (make-sparse-keymap))) |
| 928 | (set-keymap-parent km widget-keymap) | ||
| 915 | (define-key km "q" 'recentf-cancel-dialog) | 929 | (define-key km "q" 'recentf-cancel-dialog) |
| 916 | (define-key km [down-mouse-1] 'widget-button-click) | 930 | (define-key km [down-mouse-1] 'widget-button-click) |
| 917 | (set-keymap-parent km widget-keymap) | ||
| 918 | km) | 931 | km) |
| 919 | "Keymap used in recentf dialogs.") | 932 | "Keymap used in recentf dialogs.") |
| 920 | 933 | ||
| 921 | (defun recentf-dialog-mode () | 934 | (define-derived-mode recentf-dialog-mode nil "recentf-dialog" |
| 922 | "Major mode of recentf dialogs. | 935 | "Major mode of recentf dialogs. |
| 923 | 936 | ||
| 924 | \\{recentf-dialog-mode-map}" | 937 | \\{recentf-dialog-mode-map}" |
| 925 | (interactive) | 938 | :syntax-table nil |
| 926 | (kill-all-local-variables) | 939 | :abbrev-table nil |
| 927 | (setq major-mode 'recentf-dialog-mode) | 940 | (setq truncate-lines t)) |
| 928 | (setq mode-name "recentf-dialog") | 941 | |
| 929 | (use-local-map recentf-dialog-mode-map) | 942 | (defmacro recentf-dialog (name &rest forms) |
| 930 | (run-mode-hooks 'recentf-dialog-mode-hook)) | 943 | "Show a dialog buffer with NAME, setup with FORMS." |
| 944 | (declare (indent 1) (debug t)) | ||
| 945 | `(with-current-buffer (get-buffer-create ,name) | ||
| 946 | ;; Cleanup buffer | ||
| 947 | (let ((inhibit-read-only t) | ||
| 948 | (ol (overlay-lists))) | ||
| 949 | (mapc 'delete-overlay (car ol)) | ||
| 950 | (mapc 'delete-overlay (cdr ol)) | ||
| 951 | (erase-buffer)) | ||
| 952 | (recentf-dialog-mode) | ||
| 953 | ,@forms | ||
| 954 | (widget-setup) | ||
| 955 | (switch-to-buffer (current-buffer)))) | ||
| 931 | 956 | ||
| 932 | ;;; Hooks | 957 | ;;; Hooks |
| 933 | ;; | 958 | ;; |
| @@ -976,163 +1001,127 @@ That is, remove a non kept file from the recent list." | |||
| 976 | 1001 | ||
| 977 | ;;; Commands | 1002 | ;;; Commands |
| 978 | ;; | 1003 | ;; |
| 979 | (defvar recentf-edit-selected-items nil | ||
| 980 | "List of files to be deleted from the recent list. | ||
| 981 | Used internally by `recentf-edit-list'.") | ||
| 982 | 1004 | ||
| 983 | (defun recentf-edit-list-action (widget &rest ignore) | 1005 | ;;; Edit list dialog |
| 984 | "Checkbox WIDGET action that toogles a file selection. | 1006 | ;; |
| 985 | Used internally by `recentf-edit-list'. | 1007 | (defvar recentf-edit-list nil) |
| 1008 | |||
| 1009 | (defun recentf-edit-list-select (widget &rest ignore) | ||
| 1010 | "Toggle a file selection based on the checkbox WIDGET state. | ||
| 986 | IGNORE other arguments." | 1011 | IGNORE other arguments." |
| 987 | (let ((value (widget-get widget ':tag))) | 1012 | (let ((value (widget-get widget :tag)) |
| 988 | ;; if value is already in the selected items | 1013 | (check (widget-value widget))) |
| 989 | (if (memq value recentf-edit-selected-items) | 1014 | (if check |
| 990 | ;; then remove it | 1015 | (add-to-list 'recentf-edit-list value) |
| 991 | (progn | 1016 | (setq recentf-edit-list (delq value recentf-edit-list))) |
| 992 | (setq recentf-edit-selected-items | 1017 | (message "%s %sselected" value (if check "" "un")))) |
| 993 | (delq value recentf-edit-selected-items)) | 1018 | |
| 994 | (message "%s removed from selection" value)) | 1019 | (defun recentf-edit-list-validate (&rest ignore) |
| 995 | ;; else add it | 1020 | "Process the recent list when the edit list dialog is committed. |
| 996 | (push value recentf-edit-selected-items) | 1021 | IGNORE arguments." |
| 997 | (message "%s added to selection" value)))) | 1022 | (if recentf-edit-list |
| 1023 | (let ((i 0)) | ||
| 1024 | (dolist (e recentf-edit-list) | ||
| 1025 | (setq recentf-list (delq e recentf-list) | ||
| 1026 | i (1+ i))) | ||
| 1027 | (kill-buffer (current-buffer)) | ||
| 1028 | (message "%S file(s) removed from the list" i) | ||
| 1029 | (recentf-clear-data)) | ||
| 1030 | (message "No file selected"))) | ||
| 998 | 1031 | ||
| 999 | (defun recentf-edit-list () | 1032 | (defun recentf-edit-list () |
| 1000 | "Show a dialog buffer to edit the recent list. | 1033 | "Show a dialog to delete selected files from the recent list." |
| 1001 | That is to select files to be deleted from the recent list." | ||
| 1002 | (interactive) | 1034 | (interactive) |
| 1003 | (with-current-buffer | 1035 | (recentf-dialog (format "*%s - Edit list*" recentf-menu-title) |
| 1004 | (get-buffer-create (format "*%s - Edit list*" recentf-menu-title)) | 1036 | (set (make-local-variable 'recentf-edit-list) nil) |
| 1005 | (switch-to-buffer (current-buffer)) | ||
| 1006 | ;; Cleanup buffer | ||
| 1007 | (let ((inhibit-read-only t) | ||
| 1008 | (ol (overlay-lists))) | ||
| 1009 | (erase-buffer) | ||
| 1010 | ;; Delete all the overlays. | ||
| 1011 | (mapc 'delete-overlay (car ol)) | ||
| 1012 | (mapc 'delete-overlay (cdr ol))) | ||
| 1013 | (recentf-dialog-mode) | ||
| 1014 | (setq recentf-edit-selected-items nil) | ||
| 1015 | ;; Insert the dialog header | ||
| 1016 | (widget-insert | 1037 | (widget-insert |
| 1017 | "\ | 1038 | "Click on OK to delete selected files from the recent list. |
| 1018 | Select the files to be deleted from the recent list.\n\n\ | 1039 | Click on Cancel or type `q' to cancel.\n") |
| 1019 | Click on Ok to update the list. \ | ||
| 1020 | Click on Cancel or type \"q\" to quit.\n") | ||
| 1021 | ;; Insert the list of files as checkboxes | 1040 | ;; Insert the list of files as checkboxes |
| 1022 | (dolist (item recentf-list) | 1041 | (dolist (item recentf-list) |
| 1023 | (widget-create | 1042 | (widget-create 'checkbox |
| 1024 | 'checkbox | 1043 | :value nil ; unselected checkbox |
| 1025 | :value nil ; unselected checkbox | 1044 | :format "\n %[%v%] %t" |
| 1026 | :format "\n %[%v%] %t" | 1045 | :tag item |
| 1027 | :tag item | 1046 | :notify 'recentf-edit-list-select)) |
| 1028 | :notify 'recentf-edit-list-action)) | ||
| 1029 | (widget-insert "\n\n") | 1047 | (widget-insert "\n\n") |
| 1030 | ;; Insert the Ok button | ||
| 1031 | (widget-create | 1048 | (widget-create |
| 1032 | 'push-button | 1049 | 'push-button |
| 1033 | :notify (lambda (&rest ignore) | 1050 | :notify 'recentf-edit-list-validate |
| 1034 | (if recentf-edit-selected-items | 1051 | :help-echo "Delete selected files from the recent list" |
| 1035 | (let ((i 0)) | 1052 | "Ok") |
| 1036 | (kill-buffer (current-buffer)) | ||
| 1037 | (dolist (e recentf-edit-selected-items) | ||
| 1038 | (setq recentf-list (delq e recentf-list) | ||
| 1039 | i (1+ i))) | ||
| 1040 | (message "%S file(s) removed from the list" i) | ||
| 1041 | (recentf-clear-data)) | ||
| 1042 | (message "No file selected"))) | ||
| 1043 | "Ok") | ||
| 1044 | (widget-insert " ") | 1053 | (widget-insert " ") |
| 1045 | ;; Insert the Cancel button | ||
| 1046 | (widget-create | 1054 | (widget-create |
| 1047 | 'push-button | 1055 | 'push-button |
| 1048 | :notify 'recentf-cancel-dialog | 1056 | :notify 'recentf-cancel-dialog |
| 1049 | "Cancel") | 1057 | "Cancel") |
| 1050 | (widget-setup) | 1058 | (recentf-dialog-goto-first 'checkbox))) |
| 1051 | (goto-char (point-min)))) | ||
| 1052 | 1059 | ||
| 1060 | ;;; Open file dialog | ||
| 1061 | ;; | ||
| 1053 | (defun recentf-open-files-action (widget &rest ignore) | 1062 | (defun recentf-open-files-action (widget &rest ignore) |
| 1054 | "Button WIDGET action that open a file. | 1063 | "Open the file stored in WIDGET's value when notified. |
| 1055 | Used internally by `recentf-open-files'. | ||
| 1056 | IGNORE other arguments." | 1064 | IGNORE other arguments." |
| 1057 | (kill-buffer (current-buffer)) | 1065 | (kill-buffer (current-buffer)) |
| 1058 | (funcall recentf-menu-action (widget-value widget))) | 1066 | (funcall recentf-menu-action (widget-value widget))) |
| 1059 | 1067 | ||
| 1060 | (defvar recentf-open-files-item-shift "" | ||
| 1061 | "Amount of space to shift right sub-menu items. | ||
| 1062 | Used internally by `recentf-open-files'.") | ||
| 1063 | |||
| 1064 | (defun recentf-open-files-item (menu-element) | 1068 | (defun recentf-open-files-item (menu-element) |
| 1065 | "Insert an item widget for MENU-ELEMENT in the current dialog buffer. | 1069 | "Return a widget to display MENU-ELEMENT in a dialog buffer." |
| 1066 | Used internally by `recentf-open-files'." | 1070 | (if (consp (cdr menu-element)) |
| 1067 | (let ((item (car menu-element)) | 1071 | ;; Represent a sub-menu with a tree widget |
| 1068 | (file (cdr menu-element))) | 1072 | `(tree-widget |
| 1069 | (if (consp file) ; This is a sub-menu | 1073 | :open t |
| 1070 | (let* ((shift recentf-open-files-item-shift) | 1074 | :match ignore |
| 1071 | (recentf-open-files-item-shift (concat shift " "))) | 1075 | :node (item :tag ,(car menu-element) |
| 1072 | (widget-create | 1076 | :sample-face bold |
| 1073 | 'item | 1077 | :format "%{%t%}:\n") |
| 1074 | :tag item | 1078 | ,@(mapcar 'recentf-open-files-item |
| 1075 | :sample-face 'bold | 1079 | (cdr menu-element))) |
| 1076 | :format (concat shift "%{%t%}:\n")) | 1080 | ;; Represent a single file with a link widget |
| 1077 | (mapc 'recentf-open-files-item file) | 1081 | `(link :tag ,(car menu-element) |
| 1078 | (widget-insert "\n")) | 1082 | :button-prefix "" |
| 1079 | (widget-create | 1083 | :button-suffix "" |
| 1080 | 'push-button | 1084 | :button-face default |
| 1081 | :button-face 'default | 1085 | :format "%[%t%]\n" |
| 1082 | :tag item | 1086 | :help-echo ,(concat "Open " (cdr menu-element)) |
| 1083 | :help-echo (concat "Open " file) | 1087 | :action recentf-open-files-action |
| 1084 | :format (concat recentf-open-files-item-shift "%[%t%]") | 1088 | ,(cdr menu-element)))) |
| 1085 | :notify 'recentf-open-files-action | ||
| 1086 | file) | ||
| 1087 | (widget-insert "\n")))) | ||
| 1088 | 1089 | ||
| 1089 | (defun recentf-open-files (&optional files buffer-name) | 1090 | (defun recentf-open-files (&optional files buffer-name) |
| 1090 | "Show a dialog buffer to open a recent file. | 1091 | "Show a dialog to open a recent file. |
| 1091 | If optional argument FILES is non-nil, it specifies the list of | 1092 | If optional argument FILES is non-nil, it is a list of recently-opened |
| 1092 | recently-opened files to choose from. It is the whole recent list | 1093 | files to choose from. It defaults to the whole recent list. |
| 1093 | otherwise. | 1094 | If optional argument BUFFER-NAME is non-nil, it is a buffer name to |
| 1094 | If optional argument BUFFER-NAME is non-nil, it specifies which buffer | 1095 | use for the dialog. It defaults to \"*`recentf-menu-title'*\"." |
| 1095 | name to use for the interaction. It is \"*`recentf-menu-title'*\" by | ||
| 1096 | default." | ||
| 1097 | (interactive) | 1096 | (interactive) |
| 1098 | (unless files | 1097 | (recentf-dialog (or buffer-name (format "*%s*" recentf-menu-title)) |
| 1099 | (setq files recentf-list)) | 1098 | (widget-insert "Click on a file to open it. |
| 1100 | (unless buffer-name | 1099 | Click on Cancel or type `q' to cancel.\n" ) |
| 1101 | (setq buffer-name (format "*%s*" recentf-menu-title))) | 1100 | ;; Use a L&F that looks like the recentf menu. |
| 1102 | (with-current-buffer (get-buffer-create buffer-name) | 1101 | (tree-widget-set-theme "folder") |
| 1103 | (switch-to-buffer (current-buffer)) | 1102 | (apply 'widget-create |
| 1104 | ;; Cleanup buffer | 1103 | `(group |
| 1105 | (let ((inhibit-read-only t) | 1104 | :indent 2 |
| 1106 | (ol (overlay-lists))) | 1105 | :format "\n%v\n" |
| 1107 | (erase-buffer) | 1106 | ,@(mapcar 'recentf-open-files-item |
| 1108 | ;; Delete all the overlays. | 1107 | (recentf-apply-menu-filter |
| 1109 | (mapc 'delete-overlay (car ol)) | 1108 | recentf-menu-filter |
| 1110 | (mapc 'delete-overlay (cdr ol))) | 1109 | (mapcar 'recentf-make-default-menu-element |
| 1111 | (recentf-dialog-mode) | 1110 | (or files recentf-list)))))) |
| 1112 | ;; Insert the dialog header | ||
| 1113 | (widget-insert "Click on a file to open it. ") | ||
| 1114 | (widget-insert "Click on Cancel or type \"q\" to quit.\n\n" ) | ||
| 1115 | ;; Insert the list of files as buttons | ||
| 1116 | (let ((recentf-open-files-item-shift "")) | ||
| 1117 | (mapc 'recentf-open-files-item | ||
| 1118 | (recentf-apply-menu-filter | ||
| 1119 | recentf-menu-filter | ||
| 1120 | (mapcar 'recentf-make-default-menu-element files)))) | ||
| 1121 | (widget-insert "\n") | ||
| 1122 | ;; Insert the Cancel button | ||
| 1123 | (widget-create | 1111 | (widget-create |
| 1124 | 'push-button | 1112 | 'push-button |
| 1125 | :notify 'recentf-cancel-dialog | 1113 | :notify 'recentf-cancel-dialog |
| 1126 | "Cancel") | 1114 | "Cancel") |
| 1127 | (widget-setup) | 1115 | (recentf-dialog-goto-first 'link))) |
| 1128 | (goto-char (point-min)))) | ||
| 1129 | 1116 | ||
| 1130 | (defun recentf-open-more-files () | 1117 | (defun recentf-open-more-files () |
| 1131 | "Show a dialog buffer to open a recent file that is not in the menu." | 1118 | "Show a dialog to open a recent file that is not in the menu." |
| 1132 | (interactive) | 1119 | (interactive) |
| 1133 | (recentf-open-files (nthcdr recentf-max-menu-items recentf-list) | 1120 | (recentf-open-files (nthcdr recentf-max-menu-items recentf-list) |
| 1134 | (format "*%s - More*" recentf-menu-title))) | 1121 | (format "*%s - More*" recentf-menu-title))) |
| 1135 | 1122 | ||
| 1123 | ;;; Save/load/cleanup the recent list | ||
| 1124 | ;; | ||
| 1136 | (defconst recentf-save-file-header | 1125 | (defconst recentf-save-file-header |
| 1137 | ";;; Automatically generated by `recentf' on %s.\n" | 1126 | ";;; Automatically generated by `recentf' on %s.\n" |
| 1138 | "Header to be written into the `recentf-save-file'.") | 1127 | "Header to be written into the `recentf-save-file'.") |
| @@ -1149,16 +1138,16 @@ Write data into the file specified by `recentf-save-file'." | |||
| 1149 | (interactive) | 1138 | (interactive) |
| 1150 | (condition-case error | 1139 | (condition-case error |
| 1151 | (with-temp-buffer | 1140 | (with-temp-buffer |
| 1152 | (erase-buffer) | 1141 | (erase-buffer) |
| 1153 | (set-buffer-file-coding-system recentf-save-file-coding-system) | 1142 | (set-buffer-file-coding-system recentf-save-file-coding-system) |
| 1154 | (insert (format recentf-save-file-header (current-time-string))) | 1143 | (insert (format recentf-save-file-header (current-time-string))) |
| 1155 | (recentf-dump-variable 'recentf-list recentf-max-saved-items) | 1144 | (recentf-dump-variable 'recentf-list recentf-max-saved-items) |
| 1156 | (recentf-dump-variable 'recentf-filter-changer-state) | 1145 | (recentf-dump-variable 'recentf-filter-changer-state) |
| 1157 | (insert "\n\n;;; Local Variables:\n" | 1146 | (insert "\n\n;;; Local Variables:\n" |
| 1158 | (format ";;; coding: %s\n" recentf-save-file-coding-system) | 1147 | (format ";;; coding: %s\n" recentf-save-file-coding-system) |
| 1159 | ";;; End:\n") | 1148 | ";;; End:\n") |
| 1160 | (write-file (expand-file-name recentf-save-file)) | 1149 | (write-file (expand-file-name recentf-save-file)) |
| 1161 | nil) | 1150 | nil) |
| 1162 | (error | 1151 | (error |
| 1163 | (warn "recentf mode: %s" (error-message-string error))))) | 1152 | (warn "recentf mode: %s" (error-message-string error))))) |
| 1164 | 1153 | ||
| @@ -1218,5 +1207,5 @@ that were operated on recently." | |||
| 1218 | 1207 | ||
| 1219 | (run-hooks 'recentf-load-hook) | 1208 | (run-hooks 'recentf-load-hook) |
| 1220 | 1209 | ||
| 1221 | ;;; arch-tag: 78f1eec9-0d16-4d19-a4eb-2e4529edb62a | 1210 | ;; arch-tag: 78f1eec9-0d16-4d19-a4eb-2e4529edb62a |
| 1222 | ;;; recentf.el ends here | 1211 | ;;; recentf.el ends here |