Frage

In Emacs, I use recentf extensively. Rather than calling find-files, I usually call a custom function xsteve-ido-choose-from-recentf instead which allows me to choose from my recentf files.

How do I create and maintain a separate list of recent directories, separate from the list of recent files? So that instead of calling dired, I could call something like ido-choose-from-recent-directories?

War es hilfreich?

Lösung 3

Pragmatic Emacs found the solution.

Here is a function to give you a list of recent directories, using ivy (part of swiper) to narrow it dynamically, and then open the selected one in dired.

;; open recent directory, requires ivy (part of swiper)
;; borrows from http://stackoverflow.com/questions/23328037/in-emacs-how-to-maintain-a-list-of-recent-directories
(defun bjm/ivy-dired-recent-dirs ()
  "Present a list of recently used directories and open the selected one in dired"
  (interactive)
  (let ((recent-dirs
         (delete-dups
          (mapcar (lambda (file)
                    (if (file-directory-p file) file (file-name-directory file)))
                  recentf-list))))

    (let ((dir (ivy-read "Directory: "
                         recent-dirs
                         :re-builder #'ivy--regex
                         :sort nil
                         :initial-input nil)))
      (dired dir))))

(global-set-key (kbd "C-x C-d") 'bjm/ivy-dired-recent-dirs)

Source: Open a recent directory in dired: revisited | Pragmatic Emacs

Andere Tipps

You ask, in your comment replying to @Stefan's answer: And how do I get from the above to viewing a list of recent directories? -

The answer is that you use the little-known fact that if the DIRNAME argument to dired is a list of (a) the new Dired buffer name followed by (b) file (or directory) names, then Dired is opened for just those files/dirs. IOW:

M-: (dired (cons DIRED-BUFNAME YOUR-LIST-OF-RECENT-DIRECTORIES))

For example:

M-: (dired '("My Dired Buffer" "/a/recent/dir/" "/another/recent1/" "/another/"))

If you use library Dired+ then you can provide such a list interactively, by using a non-positive prefix arg with dired.

But in this case you want to write a command that first gathers the list of recent directories and then opens Dired for them. This should do it:

(defun dired-recent (buffer)
  "Open Dired in BUFFER, showing the recently used directories."
  (interactive "BDired buffer name: ")
  (let ((dirs  (delete-dups
                (mapcar (lambda (f/d)
                          (if (file-directory-p f/d)
                              f/d
                            (file-name-directory f/d)))
                        recentf-list))))
    (dired (cons (generate-new-buffer-name buffer) dirs))))

That works for me. However, vanilla Emacs does not let you use i to insert the listing for any directory that is not in the same directory tree as the default-directory of the Dired buffer. That means that the above code will work OK, but you will not be able to insert any of the listed directories.

To be able to do that, load library dired+.el. Dired+ also fixes a couple of other inadequacies wrt the vanilla handling of a cons arg to dired.

The above code, together with Dired+ should give you what you want.


UPDATE

I just added this to Dired+. These are the commands added: diredp-dired-recent-dirs and diredp-dired-recent-dirs-other-window.


UPDATE 2

I made it simple to choose which of the recently used directories to include or exclude. Use a prefix arg to initiate such choosing. With no prefix arg you get all recent dirs. I also made it possible to use a prefix arg to be prompted for the ls switches. Here is the doc s tring of diredp-dired-recent-dirs:

Open Dired in BUFFER, showing recently used directories.
You are prompted for BUFFER.

No prefix arg or a plain prefix arg (`C-u', `C-u C-u', etc.) means
list all of the recently used directories.

With a prefix arg:
* If 0, `-', or plain (`C-u') then you are prompted for the `ls'
  switches to use.
* If not plain (`C-u') then:
  * If >= 0 then the directories to include are read, one by one.
  * If  < 0 then the directories to exclude are read, one by one.

When entering directories to include or exclude, use `C-g' to end.

Finally, I added bindings for the commands: C-x R (same window) and C-x 4 R (other window), where R is Shift + r.

You don't need to maintain a separate list (which would be a lot of work). Instead, you can extract that list from the recentf list. E.g.

(delete-dups
 (mapcar (lambda (file)
           (if (file-directory-p file) file (file-name-directory file)))
         recentf-list))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top