Is there a shell which supports fuzzy completion as in Sublime Text?

I'm using bash and I was wondering if there is any plugin in bash or other shell which allows me to do this cat tfnislong.txt + [tab] completes to cat ThisFileNameIsSoLong.txt just like tab completion in Sublime Text.


Solution 1:

I know of https://github.com/mgalgs/fuzzy_bash_completion which is a bunch of shell functions used with complete.

I think we could probably do a little better though, be more concise. Time to bust open your .bashrc or .profile...

The basic hook we use is this:

complete -o nospace -o filenames -F fuzzypath cd ls cat

-F option means use a shell function for the tab-completion, where the options are set in the COMPREPLY variable. So for example:

function fuzzypath() {
    if [ -z $2 ] 
    then
        COMPREPLY=( `ls` )
    else
        DIRPATH=`echo "$2" | gsed 's|[^/]*$||'`
        BASENAME=`echo "$2" | gsed 's|.*/||'`
        FILTER=`echo "$BASENAME" | gsed 's|.|\0.*|g'`
        COMPREPLY=( `ls $DIRPATH | grep -i "$FILTER" | gsed "s|^|$DIRPATH|g"` )
    fi
}

where DIRPATH is everything before the last / on your path that you're typing and BASENAME is where your cursor is currently.

FILTER is where the fuzzy-ness comes in. Basically, take BASENAME and insert a .* between every char to produce our fuzz regex.

The rest is just combining the regex with ls to produce COMPREPLY. You may find more clever things to do here, maybe with find.

I also found http://fahdshariff.blogspot.com/2011/04/writing-your-own-bash-completion.html to be useful.

Solution 2:

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

Its install script will setup CTRL-T keybinding for your shell. The following GIF shows how it works.

Solution 3:

To go along with your other answer, you might want to look into zsh. It's backwards compatible with bash so you can use it as a drop in replacement, but it supports significantly expanded features and one of them is greatly enhanced context aware tab completion.

zsh Completion FAQ expands on the use cases, but I do believe that per your example, you would be most interested in the COMPLETE_IN_WORDfunction. It is not quite the desired behavior, but it's close. The main point is that there are a lot of ways to extend upon the base functionality in a maybe more approachable way than using bash.

Here is a fuzzy match extension that would approximate what you want more specifically; zsh-fuzzy match

For some ideas you could take a look at the popular oh-my-zsh framework that has a number of functions for managing zsh and extending it. It's more than you want, most likely, but under the plugins you'll note auto-completion scripts for a variety of roles. To get an idea of the capabilities.