I often run into programs that lack the vision to use the proper fish shell, and often have to do without fancy completions. I found a VERY nice gist that allows one to do this successfully, and have it seamlessly appear in the fish shell.
Here are some prerequisites that are necessary;
- Bash completion has to be installed
- your completions should be in an approrpiate directory as referenced by the script. For arch this is
/usr/share/bash-completion/completions - You need to use the first part of the gist as the 'caller' to the script which does the magic of working nicely with the automatic replacement of internal fish completions with the bash ones.
- You can edit the alias in your
~/.config/fish/config.fishfile to use the completions you want. I generally prefer to use the fish ones but for bash only, you just add the ones you are interested in.
Here is the gist link. I also include a local copy in case this disappears. Alas to get this to work with GRAV I put a backslash in front of the hash, since it seemed to think it was a shortcode. This is the hardest post I have ever done!
#!/bin/bash
# Author: Brian Beffa <brbsix@gmail.com>
# Original source: https://brbsix.github.io/2015/11/29/accessing-tab-completion-programmatically-in-bash/
# License: LGPLv3 (http://www.gnu.org/licenses/lgpl-3.0.txt)
get_completions(){
local completion COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS COMPREPLY=()
# load bash-completion if necessary
declare -F _completion_loader &>/dev/null || {
if [ -f /etc/bash_completion ]; then
source /etc/bash_completion
elif [ -f /usr/share/bash-completion/bash_completion ]; then
source /usr/share/bash-completion/bash_completion
fi
}
COMP_LINE=$*
# Be sure to remove the backslash here, as grav got mad at the unquoted hash)
COMP_POINT=${\#COMP_LINE}
eval set -- "$@"
COMP_WORDS=("$@")
# add '' to COMP_WORDS if the last character of the command line is a space
[[ ${COMP_LINE[@]: -1} = ' ' ]] && COMP_WORDS+=('')
# index of the last word be sure to remove the backslash in front of comp_words
COMP_CWORD=$(( ${\#COMP_WORDS[@]} - 1 ))
# load completion
_completion_loader "$1"
# detect completion
completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}')
# ensure completion was detected
[[ -n $completion ]] || return 1
# execute completion function
"$completion"
# print completions to stdout be sure to remove the backslash in front of compreply
for ((i = 0; i < ${\#COMPREPLY[@]}; i++)); do
echo "${COMPREPLY[$i]%%*( )}"
done
}
This gets you the basic get-bash-completions.sh script. I put this in ~/bin and make it executable. The second part is to add the following to your ~/.config/fish/config.fish line:
# You can add this to your ~/.config/fish/config.fish
function __fish_complete_bash
set cmd (commandline -cp)
bash -c "source get-bash-completions.sh; get_completions '$cmd'"
end
# Set the tool to use bash completions
complete -xc git -a '(__fish_complete_bash)'
complete -xc gdbus -a '(__fish_complete_bash)'
complete -xc java -a '(__fish_complete_bash)'
complete -xc distrobox -a '(__fish_complete_bash)'
# load bash-completion if necessary
declare -F _completion_loader &>/dev/null || {
if [ -f /etc/bash_completion ]; then
source /etc/bash_completion
This (in my case) that the commands for git, gdbus, java and distrobox are going to use the default bash completions instead of the fish ones. Remember that fish has its own completions which are often superior to the bash ones, but in this case I get the nice completions for distrobox!