15

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.

2
  • Why not just do cat Th + tab?
    – daviewales
    May 20, 2013 at 6:27
  • 4
    @daviewales Display all 269 reasons?
    – Fax
    Feb 26, 2019 at 10:06

3 Answers 3

11

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.

1
  • This approach has the same problem I encountered in a short version I wrote: if you hit tab and there are multiple matching results, they are listed as expected (which is good). But then the fuzzy search string you've typed so far will be replaced by the common prefix of the matching results (which can be bad because it takes your search process back to square one if that common prefix is also shared by other items not in the matching results).
    – FMc
    Nov 28, 2022 at 7:49
7

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.

1
  • FZF is great! Thanks a lot for contributing. This saved me weeks of work..I was starting to write fuzzy completion for Bash when I luckily found FZF. It works perfect, I just had to remember to save cursor position before calling fzf .. (tput sc) and later restore it with tput rc.. Apr 29, 2015 at 10:10
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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .