aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Love2000-07-24 13:39:05 +0000
committerDave Love2000-07-24 13:39:05 +0000
commitbc66a9a99a20699cbdea4535df9daca5e0947283 (patch)
treed43d9517374d67dc345e6abf97594cfcac76eeb6
parente024b10125c542b2b954ddb54ad455af9661547c (diff)
downloademacs-bc66a9a99a20699cbdea4535df9daca5e0947283.tar.gz
emacs-bc66a9a99a20699cbdea4535df9daca5e0947283.zip
Fix CRLF eols.
-rw-r--r--lisp/recentf.el2120
1 files changed, 1060 insertions, 1060 deletions
diff --git a/lisp/recentf.el b/lisp/recentf.el
index dc040be910b..82357dbe0b5 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -1,1060 +1,1060 @@
1;; recentf.el --- setup a menu of recently opened files 1;; recentf.el --- setup a menu of recently opened files
2 2
3;; Copyright (C) 1999, 2000 Free Software Foundation, Inc. 3;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
4 4
5;; Author: David Ponce <david@dponce.com> 5;; Author: David Ponce <david@dponce.com>
6;; Created: July 19 1999 6;; Created: July 19 1999
7;; Keywords: customization 7;; Keywords: customization
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
10 10
11;; GNU Emacs is free software; you can redistribute it and/or modify 11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by 12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option) 13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version. 14;; any later version.
15 15
16;; GNU Emacs is distributed in the hope that it will be useful, 16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details. 19;; GNU General Public License for more details.
20 20
21;; You should have received a copy of the GNU General Public License 21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the 22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA. 24;; Boston, MA 02111-1307, USA.
25 25
26;;; Commentary: 26;;; Commentary:
27 27
28;; This package maintains a menu for visiting files that were operated 28;; This package maintains a menu for visiting files that were operated
29;; on recently. When enabled a new "Open Recent" submenu is displayed 29;; on recently. When enabled a new "Open Recent" submenu is displayed
30;; in the "Files" menu. The recent files list is automatically saved 30;; in the "Files" menu. The recent files list is automatically saved
31;; across Emacs sessions. You can customize the number of recent 31;; across Emacs sessions. You can customize the number of recent
32;; files displayed, the location of the menu and others options (see 32;; files displayed, the location of the menu and others options (see
33;; the source code for details). To install and use, put the file on 33;; the source code for details). To install and use, put the file on
34;; your Emacs-Lisp load path and add the following into your ~/.emacs 34;; your Emacs-Lisp load path and add the following into your ~/.emacs
35;; startup file: 35;; startup file:
36;; 36;;
37;; (require 'recentf) 37;; (require 'recentf)
38;; (recentf-mode 1) 38;; (recentf-mode 1)
39 39
40;;; Code: 40;;; Code:
41 41
42(require 'easymenu) 42(require 'easymenu)
43(require 'wid-edit) 43(require 'wid-edit)
44 44
45(defconst recentf-save-file-header 45(defconst recentf-save-file-header
46 ";;; Automatically generated by `recentf' on %s.\n" 46 ";;; Automatically generated by `recentf' on %s.\n"
47 "Header to be written into the `recentf-save-file'.") 47 "Header to be written into the `recentf-save-file'.")
48 48
49(defvar recentf-list nil 49(defvar recentf-list nil
50 "List of recently opened files.") 50 "List of recently opened files.")
51 51
52(defvar recentf-update-menu-p t 52(defvar recentf-update-menu-p t
53 "Non-nil if the recentf menu must be updated.") 53 "Non-nil if the recentf menu must be updated.")
54 54
55(defvar recentf-initialized-p nil 55(defvar recentf-initialized-p nil
56 "Non-nil if recentf already initialized.") 56 "Non-nil if recentf already initialized.")
57 57
58;; IMPORTANT: This function must be defined before the following defcustoms 58;; IMPORTANT: This function must be defined before the following defcustoms
59;; because it is used in their :set clause. To avoid byte-compiler warnings 59;; because it is used in their :set clause. To avoid byte-compiler warnings
60;; the `symbol-value' function is used to access the `recentf-menu-path' 60;; the `symbol-value' function is used to access the `recentf-menu-path'
61;; and `recentf-menu-title' values. 61;; and `recentf-menu-title' values.
62(defun recentf-menu-customization-changed (sym val) 62(defun recentf-menu-customization-changed (sym val)
63 "Function called when menu customization has changed. 63 "Function called when menu customization has changed.
64It removes the recentf menu and forces its complete redrawing." 64It removes the recentf menu and forces its complete redrawing."
65 (when recentf-initialized-p 65 (when recentf-initialized-p
66 (easy-menu-remove-item nil 66 (easy-menu-remove-item nil
67 (symbol-value 'recentf-menu-path) 67 (symbol-value 'recentf-menu-path)
68 (symbol-value 'recentf-menu-title)) 68 (symbol-value 'recentf-menu-title))
69 (setq recentf-update-menu-p t)) 69 (setq recentf-update-menu-p t))
70 (custom-set-default sym val)) 70 (custom-set-default sym val))
71 71
72(defgroup recentf nil 72(defgroup recentf nil
73 "Maintain a menu of recently opened files." 73 "Maintain a menu of recently opened files."
74 :version "21.1" 74 :version "21.1"
75 :group 'files) 75 :group 'files)
76 76
77(defgroup recentf-filters nil 77(defgroup recentf-filters nil
78 "Group to customize recentf menu filters. 78 "Group to customize recentf menu filters.
79You should define the options of your own filters in this group." 79You should define the options of your own filters in this group."
80 :group 'recentf) 80 :group 'recentf)
81 81
82(defcustom recentf-max-saved-items 20 82(defcustom recentf-max-saved-items 20
83 "*Maximum number of items saved to `recentf-save-file'." 83 "*Maximum number of items saved to `recentf-save-file'."
84 :group 'recentf 84 :group 'recentf
85 :type 'integer) 85 :type 'integer)
86 86
87(defcustom recentf-save-file (expand-file-name "~/.recentf") 87(defcustom recentf-save-file (expand-file-name "~/.recentf")
88 "*File to save `recentf-list' into." 88 "*File to save `recentf-list' into."
89 :group 'recentf 89 :group 'recentf
90 :type 'file) 90 :type 'file)
91 91
92(defcustom recentf-exclude nil 92(defcustom recentf-exclude nil
93 "*List of regexps for filenames excluded from `recentf-list'." 93 "*List of regexps for filenames excluded from `recentf-list'."
94 :group 'recentf 94 :group 'recentf
95 :type '(repeat regexp)) 95 :type '(repeat regexp))
96 96
97(defcustom recentf-menu-title "Open Recent" 97(defcustom recentf-menu-title "Open Recent"
98 "*Name of the recentf menu." 98 "*Name of the recentf menu."
99 :group 'recentf 99 :group 'recentf
100 :type 'string 100 :type 'string
101 :set 'recentf-menu-customization-changed) 101 :set 'recentf-menu-customization-changed)
102 102
103(defcustom recentf-menu-path '("files") 103(defcustom recentf-menu-path '("files")
104 "*Path where to add the recentf menu. 104 "*Path where to add the recentf menu.
105If nil add it at top-level (see also `easy-menu-change')." 105If nil add it at top-level (see also `easy-menu-change')."
106 :group 'recentf 106 :group 'recentf
107 :type '(choice (const :tag "Top Level" nil) 107 :type '(choice (const :tag "Top Level" nil)
108 (sexp :tag "Menu Path")) 108 (sexp :tag "Menu Path"))
109 :set 'recentf-menu-customization-changed) 109 :set 'recentf-menu-customization-changed)
110 110
111(defcustom recentf-menu-before "open-file" 111(defcustom recentf-menu-before "open-file"
112 "*Name of the menu before which the recentf menu will be added. 112 "*Name of the menu before which the recentf menu will be added.
113If nil add it at end of menu (see also `easy-menu-change')." 113If nil add it at end of menu (see also `easy-menu-change')."
114 :group 'recentf 114 :group 'recentf
115 :type '(choice (string :tag "Name") 115 :type '(choice (string :tag "Name")
116 (const :tag "Last" nil)) 116 (const :tag "Last" nil))
117 :set 'recentf-menu-customization-changed) 117 :set 'recentf-menu-customization-changed)
118 118
119(defcustom recentf-menu-action 'recentf-find-file 119(defcustom recentf-menu-action 'recentf-find-file
120 "*Function to invoke with a filename item of the recentf menu. 120 "*Function to invoke with a filename item of the recentf menu.
121The default action `recentf-find-file' calls `find-file' to edit an 121The default action `recentf-find-file' calls `find-file' to edit an
122existing file. If the file does not exist or is not readable, it is 122existing file. If the file does not exist or is not readable, it is
123not edited and its name is removed from `recentf-list'. You can use 123not edited and its name is removed from `recentf-list'. You can use
124`find-file' instead to open non-existing files and keep them in the 124`find-file' instead to open non-existing files and keep them in the
125list of recently opened files." 125list of recently opened files."
126 :group 'recentf 126 :group 'recentf
127 :type 'function 127 :type 'function
128 :set 'recentf-menu-customization-changed) 128 :set 'recentf-menu-customization-changed)
129 129
130(defcustom recentf-max-menu-items 10 130(defcustom recentf-max-menu-items 10
131 "*Maximum number of items in the recentf menu." 131 "*Maximum number of items in the recentf menu."
132 :group 'recentf 132 :group 'recentf
133 :type 'integer 133 :type 'integer
134 :set 'recentf-menu-customization-changed) 134 :set 'recentf-menu-customization-changed)
135 135
136(defcustom recentf-menu-filter nil 136(defcustom recentf-menu-filter nil
137 "*Function used to filter files displayed in the recentf menu. 137 "*Function used to filter files displayed in the recentf menu.
138Nil means no filter. The following functions are predefined: 138Nil means no filter. The following functions are predefined:
139 139
140- - `recentf-sort-ascending' to sort menu items in ascending order. 140- - `recentf-sort-ascending' to sort menu items in ascending order.
141- - `recentf-sort-descending' to sort menu items in descending order. 141- - `recentf-sort-descending' to sort menu items in descending order.
142- - `recentf-sort-basenames-ascending' to sort file names in descending order. 142- - `recentf-sort-basenames-ascending' to sort file names in descending order.
143- - `recentf-sort-basenames-descending' to sort file names in descending order. 143- - `recentf-sort-basenames-descending' to sort file names in descending order.
144- - `recentf-sort-directories-ascending' to sort directories in ascending order. 144- - `recentf-sort-directories-ascending' to sort directories in ascending order.
145- - `recentf-sort-directories-descending' to sort directories in descending order. 145- - `recentf-sort-directories-descending' to sort directories in descending order.
146- - `recentf-show-basenames' to show file names (no directories) in menu items. 146- - `recentf-show-basenames' to show file names (no directories) in menu items.
147- - `recentf-show-basenames-ascending' to show file names in ascending order. 147- - `recentf-show-basenames-ascending' to show file names in ascending order.
148- - `recentf-show-basenames-descending' to show file names in descending order. 148- - `recentf-show-basenames-descending' to show file names in descending order.
149- - `recentf-relative-filter' to show file names relative to `default-directory'. 149- - `recentf-relative-filter' to show file names relative to `default-directory'.
150- - `recentf-arrange-by-rule' to show sub-menus following user defined rules. 150- - `recentf-arrange-by-rule' to show sub-menus following user defined rules.
151- - `recentf-arrange-by-mode' to show a sub-menu for each major mode. 151- - `recentf-arrange-by-mode' to show a sub-menu for each major mode.
152- - `recentf-arrange-by-dir' to show a sub-menu for each directory. 152- - `recentf-arrange-by-dir' to show a sub-menu for each directory.
153- - `recentf-filter-changer' to manage a ring of filters. 153- - `recentf-filter-changer' to manage a ring of filters.
154 154
155The filter function is called with one argument, the list of menu elements 155The filter function is called with one argument, the list of menu elements
156used to build the menu and must return a new list of menu elements (see 156used to build the menu and must return a new list of menu elements (see
157`recentf-make-menu-element' for menu element form)." 157`recentf-make-menu-element' for menu element form)."
158 :group 'recentf 158 :group 'recentf
159 :type 'function 159 :type 'function
160 :set 'recentf-menu-customization-changed) 160 :set 'recentf-menu-customization-changed)
161 161
162(defcustom recentf-menu-append-commands-p t 162(defcustom recentf-menu-append-commands-p t
163 "*If not-nil command items are appended to the menu." 163 "*If not-nil command items are appended to the menu."
164 :group 'recentf 164 :group 'recentf
165 :type 'boolean 165 :type 'boolean
166 :set 'recentf-menu-customization-changed) 166 :set 'recentf-menu-customization-changed)
167 167
168(defcustom recentf-keep-non-readable-files-p nil 168(defcustom recentf-keep-non-readable-files-p nil
169 "*If nil (default), non-readable files are not kept in `recentf-list'." 169 "*If nil (default), non-readable files are not kept in `recentf-list'."
170 :group 'recentf 170 :group 'recentf
171 :type 'boolean 171 :type 'boolean
172 :require 'recentf 172 :require 'recentf
173 :initialize 'custom-initialize-default 173 :initialize 'custom-initialize-default
174 :set (lambda (sym val) 174 :set (lambda (sym val)
175 (if val 175 (if val
176 (remove-hook 'kill-buffer-hook 'recentf-remove-file-hook) 176 (remove-hook 'kill-buffer-hook 'recentf-remove-file-hook)
177 (add-hook 'kill-buffer-hook 'recentf-remove-file-hook)) 177 (add-hook 'kill-buffer-hook 'recentf-remove-file-hook))
178 (custom-set-default sym val))) 178 (custom-set-default sym val)))
179 179
180(defcustom recentf-mode nil 180(defcustom recentf-mode nil
181 "Toggle recentf mode. 181 "Toggle recentf mode.
182When recentf mode is enabled, it maintains a menu for visiting files that 182When recentf mode is enabled, it maintains a menu for visiting files that
183were operated on recently. 183were operated on recently.
184Setting this variable directly does not take effect; 184Setting this variable directly does not take effect;
185use either \\[customize] or the function `recentf-mode'." 185use either \\[customize] or the function `recentf-mode'."
186 :set (lambda (symbol value) 186 :set (lambda (symbol value)
187 (recentf-mode (or value 0))) 187 (recentf-mode (or value 0)))
188 :initialize 'custom-initialize-default 188 :initialize 'custom-initialize-default
189 :type 'boolean 189 :type 'boolean
190 :group 'recentf 190 :group 'recentf
191 :require 'recentf) 191 :require 'recentf)
192 192
193(defcustom recentf-load-hook nil 193(defcustom recentf-load-hook nil
194 "*Normal hook run at end of loading the `recentf' package." 194 "*Normal hook run at end of loading the `recentf' package."
195 :group 'recentf 195 :group 'recentf
196 :type 'hook) 196 :type 'hook)
197 197
198;;; 198;;;
199;;; Common functions 199;;; Common functions
200;;; 200;;;
201(defconst recentf-case-fold-search 201(defconst recentf-case-fold-search
202 (memq system-type '(vax-vms windows-nt)) 202 (memq system-type '(vax-vms windows-nt))
203 "Non-nil if recentf searches and matches should ignore case.") 203 "Non-nil if recentf searches and matches should ignore case.")
204 204
205(defun recentf-include-p (filename) 205(defun recentf-include-p (filename)
206 "Return t if FILENAME matches none of the `recentf-exclude' regexps." 206 "Return t if FILENAME matches none of the `recentf-exclude' regexps."
207 (let ((case-fold-search recentf-case-fold-search) 207 (let ((case-fold-search recentf-case-fold-search)
208 (rl recentf-exclude)) 208 (rl recentf-exclude))
209 (while (and rl (not (string-match (car rl) filename))) 209 (while (and rl (not (string-match (car rl) filename)))
210 (setq rl (cdr rl))) 210 (setq rl (cdr rl)))
211 (null rl))) 211 (null rl)))
212 212
213(defun recentf-add-file (filename) 213(defun recentf-add-file (filename)
214 "Add or move FILENAME at the beginning of `recentf-list'. 214 "Add or move FILENAME at the beginning of `recentf-list'.
215Does nothing if FILENAME matches one of the `recentf-exclude' regexps." 215Does nothing if FILENAME matches one of the `recentf-exclude' regexps."
216 (let ((filename (expand-file-name filename))) 216 (let ((filename (expand-file-name filename)))
217 (when (recentf-include-p filename) 217 (when (recentf-include-p filename)
218 (setq recentf-list (cons filename (delete filename recentf-list))) 218 (setq recentf-list (cons filename (delete filename recentf-list)))
219 (setq recentf-update-menu-p t)))) 219 (setq recentf-update-menu-p t))))
220 220
221(defun recentf-remove-if-non-readable (filename) 221(defun recentf-remove-if-non-readable (filename)
222 "Remove FILENAME from `recentf-list' if not readable." 222 "Remove FILENAME from `recentf-list' if not readable."
223 (unless (file-readable-p filename) 223 (unless (file-readable-p filename)
224 (setq recentf-list (delete filename recentf-list)) 224 (setq recentf-list (delete filename recentf-list))
225 (setq recentf-update-menu-p t))) 225 (setq recentf-update-menu-p t)))
226 226
227(defun recentf-find-file (filename) 227(defun recentf-find-file (filename)
228 "Edit file FILENAME using `find-file'. 228 "Edit file FILENAME using `find-file'.
229If FILENAME is not readable it is removed from `recentf-list'." 229If FILENAME is not readable it is removed from `recentf-list'."
230 (if (file-readable-p filename) 230 (if (file-readable-p filename)
231 (find-file filename) 231 (find-file filename)
232 (progn 232 (progn
233 (message "File `%s' not found." filename) 233 (message "File `%s' not found." filename)
234 (setq recentf-list (delete filename recentf-list)) 234 (setq recentf-list (delete filename recentf-list))
235 (setq recentf-update-menu-p t)))) 235 (setq recentf-update-menu-p t))))
236 236
237(defun recentf-trunc-list (l n) 237(defun recentf-trunc-list (l n)
238 "Return a list of the first N elements of L." 238 "Return a list of the first N elements of L."
239 (let ((lh nil)) 239 (let ((lh nil))
240 (while (and l (> n 0)) 240 (while (and l (> n 0))
241 (setq lh (cons (car l) lh)) 241 (setq lh (cons (car l) lh))
242 (setq n (1- n)) 242 (setq n (1- n))
243 (setq l (cdr l))) 243 (setq l (cdr l)))
244 (nreverse lh))) 244 (nreverse lh)))
245 245
246(defun recentf-elements (n) 246(defun recentf-elements (n)
247 "Return a list of the first N elements of `recentf-list'." 247 "Return a list of the first N elements of `recentf-list'."
248 (recentf-trunc-list recentf-list n)) 248 (recentf-trunc-list recentf-list n))
249 249
250(defun recentf-make-menu-element (menu-item menu-value) 250(defun recentf-make-menu-element (menu-item menu-value)
251 "Create a new menu-element. 251 "Create a new menu-element.
252 252
253A menu element is a pair (MENU-ITEM . MENU-VALUE) where: 253A menu element is a pair (MENU-ITEM . MENU-VALUE) where:
254 254
255- - MENU-ITEM is the menu item string displayed. 255- - MENU-ITEM is the menu item string displayed.
256- - MENU-VALUE is the path used to open the file when the 256- - MENU-VALUE is the path used to open the file when the
257 corresponding MENU-ITEM is selected. Or it is 257 corresponding MENU-ITEM is selected. Or it is
258 a pair (SUB-MENU-TITLE . MENU-ELEMENTS) where 258 a pair (SUB-MENU-TITLE . MENU-ELEMENTS) where
259 SUB-MENU-TITLE is a sub-menu title and 259 SUB-MENU-TITLE is a sub-menu title and
260 MENU-ELEMENTS is the list of menu elements in 260 MENU-ELEMENTS is the list of menu elements in
261 the sub-menu." 261 the sub-menu."
262 (cons menu-item menu-value)) 262 (cons menu-item menu-value))
263 263
264(defun recentf-menu-element-item (e) 264(defun recentf-menu-element-item (e)
265 "Return the item part of the menu-element E." 265 "Return the item part of the menu-element E."
266 (car e)) 266 (car e))
267 267
268(defun recentf-menu-element-value (e) 268(defun recentf-menu-element-value (e)
269 "Return the value part of the menu-element E." 269 "Return the value part of the menu-element E."
270 (cdr e)) 270 (cdr e))
271 271
272(defun recentf-set-menu-element-item (e item) 272(defun recentf-set-menu-element-item (e item)
273 "Change the item part of menu-element E to ITEM." 273 "Change the item part of menu-element E to ITEM."
274 (setcar e item)) 274 (setcar e item))
275 275
276(defun recentf-set-menu-element-value (e value) 276(defun recentf-set-menu-element-value (e value)
277 "Change the value part of menu-element E to VALUE." 277 "Change the value part of menu-element E to VALUE."
278 (setcdr e value)) 278 (setcdr e value))
279 279
280(defun recentf-sub-menu-element-p (e) 280(defun recentf-sub-menu-element-p (e)
281 "Return non-nil if menu-element E defines a sub-menu." 281 "Return non-nil if menu-element E defines a sub-menu."
282 (consp (recentf-menu-element-value e))) 282 (consp (recentf-menu-element-value e)))
283 283
284(defun recentf-make-default-menu-element (file-path) 284(defun recentf-make-default-menu-element (file-path)
285 "Make a new default menu element (MENU-ITEM . MENU-VALUE) for the 285 "Make a new default menu element (MENU-ITEM . MENU-VALUE) for the
286given recent file path FILE-PATH. MENU-ITEM and MENU-VALUE are set to 286given recent file path FILE-PATH. MENU-ITEM and MENU-VALUE are set to
287FILE-PATH. See also `recentf-make-menu-element'." 287FILE-PATH. See also `recentf-make-menu-element'."
288 (recentf-make-menu-element file-path file-path)) 288 (recentf-make-menu-element file-path file-path))
289 289
290(defun recentf-menu-elements (n) 290(defun recentf-menu-elements (n)
291 "Return a list of the first N default menu elements from 291 "Return a list of the first N default menu elements from
292`recentf-list'. See also `recentf-make-default-menu-element'." 292`recentf-list'. See also `recentf-make-default-menu-element'."
293 (mapcar 'recentf-make-default-menu-element 293 (mapcar 'recentf-make-default-menu-element
294 (recentf-elements n))) 294 (recentf-elements n)))
295 295
296(defun recentf-apply-menu-filter (filter l) 296(defun recentf-apply-menu-filter (filter l)
297 "Convenient funtion to apply the function FILTER to the list of 297 "Convenient funtion to apply the function FILTER to the list of
298menu-elements L. It takes care of sub-menu elements in L and 298menu-elements L. It takes care of sub-menu elements in L and
299recursively apply FILTER to them. It is guarantee than FILTER receives 299recursively apply FILTER to them. It is guarantee than FILTER receives
300only a list of single menu-elements (no sub-menu)." 300only a list of single menu-elements (no sub-menu)."
301 (if (and (functionp filter) l) 301 (if (and (functionp filter) l)
302 (let ((case-fold-search recentf-case-fold-search) 302 (let ((case-fold-search recentf-case-fold-search)
303 menu-element sub-menu-elements single-elements) 303 menu-element sub-menu-elements single-elements)
304 ;; split L in two sub-listes: 304 ;; split L in two sub-listes:
305 ;; one of sub-menus elements and 305 ;; one of sub-menus elements and
306 ;; one of single menu elements 306 ;; one of single menu elements
307 (while l 307 (while l
308 (setq menu-element (car l)) 308 (setq menu-element (car l))
309 (if (recentf-sub-menu-element-p menu-element) 309 (if (recentf-sub-menu-element-p menu-element)
310 (setq sub-menu-elements 310 (setq sub-menu-elements
311 (cons menu-element sub-menu-elements)) 311 (cons menu-element sub-menu-elements))
312 (setq single-elements 312 (setq single-elements
313 (cons menu-element single-elements))) 313 (cons menu-element single-elements)))
314 (setq l (cdr l))) 314 (setq l (cdr l)))
315 ;; apply FILTER to the list of single menu elements 315 ;; apply FILTER to the list of single menu elements
316 (if single-elements 316 (if single-elements
317 (setq single-elements (funcall filter 317 (setq single-elements (funcall filter
318 (nreverse single-elements)))) 318 (nreverse single-elements))))
319 ;; apply FILTER to sub-menu menu element list 319 ;; apply FILTER to sub-menu menu element list
320 (setq l sub-menu-elements) 320 (setq l sub-menu-elements)
321 (setq sub-menu-elements nil) 321 (setq sub-menu-elements nil)
322 (while l 322 (while l
323 (setq menu-element (car l)) 323 (setq menu-element (car l))
324 (recentf-set-menu-element-value 324 (recentf-set-menu-element-value
325 menu-element 325 menu-element
326 (recentf-apply-menu-filter 326 (recentf-apply-menu-filter
327 filter 327 filter
328 (recentf-menu-element-value menu-element))) 328 (recentf-menu-element-value menu-element)))
329 (setq sub-menu-elements (cons menu-element sub-menu-elements)) 329 (setq sub-menu-elements (cons menu-element sub-menu-elements))
330 (setq l (cdr l))) 330 (setq l (cdr l)))
331 ;; build and return the new filtered menu element list 331 ;; build and return the new filtered menu element list
332 (nconc sub-menu-elements single-elements)) 332 (nconc sub-menu-elements single-elements))
333 l)) 333 l))
334 334
335(defvar recentf-menu-items-for-commands 335(defvar recentf-menu-items-for-commands
336 (list ["Cleanup list" recentf-cleanup t] 336 (list ["Cleanup list" recentf-cleanup t]
337 ["Edit list..." recentf-edit-list t] 337 ["Edit list..." recentf-edit-list t]
338 ["Save list now" recentf-save-list t] 338 ["Save list now" recentf-save-list t]
339 (vector "Recentf Options..." '(customize-group "recentf") t)) 339 (vector "Recentf Options..." '(customize-group "recentf") t))
340 "List of menu items for recentf commands.") 340 "List of menu items for recentf commands.")
341 341
342(defvar recentf-menu-filter-commands nil 342(defvar recentf-menu-filter-commands nil
343 "This variable can be used by menu filters to setup their own command menu. 343 "This variable can be used by menu filters to setup their own command menu.
344 344
345If non-nil it must contain a list of valid menu-items to be appended 345If non-nil it must contain a list of valid menu-items to be appended
346to the recent file list part of the menu. Before calling a menu 346to the recent file list part of the menu. Before calling a menu
347filter function this variable is reset to nil.") 347filter function this variable is reset to nil.")
348 348
349(defun recentf-make-menu-items () 349(defun recentf-make-menu-items ()
350 "Make menu items from `recentf-list'." 350 "Make menu items from `recentf-list'."
351 (setq recentf-menu-filter-commands nil) 351 (setq recentf-menu-filter-commands nil)
352 (let ((file-items 352 (let ((file-items
353 (mapcar 'recentf-make-menu-item 353 (mapcar 'recentf-make-menu-item
354 (recentf-apply-menu-filter 354 (recentf-apply-menu-filter
355 recentf-menu-filter 355 recentf-menu-filter
356 (recentf-menu-elements recentf-max-menu-items))))) 356 (recentf-menu-elements recentf-max-menu-items)))))
357 (append (or file-items (list ["No files" t nil])) 357 (append (or file-items (list ["No files" t nil]))
358 (and (< recentf-max-menu-items (length recentf-list)) 358 (and (< recentf-max-menu-items (length recentf-list))
359 (list ["More..." recentf-open-more-files t])) 359 (list ["More..." recentf-open-more-files t]))
360 (and recentf-menu-filter-commands 360 (and recentf-menu-filter-commands
361 (cons "---" 361 (cons "---"
362 recentf-menu-filter-commands)) 362 recentf-menu-filter-commands))
363 (and recentf-menu-append-commands-p 363 (and recentf-menu-append-commands-p
364 (cons "---" 364 (cons "---"
365 recentf-menu-items-for-commands))))) 365 recentf-menu-items-for-commands)))))
366 366
367(defun recentf-make-menu-item (menu-element) 367(defun recentf-make-menu-item (menu-element)
368 "Make a menu item from a menu element (see `recentf-make-menu-element')." 368 "Make a menu item from a menu element (see `recentf-make-menu-element')."
369 (let ((menu-item (recentf-menu-element-item menu-element)) 369 (let ((menu-item (recentf-menu-element-item menu-element))
370 (menu-value (recentf-menu-element-value menu-element))) 370 (menu-value (recentf-menu-element-value menu-element)))
371 (if (recentf-sub-menu-element-p menu-element) 371 (if (recentf-sub-menu-element-p menu-element)
372 (cons menu-item (mapcar 'recentf-make-menu-item menu-value)) 372 (cons menu-item (mapcar 'recentf-make-menu-item menu-value))
373 (vector menu-item 373 (vector menu-item
374 (list recentf-menu-action menu-value) 374 (list recentf-menu-action menu-value)
375 t)))) 375 t))))
376 376
377;;; 377;;;
378;;; Predefined menu filter functions 378;;; Predefined menu filter functions
379;;; 379;;;
380 380
381(defun recentf-sort-ascending (l) 381(defun recentf-sort-ascending (l)
382 "Sort the list of menu elements L in ascending order. 382 "Sort the list of menu elements L in ascending order.
383The MENU-ITEM part of each menu element is compared." 383The MENU-ITEM part of each menu element is compared."
384 (sort (copy-sequence l) 384 (sort (copy-sequence l)
385 (function 385 (function
386 (lambda (e1 e2) 386 (lambda (e1 e2)
387 (string-lessp (recentf-menu-element-item e1) 387 (string-lessp (recentf-menu-element-item e1)
388 (recentf-menu-element-item e2)))))) 388 (recentf-menu-element-item e2))))))
389 389
390(defun recentf-sort-descending (l) 390(defun recentf-sort-descending (l)
391 "Sort the list of menu elements L in descending order. 391 "Sort the list of menu elements L in descending order.
392The MENU-ITEM part of each menu element is compared." 392The MENU-ITEM part of each menu element is compared."
393 (sort (copy-sequence l) 393 (sort (copy-sequence l)
394 (function 394 (function
395 (lambda (e1 e2) 395 (lambda (e1 e2)
396 (string-lessp (recentf-menu-element-item e2) 396 (string-lessp (recentf-menu-element-item e2)
397 (recentf-menu-element-item e1)))))) 397 (recentf-menu-element-item e1))))))
398 398
399(defun recentf-sort-basenames-ascending (l) 399(defun recentf-sort-basenames-ascending (l)
400 "Sort the list of menu elements L in ascending order. 400 "Sort the list of menu elements L in ascending order.
401Only file names (without directories) are compared." 401Only file names (without directories) are compared."
402 (sort (copy-sequence l) 402 (sort (copy-sequence l)
403 (function 403 (function
404 (lambda (e1 e2) 404 (lambda (e1 e2)
405 (string-lessp 405 (string-lessp
406 (file-name-nondirectory (recentf-menu-element-value e1)) 406 (file-name-nondirectory (recentf-menu-element-value e1))
407 (file-name-nondirectory (recentf-menu-element-value e2))))))) 407 (file-name-nondirectory (recentf-menu-element-value e2)))))))
408 408
409(defun recentf-sort-basenames-descending (l) 409(defun recentf-sort-basenames-descending (l)
410 "Sort the list of menu elements L in descending order. 410 "Sort the list of menu elements L in descending order.
411Only file names (without directories) are compared." 411Only file names (without directories) are compared."
412 (sort (copy-sequence l) 412 (sort (copy-sequence l)
413 (function 413 (function
414 (lambda (e1 e2) 414 (lambda (e1 e2)
415 (string-lessp 415 (string-lessp
416 (file-name-nondirectory (recentf-menu-element-value e2)) 416 (file-name-nondirectory (recentf-menu-element-value e2))
417 (file-name-nondirectory (recentf-menu-element-value e1))))))) 417 (file-name-nondirectory (recentf-menu-element-value e1)))))))
418 418
419(defun recentf-directory-compare (p1 p2) 419(defun recentf-directory-compare (p1 p2)
420 "Compare directories then filenames in pathes P1 and P2 and return 420 "Compare directories then filenames in pathes P1 and P2 and return
421non-nil if P1 is less than P2." 421non-nil if P1 is less than P2."
422 (let ((d1 (file-name-directory p1)) 422 (let ((d1 (file-name-directory p1))
423 (f1 (file-name-nondirectory p1)) 423 (f1 (file-name-nondirectory p1))
424 (d2 (file-name-directory p2)) 424 (d2 (file-name-directory p2))
425 (f2 (file-name-nondirectory p2))) 425 (f2 (file-name-nondirectory p2)))
426 (if (string= d1 d2) 426 (if (string= d1 d2)
427 (string-lessp f1 f2) 427 (string-lessp f1 f2)
428 (string-lessp d1 d2)))) 428 (string-lessp d1 d2))))
429 429
430(defun recentf-sort-directories-ascending (l) 430(defun recentf-sort-directories-ascending (l)
431 "Sort the list of menu elements L in ascending order. 431 "Sort the list of menu elements L in ascending order.
432Compares directories then filenames to order the list." 432Compares directories then filenames to order the list."
433 (sort (copy-sequence l) 433 (sort (copy-sequence l)
434 (function 434 (function
435 (lambda (e1 e2) 435 (lambda (e1 e2)
436 (recentf-directory-compare (recentf-menu-element-value e1) 436 (recentf-directory-compare (recentf-menu-element-value e1)
437 (recentf-menu-element-value e2)))))) 437 (recentf-menu-element-value e2))))))
438 438
439(defun recentf-sort-directories-descending (l) 439(defun recentf-sort-directories-descending (l)
440 "Sort the list of menu elements L in descending order. 440 "Sort the list of menu elements L in descending order.
441Compares directories then filenames to order the list." 441Compares directories then filenames to order the list."
442 (sort (copy-sequence l) 442 (sort (copy-sequence l)
443 (function 443 (function
444 (lambda (e1 e2) 444 (lambda (e1 e2)
445 (recentf-directory-compare (recentf-menu-element-value e2) 445 (recentf-directory-compare (recentf-menu-element-value e2)
446 (recentf-menu-element-value e1)))))) 446 (recentf-menu-element-value e1))))))
447 447
448(defun recentf-show-basenames (l) 448(defun recentf-show-basenames (l)
449 "Filter the list of menu elements L to show only file names (no directories) 449 "Filter the list of menu elements L to show only file names (no directories)
450in the menu. When file names are duplicated their directory component is added." 450in the menu. When file names are duplicated their directory component is added."
451 (let ((names (mapcar (function 451 (let ((names (mapcar (function
452 (lambda (item) 452 (lambda (item)
453 (file-name-nondirectory 453 (file-name-nondirectory
454 (recentf-menu-element-value item)))) 454 (recentf-menu-element-value item))))
455 l)) 455 l))
456 (dirs (mapcar (function 456 (dirs (mapcar (function
457 (lambda (item) 457 (lambda (item)
458 (file-name-directory 458 (file-name-directory
459 (recentf-menu-element-value item)))) 459 (recentf-menu-element-value item))))
460 l)) 460 l))
461 (pathes (mapcar 'recentf-menu-element-value l)) 461 (pathes (mapcar 'recentf-menu-element-value l))
462 (pos -1) 462 (pos -1)
463 item filtered-items filtered-list) 463 item filtered-items filtered-list)
464 (while names 464 (while names
465 (setq item (car names)) 465 (setq item (car names))
466 (setq names (cdr names)) 466 (setq names (cdr names))
467 (setq pos (1+ pos)) 467 (setq pos (1+ pos))
468 (setq filtered-list 468 (setq filtered-list
469 (cons (recentf-make-menu-element 469 (cons (recentf-make-menu-element
470 (if (or (member item names) (member item filtered-items)) 470 (if (or (member item names) (member item filtered-items))
471 (concat item " (" (nth pos dirs) ")") 471 (concat item " (" (nth pos dirs) ")")
472 item) 472 item)
473 (nth pos pathes)) 473 (nth pos pathes))
474 filtered-list)) 474 filtered-list))
475 (setq filtered-items (cons item filtered-items))) 475 (setq filtered-items (cons item filtered-items)))
476 (nreverse filtered-list))) 476 (nreverse filtered-list)))
477 477
478(defun recentf-show-basenames-ascending (l) 478(defun recentf-show-basenames-ascending (l)
479 "Filter the list of menu elements L to show only file names in the menu, 479 "Filter the list of menu elements L to show only file names in the menu,
480sorted in ascending order. This filter combines the `recentf-sort-basenames-ascending' 480sorted in ascending order. This filter combines the `recentf-sort-basenames-ascending'
481and `recentf-show-basenames' filters." 481and `recentf-show-basenames' filters."
482 (recentf-show-basenames (recentf-sort-basenames-ascending l))) 482 (recentf-show-basenames (recentf-sort-basenames-ascending l)))
483 483
484(defun recentf-show-basenames-descending (l) 484(defun recentf-show-basenames-descending (l)
485 "Filter the list of menu elements L to show only file names in the menu, 485 "Filter the list of menu elements L to show only file names in the menu,
486sorted in descending order. This filter combines the `recentf-sort-basenames-descending' 486sorted in descending order. This filter combines the `recentf-sort-basenames-descending'
487and `recentf-show-basenames' filters." 487and `recentf-show-basenames' filters."
488 (recentf-show-basenames (recentf-sort-basenames-descending l))) 488 (recentf-show-basenames (recentf-sort-basenames-descending l)))
489 489
490(defun recentf-relative-filter (l) 490(defun recentf-relative-filter (l)
491 "Filter the list of `recentf-menu-elements' L to show filenames 491 "Filter the list of `recentf-menu-elements' L to show filenames
492relative to `default-directory'." 492relative to `default-directory'."
493 (setq recentf-update-menu-p t) ; force menu update 493 (setq recentf-update-menu-p t) ; force menu update
494 (mapcar (function 494 (mapcar (function
495 (lambda (menu-element) 495 (lambda (menu-element)
496 (let* ((ful-path (recentf-menu-element-value menu-element)) 496 (let* ((ful-path (recentf-menu-element-value menu-element))
497 (rel-path (file-relative-name ful-path))) 497 (rel-path (file-relative-name ful-path)))
498 (if (string-match "^\\.\\." rel-path) 498 (if (string-match "^\\.\\." rel-path)
499 menu-element 499 menu-element
500 (recentf-make-menu-element rel-path ful-path))))) 500 (recentf-make-menu-element rel-path ful-path)))))
501 l)) 501 l))
502 502
503(defcustom recentf-arrange-rules 503(defcustom recentf-arrange-rules
504 '( 504 '(
505 ("Elisp files (%d)" ".\\.el$") 505 ("Elisp files (%d)" ".\\.el$")
506 ("Java files (%d)" ".\\.java$") 506 ("Java files (%d)" ".\\.java$")
507 ("C/C++ files (%d)" "c\\(pp\\)?$") 507 ("C/C++ files (%d)" "c\\(pp\\)?$")
508 ) 508 )
509 "*List of rules used by `recentf-arrange-by-rule' to build sub-menus. 509 "*List of rules used by `recentf-arrange-by-rule' to build sub-menus.
510A rule is a pair (SUB-MENU-TITLE . MATCHER). SUB-MENU-TITLE is the 510A rule is a pair (SUB-MENU-TITLE . MATCHER). SUB-MENU-TITLE is the
511displayed title of the sub-menu where a '%d' `format' pattern is 511displayed title of the sub-menu where a '%d' `format' pattern is
512replaced by the number of items in the sub-menu. MATCHER is a regexp 512replaced by the number of items in the sub-menu. MATCHER is a regexp
513or a list of regexps. Items matching one of the regular expressions in 513or a list of regexps. Items matching one of the regular expressions in
514MATCHER are added to the corresponding sub-menu." 514MATCHER are added to the corresponding sub-menu."
515 :group 'recentf-filters 515 :group 'recentf-filters
516 :type '(repeat (cons string (repeat regexp))) 516 :type '(repeat (cons string (repeat regexp)))
517 :set 'recentf-menu-customization-changed) 517 :set 'recentf-menu-customization-changed)
518 518
519(defcustom recentf-arrange-by-rule-others "Other files (%d)" 519(defcustom recentf-arrange-by-rule-others "Other files (%d)"
520 "*Title of the `recentf-arrange-by-rule' sub-menu where items that 520 "*Title of the `recentf-arrange-by-rule' sub-menu where items that
521don't match any `recentf-arrange-rules' are displayed. If nil 521don't match any `recentf-arrange-rules' are displayed. If nil
522these items are displayed in the main recent files menu. A '%d' 522these items are displayed in the main recent files menu. A '%d'
523`format' pattern in the title is replaced by the number of items in 523`format' pattern in the title is replaced by the number of items in
524the sub-menu." 524the sub-menu."
525 :group 'recentf-filters 525 :group 'recentf-filters
526 :type '(choice (const :tag "Main menu" nil) 526 :type '(choice (const :tag "Main menu" nil)
527 (string :tag "Title")) 527 (string :tag "Title"))
528 :set 'recentf-menu-customization-changed) 528 :set 'recentf-menu-customization-changed)
529 529
530(defcustom recentf-arrange-by-rules-min-items 0 530(defcustom recentf-arrange-by-rules-min-items 0
531 "*Minimum number of items in a `recentf-arrange-by-rule' sub-menu. 531 "*Minimum number of items in a `recentf-arrange-by-rule' sub-menu.
532If the number of items in a sub-menu is less than this value the 532If the number of items in a sub-menu is less than this value the
533corresponding sub-menu items are displayed in the main recent files 533corresponding sub-menu items are displayed in the main recent files
534menu or in the `recentf-arrange-by-rule-others' sub-menu if 534menu or in the `recentf-arrange-by-rule-others' sub-menu if
535defined." 535defined."
536 :group 'recentf-filters 536 :group 'recentf-filters
537 :type 'number 537 :type 'number
538 :set 'recentf-menu-customization-changed) 538 :set 'recentf-menu-customization-changed)
539 539
540(defcustom recentf-arrange-by-rule-subfilter nil 540(defcustom recentf-arrange-by-rule-subfilter nil
541 "*Function used by `recentf-arrange-by-rule' to filter sub-menu elements. 541 "*Function used by `recentf-arrange-by-rule' to filter sub-menu elements.
542Nil means no filter. See also `recentf-menu-filter'. You can't use 542Nil means no filter. See also `recentf-menu-filter'. You can't use
543`recentf-arrange-by-rule' itself here!" 543`recentf-arrange-by-rule' itself here!"
544 :group 'recentf-filters 544 :group 'recentf-filters
545 :type 'function 545 :type 'function
546 :set (lambda (sym val) 546 :set (lambda (sym val)
547 (if (eq val 'recentf-arrange-by-rule) 547 (if (eq val 'recentf-arrange-by-rule)
548 (error "Can't use `recentf-arrange-by-rule' itself here!") 548 (error "Can't use `recentf-arrange-by-rule' itself here!")
549 (recentf-menu-customization-changed sym val)))) 549 (recentf-menu-customization-changed sym val))))
550 550
551(defun recentf-match-rule-p (matcher file-path) 551(defun recentf-match-rule-p (matcher file-path)
552 "Return non-nil if FILE-PATH match the rule specified by MATCHER. 552 "Return non-nil if FILE-PATH match the rule specified by MATCHER.
553See `recentf-arrange-rules' for details on MATCHER." 553See `recentf-arrange-rules' for details on MATCHER."
554 (if (stringp matcher) 554 (if (stringp matcher)
555 (string-match matcher file-path) 555 (string-match matcher file-path)
556 (while (and (consp matcher) 556 (while (and (consp matcher)
557 (not (string-match (car matcher) file-path))) 557 (not (string-match (car matcher) file-path)))
558 (setq matcher (cdr matcher))) 558 (setq matcher (cdr matcher)))
559 matcher)) 559 matcher))
560 560
561(defun recentf-arrange-by-rule (l) 561(defun recentf-arrange-by-rule (l)
562 "Filter the list of menu-elements L to arrange them in sub-menus 562 "Filter the list of menu-elements L to arrange them in sub-menus
563following rules in `recentf-arrange-rules'." 563following rules in `recentf-arrange-rules'."
564 (let ((sub-menus-number (length recentf-arrange-rules))) 564 (let ((sub-menus-number (length recentf-arrange-rules)))
565 (if (> sub-menus-number 0) 565 (if (> sub-menus-number 0)
566 (let ((sub-menus (apply 'vector 566 (let ((sub-menus (apply 'vector
567 (mapcar (function 567 (mapcar (function
568 (lambda (pair) 568 (lambda (pair)
569 (list (car pair)))) 569 (list (car pair))))
570 recentf-arrange-rules))) 570 recentf-arrange-rules)))
571 other-menu-elements index min-size) 571 other-menu-elements index min-size)
572 (while l 572 (while l
573 (let* ((menu-element (car l)) 573 (let* ((menu-element (car l))
574 (file-path (recentf-menu-element-value menu-element)) 574 (file-path (recentf-menu-element-value menu-element))
575 (rules recentf-arrange-rules) 575 (rules recentf-arrange-rules)
576 (found nil)) 576 (found nil))
577 (setq index 0) 577 (setq index 0)
578 (while (and (not found) rules) 578 (while (and (not found) rules)
579 (if (recentf-match-rule-p (cdar rules) file-path) 579 (if (recentf-match-rule-p (cdar rules) file-path)
580 (let ((sub-menu (aref sub-menus index))) 580 (let ((sub-menu (aref sub-menus index)))
581 (setq found t) 581 (setq found t)
582 (recentf-set-menu-element-value 582 (recentf-set-menu-element-value
583 sub-menu 583 sub-menu
584 (cons menu-element (recentf-menu-element-value sub-menu))) 584 (cons menu-element (recentf-menu-element-value sub-menu)))
585 )) 585 ))
586 (setq index (1+ index)) 586 (setq index (1+ index))
587 (setq rules (cdr rules))) 587 (setq rules (cdr rules)))
588 (or found 588 (or found
589 (setq other-menu-elements 589 (setq other-menu-elements
590 (cons menu-element other-menu-elements))) 590 (cons menu-element other-menu-elements)))
591 (setq l (cdr l)))) 591 (setq l (cdr l))))
592 (setq index 0) 592 (setq index 0)
593 (setq l nil) 593 (setq l nil)
594 (setq min-size (if (integerp recentf-arrange-by-rules-min-items) 594 (setq min-size (if (integerp recentf-arrange-by-rules-min-items)
595 (max 0 recentf-arrange-by-rules-min-items) 595 (max 0 recentf-arrange-by-rules-min-items)
596 0)) 596 0))
597 (while (< index sub-menus-number) 597 (while (< index sub-menus-number)
598 (let* ((sub-menu (aref sub-menus index)) 598 (let* ((sub-menu (aref sub-menus index))
599 (sub-menu-title (recentf-menu-element-item sub-menu)) 599 (sub-menu-title (recentf-menu-element-item sub-menu))
600 (sub-menu-elements (recentf-menu-element-value sub-menu)) 600 (sub-menu-elements (recentf-menu-element-value sub-menu))
601 (sub-menu-length (length sub-menu-elements))) 601 (sub-menu-length (length sub-menu-elements)))
602 (if (> sub-menu-length 0) 602 (if (> sub-menu-length 0)
603 (cond 603 (cond
604 ((< sub-menu-length min-size) 604 ((< sub-menu-length min-size)
605 (setq other-menu-elements 605 (setq other-menu-elements
606 (nconc sub-menu-elements other-menu-elements))) 606 (nconc sub-menu-elements other-menu-elements)))
607 ((>= sub-menu-length min-size) 607 ((>= sub-menu-length min-size)
608 (recentf-set-menu-element-item 608 (recentf-set-menu-element-item
609 sub-menu 609 sub-menu
610 (format sub-menu-title sub-menu-length)) 610 (format sub-menu-title sub-menu-length))
611 (recentf-set-menu-element-value 611 (recentf-set-menu-element-value
612 sub-menu 612 sub-menu
613 (recentf-apply-menu-filter 613 (recentf-apply-menu-filter
614 recentf-arrange-by-rule-subfilter 614 recentf-arrange-by-rule-subfilter
615 (nreverse sub-menu-elements))) 615 (nreverse sub-menu-elements)))
616 (setq l (cons sub-menu l))))) 616 (setq l (cons sub-menu l)))))
617 (setq index (1+ index)))) 617 (setq index (1+ index))))
618 (if (and (stringp recentf-arrange-by-rule-others) 618 (if (and (stringp recentf-arrange-by-rule-others)
619 other-menu-elements) 619 other-menu-elements)
620 (setq l 620 (setq l
621 (nreverse 621 (nreverse
622 (cons (recentf-make-menu-element 622 (cons (recentf-make-menu-element
623 (format recentf-arrange-by-rule-others 623 (format recentf-arrange-by-rule-others
624 (length other-menu-elements)) 624 (length other-menu-elements))
625 (recentf-apply-menu-filter 625 (recentf-apply-menu-filter
626 recentf-arrange-by-rule-subfilter 626 recentf-arrange-by-rule-subfilter
627 (nreverse other-menu-elements))) 627 (nreverse other-menu-elements)))
628 l))) 628 l)))
629 (setq l (nconc (nreverse l) 629 (setq l (nconc (nreverse l)
630 (recentf-apply-menu-filter 630 (recentf-apply-menu-filter
631 recentf-arrange-by-rule-subfilter 631 recentf-arrange-by-rule-subfilter
632 (nreverse other-menu-elements))))))) 632 (nreverse other-menu-elements)))))))
633 l)) 633 l))
634 634
635(defun recentf-build-mode-rules () 635(defun recentf-build-mode-rules ()
636 "Convert `auto-mode-alist' to `recentf-arrange-rules' format." 636 "Convert `auto-mode-alist' to `recentf-arrange-rules' format."
637 (let ((case-fold-search recentf-case-fold-search) 637 (let ((case-fold-search recentf-case-fold-search)
638 (modes auto-mode-alist) 638 (modes auto-mode-alist)
639 regexp mode rule-name rule rules) 639 regexp mode rule-name rule rules)
640 (while modes 640 (while modes
641 (setq regexp (caar modes)) 641 (setq regexp (caar modes))
642 (setq mode (cdar modes)) 642 (setq mode (cdar modes))
643 (when (symbolp mode) 643 (when (symbolp mode)
644 (setq rule-name (symbol-name mode)) 644 (setq rule-name (symbol-name mode))
645 (if (string-match "\\(.*\\)-mode$" rule-name) 645 (if (string-match "\\(.*\\)-mode$" rule-name)
646 (setq rule-name (match-string 1 rule-name))) 646 (setq rule-name (match-string 1 rule-name)))
647 (setq rule-name (concat rule-name " (%d)")) 647 (setq rule-name (concat rule-name " (%d)"))
648 (setq rule (assoc rule-name rules)) 648 (setq rule (assoc rule-name rules))
649 (if rule 649 (if rule
650 (setcdr rule (cons regexp (cdr rule))) 650 (setcdr rule (cons regexp (cdr rule)))
651 (setq rules (cons (list rule-name regexp) rules)))) 651 (setq rules (cons (list rule-name regexp) rules))))
652 (setq modes (cdr modes))) 652 (setq modes (cdr modes)))
653 ;; It is important to preserve auto-mode-alist order 653 ;; It is important to preserve auto-mode-alist order
654 ;; to ensure the right file <-> mode association 654 ;; to ensure the right file <-> mode association
655 (nreverse rules))) 655 (nreverse rules)))
656 656
657(defun recentf-arrange-by-mode (l) 657(defun recentf-arrange-by-mode (l)
658 "Filter the list of menu-elements L to build sub-menus for each 658 "Filter the list of menu-elements L to build sub-menus for each
659major mode." 659major mode."
660 (let ((recentf-arrange-rules (recentf-build-mode-rules)) 660 (let ((recentf-arrange-rules (recentf-build-mode-rules))
661 (recentf-arrange-by-rule-others "others (%d)")) 661 (recentf-arrange-by-rule-others "others (%d)"))
662 (recentf-arrange-by-rule l))) 662 (recentf-arrange-by-rule l)))
663 663
664(defun recentf-build-dir-rules (l) 664(defun recentf-build-dir-rules (l)
665 "Convert directories in the list of menu-elements L to rules in 665 "Convert directories in the list of menu-elements L to rules in
666`recentf-arrange-rules' format." 666`recentf-arrange-rules' format."
667 (let (dirs) 667 (let (dirs)
668 (mapcar (function 668 (mapcar (function
669 (lambda (e) 669 (lambda (e)
670 (let ((dir (file-name-directory 670 (let ((dir (file-name-directory
671 (recentf-menu-element-value e)))) 671 (recentf-menu-element-value e))))
672 (or (member dir dirs) 672 (or (member dir dirs)
673 (setq dirs (cons dir dirs)))))) 673 (setq dirs (cons dir dirs))))))
674 l) 674 l)
675 (mapcar (function 675 (mapcar (function
676 (lambda (d) 676 (lambda (d)
677 (cons (concat d " (%d)") 677 (cons (concat d " (%d)")
678 (concat "\\`" d)))) 678 (concat "\\`" d))))
679 (nreverse (sort dirs 'string-lessp))))) 679 (nreverse (sort dirs 'string-lessp)))))
680 680
681(defun recentf-file-name-nondir (l) 681(defun recentf-file-name-nondir (l)
682 "Filter the list of menu-elements L to show only filenames. This 682 "Filter the list of menu-elements L to show only filenames. This
683simplified version of `recentf-show-basenames' do not handle 683simplified version of `recentf-show-basenames' do not handle
684duplicates. It is used by `recentf-arrange-by-dir' as its 684duplicates. It is used by `recentf-arrange-by-dir' as its
685`recentf-arrange-by-rule-subfilter'." 685`recentf-arrange-by-rule-subfilter'."
686 (mapcar (function 686 (mapcar (function
687 (lambda (e) 687 (lambda (e)
688 (recentf-make-menu-element 688 (recentf-make-menu-element
689 (file-name-nondirectory (recentf-menu-element-value e)) 689 (file-name-nondirectory (recentf-menu-element-value e))
690 (recentf-menu-element-value e)))) 690 (recentf-menu-element-value e))))
691 l)) 691 l))
692 692
693(defun recentf-arrange-by-dir (l) 693(defun recentf-arrange-by-dir (l)
694 "Filter the list of menu-elements L to build sub-menus for each 694 "Filter the list of menu-elements L to build sub-menus for each
695directory." 695directory."
696 (let ((recentf-arrange-rules (recentf-build-dir-rules l)) 696 (let ((recentf-arrange-rules (recentf-build-dir-rules l))
697 (recentf-arrange-by-rule-subfilter 'recentf-file-name-nondir) 697 (recentf-arrange-by-rule-subfilter 'recentf-file-name-nondir)
698 recentf-arrange-by-rule-others) 698 recentf-arrange-by-rule-others)
699 (nreverse (recentf-arrange-by-rule l)))) 699 (nreverse (recentf-arrange-by-rule l))))
700 700
701(defvar recentf-filter-changer-state nil 701(defvar recentf-filter-changer-state nil
702 "Used by `recentf-filter-changer' to hold its state.") 702 "Used by `recentf-filter-changer' to hold its state.")
703 703
704(defcustom recentf-filter-changer-alist 704(defcustom recentf-filter-changer-alist
705 '( 705 '(
706 (recentf-arrange-by-mode . "*Files by Mode*") 706 (recentf-arrange-by-mode . "*Files by Mode*")
707 (recentf-arrange-by-dir . "*Files by Directory*") 707 (recentf-arrange-by-dir . "*Files by Directory*")
708 (recentf-arrange-by-rule . "*Files by User Rule*") 708 (recentf-arrange-by-rule . "*Files by User Rule*")
709 ) 709 )
710 "*List of filters managed by `recentf-filter-changer'. 710 "*List of filters managed by `recentf-filter-changer'.
711Each filter is defined by a pair (FILTER-FUN . FILTER-LBL) where: 711Each filter is defined by a pair (FILTER-FUN . FILTER-LBL) where:
712 712
713- - FILTER-FUN is the function that filters menu-elements 713- - FILTER-FUN is the function that filters menu-elements
714- - FILTER-LBL is the menu item used to activate the filter" 714- - FILTER-LBL is the menu item used to activate the filter"
715 :group 'recentf-filters 715 :group 'recentf-filters
716 :type '(repeat (cons function string)) 716 :type '(repeat (cons function string))
717 :set (lambda (sym val) 717 :set (lambda (sym val)
718 (setq recentf-filter-changer-state nil) 718 (setq recentf-filter-changer-state nil)
719 (recentf-menu-customization-changed sym val))) 719 (recentf-menu-customization-changed sym val)))
720 720
721(defun recentf-filter-changer-goto-next () 721(defun recentf-filter-changer-goto-next ()
722 "Go to the next filter available (see `recentf-filter-changer')." 722 "Go to the next filter available (see `recentf-filter-changer')."
723 (and (consp recentf-filter-changer-state) 723 (and (consp recentf-filter-changer-state)
724 (setq recentf-filter-changer-state 724 (setq recentf-filter-changer-state
725 (cdr recentf-filter-changer-state))) 725 (cdr recentf-filter-changer-state)))
726 (setq recentf-update-menu-p t)) 726 (setq recentf-update-menu-p t))
727 727
728(defun recentf-filter-changer-get-current () 728(defun recentf-filter-changer-get-current ()
729 "Get the current filter available (see `recentf-filter-changer')." 729 "Get the current filter available (see `recentf-filter-changer')."
730 (if (null recentf-filter-changer-state) 730 (if (null recentf-filter-changer-state)
731 (setq recentf-filter-changer-state recentf-filter-changer-alist)) 731 (setq recentf-filter-changer-state recentf-filter-changer-alist))
732 (and (consp recentf-filter-changer-state) 732 (and (consp recentf-filter-changer-state)
733 (car recentf-filter-changer-state))) 733 (car recentf-filter-changer-state)))
734 734
735(defun recentf-filter-changer-get-next () 735(defun recentf-filter-changer-get-next ()
736 "Get the next filter available (see `recentf-filter-changer')." 736 "Get the next filter available (see `recentf-filter-changer')."
737 (let ((filters recentf-filter-changer-state)) 737 (let ((filters recentf-filter-changer-state))
738 (cond ((consp filters) 738 (cond ((consp filters)
739 (setq filters (cdr filters)) 739 (setq filters (cdr filters))
740 (if (null filters) 740 (if (null filters)
741 (setq filters recentf-filter-changer-alist))) 741 (setq filters recentf-filter-changer-alist)))
742 (t 742 (t
743 (setq filters recentf-filter-changer-alist) 743 (setq filters recentf-filter-changer-alist)
744 (if (consp filters) 744 (if (consp filters)
745 (setq filters (cdr filters))))) 745 (setq filters (cdr filters)))))
746 (if (consp filters) 746 (if (consp filters)
747 (car filters)))) 747 (car filters))))
748 748
749(defun recentf-filter-changer (l) 749(defun recentf-filter-changer (l)
750 "Manage a ring of filters. `recentf-filter-changer-alist' defines 750 "Manage a ring of filters. `recentf-filter-changer-alist' defines
751the filters in the ring. Actual filtering of L is delegated to the 751the filters in the ring. Actual filtering of L is delegated to the
752current filter in the ring. A filter menu item is displayed allowing 752current filter in the ring. A filter menu item is displayed allowing
753to dynamically activate the next filter in the ring. If the filter 753to dynamically activate the next filter in the ring. If the filter
754ring is empty L is left unchanged." 754ring is empty L is left unchanged."
755 (let ((current-filter-item (recentf-filter-changer-get-current)) 755 (let ((current-filter-item (recentf-filter-changer-get-current))
756 (next-filter-item (recentf-filter-changer-get-next))) 756 (next-filter-item (recentf-filter-changer-get-next)))
757 (when current-filter-item 757 (when current-filter-item
758 (setq l (recentf-apply-menu-filter (car current-filter-item) l)) 758 (setq l (recentf-apply-menu-filter (car current-filter-item) l))
759 (if next-filter-item 759 (if next-filter-item
760 (setq recentf-menu-filter-commands 760 (setq recentf-menu-filter-commands
761 (list (vector (cdr next-filter-item) 761 (list (vector (cdr next-filter-item)
762 '(recentf-filter-changer-goto-next) 762 '(recentf-filter-changer-goto-next)
763 t))))) 763 t)))))
764 l)) 764 l))
765 765
766;;; 766;;;
767;;; Dialogs stuff 767;;; Dialogs stuff
768;;; 768;;;
769 769
770(defun recentf-cancel-dialog (&rest ignore) 770(defun recentf-cancel-dialog (&rest ignore)
771 "Cancel the current dialog. Used by `recentf-edit-list' and 771 "Cancel the current dialog. Used by `recentf-edit-list' and
772`recentf-open-files' dialogs." 772`recentf-open-files' dialogs."
773 (interactive) 773 (interactive)
774 (kill-buffer (current-buffer)) 774 (kill-buffer (current-buffer))
775 (message "Dialog canceled.")) 775 (message "Dialog canceled."))
776 776
777(defvar recentf-dialog-mode-map nil 777(defvar recentf-dialog-mode-map nil
778 "`recentf-dialog-mode' keymap.") 778 "`recentf-dialog-mode' keymap.")
779 779
780(if recentf-dialog-mode-map 780(if recentf-dialog-mode-map
781 () 781 ()
782 (setq recentf-dialog-mode-map (make-sparse-keymap)) 782 (setq recentf-dialog-mode-map (make-sparse-keymap))
783 (define-key recentf-dialog-mode-map "q" 'recentf-cancel-dialog) 783 (define-key recentf-dialog-mode-map "q" 'recentf-cancel-dialog)
784 (set-keymap-parent recentf-dialog-mode-map widget-keymap)) 784 (set-keymap-parent recentf-dialog-mode-map widget-keymap))
785 785
786(defun recentf-dialog-mode () 786(defun recentf-dialog-mode ()
787 "Major mode used in recentf dialogs. 787 "Major mode used in recentf dialogs.
788 788
789These are the special commands of recentf-dialog-mode mode: 789These are the special commands of recentf-dialog-mode mode:
790 q -- cancel this dialog." 790 q -- cancel this dialog."
791 (interactive) 791 (interactive)
792 (setq major-mode 'recentf-dialog-mode) 792 (setq major-mode 'recentf-dialog-mode)
793 (setq mode-name "recentf-dialog") 793 (setq mode-name "recentf-dialog")
794 (use-local-map recentf-dialog-mode-map)) 794 (use-local-map recentf-dialog-mode-map))
795 795
796;;; 796;;;
797;;; Hooks and Commands 797;;; Hooks and Commands
798;;; 798;;;
799 799
800(defun recentf-add-file-hook () 800(defun recentf-add-file-hook ()
801 "Insert the name of the file just opened or written into `recentf-list'." 801 "Insert the name of the file just opened or written into `recentf-list'."
802 (and buffer-file-name (recentf-add-file buffer-file-name)) 802 (and buffer-file-name (recentf-add-file buffer-file-name))
803 nil) 803 nil)
804 804
805(defun recentf-remove-file-hook () 805(defun recentf-remove-file-hook ()
806 "When a buffer is killed remove a non readable file from `recentf-list'." 806 "When a buffer is killed remove a non readable file from `recentf-list'."
807 (and buffer-file-name (recentf-remove-if-non-readable buffer-file-name)) 807 (and buffer-file-name (recentf-remove-if-non-readable buffer-file-name))
808 nil) 808 nil)
809 809
810(defun recentf-update-menu-hook () 810(defun recentf-update-menu-hook ()
811 "Update the recentf menu from the current `recentf-list'." 811 "Update the recentf menu from the current `recentf-list'."
812 (when recentf-update-menu-p 812 (when recentf-update-menu-p
813 (condition-case nil 813 (condition-case nil
814 (progn 814 (progn
815 (setq recentf-update-menu-p nil) 815 (setq recentf-update-menu-p nil)
816 (easy-menu-change recentf-menu-path 816 (easy-menu-change recentf-menu-path
817 recentf-menu-title 817 recentf-menu-title
818 (recentf-make-menu-items) 818 (recentf-make-menu-items)
819 recentf-menu-before)) 819 recentf-menu-before))
820 (error nil)))) 820 (error nil))))
821 821
822(defun recentf-dump-variable (variable &optional limit) 822(defun recentf-dump-variable (variable &optional limit)
823 "Insert a \"(setq VARIABLE value)\" in the current buffer. Optional 823 "Insert a \"(setq VARIABLE value)\" in the current buffer. Optional
824argument LIMIT specifies a maximum length when VARIABLE value is a 824argument LIMIT specifies a maximum length when VARIABLE value is a
825list (default to the full list)." 825list (default to the full list)."
826 (let ((value (symbol-value variable))) 826 (let ((value (symbol-value variable)))
827 (insert (format "(setq %S\n '(\n" variable)) 827 (insert (format "(setq %S\n '(\n" variable))
828 (cond ((consp value) 828 (cond ((consp value)
829 (if (and (integerp limit) (> limit 0)) 829 (if (and (integerp limit) (> limit 0))
830 (setq value (recentf-trunc-list value limit))) 830 (setq value (recentf-trunc-list value limit)))
831 (mapcar (function 831 (mapcar (function
832 (lambda (e) 832 (lambda (e)
833 (insert (format " %S\n" e)))) 833 (insert (format " %S\n" e))))
834 value)) 834 value))
835 (t 835 (t
836 (insert (format " %S\n" value)))) 836 (insert (format " %S\n" value))))
837 (insert " ))\n") 837 (insert " ))\n")
838 )) 838 ))
839 839
840;;;###autoload 840;;;###autoload
841(defun recentf-save-list () 841(defun recentf-save-list ()
842 "Save the current `recentf-list' to the file `recentf-save-file'." 842 "Save the current `recentf-list' to the file `recentf-save-file'."
843 (interactive) 843 (interactive)
844 (with-temp-buffer 844 (with-temp-buffer
845 (erase-buffer) 845 (erase-buffer)
846 (insert (format recentf-save-file-header (current-time-string))) 846 (insert (format recentf-save-file-header (current-time-string)))
847 (recentf-dump-variable 'recentf-list recentf-max-saved-items) 847 (recentf-dump-variable 'recentf-list recentf-max-saved-items)
848 (recentf-dump-variable 'recentf-filter-changer-state) 848 (recentf-dump-variable 'recentf-filter-changer-state)
849 (if (file-writable-p recentf-save-file) 849 (if (file-writable-p recentf-save-file)
850 (write-region (point-min) (point-max) recentf-save-file)) 850 (write-region (point-min) (point-max) recentf-save-file))
851 (kill-buffer (current-buffer))) 851 (kill-buffer (current-buffer)))
852 nil) 852 nil)
853 853
854(defvar recentf-edit-selected-items nil 854(defvar recentf-edit-selected-items nil
855 "Used by `recentf-edit-list' to hold the list of files to be deleted 855 "Used by `recentf-edit-list' to hold the list of files to be deleted
856from `recentf-list'.") 856from `recentf-list'.")
857 857
858(defun recentf-edit-list-action (widget &rest ignore) 858(defun recentf-edit-list-action (widget &rest ignore)
859 "Checkbox widget action used by `recentf-edit-list' to select/unselect a file." 859 "Checkbox widget action used by `recentf-edit-list' to select/unselect a file."
860 (let ((value (widget-get widget ':tag))) 860 (let ((value (widget-get widget ':tag)))
861 ;; if value is already in the selected items 861 ;; if value is already in the selected items
862 (if (memq value recentf-edit-selected-items) 862 (if (memq value recentf-edit-selected-items)
863 ;; then remove it 863 ;; then remove it
864 (progn 864 (progn
865 (setq recentf-edit-selected-items 865 (setq recentf-edit-selected-items
866 (delq value recentf-edit-selected-items)) 866 (delq value recentf-edit-selected-items))
867 (message "%s removed from selection." value)) 867 (message "%s removed from selection." value))
868 ;; else add it 868 ;; else add it
869 (progn 869 (progn
870 (setq recentf-edit-selected-items 870 (setq recentf-edit-selected-items
871 (nconc (list value) recentf-edit-selected-items)) 871 (nconc (list value) recentf-edit-selected-items))
872 (message "%s added to selection." value))))) 872 (message "%s added to selection." value)))))
873 873
874;;;###autoload 874;;;###autoload
875(defun recentf-edit-list () 875(defun recentf-edit-list ()
876 "Allow the user to edit the files that are kept in the recent list." 876 "Allow the user to edit the files that are kept in the recent list."
877 (interactive) 877 (interactive)
878 (with-current-buffer (get-buffer-create (concat "*" recentf-menu-title " - Edit list*")) 878 (with-current-buffer (get-buffer-create (concat "*" recentf-menu-title " - Edit list*"))
879 (switch-to-buffer (current-buffer)) 879 (switch-to-buffer (current-buffer))
880 (kill-all-local-variables) 880 (kill-all-local-variables)
881 (let ((inhibit-read-only t)) 881 (let ((inhibit-read-only t))
882 (erase-buffer)) 882 (erase-buffer))
883 (let ((all (overlay-lists))) 883 (let ((all (overlay-lists)))
884 ;; Delete all the overlays. 884 ;; Delete all the overlays.
885 (mapcar 'delete-overlay (car all)) 885 (mapcar 'delete-overlay (car all))
886 (mapcar 'delete-overlay (cdr all))) 886 (mapcar 'delete-overlay (cdr all)))
887 (setq recentf-edit-selected-items nil) 887 (setq recentf-edit-selected-items nil)
888 ;; Insert the dialog header 888 ;; Insert the dialog header
889 (widget-insert "Select the files to be deleted from the 'recentf-list'.\n\n") 889 (widget-insert "Select the files to be deleted from the 'recentf-list'.\n\n")
890 (widget-insert "Click on Ok to update the list. ") 890 (widget-insert "Click on Ok to update the list. ")
891 (widget-insert "Click on Cancel or type \"q\" to quit.\n") 891 (widget-insert "Click on Cancel or type \"q\" to quit.\n")
892 ;; Insert the list of files as checkboxes 892 ;; Insert the list of files as checkboxes
893 (mapcar (function 893 (mapcar (function
894 (lambda (item) 894 (lambda (item)
895 (widget-create 'checkbox 895 (widget-create 'checkbox
896 :value nil ; unselected checkbox 896 :value nil ; unselected checkbox
897 :format "\n %[%v%] %t" 897 :format "\n %[%v%] %t"
898 :tag item 898 :tag item
899 :notify 'recentf-edit-list-action))) 899 :notify 'recentf-edit-list-action)))
900 recentf-list) 900 recentf-list)
901 (widget-insert "\n\n") 901 (widget-insert "\n\n")
902 ;; Insert the Ok button 902 ;; Insert the Ok button
903 (widget-create 'push-button 903 (widget-create 'push-button
904 :notify (lambda (&rest ignore) 904 :notify (lambda (&rest ignore)
905 (if recentf-edit-selected-items 905 (if recentf-edit-selected-items
906 (progn (kill-buffer (current-buffer)) 906 (progn (kill-buffer (current-buffer))
907 (mapcar (function 907 (mapcar (function
908 (lambda (item) 908 (lambda (item)
909 (setq recentf-list 909 (setq recentf-list
910 (delq item recentf-list)))) 910 (delq item recentf-list))))
911 recentf-edit-selected-items) 911 recentf-edit-selected-items)
912 (message "%S file(s) removed from the list" 912 (message "%S file(s) removed from the list"
913 (length recentf-edit-selected-items)) 913 (length recentf-edit-selected-items))
914 (setq recentf-update-menu-p t)) 914 (setq recentf-update-menu-p t))
915 (message "No file selected."))) 915 (message "No file selected.")))
916 "Ok") 916 "Ok")
917 (widget-insert " ") 917 (widget-insert " ")
918 ;; Insert the Cancel button 918 ;; Insert the Cancel button
919 (widget-create 'push-button 919 (widget-create 'push-button
920 :notify 'recentf-cancel-dialog 920 :notify 'recentf-cancel-dialog
921 "Cancel") 921 "Cancel")
922 (recentf-dialog-mode) 922 (recentf-dialog-mode)
923 (widget-setup) 923 (widget-setup)
924 (goto-char (point-min)))) 924 (goto-char (point-min))))
925 925
926;;;###autoload 926;;;###autoload
927(defun recentf-cleanup () 927(defun recentf-cleanup ()
928 "Remove all non-readable and excluded files from `recentf-list'." 928 "Remove all non-readable and excluded files from `recentf-list'."
929 (interactive) 929 (interactive)
930 (let ((count (length recentf-list))) 930 (let ((count (length recentf-list)))
931 (setq recentf-list 931 (setq recentf-list
932 (delq nil 932 (delq nil
933 (mapcar (function 933 (mapcar (function
934 (lambda (filename) 934 (lambda (filename)
935 (and (file-readable-p filename) 935 (and (file-readable-p filename)
936 (recentf-include-p filename) 936 (recentf-include-p filename)
937 filename))) 937 filename)))
938 recentf-list))) 938 recentf-list)))
939 (setq count (- count (length recentf-list))) 939 (setq count (- count (length recentf-list)))
940 (message "%s removed from the list" 940 (message "%s removed from the list"
941 (cond ((= count 0) "No file") 941 (cond ((= count 0) "No file")
942 ((= count 1) "One file") 942 ((= count 1) "One file")
943 (t (format "%d files" count))))) 943 (t (format "%d files" count)))))
944 (setq recentf-update-menu-p t)) 944 (setq recentf-update-menu-p t))
945 945
946(defun recentf-open-files-action (widget &rest ignore) 946(defun recentf-open-files-action (widget &rest ignore)
947 "Button widget action used by `recentf-open-files' to open a file." 947 "Button widget action used by `recentf-open-files' to open a file."
948 (kill-buffer (current-buffer)) 948 (kill-buffer (current-buffer))
949 (funcall recentf-menu-action (widget-value widget))) 949 (funcall recentf-menu-action (widget-value widget)))
950 950
951(defvar recentf-open-files-item-shift "" 951(defvar recentf-open-files-item-shift ""
952 "String used by `recentf-open-files' to shift right sub-menu 952 "String used by `recentf-open-files' to shift right sub-menu
953items.") 953items.")
954 954
955(defun recentf-open-files-item (menu-element) 955(defun recentf-open-files-item (menu-element)
956 "Function called by `recentf-open-files' to insert a menu-element 956 "Function called by `recentf-open-files' to insert a menu-element
957item in the current interaction buffer." 957item in the current interaction buffer."
958 (let ((menu-item (car menu-element)) 958 (let ((menu-item (car menu-element))
959 (file-path (cdr menu-element))) 959 (file-path (cdr menu-element)))
960 (if (consp file-path) ; This is a sub-menu 960 (if (consp file-path) ; This is a sub-menu
961 (let* ((shift recentf-open-files-item-shift) 961 (let* ((shift recentf-open-files-item-shift)
962 (recentf-open-files-item-shift (concat shift " "))) 962 (recentf-open-files-item-shift (concat shift " ")))
963 (widget-create 'item 963 (widget-create 'item
964 :tag menu-item 964 :tag menu-item
965 :sample-face 'bold 965 :sample-face 'bold
966 :format (concat shift "%{%t%}:\n")) 966 :format (concat shift "%{%t%}:\n"))
967 (mapcar 'recentf-open-files-item 967 (mapcar 'recentf-open-files-item
968 file-path) 968 file-path)
969 (widget-insert "\n")) 969 (widget-insert "\n"))
970 (widget-create 'push-button 970 (widget-create 'push-button
971 :button-face 'default 971 :button-face 'default
972 :tag menu-item 972 :tag menu-item
973 :help-echo (concat "Open " file-path) 973 :help-echo (concat "Open " file-path)
974 :format (concat recentf-open-files-item-shift "%[%t%]") 974 :format (concat recentf-open-files-item-shift "%[%t%]")
975 :notify 'recentf-open-files-action 975 :notify 'recentf-open-files-action
976 file-path) 976 file-path)
977 (widget-insert "\n")))) 977 (widget-insert "\n"))))
978 978
979;;;###autoload 979;;;###autoload
980(defun recentf-open-files (&optional files buffer-name) 980(defun recentf-open-files (&optional files buffer-name)
981 "Open a buffer that allows the user to choose a file to open from 981 "Open a buffer that allows the user to choose a file to open from
982the list of recently opened files. The optional argument FILES may be 982the list of recently opened files. The optional argument FILES may be
983used to specify the list, otherwise recentf-list is used. The optional 983used to specify the list, otherwise recentf-list is used. The optional
984argument BUFFER-NAME specifies which buffer to use for the interaction." 984argument BUFFER-NAME specifies which buffer to use for the interaction."
985 (interactive) 985 (interactive)
986 (if (null files) 986 (if (null files)
987 (setq files recentf-list)) 987 (setq files recentf-list))
988 (if (null buffer-name) 988 (if (null buffer-name)
989 (setq buffer-name (concat "*" recentf-menu-title "*"))) 989 (setq buffer-name (concat "*" recentf-menu-title "*")))
990 (with-current-buffer (get-buffer-create buffer-name) 990 (with-current-buffer (get-buffer-create buffer-name)
991 (switch-to-buffer (current-buffer)) 991 (switch-to-buffer (current-buffer))
992 (kill-all-local-variables) 992 (kill-all-local-variables)
993 (let ((inhibit-read-only t)) 993 (let ((inhibit-read-only t))
994 (erase-buffer)) 994 (erase-buffer))
995 (let ((all (overlay-lists))) 995 (let ((all (overlay-lists)))
996 ;; Delete all the overlays. 996 ;; Delete all the overlays.
997 (mapcar 'delete-overlay (car all)) 997 (mapcar 'delete-overlay (car all))
998 (mapcar 'delete-overlay (cdr all))) 998 (mapcar 'delete-overlay (cdr all)))
999 ;; Insert the dialog header 999 ;; Insert the dialog header
1000 (widget-insert "Click on a file to open it. ") 1000 (widget-insert "Click on a file to open it. ")
1001 (widget-insert "Click on Cancel or type \"q\" to quit.\n\n" ) 1001 (widget-insert "Click on Cancel or type \"q\" to quit.\n\n" )
1002 ;; Insert the list of files as buttons 1002 ;; Insert the list of files as buttons
1003 (let ((recentf-open-files-item-shift "")) 1003 (let ((recentf-open-files-item-shift ""))
1004 (mapcar 'recentf-open-files-item 1004 (mapcar 'recentf-open-files-item
1005 (recentf-apply-menu-filter 1005 (recentf-apply-menu-filter
1006 recentf-menu-filter 1006 recentf-menu-filter
1007 (mapcar 'recentf-make-default-menu-element files)))) 1007 (mapcar 'recentf-make-default-menu-element files))))
1008 (widget-insert "\n") 1008 (widget-insert "\n")
1009 ;; Insert the Cancel button 1009 ;; Insert the Cancel button
1010 (widget-create 'push-button 1010 (widget-create 'push-button
1011 :notify 'recentf-cancel-dialog 1011 :notify 'recentf-cancel-dialog
1012 "Cancel") 1012 "Cancel")
1013 (recentf-dialog-mode) 1013 (recentf-dialog-mode)
1014 (widget-setup) 1014 (widget-setup)
1015 (goto-char (point-min)))) 1015 (goto-char (point-min))))
1016 1016
1017;;;###autoload 1017;;;###autoload
1018(defun recentf-open-more-files () 1018(defun recentf-open-more-files ()
1019 "Allow the user to open files that are not in the menu." 1019 "Allow the user to open files that are not in the menu."
1020 (interactive) 1020 (interactive)
1021 (recentf-open-files (nthcdr recentf-max-menu-items recentf-list) 1021 (recentf-open-files (nthcdr recentf-max-menu-items recentf-list)
1022 (concat "*" recentf-menu-title " - More*"))) 1022 (concat "*" recentf-menu-title " - More*")))
1023 1023
1024;;;###autoload 1024;;;###autoload
1025(defun recentf-mode (&optional arg) 1025(defun recentf-mode (&optional arg)
1026 "Toggle recentf mode. 1026 "Toggle recentf mode.
1027With prefix ARG, turn recentf mode on if and only if ARG is positive. 1027With prefix ARG, turn recentf mode on if and only if ARG is positive.
1028Returns the new status of recentf mode (non-nil means on). 1028Returns the new status of recentf mode (non-nil means on).
1029 1029
1030When recentf mode is enabled, it maintains a menu for visiting files that 1030When recentf mode is enabled, it maintains a menu for visiting files that
1031were operated on recently." 1031were operated on recently."
1032 (interactive "P") 1032 (interactive "P")
1033 (let ((on-p (if arg 1033 (let ((on-p (if arg
1034 (> (prefix-numeric-value arg) 0) 1034 (> (prefix-numeric-value arg) 0)
1035 (not recentf-mode)))) 1035 (not recentf-mode))))
1036 (if on-p 1036 (if on-p
1037 (unless recentf-initialized-p 1037 (unless recentf-initialized-p
1038 (setq recentf-initialized-p t) 1038 (setq recentf-initialized-p t)
1039 (if (file-readable-p recentf-save-file) 1039 (if (file-readable-p recentf-save-file)
1040 (load-file recentf-save-file)) 1040 (load-file recentf-save-file))
1041 (setq recentf-update-menu-p t) 1041 (setq recentf-update-menu-p t)
1042 (add-hook 'find-file-hooks 'recentf-add-file-hook) 1042 (add-hook 'find-file-hooks 'recentf-add-file-hook)
1043 (add-hook 'write-file-hooks 'recentf-add-file-hook) 1043 (add-hook 'write-file-hooks 'recentf-add-file-hook)
1044 (add-hook 'menu-bar-update-hook 'recentf-update-menu-hook) 1044 (add-hook 'menu-bar-update-hook 'recentf-update-menu-hook)
1045 (add-hook 'kill-emacs-hook 'recentf-save-list)) 1045 (add-hook 'kill-emacs-hook 'recentf-save-list))
1046 (when recentf-initialized-p 1046 (when recentf-initialized-p
1047 (setq recentf-initialized-p nil) 1047 (setq recentf-initialized-p nil)
1048 (recentf-save-list) 1048 (recentf-save-list)
1049 (easy-menu-remove-item nil recentf-menu-path recentf-menu-title) 1049 (easy-menu-remove-item nil recentf-menu-path recentf-menu-title)
1050 (remove-hook 'find-file-hooks 'recentf-add-file-hook) 1050 (remove-hook 'find-file-hooks 'recentf-add-file-hook)
1051 (remove-hook 'write-file-hooks 'recentf-add-file-hook) 1051 (remove-hook 'write-file-hooks 'recentf-add-file-hook)
1052 (remove-hook 'menu-bar-update-hook 'recentf-update-menu-hook) 1052 (remove-hook 'menu-bar-update-hook 'recentf-update-menu-hook)
1053 (remove-hook 'kill-emacs-hook 'recentf-save-list))) 1053 (remove-hook 'kill-emacs-hook 'recentf-save-list)))
1054 (setq recentf-mode on-p))) 1054 (setq recentf-mode on-p)))
1055 1055
1056(provide 'recentf) 1056(provide 'recentf)
1057 1057
1058(run-hooks 'recentf-load-hook) 1058(run-hooks 'recentf-load-hook)
1059 1059
1060;;; recentf.el ends here. 1060;;; recentf.el ends here.