Ido mode

Posted on October 12, 2015

Ido mode is one of those Emacs packages that you can’t imagine living without once you embed it into your workflow. It stands for “interactive do” and in this post I’m going to talk about what it does, some of the configuration options that come bundled with it and how you can enhance it further.

What it does

Ido extends the built-in find-file and switch-to-buffer commands with interactive completion. It displays all the items that are available to you based on the current selection, narrowing down to the most relevant ones as you type to expand said selection. You can find a brief demonstration of this functionality here.

Turn it on by calling ido-mode.

  (require 'ido)
  (ido-mode)

Calling ido-everywhere will ensure that ido is used for all buffer and file selections in Emacs.

  (ido-everywhere)

If, for some reason, you’d prefer to only apply ido to one of those commands but not the other you can do so by calling ido-mode with a ​'buffer or ​'file argument to limit ido to buffer switching and finding files respectively.

Completion

As you type, ido narrows the result set based on which items your selection is a substring of. You can select the first result by pressing RET and you can cycle through the result set at any point with C-s and C-r. This can pose a problem if, for example, you want to create a new file whose name is a substring of another file in the current directory. You can use C-j to tell ido to use whatever you typed verbatim.

Ido limits the list of visible completions to a few at a time, but if you want to view the full list of available completions you can hit ?. Doing so will display all of the available completions in a separate buffer.

Prefix matching

Toggle prefix matching inside an ido buffer by hitting C-p. This is similar to the standard Emacs completion method in that it will only display results that start with your selection.

You can make prefix matching the default behavior by setting ido-enable-prefix to a truthy value.

  (setq ido-enable-prefix t)

Flexible matching

Ido’s flexible matching makes it so that any items containing all of the selection’s characters in order will appear in the result set.

Turn it on by setting ido-enable-flex-matching to a truthy value.

  (setq ido-enable-flex-matching t)

Finding files

ido-find-file comes with a few file-specific bindings. Find more information about this command with C-h f ido-find-file RET.

I most commonly use C-d to open the current matching directory in dired and C-k to delete the current matching file.

To ignore certain file extensions when finding files set ido-ignore-extensions to a truthy value and add the extension to the completion-ignored-extensions list.

  (setq ido-ignore-extensions t)
  (add-to-list 'completion-ignored-extensions ".pyc")

Sometimes it is convenient to use the filename under the cursor as a starting point for ido completion, ido-use-filename-at-point tells ido to do just that.

  (setq ido-use-filename-at-point 'guess)

By default, ido will ask for confirmation every time you attempt to create a new buffer. This can become annoying if you like to create many buffers. Turn it off with:

  (setq ido-create-new-buffer 'always)

Switching buffers

As with finding files, switching buffers using ido comes with a number of commands you can run on the current selection. Find out more about this command with C-h f ido-switch-buffer RET.

I most commonly use C-k to kill the current matching buffer. If you find that the buffer you meant to switch to isn’t open, you can switch to find-file by hitting C-f.

You can use ido-switch-buffer to switch to recently-used buffers by enabling ido-use-virtual-buffers. Doing so will turn recentf mode on which means you will be able to open a file in Emacs, close it then start it back up and switch to that file’s buffer as if it were already open.

  (setq ido-use-virtual-buffers t)

Extensions

smex

smex is an ido-based replacement for M-x. In addition to bringing ido completion to M-x, smex maintains a list of your most-used commands so that it can order results by frequency.

You can grab it off of MELPA and bind it to your preferred key.

  (require 'smex)
  (smex-initialize)

  ;; My personal preference is C-;
  (global-set-key (kbd "C-;") #'smex)
  ;; but you can also override M-x
  (global-set-key (kbd "M-x") #'smex)

Smex comes with command completion for the current major mode. You can use this by binding smex-major-mode-commands to a key.

  (global-set-key (kbd "M-X") #'smex-major-mode-commands)

ido-ubiquitous

Like the name implies, ido-ubiquitous is a package that attempts to weave in ido completion wherever it can. With this package, most functions that use completing-read will automatically start using ido for completion.

The package is available on MELPA and you can turn it on by calling ido-ubiquitous-mode.

  (require 'ido-ubiquitous)
  (ido-ubiquitous-mode)

If you run into any issues because of ido-ubiquitous, view the documentation for ido-ubiquitous-command-overrides and ido-ubiquitous-function-overrides by calling describe-variable (bound to C-h v by default). You can use those variables to turn ido off for specific functions or commands.

Note that ido-ubiquitous does not turn ido completion on for packages that come with built in ido support (even if it is not turned on by default) like Magit and Org mode. I have included a section below on how you can turn ido on for both of those modes.

ido-vertical-mode

ido-vertical-mode modifies the ido completion buffer so that it displays vertically rather than horizontally, making it so that the most relevant completions are displayed at the top.

ido-vertical-mode is available on MELPA.

  (require 'ido-vertical-mode)
  (ido-vertical-mode)

ido-clever-match

Finally, ido-clever-match is a simple package I wrote that wraps the built-in ido matching function in order to try to provide predictable prefix, substring and flex matching. You can find more information about how it works on its Github page but the gist of it is it ranks matches based on class (exact, prefix, substring or flex) and then some sub-metric within that class. The package ensures that prefix matches always come before substring which always come before flex matches.

It is available on MELPA and you can enable it with:

  (require 'ido-clever-match)
  (ido-clever-match-enable)

If you find that you prefer ido’s standard matching behavior and would like to go back simply call ido-clever-match-disable.

Other packages

I’ve found that the following packages work particularly well when paired with ido.

Magit

Magit comes with its own completion function which you can replace with ido by setting magit-completing-read-function to magit-ido-completing-read.

  (setq magit-completing-read-function #'magit-ido-completing-read)

Org mode

Like Magit, Org mode comes with its own completion function which you can replace with ido by setting org-completion-use-ido to a truthy value. The documentation recommends that you turn off org-outline-complete-in-steps if you switch to ido completion.

  (setq org-completion-use-ido t
        org-outline-path-complete-in-steps nil)

Projectile

Ido is Projectile’s default completion method. The maintainers recommend you install flx-ido for its flexible matching but you can also use Projectile with ido-clever-match.

Wrapping up

In closing, ido-mode is an extremely versatile package that can massively enhance one’s workflow when using Emacs. I highly recommend you try it out!