Recentf is a minor mode that builds a list of recently opened files. This list is is automatically saved across Emacs sessions. You can then access this list through a menu.
This mode is part of GNU Emacs 21. Or you can download it here:
To enable ‘recentf-mode’, put this in your `~/.emacs’:
(require 'recentf)
(recentf-mode 1)
(setq recentf-max-menu-items 25)
(global-set-key "\C-x\ \C-r" 'recentf-open-files)Recentf lets you structure its menus in various ways, using what it calls filters. This section describes ways to take advantage of that menu organization at the keyboard, with completion.
You can take advantage of recentf filters (that is, structured menus) from the keyboard (with completion and so on) by using library LaCarte.
Assuming that you have `ESC ESC x’ (that is, `ESC M-x’) bound to ‘lacarte-execute-menu-command’ (which you should ;-)), just type part of a recent file name (any part, or a regexp), then hit ‘S-TAB’ to complete to matching recent files.
If you use, say, the recentf filter ‘recentf-arrange-by-dir’, then the File > Open Recent menu is organized by directory, and this is reflected in the completion candidates used by ‘lacarte-execute-menu-command’.
2006-03-15, SteveBerman? posted some code to gnu-emacs-sources@gnu.org that takes recentf filters into account in another way. Here is Steve’s commentary, followed by his code. Steve: Why don’t you upload this as an Emacs-Lisp library? – DrewAdams
recentf.el that I find most useful is the possibility of filtering ‘recentf-list’ and structuring the recent file menu in accordance with the filter. So I wrote some code that makes the filtering and structuring of the recent file menu accessible from the minibuffer, with standard tabbed completion. Here it is. (I find it convenient to globally bind ‘C-c r’ to the command ‘recentf-minibuffer-dialog’.) – SteveBerman?(defun recentf-filtered-list (arg)
"Return a filtered list of ARG recentf items."
(recentf-apply-menu-filter
recentf-menu-filter
(mapcar 'recentf-make-default-menu-element
(butlast recentf-list (- (length recentf-list) arg)))))
(defun recentf-list-submenus (arg)
"Return a list of the recentf submenu names."
(if (listp (cdar (recentf-filtered-list arg))) ; submenues exist
(delq nil (mapcar 'car (recentf-filtered-list arg)))))
(defmacro recentf-list-entries (fn arg)
"Return a list of ARG recentf menu entries as determined by FN.
When FN is `'car' return the menu entry names, when FN is `'cdr'
return the absolute file names."
`(mapcar (lambda (x) (mapcar ,fn x))
(if (recentf-list-submenus ,arg)
(mapcar 'cdr (recentf-filtered-list ,arg))
(list (recentf-filtered-list ,arg)))))
;; This function is not specific to recentf mode but is needed by
;; `recentf-minibuffer-dialog'. I've also made enough use of it in
;; other contexts that I'm surprised it's not part of Emacs, and the
;; fact that it isn't makes me wonder if there's a preferred way of
;; doing what I use this function for.
(defun recentf-memindex (mem l)
"Return the index of MEM in list L."
(let ((mempos -1) ret)
(while (eq ret nil)
(setq mempos (1+ mempos))
(when (equal (car l) mem) (setq ret mempos))
(setq l (cdr l)))
ret))
(defun recentf-minibuffer-dialog (arg)
"Open the recentf menu via the minubuffer, with completion.
With positive prefix ARG, show the ARG most recent items.
Otherwise, show the default maximum number of recent items."
(interactive "P")
(let* ((num (prog1 (if (and (not (null arg))
(> arg 0))
(min arg (length recentf-list))
recentf-max-menu-items)
(and (not (null arg))
(> arg (length recentf-list))
(message "There are only %d recent items."
(length recentf-list))
(sit-for 2))))
(menu (if (recentf-list-submenus num)
(completing-read "Open recent: "
(recentf-list-submenus num))))
(i (recentf-memindex menu (recentf-list-submenus num)))
(items (nth i (recentf-list-entries 'car num)))
(files (nth i (recentf-list-entries 'cdr num)))
(item (completing-read "Open recent: " items))
(j (recentf-memindex item items))
(file (nth j files)))
(funcall recentf-menu-action file))) ; find-file by default
‘recentf-mode’ of vanilla Emacs forces you to open a file using a menu interface. Icicles command ‘icicle-recent-file’ lets you use the usual ‘find-file’ minibuffer interface, with completion and cycling among your recent files. It is also a multi-command, so you can use it to open several recently used files at once.
Here is another version of recent-files completion, which use InteractivelyDoThings (ido). Not perfect, but seems to work ok. You first choose among filenames and if more than one filename matches, you are prompted to choose again among the matching files, but the path is added to the list.
It should work (untested – see UseIswitchBuffer) using the IswitchBuffers package instead, by replacing:
(defun recentf-interactive-complete ()
"find a file in the recently open file using ido for completion"
(interactive)
(let* ((all-files recentf-list)
(file-assoc-list (mapcar (lambda (x) (cons (file-name-nondirectory x) x)) all-files))
(filename-list (remove-duplicates (mapcar 'car file-assoc-list) :test 'string=))
(ido-make-buffer-list-hook
(lambda ()
(setq ido-temp-list filename-list)))
(filename (ido-read-buffer "Find Recent File: "))
(result-list (delq nil (mapcar (lambda (x) (if (string= (car x) filename) (cdr x))) file-assoc-list)))
(result-length (length result-list)))
(find-file
(cond
((= result-length 0) filename)
((= result-length 1) (car result-list))
( t
(let ( (ido-make-buffer-list-hook
(lambda ()
(setq ido-temp-list result-list))))
(ido-read-buffer (format "%d matches:" result-length))))
))))
Or this somewhat simpler version:
(defun recentf-ido-find-file ()
"Find a recent file using Ido."
(interactive)
(let ((file (ido-completing-read "Choose recent file: " recentf-list nil t)))
(when file
(find-file file))))
where file-name-nondirectory could be applied to recentf-list if preferred.
And this is a version with file-name-nondirectory.
(defun recentf-ido-find-file ()
"Find a recent file using Ido."
(interactive)
(let* ((file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
recentf-list))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Choose recent file: "
filename-list
nil
t)))
(when filename
(find-file (cdr (assoc filename
file-assoc-list))))))
This command also provides completion for your recent files. It was written by Jerome B. and first posted in an article for http://www.emacsfr.org/:
(defun recentf-open-files-compl ()
(interactive)
(let* ((all-files recentf-list)
(tocpl (mapcar (function
(lambda (x) (cons (file-name-nondirectory x) x))) all-files))
(prompt (append '("File name: ") tocpl))
(fname (completing-read (car prompt) (cdr prompt) nil nil)))
(find-file (cdr (assoc-ignore-representation fname tocpl))))) Jerome binds it to C-x C-r. (He rarely uses ‘find-file-read-only’.)
(global-set-key "\C-x\C-r" 'recentf-open-files-compl)
Jerome uses this function more often than ‘find-file’.
This function does not work on XEmacs 21.4.14 nor does it work with XEmacs/TrampMode, but it does with the following modifications:
(defun recentf-open-files-compl ()
(interactive)
(let* ((all-files recentf-list)
(tocpl (mapcar (function
(lambda (x) (cons (file-name-nondirectory x) x))) all-files))
(prompt (append '("Recent File name: ") tocpl))
(fname (completing-read (car prompt) (cdr prompt) nil nil)))
(find-file (or (cdr (assoc fname tocpl))
fname))))On modern Emacs, assoc-ignore-representation is deprecated and the lisp style of the functions above is somewhat odd. Here’s a tidier version of the same (excellent) idea:
(defun recentf-open-files-compl ()
(interactive)
(let* ((tocpl (mapcar (lambda (x) (cons (file-name-nondirectory x) x))
recentf-list))
(fname (completing-read "File name: " tocpl nil nil)))
(when fname
(find-file (cdr (assoc-string fname tocpl)))))) See IswitchRecentFiles for using recent files with IswitchB.
Anything is a candidate selection framework.
Start with ‘M-x anything-for-files’, narrow the list (including recent files) by typing some patterns(multiple patterns are space-delimited string), select with up/down/pgup/pgdown/C-p/C-n/C-v/M-v, choose with enter, With TAB actions can be selected if the selected files has more than one possible action. With C-z content of files is displayed without quitting anything session.
When using TrampMode with recentf.el, it’s advisable to turn off the cleanup feature of recentf that attempts to stat all the files and remove them from the recently accessed list if they are readable. Tramp means that this requires recentf to open up a remote site which will block your emacs process at the most inopportune times.
(require 'recentf)
(setq recentf-auto-cleanup 'never) ;; disable before we start recentf!
(recentf-mode 1)I use Gnus in one process, and everything related to plain file editing in another emacs process. My initial load starts recentf-mode but for gnus, I really needed the recentf to use a different history file.
;; use a different set of recent files for gnus ;; cmg@dok.org (setq recentf-save-file (recentf-expand-file-name "~/.recentf.gnus"))
;; prevent double initialization of recentf
(if (not (boundp 'cmg:prevent-gnus-recentf-double-init))
(setq cmg:prevent-gnus-recentf-double-init nil)) (if (not cmg:prevent-gnus-recentf-double-init)
(progn
(load-file recentf-save-file)
(setq cmg:prevent-gnus-recentf-double-init t)))picklist was once forked from recent-files when the latter didn’t store positions in the file and has evolved since then. It introduced merging of lists and a regexp based apropos.
Please note, that it vanished from the internet but if someone wants the code I can still send it via Email – StefanKamphausen
Lisp:recentf-buffer.el – creates a buffer with the list of recently open files. It’s an addition to recentf.el. To install:
(load "recentf-buffer") (global-set-key [?\C-c ?r ?f] 'recentf-open-files-in-simply-buffer)
Icicles gives you the list when you use ‘icicle-recent-file’ or ‘icicle-recent-file-other-window’ (see RecentFilesWithCompletion above). Just hit ‘TAB’ or ‘S-TAB’. If you type a regexp, ‘S-TAB’ will give you the list of matching recent files. – DrewAdams
Lisp:recentf-ext.el extends recentf package.
‘dired’ buffers can be handled.This concerns buffers visiting files, so it is related to some of the topics on this page. But this does not concern a persistent visited-files list.
See BufferMenuPlus for a description of the functionality of library Lisp:buff-menu+.el. With this library, you can sort visited files by date/time in two different ways (each either ascending or descending):
‘mouse-2’ on column heading CRM‘mouse-2’ on column heading TimeThis is especially useful if you have a large number of visited files, and you want to choose one of the recently used file buffers (time of last access) or one of the recently opened files (time of first visit, reversed). Reminder: You can use ‘T’ (command ‘Buffer-menu-toggle-files-only’) to display only buffers visiting files.
Note that these two kinds of sort are not inverses. Example: if you opened a file yesterday that you are still visiting, and all other currently visited files were opened today, then that file is at the top (or bottom) when you sort by column CRM. When you sort by column Time, its position depends on the last time it was accessed. – DrewAdams
I wrote to the maintainer of recentf.el but received no feedback til now, so I might as well share my code here.
I have the habit to start one Emacs dedicated to Gnus first thing in the morning and close it last thing in the evening. With the standard recentf storage habit this Emacs will always overwrite the list of recent files, thus making it more or less constant. There are several ways to solve this, one would be to read the list before saving it and merging the list from the file with that in the current instance of Emacs before saving it back. My code for this, which I have in daily usage for a while now, is listed below. Somehow I can’t just overwrite the functions from recentf but I need to find the right time for that, that’s why I put it after the requiring and befor the activation. – StefanKamphausen
(defun try-require (feature)
(condition-case nil
(require feature)
(error (progn
(message "could not require %s" feature)
nil))))
(when (try-require 'recentf)
(setq recentf-exclude '("~$"))
(setq recentf-max-saved-items 99)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Here I override some functions of recentf to get a merged list
;; This seems to be stable (used it for approx two weeks at the time
;; of this writing)
(defun recentf-save-list ()
"Save the recent list.
Load the list from the file specified by `recentf-save-file',
merge the changes of your current session, and save it back to the
file."
(interactive)
(let ((instance-list (copy-list recentf-list)))
(recentf-load-list)
(recentf-merge-with-default-list instance-list)
(recentf-write-list-to-file)))
(defun recentf-merge-with-default-list (other-list)
"Add all items from `other-list' to `recentf-list'."
(dolist (oitem other-list)
;; add-to-list already checks for equal'ity
(add-to-list 'recentf-list oitem)))
(defun recentf-write-list-to-file ()
"Write the recent files list to file.
Uses `recentf-list' as the list and `recentf-save-file' as the
file to write to."
(condition-case error
(with-temp-buffer
(erase-buffer)
(set-buffer-file-coding-system recentf-save-file-coding-system)
(insert (format recentf-save-file-header (current-time-string)))
(recentf-dump-variable 'recentf-list recentf-max-saved-items)
(recentf-dump-variable 'recentf-filter-changer-current)
(insert "\n \n;;; Local Variables:\n"
(format ";;; coding: %s\n" recentf-save-file-coding-system)
";;; End:\n")
(write-file (expand-file-name recentf-save-file))
(when recentf-save-file-modes
(set-file-modes recentf-save-file recentf-save-file-modes))
nil)
(error
(warn "recentf mode: %s" (error-message-string error)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(recentf-mode 1))
If you, for example, use CEDET, the recentf package may be fairly useless by default. The problem is that CEDET can scan lots of source files and make files in the process of building a tags database or managing the build system. The recentf list is then saturated with files you haven’t displayed or edited on screen.
This is fixed in the CVS version of CEDET.
The following is a workaround.
(require 'recentf)
(recentf-mode 1)
(defsubst file-was-visible-p (file)
"Return non-nil if FILE's buffer exists and has been displayed."
(let ((buf (find-buffer-visiting file)))
(if buf
(let ((display-count (buffer-local-value 'buffer-display-count buf)))
(if (> display-count 0) display-count nil)))))
(defsubst keep-default-and-visible-recentf-p (file)
"Return non-nil if recentf would, by default, keep FILE, and
FILE has been displayed."
(if (recentf-keep-default-predicate file)
(file-was-visible-p file)))
;; When a buffer is closed, remove the associated file from the recentf
;; list if (1) recentf would have, by default, removed the file, or
;; (2) the buffer was never displayed. This is useful because, for
;; example, CEDET opens a lot of files in the background to generate
;; its tags database, etc.
(setq recentf-keep '(keep-default-and-visible-recentf-p))
The Opera web browser has a surprisingly useful feature called the “trash can”. After you close a tab you can “undo” the close with C-z. As it turns out when I want a tab reopened it’s usually one of the last few I closed, so I almost never end up looking in the history. I missed this feature in Emacs, so I implemented it on top of recentf.
(defun undo-kill-buffer (arg)
"Re-open the last buffer killed. With ARG, re-open the nth buffer."
(interactive "p")
(let ((recently-killed-list (copy-sequence recentf-list))
(buffer-files-list
(delq nil (mapcar (lambda (buf)
(when (buffer-file-name buf)
(expand-file-name (buffer-file-name buf)))) (buffer-list)))))
(mapc
(lambda (buf-file)
(setq recently-killed-list
(delq buf-file recently-killed-list)))
buffer-files-list)
(find-file
(if arg (nth arg recently-killed-list)
(car recently-killed-list)))))
See Also: GnomeIntegration for opening files in GNOME’s recent-files list.
CategoryCommands CategoryDotEmacs CategoryPersistence CategoryCompletion