comparison lisp/packages/recent-files.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 131b0175ea99
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; recent-files.el --- Maintain menu of recently opened files.
2 ;;; $Header: /afs/informatik.uni-tuebingen.de/local/web/xemacs/xemacs-cvs/XEmacs/xemacs-19/lisp/packages/recent-files.el,v 1.1.1.1 1996/12/18 03:31:56 steve Exp $
3 ;;;
4 ;;; Copyright (C) 1994, 1995 Juergen Nickelsen <nickel@cs.tu-berlin.de>
5 ;;;
6 ;; Keywords: menu, file
7
8 ;; This file is part of XEmacs.
9
10 ;; XEmacs is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; XEmacs is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;; General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with XEmacs; see the file COPYING. If not, write to the Free
22 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 ;;; Synched up with: Not in FSF.
25 ;;;
26 ;;; recent-files.el is free software; you can redistribute it and/or
27 ;;; modify it under the terms of the GNU General Public License as
28 ;;; published by the Free Software Foundation; either version 2, or
29 ;;; (at your option) any later version.
30 ;;;
31 ;;; It is distributed in the hope that it will be useful, but WITHOUT
32 ;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
33 ;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
34 ;;; License for more details.
35 ;;;
36 ;;; You should have received a copy of the GNU General Public License
37 ;;; along with XEmacs; see the file COPYING. If not, write to the
38 ;;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
39 ;;; ------------------------------------------------------------------
40 ;;;
41 ;;; Enough of this boring stuff. To install recent-files, put the
42 ;;; following statements into your .emacs file
43 ;;; (load "recent-files")
44 ;;; (recent-files-initialize)
45 ;;; and place the file recent-files.el in a directory in your XEmacs's
46 ;;; load-path. In order to use recent-files with dired, dired has to
47 ;;; be loaded first. recent-files is known to work with Lucid Emacs /
48 ;;; XEmacs 19.8 and higher; it does not work correctly with 19.6 or
49 ;;; earlier versions due to a bug in add-menu.
50 ;;;
51 ;;; recent-files adds the menu "Recent Files" (or whatever name you
52 ;;; choose, see "Customization:" below) to Emacs's menubar. Its
53 ;;; entries are the files (and directories) that have recently been
54 ;;; opened by Emacs. You can open one of these files again by
55 ;;; selecting its entry in the "Recent Files" menu. The list of file
56 ;;; entries in this menu is preserved from one Emacs session to
57 ;;; another. You can prevent Emacs from saving this list by selecting
58 ;;; "Don't save recent-files list on exit" from the menu. If you have
59 ;;; disabled saving, you can re-enable it by selecting "Save
60 ;;; recent-files list on exit".
61 ;;;
62 ;;; The menu has permanent and non-permanent entries. Permanent
63 ;;; entries are marked with an asterisk in front of the filename. The
64 ;;; non-permanent entries are hidden in a submenu.
65 ;;;
66 ;;; Each time you open a file in Emacs, it is added as a non-permanent
67 ;;; entry to the menu. The value of `recent-files-number-of-entries'
68 ;;; determines how many non-permanent entries are held in the
69 ;;; menu. When the number of non-permanent entries reaches this value,
70 ;;; the least recently added non-permanent entry is removed from the
71 ;;; menu when another non-permanent entry is added. It is not removed
72 ;;; from the list, though; it may reappear when entries are deleted
73 ;;; from the list. The number of entries saved to disk is the value of
74 ;;; the variable `recent-files-number-of-saved-entries'.
75 ;;;
76 ;;; Permanent entries are not removed from the menu. You can make a
77 ;;; file entry permanent by selecting "Make <buffer> permanent" (where
78 ;;; <buffer> is the name of the current buffer) when the current
79 ;;; buffer holds this file. "Make <buffer> non-permanent" makes the
80 ;;; file entry of the current buffer non-permanent.
81 ;;;
82 ;;; The command "Kill buffer <buffer> and delete entry" is handy when
83 ;;; you have accidently opened a file but want to keep neither the
84 ;;; buffer nor the entry.
85 ;;;
86 ;;; You can erase the list of non-permanent entries by selecting
87 ;;; "Erase non-permanent entries" from the menu.
88 ;;;
89 ;;; Customization:
90 ;;;
91 ;;; There are lots of variables to control the behaviour of
92 ;;; recent-files. You do not have to change any of them if you like it
93 ;;; as it comes out of the box. However, you may want to look at these
94 ;;; options to make it behave different.
95 ;;;
96 ;;; `recent-files-number-of-entries'
97 ;;; Controls how many non-permanent entries are shown in the
98 ;;; recent-files list. The default is 15.
99 ;;;
100 ;;; `recent-files-number-of-saved-entries'
101 ;;; Controls how many non-permanent entries are saved to disk when
102 ;;; Emacs exits or recent-files-save-the-list is called. The
103 ;;; default is 50.
104 ;;;
105 ;;; `recent-files-save-file'
106 ;;; The name of the file where the recent-files list is saved
107 ;;; between Emacs session. You probably don't need to change this.
108 ;;; The default is ".recent-files.el" in your home directory.
109 ;;;
110 ;;; `recent-files-dont-include'
111 ;;; A list of regular expressions for files that should not be
112 ;;; included into the recent-files list. This list is empty by
113 ;;; default. For instance, a list to exclude all .newsrc
114 ;;; files, all auto-save-files, and all files in the /tmp
115 ;;; directory (but not the /tmp directory itself) would look
116 ;;; like this:
117 ;;; (setq recent-files-dont-include
118 ;;; '("/\\.newsrc" "~$" "^/tmp/."))
119 ;;; The default is empty.
120 ;;;
121 ;;; `recent-files-use-full-names'
122 ;;; If the value of this variable is non-nil, the full pathnames of
123 ;;; the files are shown in the recent-files menu. Otherwise only
124 ;;; the filename part (or the last name component if it is a
125 ;;; directory) is shown in the menu. The default it t, i.e. show
126 ;;; full names.
127 ;;;
128 ;;; `recent-files-filename-replacements'
129 ;;; This is a list of pairs of regular expressions and replacement
130 ;;; strings. If a filename matches one of the regular expressions,
131 ;;; the matching part is replaced by the replacement string for
132 ;;; display in the recent-files menu.
133 ;;; Example: My home directory is "/users/mmc/nickel/". I want to
134 ;;; replace it with "~/". I also want to replace the directory
135 ;;; "/imports/teleservices/mmc/avc2/", where I work a lot, with
136 ;;; ".../avc2/". The list then looks like
137 ;;; (setq recent-files-filename-replacements
138 ;;; '(("/users/mmc/nickel/" . "~/")
139 ;;; ("/imports/teleservices/mmc/avc2/" . ".../avc2/")))
140 ;;; Only the first match is replaced. So, if you have several
141 ;;; entries in this list that may match a filename simultaneously,
142 ;;; put the one you want to match (usually the most special) in
143 ;;; front of the others. The default is to replace the home
144 ;;; directory with "~".
145 ;;;
146 ;;; `recent-files-sort-function'
147 ;;; Contains a function symbol to sort the display of filenames in
148 ;;; the recent-files menu. Supplied are two functions,
149 ;;; 'recent-files-dont-sort and 'recent-files-sort-alphabetically.
150 ;;; The first, which is the default, preserves the order of "most
151 ;;; recent on top".
152 ;;;
153 ;;; `recent-files-permanent-submenu'
154 ;;; If this variable is non-nil, the permanent entries are put into
155 ;;; a separate submenu of the recent-files menu. The default is
156 ;;; nil.
157 ;;;
158 ;;; `recent-files-non-permanent-submenu'
159 ;;; If this variable is non-nil, the non-permanent entries are put
160 ;;; into a separate submenu of the recent-files menu. The default
161 ;;; is nil. (You can set both `recent-files-permanent-submenu' and
162 ;;; `recent-files-non-permanent-submenu' to t to have both lists in
163 ;;; separate submenus.)
164 ;;;
165 ;;; `recent-files-commands-submenu'
166 ;;; If this variable is non-nil, the commands if recent-files are
167 ;;; placed in a submenu of the recent-files menu. The default is
168 ;;; nil.
169 ;;;
170 ;;; `recent-files-commands-submenu-title'
171 ;;; If the commands are placed in a submenu, this string is used as
172 ;;; the title of the submenu. The default is "Commands...".
173 ;;;
174 ;;; `recent-files-actions-on-top'
175 ;;; If this variable is non-nil, the "action" menu entries ("Make
176 ;;; <buffer> permanent" etc.) are put on top of the menu. Otherwise
177 ;;; they appear below the file entries or submenus. The default is
178 ;;; nil.
179 ;;;
180 ;;; `recent-files-permanent-first'
181 ;;; If this variable is t, the permanent entries are put first in
182 ;;; the recent-files menu, i.e. above the non-permanent entries. If
183 ;;; the value is nil, non-permanent entries appear first. If the
184 ;;; value is neither t nor nil, the entries are sorted according to
185 ;;; recent-files-sort-function. The default is 'sort.
186 ;;;
187 ;;; `recent-files-find-file-command'
188 ;;; This variable contains to commandto execute when a file entry
189 ;;; is selected from the menu. Usually this will be `find-file',
190 ;;; which is the default.
191 ;;;
192 ;;; KNOWN BUG:
193 ;;; - recent-files overwrites the recent-files-save-file
194 ;;; unconditionally when Emacs exits. If you have two Emacs
195 ;;; processes running, the one exiting later will overwrite the
196 ;;; file without merging in the new entries from the other Emacs
197 ;;; process. This can be avoided by disabling the save on exit from
198 ;;; the menu.
199
200 (if (not (string-match "XEmacs" (emacs-version)))
201 (error "recent-files works with Lucid Emacs / XEmacs only."))
202
203 (provide 'recent-files)
204
205
206 ;;; User options
207
208 (defvar recent-files-number-of-entries 15
209 "*Maximum of non-permanent entries in the recent-files menu.")
210
211 (defvar recent-files-number-of-saved-entries 50
212 "*Maximum of non-permanent entries saved to `recent-files-save-file'.")
213
214 (defvar recent-files-save-file (expand-file-name "~/.recent-files.el")
215 "*File to save the recent-files list in.")
216
217 (defvar recent-files-dont-include nil
218 "*List of regexps for filenames *not* to keep in recent-files.")
219
220 (defvar recent-files-use-full-names t
221 "*If non-nil, use the full pathname of a file in the recent-files menu.
222 Otherwise use only the filename part. The `recent-files-filename-replacements'
223 are not applied in the latter case.")
224
225 (defvar recent-files-filename-replacements
226 (list (cons (expand-file-name "~") "~"))
227 "*List of regexp/replacement pairs for filename filenamees.
228 If a filename of a filename matches one of the regexps, it is replaced
229 by the corresponding replacement.")
230
231 (defvar recent-files-sort-function (function recent-files-dont-sort)
232 "*Function to sort the recent-files list with.
233 The value `recent-files-dont-sort' means to keep the \"most recent on top\"
234 order.")
235
236 (defvar recent-files-permanent-submenu nil
237 "*If non-nil, put the permanent entries of recent-files into a submenu.")
238
239 (defvar recent-files-non-permanent-submenu t
240 "*If non-nil, put the non-permanent entries of recent-files into a submenu.")
241
242 (defvar recent-files-commands-submenu nil
243 "*If non-nil, put the commands of recent-files into a submenu.")
244
245 (defvar recent-files-commands-submenu-title "Commands..."
246 "*Title of the commands submenu of recent-files.")
247
248 (defvar recent-files-menu-title "Recent Files"
249 "*Name to be displayed as title of the recent-files menu.")
250
251 (defvar recent-files-menu-path nil
252 "*Path where to add the recent-files menu.
253 A value of nil means add it as top-level menu.
254 For more information look up the documentation of `add-menu'.")
255
256 (defvar recent-files-add-menu-before nil
257 "*Name of the menu before which the recent-files menu shall be added.
258 A value of nil means add it as the last menu in recent-files-menu-path.
259 For more information look up the documentation of `add-menu'.")
260
261 (defvar recent-files-actions-on-top nil
262 "*If non-nil, put the actions on top of the recent-files menu.")
263
264 (defvar recent-files-permanent-first 'sort
265 "*Control the placement of entries in the recent-files menu.
266 If the value is t, permanent entries are put first.
267 If the value is nil, non-permanent entries are put first.
268 If the value is neither, the entries are mixed following
269 recent-files-sort-function if neither appear in a submenu.")
270
271 (defvar recent-files-find-file-command (function find-file)
272 "*Command to invoke with an entry of the recent-files list.")
273
274 (defvar recent-files-include-save-now nil
275 "*If non-nil, have a menu entry to save the recent-files list immediately.")
276
277 ;;; Internal variables
278
279 (defconst recent-files-save-list-on-exit t
280 "If non-nil, save the recent-files list on exit.
281 This value is toggled by a menu entry.")
282
283 (defvar recent-files-list nil
284 "List of recently opened files.
285 Entries are pairs like (<filename> . <permant-p>).
286 If <permanent-p> is non-nil, the file stays permanently in the list.")
287
288 (defvar recent-files-commands-menu
289 '(list (vector (concat "Make " lastpart " permanent")
290 (function recent-files-make-permanent)
291 (and lastpart
292 (not (recent-files-permanent-p filename))
293 ;; (not (not ...)) is needed to enforce t for non-nil
294 (not (not (recent-files-retrieve-entry filename)))))
295 (vector (concat "Make " lastpart " non-permanent")
296 (function recent-files-make-non-permanent)
297 (and lastpart
298 (recent-files-permanent-p filename)
299 (not (not (recent-files-retrieve-entry filename)))))
300 (vector "Erase non-permanent entries"
301 (function recent-files-erase-non-permanent)
302 t)
303 (vector (if recent-files-save-list-on-exit
304 "Don't save recent-files list on exit"
305 "Save recent-files list on exit")
306 ;; for some weird reason a (function (lambda ...))
307 ;; doesn't work here
308 (function recent-files-toggle-save-list-on-exit)
309 t)
310 (vector "Save recent-files list now"
311 (function recent-files-save-the-list)
312 t)
313 (vector (concat "Kill buffer " lastpart
314 " and delete entry")
315 (function recent-files-kill-buffer-delete-entry)
316 lastpart))
317 "Command menu definition for recent-files.
318 This definition is evaluated in a context where `filename' holds the file
319 name of the current buffer and `lastpart' holds the last component of
320 `filename'.")
321
322
323 (defconst recent-files-save-file-header
324 ";; This file is generated by recent-files.
325 ;; The car of each entry of recent-files-save-list is to appear in the
326 ;; `recent-files' menu. If the cdr of an entry is t, the file is to stay
327 ;; in the menu permanently.
328 ;; Saved at %s.
329
330 " "Header to be written into the `recent-files-save-file'.")
331
332
333 (defconst recent-files-buffer-name " *recent files save list*"
334 "Name of the buffer to build the save file in.")
335
336 (defvar recent-files-list-changed-p t
337 "Non-nil if the recent-files-list has changed after last menubar update.")
338
339 (defvar recent-files-last-buffer nil
340 "Buffer at the time of last recent-files menu rebuild.
341 If the buffer has changed, the menu must be rebuilt.")
342
343 ;;; Module initialization
344
345 (defun recent-files-initialize ()
346 "Initialize the recent-files menu."
347 (interactive)
348 (add-hook 'find-file-hooks (function recent-files-find-and-write-file-hook))
349 (add-hook 'dired-after-readin-hook
350 (function recent-files-find-and-write-file-hook))
351 (add-hook 'kill-emacs-hook (function recent-files-save-the-list))
352 (add-hook 'activate-menubar-hook (function recent-files-update-menu))
353 (add-hook 'write-file-hooks (function recent-files-find-and-write-file-hook))
354 ;; Initialize recent-files-list only if it is non-nil.
355 (cond (recent-files-list
356 (message "recent-files is already initialized."))
357 ((file-readable-p recent-files-save-file)
358 (setq recent-files-list-changed-p t)
359 (load-file recent-files-save-file)))
360 (recent-files-update-menu))
361
362
363 (defun recent-files-version ()
364 "Return a string identifying the current verion of recent-files.
365 If called interactively, show it in the echo area."
366 (interactive)
367 (let ((version "$Header: /afs/informatik.uni-tuebingen.de/local/web/xemacs/xemacs-cvs/XEmacs/xemacs-19/lisp/packages/recent-files.el,v 1.1.1.1 1996/12/18 03:31:56 steve Exp $"))
368 (if (interactive-p)
369 (message version)
370 version)))
371
372
373 ;;; Hook functions
374
375 (defun recent-files-find-and-write-file-hook ()
376 "Find-file-hook, write-file-hook, and dired-mode-hook for recent-files.
377 Inserts the name of the file just opened or written into the
378 `recent-files-list' and updates the recent-files menu."
379 (recent-files-add-file (recent-files-get-file-name))
380 nil)
381
382
383 (defun recent-files-get-file-name ()
384 "Return the filename of the current buffer or nil, if there is none.
385 This functions is supposed to do \"the right thing\" also for some modes
386 with no buffer-file-name. Currently supported: 'dired-mode."
387 (cond (buffer-file-name
388 buffer-file-name)
389 ((eq major-mode 'dired-mode)
390 (dired-current-directory))))
391
392
393 (defun recent-files-save-the-list ()
394 "Save the current `recent-files-list' to the file `recent-files-save-file'.
395 This is done by writing a `setq' statement to `recent-files-list' into
396 the file."
397 (interactive)
398 (if recent-files-save-list-on-exit
399 (let ((l (recent-files-enforce-max-length
400 recent-files-number-of-saved-entries
401 recent-files-list)))
402 (save-excursion
403 (set-buffer (get-buffer-create recent-files-buffer-name))
404 (erase-buffer)
405 (insert (format recent-files-save-file-header (current-time-string)))
406 (insert "(setq recent-files-list \n '(")
407 (if l
408 (progn
409 (while l
410 (if (bolp)
411 (insert " "))
412 (prin1 (car l) (current-buffer))
413 (insert "\n")
414 (setq l (cdr l)))
415 (forward-line -1)))
416 (end-of-line)
417 (insert "))")
418 (if (file-writable-p recent-files-save-file)
419 (write-region (point-min) (point-max) recent-files-save-file))
420 (kill-buffer (current-buffer))))))
421
422
423 ;;; Construct the menu
424
425 (defun recent-files-update-menu ()
426 "Update the recent-files menu from the recent-files-list."
427 (if (or recent-files-list-changed-p
428 (not recent-files-last-buffer)
429 (not (eq recent-files-last-buffer
430 (current-buffer))))
431 ;; This is an ugly mess...
432 (let ((action-menu-entries
433 (let ((entries
434 (let* ((filename (recent-files-get-file-name))
435 (lastpart (recent-files-last-part-of-name
436 filename)))
437 (eval recent-files-commands-menu))))
438 (if recent-files-commands-submenu
439 (list (cons recent-files-commands-submenu-title
440 entries))
441 entries)))
442 permanent non-permanent all)
443 ;; ... getting weirder by the minute ...
444 (if (or recent-files-permanent-submenu
445 recent-files-non-permanent-submenu
446 (null recent-files-permanent-first)
447 (eq t recent-files-permanent-first))
448 (progn
449 (setq permanent (recent-files-make-file-menu-entries
450 recent-files-list
451 (function recent-files-filter-permanent)))
452 (setq non-permanent (recent-files-make-file-menu-entries
453 recent-files-list
454 (function
455 recent-files-filter-non-permanent))))
456 (setq all (recent-files-make-file-menu-entries
457 recent-files-list
458 (function (lambda (l) l)))))
459 (if recent-files-permanent-submenu
460 (setq permanent (list (cons "Permanent entries..." permanent))))
461 (if recent-files-non-permanent-submenu
462 (setq non-permanent (list (cons "Non-permanent entries..."
463 non-permanent))))
464 ;;; ... and now even uglier.
465 (add-menu recent-files-menu-path recent-files-menu-title
466 (nconc
467 (if recent-files-actions-on-top
468 (append action-menu-entries (list "-----")))
469 (if (or recent-files-permanent-submenu
470 recent-files-non-permanent-submenu)
471 (if recent-files-permanent-first
472 (nconc permanent non-permanent)
473 (nconc non-permanent permanent))
474 (cond ((eq t recent-files-permanent-first)
475 (nconc permanent non-permanent))
476 ((null recent-files-permanent-first)
477 (nconc non-permanent permanent))
478 (t all)))
479 (if (not recent-files-actions-on-top)
480 (cons "-----"
481 action-menu-entries)))
482 recent-files-add-menu-before)
483 (setq recent-files-list-changed-p nil)
484 (setq recent-files-last-buffer (current-buffer))))
485 nil)
486
487
488 (defun recent-files-retrieve-entry (filename)
489 "Retrieve an entry from the recent-files list."
490 (assoc filename recent-files-list))
491
492
493 (defun recent-files-make-file-menu-entries (recent-list filter)
494 "Make file menu entries for recent-files from RECENT-LIST using FILTER."
495 (mapcar (function recent-files-entry-to-menu-entry)
496 (funcall filter
497 (funcall recent-files-sort-function
498 (recent-files-enforce-max-length
499 recent-files-number-of-entries
500 recent-list)))))
501
502
503 (defun recent-files-last-part-of-name (filename)
504 "Return last part of FILENAME."
505 (if filename
506 (if (and (file-directory-p filename)
507 (equal (substring filename -1) "/"))
508 (concat (file-name-nondirectory
509 (substring filename 0 -1))
510 "/")
511 (file-name-nondirectory filename))))
512
513
514 (defun recent-files-filter-permanent (recent-list)
515 "Return list of permanent entries in RECENT-LIST."
516 (cond ((null recent-list) nil)
517 ((recent-files-permanent-p (car (car recent-list)))
518 (cons (car recent-list)
519 (recent-files-filter-permanent (cdr recent-list))))
520 (t (recent-files-filter-permanent (cdr recent-list)))))
521
522
523 (defun recent-files-filter-non-permanent (recent-list)
524 "Return list of non-permanent entries in RECENT-LIST."
525 (cond ((null recent-list) nil)
526 ((recent-files-permanent-p (car (car recent-list)))
527 (recent-files-filter-non-permanent (cdr recent-list)))
528 (t (cons (car recent-list)
529 (recent-files-filter-non-permanent (cdr recent-list))))))
530
531
532 (defun recent-files-permanent-p (filename)
533 "Return non-nil if FILENAME is a permanent entry in the recent-files menu."
534 (cdr (recent-files-retrieve-entry filename)))
535
536
537 (defun recent-files-entry-to-menu-entry (entry)
538 "Build a menu entry from an entry in `recent-files-list'."
539 (vector (concat (if (cdr entry)
540 "* "
541 " ")
542 (if recent-files-use-full-names
543 (recent-files-replace-filenames (car entry))
544 (recent-files-last-part-of-name (car entry))))
545 (list recent-files-find-file-command (car entry))
546 t))
547
548
549 (defun recent-files-replace-filenames (filename)
550 "Replace the part of FILENAME that matches a regular expression
551 in recent-files-filename-replacements with the corrensponding replacement.
552 If FILENAME does not match any regular expression, return it unchanged.
553 Only the first matching regexp/replacement pair is applied."
554 (let ((replist recent-files-filename-replacements)
555 (retval filename)
556 (matched nil))
557 (while (and replist
558 (not matched))
559 (if (string-match (car (car replist)) filename)
560 (progn
561 (setq matched t)
562 (setq retval (concat (substring filename 0 (match-beginning 0))
563 (cdr (car replist))
564 (substring filename (match-end 0))))))
565 (setq replist (cdr replist)))
566 retval))
567
568
569 ;;; add a new entry
570
571 (defun recent-files-add-file (filename)
572 "Add file FILENAME to `recent-files-list'.
573 FILENAME is not really added if it matches one of the regexps in
574 `recent-files-dont-include'."
575 (if (recent-files-no-match filename recent-files-dont-include)
576 (progn
577 (setq recent-files-list-changed-p t)
578 (setq recent-files-list
579 (cons (or (recent-files-retrieve-entry filename)
580 (cons filename nil))
581 (recent-files-remove-entry filename
582 recent-files-list))))))
583
584
585 (defun recent-files-dont-sort (recent-list)
586 "Return RECENT-LIST.
587 This is a dummy sorting function for the recent-files-list."
588 recent-list)
589
590 (defun recent-files-sort-alphabetically (recent-list)
591 "Return RECENT-LIST sorted alphabetically by the cars of the elements."
592 (sort recent-list (function
593 (lambda (e1 e2)
594 (string-lessp (car e1) (car e2))))))
595
596
597 (defun recent-files-enforce-max-length (n l)
598 "Return a list of all permanent and the first N non-permanent entries of L.
599 Preserve the order of the entries."
600 (let ((count 0)
601 (newlist nil))
602 (while l
603 (if (cdr (car l))
604 (setq newlist (cons (car l) newlist))
605 (if (< count n)
606 (setq newlist (cons (car l) newlist)))
607 (setq count (1+ count)))
608 (setq l (cdr l)))
609 (nreverse newlist)))
610
611
612 (defun recent-files-remove-entry (fname recent-list)
613 "Delete all elements that have FNAME as a car from RECENT-LIST.
614 The constructed list returned, RECENT-LIST is not changed.
615 Comparison is done with equal."
616 (let ((newlist nil))
617 (while recent-list
618 (if (not (equal (car (car recent-list)) fname))
619 (setq newlist (cons (car recent-list) newlist)))
620 (setq recent-list (cdr recent-list)))
621 (nreverse newlist)))
622
623 (defun recent-files-no-match (string re-list)
624 "Return t if STRING matches none of the regexps in RE-LIST."
625 (while (and re-list
626 (not (string-match (car re-list) string)))
627 (setq re-list (cdr re-list)))
628 (null re-list))
629
630
631 ;;; Menu commands
632
633 (defun recent-files-make-permanent ()
634 "Make the file in current buffer a permanent entry in recent-files."
635 (interactive)
636 (rplacd (recent-files-retrieve-entry (recent-files-get-file-name)) t)
637 (setq recent-files-list-changed-p t))
638
639
640 (defun recent-files-make-non-permanent ()
641 "Make the file in current buffer a non-permanent entry in recent-files."
642 (interactive)
643 (rplacd (recent-files-retrieve-entry (recent-files-get-file-name)) nil)
644 (setq recent-files-list-changed-p t))
645
646
647 (defun recent-files-kill-buffer-delete-entry ()
648 "Kill the current buffer and delete its entry in the recent-files menu."
649 (interactive)
650 (setq recent-files-list
651 (recent-files-remove-entry (recent-files-get-file-name)
652 recent-files-list))
653 (setq recent-files-list-changed-p t)
654 (kill-buffer (current-buffer)))
655
656 (defun recent-files-erase-non-permanent ()
657 "Erase all non-permanent entries from the recent-files menu."
658 (interactive)
659 (setq recent-files-list
660 (recent-files-filter-permanent recent-files-list))
661 (setq recent-files-list-changed-p t))
662
663 (defun recent-files-toggle-save-list-on-exit ()
664 "Toggle the value of `recent-files-save-list-on-exit'."
665 (interactive)
666 (setq recent-files-save-list-on-exit (not recent-files-save-list-on-exit))
667 (setq recent-files-list-changed-p t))
668
669 ;;; EOF