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_WORD
function. 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.