21

I've recently fallen in love with efficient text completion systems. One of my favourite kinds of completion is so-called fuzzy completion. This is a mode where the program will complete the user's input based on only a couple of characters that can occur 'anywhere' (almost) in the file name or path. This feature exists at least for these programs:

Usage example of this mode in a text editor:

User is trying to complete the word longWordNameThatTheyDontWantToWriteByHand, and they can do so by typing e.g. the first letter and some of the capital case letters. So typing lwnt could complete to the whole word.

My question is: is there a mode or something similar that I could use with the zsh shell?

26

I have this in my .zshrc

# 0 -- vanilla completion (abc => abc)
# 1 -- smart case completion (abc => Abc)
# 2 -- word flex completion (abc => A-big-Car)
# 3 -- full flex completion (abc => ABraCadabra)
zstyle ':completion:*' matcher-list '' \
  'm:{a-z\-}={A-Z\_}' \
  'r:[^[:alpha:]]||[[:alpha:]]=** r:|=* m:{a-z\-}={A-Z\_}' \
  'r:|?=** m:{a-z\-}={A-Z\_}'

It adds full fuzzy matching to zsh's completion engine. It lacks the super smarts of sublime text, but, yes, it will complete lwnt -> longWordNameThatTheyDontWantToWriteByHand.

  • 1
    I just found a bug: doesn't work for filenames with spaces, given you're typing anything after the space ☹ I.e. stack install && vlc ~/Music/erf doesn't complete to stack install && vlc ~/Music/FGFC820\ -\ Perfect\ War.mp3. – Hi-Angel Aug 28 '16 at 19:44
  • 5
    @Hi-Angel hey, thanks for bumping this. I actually use 'r:|?=** m:{a-z\-}={A-Z\_}' now, which is a bunch simpler, and doesn't suffer from the problem you describe. – PythonNut Sep 1 '16 at 23:05
  • That's great! Maybe you could make a plugin with this code. Just so that it's easier to find. – Julien__ Nov 26 '18 at 1:13
15

Check out my project fzf.

It's a general purpose fuzzy finder written in Golang that can be used with any list of things: files, processes, command history, git branches, etc.

For zsh, it provide the following key bindings:

  • CTRL-T - Paste the selected file path(s) into the command line
  • CTRL-R - Paste the selected command from history into the command line
  • ALT-C - cd into the selected directory

and fuzzy completion mode:

# Files under current directory
# - You can select multiple items with TAB key
vim **<TAB>

# Files under parent directory
vim ../**<TAB>

# Files under parent directory that match `fzf`
vim ../fzf**<TAB>

# Files under your home directory
vim ~/**<TAB>

# Directories under current directory (single-selection)
cd **<TAB>

# Directories under ~/github that match `fzf`
cd ~/github/fzf**<TAB>

# Process IDs. Can select multiple processes with TAB or Shift-TAB
kill -9 <TAB>

# Host names
ssh **<TAB>
telnet **<TAB>

# Environment variables / aliases
unset **<TAB>
export **<TAB>
unalias **<TAB>
  • 3
    How can I make it tab complete with this by default? Without having to type ** – theonlygusti Nov 9 '17 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.