• Stars
    star
    146
  • Rank 252,549 (Top 5 %)
  • Language
    Emacs Lisp
  • License
    GNU General Publi...
  • Created about 3 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Insert paths into the minibuffer prompt in Emacs

consult-dir: insert paths into minibuffer prompts in Emacs

https://melpa.org/packages/consult-dir-badge.svg

media/consult-dir.png

Consult-dir allows you to easily insert directory paths into the minibuffer prompt in Emacs.

When using the minibuffer, you can switch - with completion and filtering provided by your completion setup - to any directory you’ve visited recently, or to a project, a bookmarked directory or even a remote host via tramp. The minibuffer prompt will be replaced with the directory you choose.

Why would you want to do this?

To avoid “navigating” long distances when picking a file or directory in any Emacs command that requires one. Here I use it to select a distant directory when copying a file with dired:

demo-dired.mp4

Think of it like the shell tools autojump, fasd or z but for Emacs. See the demos section below for many more examples. consult-dir works with all Emacs commands that require you to specify file paths, and with Embark actions on files.

The directory candidates are collected from user bookmarks, Projectile project roots (if available), project.el project roots (if available) and recentf file locations. The default-directory variable is not changed in the process.

Contents

Installation

consult-dir is on MELPA.

With use-package

(use-package consult-dir
  :ensure t
  :bind (("C-x C-d" . consult-dir)
         :map minibuffer-local-completion-map
         ("C-x C-d" . consult-dir)
         ("C-x C-j" . consult-dir-jump-file)))

Replace minibuffer-local-completion-map above with

  • vertico-map if you use Vertico,
  • selectrum-minibuffer-map if you use Selectrum.

General method

After adding MELPA to your package archives,

(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))

you can install it with M-x package-install consult-dir and bind consult-dir as convenient:

(define-key global-map (kbd "C-x C-d") #'consult-dir)
(define-key minibuffer-local-completion-map (kbd "C-x C-d") #'consult-dir)

If you want to use the file-jump functionality, you can bind consult-dir-jump-file in the minibuffer-local-completion-map.

(define-key minibuffer-local-completion-map (kbd "C-x C-j") #'consult-dir-jump-file)

Replace minibuffer-local-completion-map above with

  • vertico-map if you use Vertico,
  • selectrum-minibuffer-map if you use Selectrum.

Usage

Call consult-dir when in the minibuffer to choose a directory with completion and insert it into the minibuffer prompt, shadowing or replacing the directory path showing currently. The file name part of the text is retained. This lets the user switch to distant directories very quickly when finding files, for instance.

Call consult-dir from a regular buffer to choose a directory with completion and then interactively find a file in that directory. The command run with this directory is configurable via consult-dir-default-command and defaults to find-file.

Call consult-dir-jump-file from the minibuffer to asynchronously find a file anywhere under the directory that is currently in the prompt. This can be used with consult-dir to quickly switch directories and find files at an arbitrary depth under them. consult-dir-jump-file uses consult-find under the hood.

Demos

Here I show the different directory sources using Consult’s narrowing feature, then use consult-dir to easily jump around the filesystem and open files. I also use consult-dir-jump-file to quickly drill down a directory when I don’t find the file I’m looking for at the top level:

demo-1.mp4

In this demo I call consult-grep with a prefix argument. This requires me to specify a directory to grep inside of, so I use consult-dir to specify that directory:

demo-2.mp4

Here I use consult-dir to jump to one of my project directories when attaching a file to an email:

demo-3.mp4

In this example I combine consult-dir with Embark. I use consult-dir to specify a directory, then Embark to spawn an eshell there. I then use consult-dir again when tab-completing inside eshell to specify a distant directory to copy files from. Finally I use consult-dir with Embark to jump to a bookmark in a window-split:

demo-embark-1.mp4

(In these demos I am using Vertico as my completion system.)

Configuration

consult-dir should work out of the box with no configuration needed beyond binding it to a key.

However, only bookmarked directories and Project.el projects are displayed by default. if you use Projectile or want finer control over the directories that are offered as candidates to jump to, read on.

Directory sources

Bookmarks

Enabled by default. To disable, customize consult-dir-sources.

Recent directories

To enable, turn on recentf-mode. (M-x recentf-mode). Note that if you don’t already use recentf-mode, the recentf directory cache will start out empty and build up over time as you use Emacs.

Project directories (Project.el)

Enabled by default. To disable, customize consult-dir-project-list-function or

(setq consult-dir-project-list-function nil)

Project directories (Projectile)

To enable, customize consult-dir-project-list-function or

(setq consult-dir-project-list-function #'consult-dir-projectile-dirs)

Remote hosts

Also included are a number of sources for interacting with remote hosts via tramp, principally:

  • consult-dir--source-tramp-local for a set list of local/custom hosts (see consult-dir-tramp-local-hosts to customize)
  • consult-dir--source-tramp-ssh for a list of parsed hosts from your ~/.ssh/config

By default consult-dir does not display known SSH hosts as a separate directory source. If you wish to enable it, customize consult-dir-sources or use the following:

(add-to-list 'consult-dir-sources 'consult-dir--source-tramp-ssh t)

Docker hosts

It’s also possible to define a source to switch to containers using consult-dir. This approach will work for both podman and docker containers, so adjust as desired.

If you’re using Emacs 29+, you can also wrap tramp-container--completion-function instead.

(defcustom consult-dir--tramp-container-executable "docker"
  "Default executable to use for querying container hosts."
  :group 'consult-dir
  :type 'string)

(defcustom consult-dir--tramp-container-args nil
  "Optional list of arguments to pass when querying container hosts."
  :group 'consult-dir
  :type '(repeat string))

(defun consult-dir--tramp-container-hosts ()
  "Get a list of hosts from a container host."
  (cl-loop for line in (cdr
                        (ignore-errors
                          (apply #'process-lines consult-dir--tramp-container-executable
                                 (append consult-dir--tramp-container-args (list "ps")))))
           for cand = (split-string line "[[:space:]]+" t)
           collect (let ((user (unless (string-empty-p (car cand))
                                 (concat (car cand) "@")))
                         (hostname (car (last cand))))
                     (format "/docker:%s%s:/" user hostname))))

(defvar consult-dir--source-tramp-docker
  `(:name     "Docker"
    :narrow   ?d
    :category file
    :face     consult-file
    :history  file-name-history
    :items    ,#'consult-dir--tramp-docker-hosts)
  "Docker candiadate source for `consult-dir'.")

;; Adding to the list of consult-dir sources
(add-to-list 'consult-dir-sources 'consult-dir--source-tramp-docker t)

Then amend consult-dir-sources as in the above snippet to include the source you defined.

Writing your own directory source

If none of the above include directories you want to jump to, you can write your own source. As a template, here is a source that adds paths provided by the shell tool Fasd to consult-dir:

;; A function that returns a list of directories
(defun consult-dir--fasd-dirs ()
  "Return list of fasd dirs."
  (split-string (shell-command-to-string "fasd -ld") "\n" t))

;; A consult source that calls this function
(defvar consult-dir--source-fasd
 `(:name     "Fasd dirs"
   :narrow   ?f
   :category file
   :face     consult-file
   :history  file-name-history
   :enabled  ,(lambda () (executable-find "fasd"))
   :items    ,#'consult-dir--fasd-dirs)
  "Fasd directory source for `consult-dir'.")

;; Adding to the list of consult-dir sources
(add-to-list 'consult-dir-sources 'consult-dir--source-fasd t)

For additional directory sources, check out the wiki.

Default consult-dir action

When called from a regular buffer (i.e not the minibuffer), consult-dir defaults to calling find-file after you choose a directory. To set it to open the directory in dired instead or to run a custom command, customize consult-dir-default-command.

File name shadowing

By default, choosing a directory using consult-dir when in the minibuffer results in the text already in the prompt being “shadowed” or made inactive, but you can still delete the new text to recover it. You can make the new text replace the old instead by setting consult-dir-shadow-filenames to nil.

Alternatives

consult-dir is akin to shell tools like autojump or fasd but for all file/directory contexts in Emacs.

consult-buffer (part of Consult) already allows you to switch to bookmarks and recentf files, so this might be sufficient for you if you need to visit a proximal set of files quickly. consult-dir is different in that it is composable with all Emacs commands that require you to specify a directory and thus works in more contexts.

Projectile and the built-in project.el have extensive support for listing and quickly switching projects and running actions on them. consult-dir is more of a one-stop shop (“just get me there”) for switching directories as it includes recent directories and bookmarks in the mix, allows jumping to files with consult-dir-jump-file, and supports running arbitrary actions on directories using Embark. Of course, it also allows for fast directory selection when using any Emacs command that requires specifying a directory.

Acknowledgements

More Repositories

1

gptel

A simple LLM client for Emacs
Emacs Lisp
1,092
star
2

popper

Emacs minor-mode to summon and dismiss buffers easily.
Emacs Lisp
439
star
3

elfeed-tube

Youtube integration for Elfeed, the feed reader for Emacs
Emacs Lisp
247
star
4

.emacs.d

My personal emacs settings
Emacs Lisp
110
star
5

org-auctex

Better latex previews for org-mode
Emacs Lisp
78
star
6

project-x

Ehancements to Emacs' built in project library.
Emacs Lisp
73
star
7

org-preview

Asynchronous, super fast LaTeX previews for Org mode.
Emacs Lisp
64
star
8

dired-hist

Traverse dired history in Emacs
Emacs Lisp
30
star
9

dired-delight

Tag files with colors in Dired
Emacs Lisp
29
star
10

repeat-help

Emacs Lisp
25
star
11

wombag

A Wallabag client for Emacs
Emacs Lisp
23
star
12

lazytab

Easy array, matrix or table entry in LaTeX buffers in Emacs
Emacs Lisp
22
star
13

consult-reftex

Emacs Lisp
20
star
14

org-src-context

LSP support for Org source buffers.
Emacs Lisp
19
star
15

timeout

Throttle or debounce elisp code
Emacs Lisp
18
star
16

gptel-quick

Quick LLM lookups in Emacs
Emacs Lisp
15
star
17

yasnippets

My (mostly) LaTeX snippets for Emacs
YASnippet
13
star
18

calc-transient

Transient interface for the Emacs calculator
Emacs Lisp
13
star
19

elmo

Embark Live MOde for Emacs
Emacs Lisp
12
star
20

popup-buffers

Emacs Lisp
11
star
21

org-image-preview

Emacs Lisp
5
star
22

latex-preview

LaTeX previews everywhere in Emacs
Emacs Lisp
3
star
23

dired-preview

Emacs Lisp
3
star
24

glof

Generally Less Obtuse Fidgeting
Emacs Lisp
2
star
25

wallabag-post

Post URLs to Wallabag from Emacs.
Emacs Lisp
2
star
26

reftex-xref

xref and eldoc support for RefTeX
Emacs Lisp
2
star
27

sicp

My solutions to SICP exercises (in scheme)
Scheme
1
star
28

ffmpeg-dispatch

Emacs Lisp
1
star
29

ffmpeg-crop

An Emacs helper to run ffmpeg on videos
Emacs Lisp
1
star