This package defines a global minor mode to display Icomplete
completion candidates vertically. You could get a vertical display
without this package, by using (setq icomplete-separator "\n")
, but
that has two problems which icomplete-vertical-mode
solves:
- Usually the minibuffer prompt and the text you type scroll off to the left! This conceals the minibuffer prompt, and worse, the text you enter.
- The first candidate appears on the same line as the one you are typing in. This makes it harder to visually scan the candidates as the first one starts in a different column from the others.
The screenshots explain this better than words can.
This is what describe-function
looks like in icomplete-vertical-mode
(with Protesilaos Stavrou’s lovely modus-operandi theme):
For comparison this is what you get without this package, simply
setting icomplete-separator
to a newline:
Notice the missing prompt and text typed so far (icom
), and how the
first candidate (icomplete-tidy
) is on the line where you type.
If you use MELPA, the easiest way to install icomplete-vertical
is via
package-install
. Alternatively, download icomplete-vertical.el
, put it
somewhere in your load-path
, and require
it. Turn the minor mode on or
off with M-x icomplete-vertical-mode
. It only does something when
icomplete-mode
is also active.
You might also want to bind icomplete-vertical-toggle
to some key in
the icomplete-minibuffer-map
keymap. I use C-v
, for “vertical”, since
paging in the minibuffer isn’t very useful. (Running
icomplete-vertical-toggle
has the same toggling effect as running
icomplete-vertical-mode
, except that it doesn’t print a message in the
echo area disturbing your candidate display until the next keypress.)
If you manage your configuration with use-package
, you can use this
form to install and configure icomplete-vertical
:
(use-package icomplete-vertical
:ensure t
:demand t
:custom
(completion-styles '(partial-completion substring))
(completion-category-overrides '((file (styles basic substring))))
(read-file-name-completion-ignore-case t)
(read-buffer-completion-ignore-case t)
(completion-ignore-case t)
:config
(icomplete-mode)
(icomplete-vertical-mode)
:bind (:map icomplete-minibuffer-map
("<down>" . icomplete-forward-completions)
("C-n" . icomplete-forward-completions)
("<up>" . icomplete-backward-completions)
("C-p" . icomplete-backward-completions)
("C-v" . icomplete-vertical-toggle)))
A completion framework is probably something you don’t want to defer
loading, that’s what the :demand t
is there for.
The settings shown in the :custom
part of the form are the ones I use,
but I’ll stop short of recommending them, and instead just recommend
that you lookup those variables in the documentation and think about
what value you want for them.
The default keybindings for icomplete-forward-completions
and
icomplete-backward-completions
are C-. and C-, which are difficult to
use with some terminal emulators (they cause no problem at all for
graphical Emacs).
(The above block mixes configuration for icomplete-vertical
, icomplete
and the built-in completion framework. A use-package
purist might want
to separate that into different use-package
forms.)
This package is meant to be used in conjunction with Icomplete, which
is a built-in Emacs completion UI (similar to Ido) that provides a
display of the completion candidates and interactive narrowing.
Icomplete has several configuration options but even just sticking
(icomplete-mode)
in your init file is enough to make it useful. The
documentation that comes with Emacs is a little sparse (see (info
"(Emacs)Icomplete")
), so for a demo and longer introduction see
Protesilaos Stavrou’s icomplete video.
Icomplete is a UI for the built-in completion system in Emacs which is
very customizable and has various styles of matching candidates
(notably including flex
completion starting from Emacs 27). See the
Completion section of the manual, particularly the subsections (info
"(Emacs)Completion Styles")
and (info "(Emacs)Completion Options")
.
The maximum number of lines you want to use to display candidates
during completion is determined by the variable
icomplete-vertical-prospects-height
, which you can customize. This was
made a separate variable from icomplete-prospects-height
because if
you use icomplete both horizontally and vertically you are likely to
want different values for the two settings.
You can control whether the minibuffer has a fixed height or grows and
shrinks as the number of candidates changes while using
icomplete-vertical-mode
completion. This is controlled by the
value of the standard Emacs variable resize-mini-windows
at the time
icomplete-vertical-mode
is activated.
If resize-mini-windows
is set to t
, then the minibuffer will grow and
shrink depending on the number of candidates —up to a maximum of
icomplete-vertical-prospects-height
lines of candidates.
On the other hand, if resize-mini-windows
is set to any other value
(either nil
or grow-only
) then icomplete-vertical-mode
will keep the
height fixed at icomplete-vertical-prospects-height
lines of
candidates.
The value of variable icomplete-vertical-separator
is used to separate
the candidates in vertical completion; it defaults to a single newline
and should always contain at least one newline. You can customize this
variable and the custom UI will offer some predefined choices: a
newline, a dashed line, a dotted line, a solid line.
The variable can be set to a string with text properties, such as
faces. If the string has any faces applied, they will be
respected. If, on the other hand, it has no faces at all, then the
icomplete-vertical-separator
face will be applied to it. That face by
default simply inherits from the shadow
face used for deemphasized
text.
You can define named vertical completion separators by customizing
icomplete-vertical-separator-alist
. The symbols used as keys in this
alist are valid values for icomplete-vertical-separator
and for
:separator
options in icomplete-vertical-do
(see below).
If you choose to use Icomplete horizontally by default but want to
define a few commands that leverage icomplete-vertical-mode
, use the
icomplete-vertical-do
macro. Use this for lists with naturally long
candidates, such as filesystem paths or kill-ring entries.
For example, let’s implement a command to yank from the kill-ring using completion. Often the kills are multiline, so for improved usability we’ll need (1) the completion to start in vertical mode, (2) the number of lines used to display entries to be relatively large, and (3) the separator to be, say, a dotted line:
(defun insert-kill-ring-item ()
"Insert item from kill-ring, selected with completion."
(interactive)
(icomplete-vertical-do (:separator 'dotted-line :height 20)
(insert (completing-read "Yank: " kill-ring nil t))))
Note that the completion merely starts out in vertical mode: nothing
keeps you from toggling between vertical and horizontal while
insert-kill-ring-item
is active. Once the command finishes running,
your previous completion configuration will be restored.
Both the :separator
and :height
are optional and default to
icomplete-vertical-separator
and to
icomplete-vertical-prospects-height
, respectively. If you omit both
parts you still need to include the empty parenthesis:
(icomplete-vertical-do () ...)
!.
Everything described above for the variable
icomplete-vertical-separator
, applies equally to the separator passed
to icomplete-vertical-do
: if it is a symbol it is looked up in
icomplete-vertical-separator-alist
; if it is a string it should
contain at least one newline, it can have text properties, such as
faces, which control the display, and if it has no faces it will have
icomplete-vertical-separator
face applied to it. For example, the
following specification makes a red dotted line:
(:separator (propertize "\n··········\n" 'face '(:foreground "red"))
:height 20)
This package contains the icomplete-vertical-do
macro for you to
implement your own commands. It does not define any commands that use
the macro.