Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for ssh completion using files in .ssh/config.d too #529

37 changes: 30 additions & 7 deletions completions/ssh.completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,44 @@ function _omb_completion_ssh {
local cur
_omb_completion_reassemble_breaks :

local -a options
if [[ $cur == *@* ]] ; then
local -a options=(-P "${cur%%@*}@" -- "${cur#*@}")
options=(-P "${cur%%@*}@" -- "${cur#*@}")
else
local -a options=(-- "$cur")
options=(-- "$cur")
fi

local IFS=$'\n'

# parse all defined hosts from .ssh/config
if [[ -r $HOME/.ssh/config ]]; then
COMPREPLY=($(compgen -W "$(grep ^Host "$HOME/.ssh/config" | awk '{for (i=2; i<=NF; i++) print $i}' )" "${options[@]}"))
if [[ -r ~/.ssh/config ]]; then
local -a config_files=(~/.ssh/config)

# check if .ssh/config contains Include options
local -a include_patterns
_omb_util_split include_patterns "$(awk -F' ' '/^Include/{print $2}' ~/.ssh/config 2>/dev/null)" $'\n'
local i
for i in "${!include_patterns[@]}"; do
# relative or absolute path, if relative transforms to absolute
[[ ${include_patterns[i]} == /* ]] || include_patterns[i]=~/.ssh/${include_patterns[i]}
done

# interpret possible globbing
local -a include_files
_omb_util_glob_expand include_files '${include_patterns[*]}'
local include_file
for include_file in "${include_files[@]}";do
# parse all defined hosts from that file
[[ -s $include_file ]] && config_files+=("$include_file")
done
akinomyoga marked this conversation as resolved.
Show resolved Hide resolved

COMPREPLY+=($(compgen -W "$(awk '/^Host/ {for (i=2; i<=NF; i++) print $i}' "${config_files[@]}")" "${options[@]}"))
fi

# parse all hosts found in .ssh/known_hosts
if [[ -r $HOME/.ssh/known_hosts ]]; then
if grep -v -q -e '^ ssh-rsa' "$HOME/.ssh/known_hosts" ; then
COMPREPLY+=($(compgen -W "$( awk '{print $1}' "$HOME/.ssh/known_hosts" | grep -v ^\| | cut -d, -f 1 | sed -e 's/\[//g' | sed -e 's/\]//g' | cut -d: -f1 | grep -v ssh-rsa)" "${options[@]}"))
if [[ -r ~/.ssh/known_hosts ]]; then
if grep -v -q -e '^ ssh-rsa' ~/.ssh/known_hosts; then
COMPREPLY+=($(compgen -W "$( awk '{print $1}' ~/.ssh/known_hosts | grep -v ^\| | cut -d, -f 1 | sed -e 's/\[//g' | sed -e 's/\]//g' | cut -d: -f1 | grep -v ssh-rsa)" "${options[@]}"))
fi
fi

Expand Down
22 changes: 14 additions & 8 deletions lib/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ function _omb_util_add_prompt_command {
}

## @fn _omb_util_split array str [sep]
## Split STR with SEP in a safe way and store the result in ARRAY.
## @param[out] array
## The name of an array variable to which the split result is stored.
## @param[in] str
## The string to split
## @param[in,opt]
## The set of separator characters. The default is ' <tab><newline>'.
function _omb_util_split {
local __set=$- IFS=${3:-$' \t\n'}
set -f
Expand All @@ -374,6 +381,13 @@ function _omb_util_split {
return 0
}

## @fn _omb_util_glob_expand array glob
## Perform the pathname expansion of a glob pattern GLOB in a safe way and
## store the filenames in ARRAY.
## @param[out] array
## The name of an array variable to which the filenames are stored.
## @param[in] glob
## The glob pattern that is attempted to match filenames
function _omb_util_glob_expand {
local __set=$- __shopt __gignore=$GLOBIGNORE
_omb_util_get_shopt failglob nullglob extglob
Expand All @@ -400,14 +414,6 @@ function _omb_util_glob_expand {
return 0
}

function _omb_util_split {
local __set=$- IFS=${3:-$' \t\n'}
set -f
eval -- "$1=(\$2)"
[[ $__set == *f* ]] || set +f
return 0
}

function _omb_util_alias {
case ${OMB_DEFAULT_ALIASES:-enable} in
(disable) return 0 ;;
Expand Down
Loading