Sometimes I got itchy finger and kill some buffer that I meant to bury instead. The problem is, I use tramp to edit files from multiple machines, and those file names get long and nasty and just in general I'm not that good at finding where my files are anyways. So I would like to have emacs keep track of the files I just closed so that I can re-open them easily (via, ideally, an ido prompt).
Here is what I have so far, which is not working:
(defvar closed-files '())
(defun track-closed-file ()
(message buffer-file-name)
(and buffer-file-name
(cons buffer-file-name closed-files)))
(defun last-closed-files ()
(interactive)
(find-file (ido-completing-read "Last closed: " closed-files)))
(add-hook 'kill-buffer-hook 'track-closed-file)
I'm really not great at elisp and probably mess up somewhere 开发者_Python百科in defining the variable and adding cell to it...
[I do know about recentf
, but that keeps track of opened files, instead of closed files.]
I have just tested this and it works with the use of a list and add-to-list
This also eliminates duplicate entries. Does this meet your needs?
(defvar closed-files (list))
(defun track-closed-file ()
(message buffer-file-name)
(and buffer-file-name
(add-to-list 'closed-files buffer-file-name)))
(defun last-closed-files ()
(interactive)
(find-file (ido-completing-read "Last closed: " closed-files)))
(add-hook 'kill-buffer-hook 'track-closed-file)
Update
I quite like this functionality and have placed it in my emacs configuration. You may as well benefit from changes I have made.
This addition will push most recently closed files to the head of the list even if they have previously been closed (and are already in the closed-files
list).
(defun track-closed-file ()
(and buffer-file-name
(message buffer-file-name)
(or (delete buffer-file-name closed-files) t)
(add-to-list 'closed-files buffer-file-name)))
Your original problem was that cons
will return you the new list, not manipulate the input list:
(setq mylist '(2 3))
=> (2 3)
(cons 1 mylist)
=> (1 2 3)
mylist
=> (2 3)
in this case you would need to do:
(setq mylist (cons 1 mylist))
=> (1 2 3)
mylist
=> (1 2 3)
Have you tried using recentf? It should be provided with Emacs.
I originally saw it via XSteve's Emacs power-user tips where he suggests binding it to F12, and provides an interactive interface:
;;recentf
(require 'recentf)
(recentf-mode 1)
(setq recentf-max-saved-items 500)
(setq recentf-max-menu-items 60)
(global-set-key [(meta f12)] 'recentf-open-files)
(defun xsteve-ido-choose-from-recentf ()
"Use ido to select a recently opened file from the `recentf-list'"
(interactive)
(let ((home (expand-file-name (getenv "HOME"))))
(find-file
(ido-completing-read "Recentf open: "
(mapcar (lambda (path)
(replace-regexp-in-string home "~" path))
recentf-list)
nil t))))
[update]: whups, just saw your note about recentf awareness. True, it is for all opened files, so it included those currently in open buffers, too. Since I've only ever accessed it when I'm trying to track down a recently closed file, I never thought about that. Still, maybe filtering open files from that output might be easier than reinventing the entire wheel?
A way to do this:
https://github.com/ajvargo/Lazarus
Have you thought about rebinding "C-x k" to bury-buffer instead of kill-buffer? (You can then periodically clean up your buffer list with something like 'midnight.el' if necessary.)
This beautiful feature is also available as part of "anything" package. Strongly suggest to give this a go.
But "anything" has a newer version called "helm" that does not seem to have this feature.
精彩评论