Skip to content

Global Emacs minor mode to display icomplete candidates vertically

License

Notifications You must be signed in to change notification settings

oantolin/icomplete-vertical

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

icomplete-vertical

https://melpa.org/packages/icomplete-vertical-badge.svg https://stable.melpa.org/packages/icomplete-vertical-badge.svg

Overview

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:

  1. 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.
  2. 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.

Screenshots

This is what describe-function looks like in icomplete-vertical-mode (with Protesilaos Stavrou’s lovely modus-operandi theme):

images/describe-function-vertical.png

For comparison this is what you get without this package, simply setting icomplete-separator to a newline:

images/describe-function-just-sep.png

Notice the missing prompt and text typed so far (icom), and how the first candidate (icomplete-tidy) is on the line where you type.

Installation and usage

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.)

Quick setup with use-package

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.)

About Icomplete

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").

Configuration for icomplete-vertical

Maximum minibuffer height

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.

Fixed or variable height minibuffer

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 candidate separator

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).

Defining your own vertical commands

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.

About

Global Emacs minor mode to display icomplete candidates vertically

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published