SSH Config Host Autocomplete Command not Autocompleting
I wrote a function to get my hosts from ssh config without getting wildcard hosts:
sshConfAutoComplete() {
cat ~/.ssh/config |
grep 'host ' |
sed '
s#.**##g;
s#host ##g
'
}
Output:
pi
lynx
iridium
batchelorantor
rasp
The output is correct, so I added this function to:
/usr/local/etc/bash_completion.d/ssh
Like this:
sshConfAutoComplete() {
cat ~/.ssh/config |
grep 'host ' |
sed '
s#.**##g;
s#host ##g
'
}
complete -F sshConfAutoComplete ssh
Then I added this source: . /usr/local/etc/bash_completion.d/ssh
to ~/.bash_profile
Sourced ~/bash_profile
, then when I type ssh <tab>
the following comes up:
pi
lynx
iridium
batchelorantor
rasp
If I type ssh ly <tab>
it doesn’t autocomplete to lynx
, it just outputs the above.
How do I fix this?
In man bash
the section headed Programmable Completion explains how the
function called by -F
needs to provide the matching results in the array
variable COMPREPLY
. Typically the full list as provided by your sed
commands are passed to the command compgen -W
for it to try matching the
words against the target word, which is arg 2 ($2
) of your function.
Simplifying a little we get:
sshConfAutoComplete() {
COMPREPLY=( $(compgen -W
"$(sed -n ' /host /{s#.**##g; s#host ##g; p} ' ~/.ssh/config)" -- "$2"))
}
complete -F sshConfAutoComplete ssh
For MacOS the standard sed
command does not accept ;
so each command must be on a new line:
COMPREPLY=( $(compgen -W
"$(sed -n '/^host /{
s#.**##g
s#host ##g
p
}' ~/.ssh/config)" -- "$2"))
I got it working doing this and adding it my ~/bash_profile
:
IFS=$'n'
getSshConfHosts() {
grep '^host' ~/.ssh/config |
grep -v '[?*]' |
cut -d ' ' -f 2-
}
sshConfAutoComplete() {
local cur prev opts
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
opts=$(getSshConfHosts)
COMPREPLY=( $(compgen -W "$opts" -- $cur ) )
}
complete -F sshConfAutoComplete ssh
My previous sed command left a blank line at the deletion of host *
Update
This answer works, but I gave it to the accepted answer as he didn’t know I was on Mac, and he hadn’t written it first. His version is much easier to understand.
I use the regex part in another function so I have it like this in my bash_profile
:
IFS=$'n'
getSshConfHosts() {
sed -n '/^host /{
s#.**##g
s#host ##g; p
}' ~/.ssh/config
}
sshConfAutoComplete() {
local wordList
wordList=$(getSshConfHosts)
COMPREPLY=( $(compgen -W "$wordList" -- $2 ) )
}
complete -F sshConfAutoComplete ssh