(or emacs irrelevant)

Ivy-mode 0.6.0 is out

For those who don't keep up, ivy-mode is a completion method that's similar to ido, but with emphasis on simplicity and customizability. Currently, there are two related packages on MELPA: swiper and counsel:

  • swiper provides an isearch replacement, using ivy-read for completion, as well as the basic ivy-mode.
  • counsel provides some extra commands, like -M-x, -ag, -load-theme etc.

The reasoning behind the split into two packages is that there's less update overhead if only one of them is updated.

completing-read-function conundrum

This is to explain a bit the presence of the counsel package. Initially, I hoped that ivy-mode could do most of the work, via the Emacs' completing-read-function interface. How it works: most built-in packages will call completing-read when they require completion. That function will forward the completion to completing-read-function if it's set. This is the way how things like icomplete-mode or ivy-mode or helm-mode work.

Unfortunately, the interface rather limits what you can do in completing-read-function. Essentially, you're given a list of strings and you have to return a string. You have no idea which function called you, so you can't do any fancy stuff depending on the caller, short of examining this-command which isn't very reliable. You have no idea what will be done with the one string that you return, so you can't do something fancy like select two or three strings and perform that action for each of them.

The result is that sometimes I have to replace the built-in functions, instead of re-using them. So instead of re-using find-file, I wrote my own counsel-find-file that looks like this:

(defun counsel-find-file ()
  "Forward to `find-file'."
  (interactive)
  (ivy-read "Find file: " 'read-file-name-internal
            :matcher #'counsel--find-file-matcher
            :action
            (lambda (x)
              (with-ivy-window
                (find-file (expand-file-name x ivy--directory))))
            :preselect (when counsel-find-file-at-point
                         (require 'ffap)
                         (ffap-guesser))
            :require-match 'confirm-after-completion
            :history 'file-name-history
            :keymap counsel-find-file-map))

It's still possible to call the original find-file, and you'll get ivy-read completion for it, but:

  • ivy-resume won't work, since ivy-read doesn't know what to do with the string that you select.
  • C-M-n (ivy-next-line-and-call) won't work to select another file within the same completion session, for the same reason.
  • M-o (ivy-dispatching-done) may work with some customization, but since it dispatches on this-command to get the extra actions, it can cause a problem if the command wasn't called directly.

I think it would be cool to extend the built-in completing-read-function interface in the future Emacs versions. Both Ivy and Helm (which uses the same strategy of passing the action to the completion) would benefit from this.

Release summary and highlights

It's been two months and 150 commits since the last version. The full release notes can be found inside the repository in Changelog.org or at Github's release tab.

I recommend to look through the whole list to see if anything catches your attention. I'll highlight a few things that I think the users might be interested in most.

Fuzzy completion

This is off by default, since I think having less candidates is better than having more. You can customize this for all commands or per-command. For example:

(setq ivy-re-builders-alist
      '((t . ivy--regex-fuzzy)))

swiper has a case-fold-search optimization

Binds case-fold-search to t when the input is all lower-case:

  • input "the" matches both "the" and "The".
  • input "The" matches only "The".

Anzu things

To see not only the number of matched candidates, but also the index of the current one, set this:

(setq ivy-count-format "(%d/%d) ")

Customize additional exit points for any command

For any command that uses ivy-read that is. Example for ivy-switch-to-buffer:

(ivy-set-actions
 'ivy-switch-buffer
 '(("k"
    (lambda (x)
      (kill-buffer x)
      (ivy--reset-state ivy-last))
    "kill")
   ("j"
    ivy--switch-buffer-other-window-action
    "other")))

After this:

  • Use M-o k to kill a buffer.
  • Use M-o j to switch to a buffer in other window.

You can always use M-o o to access the default action. When there is only one action, M-o does the same as C-m.

More descriptions with a built-in Hydra

Toggle C-o in any completion session to get an overview of the things that you can do.

Many commands that interface with shell calls

The following commands will call the appropriate shell tool to give you a list of candidates:

  • counsel-git-grep
  • counsel-ag
  • counsel-locate
  • counsel-recoll

These commands will refresh after each new letter entered, and they account for the fact that the shell call will usually take more time than the time it takes to input a new letter. So the process will be killed and restarted, resulting in virtually no keyboard delay and no downtime.

Many commands that offer more options than the built-in counterparts

This list includes:

  • counsel-find-file,
  • counsel-M-x,
  • counsel-load-theme,
  • counsel-org-tag and counsel-org-tag-agenda.

Most extra things that you can do are:

  • Doing stuff with multiple candidates through C-M-n like in this video.
  • Using ivy-resume to resume the last completion session.

Make sure to try counsel-org-tag, this one is a bit tricky for completion, since it requires to return multiple candidates at once. So you can toggle each tag with C-M-m (ivy-call) and then exit with C-m (ivy-done). The currently selected tags will be displayed in the prompt.

Outro

A big thanks to all people who contributed code and issues towards this release. I'm really happy that you're helping me to refine this nice package.