Here are two possible solutions (depending on exactly the use case you want).
(defun zin/open-recent-file ()
"Open the most recent currently closed file.
This will omit currently open files, instead it will retrieve the
next oldest file in recentf-list."
(interactive)
(let* ((count 0)
(recent recentf-list)
(r-length (length recent))
(buffers (mapcar 'buffer-file-name (buffer-list))))
;; Compare next file on the list to open buffers, if open skip it.
(while (member (nth count recent)
buffers)
(setq count (1+ count))
(if (= r-length count)
(error "All recent buffers already open")))
(find-file (nth count recent))))
(lexical-let ((recent-count 0))
(defun zin/visit-recent-file ()
"Visit files on the recentf-list in descending order.
This will work backwards through recentf-list visiting each file
in turn."
(interactive)
;; If last command was not to cycle through the files, then start
;; back at the first in the list.
(unless (eq last-command 'zin/visit-recent-file)
(setq recent-count 0))
;; If current buffer is the current entry on the list, increment.
(if (equal (buffer-file-name) (nth 0 recentf-list))
(setq recent-count (1+ recent-count)))
;; Error if all entries have been processed
(if (= recent-count (length recentf-list))
(error "At oldest recent buffer"))
;; Open appropriate file.
(find-file (nth recent-count recentf-list))))
The first will go through the list of recent files (recentf-list
) and open the next unopened file. The second will use recentf-list
to cycle to the next buffer in the list, until all have been visited then erroring out (since the list order will change as files are reopened).
To have it restart cycling when it reaches the end, just change the (error ...)
to
(setq recent-count 0)