Emacs Dired “Shortcuts”
I’m always trying to make my development workflow more efficient – whether it be tools or process – and this post solved one of my recent pain points – as well as giving me another practical problem to solve with Lisp.
As I noted previously, I’m really heavy into Emacs use at the moment: development, calendaring, RSS, news, Jabber IM – all from within this awesome thing called Emacs.
As I started to use it more and more for all types of different chores – and more specific to this post – file editing, I began to notice fairly quickly that directory navigation with Dired (Ctrl-X d, by default) led to far too many keystrokes to get to disparate locations – and to boot there was no notion of persistent “favorites” or “shortcuts”.
The above may just be my newness to the Emacs ecosystem and the functionality may actually exist – but it never turned up in my many searches. So I went about providing my own solution.
NOTE: This effort had no intention of making handy-dandy menu items as I don’t like them – or the mouse for that matter – all that much. Maybe I’ll add that at some point for thoroughness sake – we’ll see.
The plan was simple:
- Create a dictionary of shortcut to locations
- Use Emacs interactive ability to select a shortcut name and open its location with Dired.
The dictionary was easy once I got familiar with the alist syntax:
("dev_seamonkey" . "g:/code/projects/my-projects-pre-change/seamonkey")
Now to just add a list of those guys (one for each shortcut) to my shorcuts alist.
1 2 3
(setq my-shortcuts-alist '( ("dev_seamonkey" . "g:/code/projects/my-projects-pre-change/seamonkey") ("dev_legacy" . "g:/code/projects/my-projects-pre-change/my-projects"))
Cool, simple enough. Now, how do I get the keys out of this guy to be used with Emacs interactive? I searched around a bit and found a decent snippet that I modified for my purposes.
1 2 3
(interactive (list (completing-read "Choose shortcut: " (mapcar '(lambda (arg) (car arg)) my-shortcuts-alist))))
Ok, so that guy is quite a bit more confusing – here’s the gist:
- mapcar is a form that takes a function and a list, to which it applies the supplied function to each list member
- Remember our alist is a list of lists – so mapcar sends each list as the arg to lambda
- lambda returns the car (first item) of the arg (a list) – meaning it returns the key for each of our lists
- completing-read assembles them into a list to return to interactive.
Voila – Emacs interactive now has a list of defined shortcuts from which it will let the user choose – awesome!
After that, the last part was simple (well it was after I figured out how to pull a list out of the alist by key)
(cdr(assoc shortcut my-shortcuts-alist))
Again, this is pretty simple once you know what functions to use to do the task at hand.
- assoc takes a string and an alist and will return the list with the first element matching the key, or nil
- We then cdr that list (get the last element) – which is the actual location
- The dired command then uses that value to open your desired directory location
Full Code: dired_util.el