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!