Fuzzy Bash Completion
18 Dec 2021, Bangkok
On my little laptop, I have lots of books organized by tags. And when I’m interested in a particular topic, I’d go to that tag and browse it.
However, I also have a few favourites or currently reading books that I’d like to be able to quickly access. To make it simpler, I decided to put links to these favourites in a separate folder called ~/tags/rread
.
And to make it transparent, listing all these favourites is done via a helper function rread
that relies on bash completion to list all the contents of the folder, which is fine except for one small thing - bash-completion requires exact matching.
$ ls ~/tags/rread # Contents of ~/tags/rread
bash_pocket_reference.pdf
still-flowing-water-ajahn-chah.pdf
$ rread flow[TAB TAB] # No matches
I’d like bash completion to match still-flowing-water-ajahn-chah.pdf
in the example above.
And after digging quite a bit, here’s what I came up with that seemed to do the job.
function rread {
# Tab completion for rread helper
# Usage: rread [TAB Tab]
# ~/tags/rread contains symlinks to actual files
xdg-open ~/tags/rread/${1} &
}
_rread_completions() {
if [ -z ${COMP_WORDS[1]} ];
then
# COMP_WORDS[1] not defined
COMPREPLY=($(compgen -W "$(ls -1 ~/tags/rread )" -- "${COMP_WORDS[1]}"))
else
# COMP_WORDS[1] defined
COMPREPLY=( $(compgen -W "$(ls -1 ~/tags/rread | grep ${2} 2>/dev/null)") )
# grep ${2} 2>/dev/null
# 2>/dev/null - send grep usage errors to /dev/null
# e.g. Usage: grep [OPTION]... PATTERNS [FILE]...
# Try 'grep --help' for more information.
# ${2} - Use this instead of ${COMP_WORDS[1]}
# because otherwise COMPREPLY always has a value
fi
}
complete -F _rread_completions rread
To learn more about bash completion:
Man page on bash completion
help complete
help compgen
GNU manual on bash completion
https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html
Tutorial on bash completion
https://iridakos.com/programming/2018/03/01/bash-programmable-completion-tutorial
A fuzzy bash completion tool
https://github.com/mgalgs/fuzzy_bash_completion