Autocomplete for Zsh
This plugin for Zsh adds real-time type-ahead autocompletion to your command line, similar to what
you find desktop apps. While you type on the command line, available completions are listed
automatically; no need to press any keyboard shortcuts. Press Tab to insert the top
completion or ↓ to select a different one.
Additional features:
- Out-of-the-box configuration of Zsh's completion system
- Multi-line history search
- Completion of recent directories
- Useful keyboard shortcuts
- Easy to configure
Enjoy using this software? Become a sponsor! 💝
Requirements
Recommended:
- Tested to work with Zsh 5.8 and newer.
Minimum:
- Should theoretically work with Zsh 5.4, but I'm unable to test that.
Installation & setup
First, install Autocomplete itself. Here are some way to do so:
- To use only releases (instead of the
main
branch), install zsh-autocomplete
with a package
manager. As of this writing, this package is available through Homebrew, Nix, pacman
, Plumage,
and (as app-shells/zsh-autocomplete
) Portage. - To always use the latest commit on the
main
branch, do one of the following:
After installing, make the following modifications to your shell config:
Finally, restart your shell. Here's two ways to do so:
- Open a new tab or window in your terminal.
- Replace the current shell with a new one:
% exec zsh
Updating
If you installed manually, run:
% git -C ~autocomplete pull
Otherwise, simply use your package manager or plugin manager's update mechanisms.
Uninstalling
- Revert the actions you took to install.
- Restart your shell.
Keyboard shortcuts
main | emacs | vicmd | On the command line | In the menus |
---|
Enter Return | | | | Exit menu text search or exit menu |
Tab | | | Insert first listed menu item | Exit menu text search or exit menu |
ShiftTab | | | Insert substring occurring in all listed completions | Exit menu text search or exit menu |
↓ | CtrlN | J | Cursor down or enter completion menu | Change selection |
↑ | CtrlP | K | Cursor up or enter history menu | Change selection |
Alt↓ | AltN | CtrlN | Enter completion menu | Next section |
Alt↑ | AltP | CtrlP | Enter history menu | Previous section |
PgDn | | | | Page down |
PgUp | | | | Page up |
| CtrlX / | | Toggle recent path search | |
| CtrlR | / | Toggle history search | Start menu text search or go to previous match |
| CtrlS | ? | Start menu text search | Start menu text search or go to next match |
| CtrlSpace | V | Toggle selection mode | Add another item |
| Ctrl- Ctrl/ | U | | Undo last item |
| CtrlG | | | Undo all added items |
Caveats
main
is whichever keymap was aliased to main
when Autocomplete was sourced.
- By default, this is
emacs
. - If you run
bindkey -v
before sourcing Autocomplete, then main
will be viins
when
Autocomplete installs keybindings.
- Plugins or other scripts that you load after loading Autocomplete may override these bindings.
If you find that some shortcuts don't work as expected, then you can fix them by
- changing the order in which you source your plugins or by
- running
bindkey
commands in your dotfiles after you source your plugins.
- Depending on your terminal, not all keybindings might be available to you.
- Instead of Alt, your terminal might require you to press Escape,
Option or Meta.
- In the menus, the bindings listed under
vicmd
require you to press Alt for each,
instead of just once. - The bindings listed under
emacs
and vicmd
are always both active in the menus, no matter which
keymap you actually use. This is a limitation of Zsh. - What any other keys do while you're in a menu depends on the keymap from which you opened the
menu. See the Zsh manual section on menu
selection for more info.
Configuration
The following are the most commonly requested ways to configure Autocomplete's behavior. To use any
of these, add the code shown to your .zshrc
file and modify it there, then restart you shell.
Reassign keys
You can use Zsh's bindkey
command, after loading
Autocomplete, to customize your keybindings. Below are some examples of what you can do with this.
Make Tab and ShiftTab cycle completions on the command line
This makes Tab and ShiftTab, when pressed on the command line,
cycle through listed completions, without changing what's listed in the menu:
bindkey '^I' menu-complete
bindkey "$terminfo[kcbt]" reverse-menu-complete
Make Tab and ShiftTab go to the menu
This makes Tab and ShiftTab, when pressed on the command line,
enter the menu instead of inserting a completion:
bindkey '^I' menu-select
bindkey "$terminfo[kcbt]" menu-select
Make Tab and ShiftTab change the selection in the menu
This makes Tab and ShiftTab move the selection in the menu right
and left, respectively, instead of exiting the menu:
bindkey -M menuselect '^I' menu-complete
bindkey -M menuselect "$terminfo[kcbt]" reverse-menu-complete
Make ← and → always move the cursor on the command line
This makes ← and → always move the cursor on the command line, even when you
are in the menu:
bindkey -M menuselect '^[[D' .backward-char '^[OD' .backward-char
bindkey -M menuselect '^[[C' .forward-char '^[OC' .forward-char
Make Enter always submit the command line
This makes Enter always submit the command line, even when you are in the menu:
bindkey -M menuselect '^M' .accept-line
Restore Zsh-default functionality
Autocomplete overrides the behavior of some of Zsh's built-in keyboard widgets. To use the original
widget instead, prefix it with a .
:
bindkey '^R' .history-incremental-search-backward
bindkey '^S' .history-incremental-search-forward
Pass arguments to compinit
If necessary, you can let Autocomplete pass arguments to compinit
as follows:
zstyle '*:compinit' arguments -D -i -u -C -w
First insert the common substring
You can make any completion widget first insert the longest sequence of characters
that will complete to all completions shown, if any, before inserting actual completions:
# all Tab widgets
zstyle ':autocomplete:*complete*:*' insert-unambiguous yes
# all history widgets
zstyle ':autocomplete:*history*:*' insert-unambiguous yes
# ^S
zstyle ':autocomplete:menu-search:*' insert-unambiguous yes
Insert prefix instead of substring
When using the above, if you want each widget to first try to insert only the longest prefix that
will complete to all completions shown, if any, then add the following:
zstyle ':completion:*:*' matcher-list 'm:{[:lower:]-}={[:upper:]_}' '+r:|[.]=**'
Note, though, that this will also slightly change what completions are listed initially. This is a
limitation of the underlying implementation in Zsh.
Make Enter submit the command line straight from the menu
By default, pressing Enter in the menu search exits the search and
pressing it otherwise in the menu exits the menu. If you instead want to make
Enter always submit the command line, use the following:
bindkey -M menuselect '\r' .accept-line
Add or don't add a space after certain completions
When inserting a completion, a space is added after certain types of
completions. The default list is as follows:
zstyle ':autocomplete:*' add-space \
executables aliases functions builtins reserved-words commands
Modifying this list will change when a space is inserted. If you change the
list to '*'
, a space is always inserted. If you put no elements in the list,
then a space is never inserted.
Start each command line in history search mode
This will make Autocomplete behave as if you pressed CtrlR at the start of each new command line:
zstyle ':autocomplete:*' default-context history-incremental-search-backward
Wait for a minimum amount of input
To suppress autocompletion until a minimum number of characters have been typed:
zstyle ':autocomplete:*' min-input 3
Wait with autocompletion until typing stops for a certain amount of seconds
Normally, Autocomplete fetches completions after you stop typing for about 0.05 seconds. You can
change this as follows:
zstyle ':autocomplete:*' delay 0.1 # seconds (float)
Don't show completions if the current word matches a pattern
For example, this will stop completions from showing whenever the current word consists of two or more dots:
zstyle ':autocomplete:*' ignored-input '..##'
Change the max number of lines shown
By default, Autocomplete lets the history menu fill half of the screen, and limits all real-time
listings to a maximum of 16 lines. You can change these limits as follows:
# Note: -e lets you specify a dynamically generated value.
# Override default for all listings
# $LINES is the number of lines that fit on screen.
zstyle -e ':autocomplete:*:*' list-lines 'reply=( $(( LINES / 3 )) )'
# Override for recent path search only
zstyle ':autocomplete:recent-paths:*' list-lines 10
# Override for history search only
zstyle ':autocomplete:history-incremental-search-backward:*' list-lines 8
# Override for history menu only
zstyle ':autocomplete:history-search-backward:*' list-lines 2000
Note that for all real-time listings, the maximum number of lines is additionally capped to the
number of lines that fit on screen. However, there is no such limit for the history menu. If that
generates more lines than fit on screen, you can simply use PgUp and PgDn to
scroll through the excess lines. (Note: On some terminals, you have to additionally hold
Shift or, otherwise, it will scroll the terminal buffer instead.)
Use a custom backend for recent directories
Autocomplete comes with its own backend for keeping track of and listing recent directories (which
uses part of
cdr
under the
hood). However, you can override this and supply Autocomplete with recent directories from any
source that you like. To do so, define a function like this:
+autocomplete:recent-directories() {
<code>
typeset -ga reply=( <any number of absolute paths> )
}
Add a backend for recent files
Out of the box, Autocomplete doesn't track or offer recent files. However, it will do so if you add
a backend for it:
+autocomplete:recent-files() {
<code>
typeset -ga reply=( <any number of absolute paths> )
}
Troubleshooting
Try the steps in the
bug report template.
Author
© 2020-2023 Marlon Richert
License
This project is licensed under the MIT License. See the LICENSE file
for details.