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