(or emacs irrelevant)

Introducing ivy-mode

Today 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, like snake_case, or kebab-case (yeah, it's totally called that, check the wiki), or whatever/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 customize ido-completion-map, the change will be reset. That was fixed only in the current master.
  • You don't have to rely on flx or flx-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.