I'm writing a function that mimics the ssh command host completion; the main difference being that it uses the hosts of the xyz.com domain found in ~/.ssh/known_hosts for the completion.
Here is the function:
_xyzssh() {
COMPREPLY=()
local arg="${COMP_WORDS[COMP_CWORD]}"
[[ $arg != -* ]] || return 0
[ -f ~/.ssh/known_hosts ] || return 0
local -a known_hosts
read -d '' -a known_hosts < <(awk '{
n = split($1,arr,",");
for (i = 1; i <= n; i++)
if (arr[i] ~ /\.xyz\.com$/)
print arr[i]
}' ~/.ssh/known_hosts)
if [[ $arg == *@* ]]
then
known_hosts=( ${known_hosts[@]/#/${arg%%@*}@} )
fi
COMPREPLY=( $(compgen -W "${known_hosts[*]}" -- $arg) )
return 0
}
complete -F _xyzssh xyzssh
This code works fine in Linux (bash 4.2) but it has a weird behavior in macOS (bash 3.2). For example, when I type:
xyzssh -X user@server Tab
On Linux it completes with:
xyzssh -X user@server.xyz.comOn macOS it "doubles" the username:
xyzssh -X useruser@server.xyz.com
I'm guessing that there is something fishy with the @ because when I type:
xyzssh -X user\@server Tab
It completes correctly on both Linux and macOS.
Is there a way to fix this behavior on macOS? fixed: see accepted answer below
Update
Just found out about COMP_WORDBREAKS, which contains @ in macOS while in Linux it doesn't.
I can fix the issue when I set COMP_WORDBREAKS="${COMP_WORDBREAKS//@}" in the shell, but making the change resilient is not that easy in macOS (exporting this setting in my .bash_profile or .bashrc doesn't seem to work)...
Update
I got other issues, with Solaris (bash 4.4) this time, in which ${COMP_WORDS[COMP_CWORD]} doesn't even contain the user@ part when the completion function is called... I' m still investigating how to fix it. fixed: see accepted answer below
It's my first time writing a completion function so I might be missing something obvious.