tilde in ido-find-file
09 Jan 2015On seeing
this Emacs Stack Exchange question,
it occurred to me that if some config code is old for me, it's not old
for the new Emacs users. So I'll share one of the old ido-find-file
hacks that I've been using for ages.
This song is an oldie ...but, uh ... pause Well, it's an oldie where I come from.
-- Marty
The code
This is the original code that I was using:
(defun oleh-ido-setup-hook ()
(define-key ido-file-dir-completion-map "~"
(lambda ()
(interactive)
(ido-set-current-directory "~/")
(setq ido-exit 'refresh)
(exit-minibuffer))))
(add-hook 'ido-setup-hook 'oleh-ido-setup-hook)
The generalization
It wouldn't be a LISP if I couldn't generalize the code:
(defun ido-find-file-jump (dir)
"Return a command that sends DIR to `ido-find-file'."
`(lambda ()
(interactive)
(ido-set-current-directory ,dir)
(setq ido-exit 'refresh)
(exit-minibuffer)))
And here's how to leverage this generalization:
(defun oleh-ido-setup-hook ()
(define-key ido-file-dir-completion-map "~"
(ido-find-file-jump "~/"))
(define-key ido-file-dir-completion-map "!"
(ido-find-file-jump "~/Dropbox/source/site-lisp/"))
(define-key ido-file-dir-completion-map "@"
(ido-find-file-jump "~/git/lispy/")))
Note that this is pretty ugly, implementation-wise, since
ido-find-file-jump
would be called three times each time you do an
ido
related command, like ido-switch-buffer
etc.
I would have preferred to do it like this instead:
(eval-after-load "ido"
`(progn
(define-key ido-file-dir-completion-map "~"
(ido-find-file-jump "~/"))
(define-key ido-file-dir-completion-map "!"
(ido-find-file-jump "~/Dropbox/source/site-lisp/"))
(define-key ido-file-dir-completion-map "@"
(ido-find-file-jump "~/git/lispy/"))))
But, for some strange reason, ido
keeps overriding
ido-file-dir-completion-map
and I actually have to re-set my
bindings in ido-setup-hook
.
The further generalization
Here is the final iteration of the code:
(defvar oleh-ido-shortcuts
'(("~/" "~")
("~/Dropbox/source/site-lisp/" "!")
("~/git/lispy/" "@")))
(mapc (lambda (x)
(setcar x (ido-find-file-jump (car x))))
oleh-ido-shortcuts)
(defun oleh-ido-setup-hook ()
(mapc
(lambda (x)
(define-key ido-file-dir-completion-map (cadr x) (car x)))
oleh-ido-shortcuts))
(add-hook 'ido-setup-hook 'oleh-ido-setup-hook)
The customize tricks
"Custom setters?
In my Elisp?"It's more likely than you think.
Note that the mapc
statement needs to be evaluated if I dynamically
modify oleh-ido-shortcuts
. This isn't a problem for me, but if I
wanted to package a code like this, I would define
oleh-ido-shortcuts
like this:
(defcustom oleh-ido-shortcuts
'(("~/" "~")
("~/Dropbox/source/site-lisp/" "!")
("~/git/lispy/" "@"))
"A list of directory-shortcut pairs for `ido-find-file'."
:set (lambda (symbol value)
(set-default
symbol
(mapcar
(lambda (x)
(if (stringp (car x))
(cons (ido-find-file-jump (car x))
(cdr x))
x))
value))))
Now, this should work:
(csetq oleh-ido-shortcuts
(progn
(setcar (rassoc '("@") oleh-ido-shortcuts)
"~/git/worf")
oleh-ido-shortcuts))
(csetq oleh-ido-shortcuts
(cons '("~/git/" "^")
oleh-ido-shortcuts))
Here, the appropriate lambda is auto-generated by using the :set
property of oleh-ido-shortcuts
.
And csetq
is just a customize
-aware version of setq
:
(defmacro csetq (variable value)
`(funcall (or (get ',variable 'custom-set) 'set-default)
',variable ,value))