Introducing ivy-mode
16 Apr 2015Today I'd like to introduce a function that has completely replaced
ido-mode
for me: ivy-mode
. It comes with the
swiper package, available both in
MELPA and
GNU ELPA.
The latter is a bit slower to update, so the version there can be a bit outdated sometimes.
The quick video demo
If you prefer listening and watching to reading, check out the video demo here. It repeats most of the stuff written down below.
Generic completion
ivy-mode
is simply a minor mode that changes
completing-read-function
to ivy-completing-read
while it's active.
This function is used in most of the places where Emacs requires
completion, like:
- M-x
execute-extended-command
- C-h f
describe-function
- C-h v
describe-variable
package-install
- C-x b
switch-to-buffer
- C-x C-f
find-file
So, while ivy-mode
is on, all these functions and more will use ivy completion.
Package-specific completion
org-mode
With the most recent master version, org-mode
will obey
completing-read-function
, so it should work by default. If you try
it for refiling to headings with similar names, you'll really notice
how much better ivy-mode
is at it. helm-mode
also does well, if
you don't mind the large window.
magit
This setting is needed to use ivy completion:
(setq magit-completing-read-function 'ivy-completing-read)
find-file-in-project
find-file-in-project will use ivy by default if it's available.
projectile
You can set this to make it work:
(setq projectile-completion-system 'ivy)
smex
Yes, it's also possible, since today. Although you'll have to use my fork of smex if you want to try it. I've sent a pull request, it's all backwards-compatible, so hopefully it'll get merged.
The nice thing is that smex
can take care of the sorting all by
itself, since ivy
doesn't do that yet.
my packages
lispy and
function-args use ivy
by
default. You can also enable it for
helm-make, for which the
default is obviously helm
.
File name completion
When ivy-mode
is on, find-file
will also use it. The completion
is considerably different from all other cases, since it's done in
stages, just like ido-find-file
does it.
The key bindings are:
- RET will select the current candidate and finish.
- C-j will try to continue the completion, i.e. if the
current candidate is a directory, move to that directory. But if the
current candidate is a file or
./
, then finish. - / will switch to completing the sub-directories of
/
, but if the candidate is a perfect match, it will act like C-j. - ~ will switch to completing the sub-directories of
~/
. - C-n and C-p naturally select the next and the previous candidate.
What's it all for?
Well, for me the advantage is obvious: I get my completion just the way I like it. You can use it as well if you find that you like it more than ido. I'll just list a list of features that I like:
- The current number of candidates is robustly displayed and updated after each key stroke.
- The minibuffer is an actual editing area, where the bindings like C-a, M-DEL and C-k etc. work just as you expect. Once you internalize the way that the regex is built, you can get your match very quickly and intuitively.
- The actual regular expressions constructs like
\\b
or$
and^
work. The only thing that works differently is the space: you can't match a single space because any amount of spaces translates into the.*
wild card. But you can use it to your advantage and use the space instead of all the various symbol joining constructs out there, likesnake_case
, orkebab-case
(yeah, it's totally called that, check the wiki), orwhatever/this/is/case
. - The familiar M-< and M-> key bindings also work as expected, navigating you to the first and last candidate respectively.
When you press C-p on the first match or C-n on the last match, the match will not change, unlike the behavior
of
ido
that has annoyed me a lot. - The minibuffer key bindings can actually be properly customized:
just set
ivy-minibuffer-map
to whatever you like, it won't be changed. Even in Emacs 24.5, if you customizeido-completion-map
, the change will be reset. That was fixed only in the current master. - You don't have to rely on
flx
orflx-ido
to save you from the overwhelming number of matches. Instead, you type maybe a bit more, but in return you get a very consistent and predictable result. No black boxes or hidden variables that dramatically change the order of candidates from time to time.
Outro
Check it out, I hope you like it. And a big thanks to all who contributed code or bug reports.