diff --git a/plugins/ssh/ssh.plugin.zsh b/plugins/ssh/ssh.plugin.zsh index b5b050536..545730efa 100644 --- a/plugins/ssh/ssh.plugin.zsh +++ b/plugins/ssh/ssh.plugin.zsh @@ -4,16 +4,52 @@ # Filter out wildcard host sections. _ssh_configfile="$HOME/.ssh/config" if [[ -f "$_ssh_configfile" ]]; then - _ssh_hosts=($( - egrep '^Host.*' "$_ssh_configfile" |\ - awk '{for (i=2; i<=NF; i++) print $i}' |\ - sort |\ - uniq |\ - grep -v '^*' |\ - sed -e 's/\.*\*$//' - )) - zstyle ':completion:*:hosts' hosts $_ssh_hosts + + parse_ssh_config() { + local config_file="$1" + + if [[ -f "$config_file" ]]; then + # Extract all "Host" entries + local hosts=($( + egrep -i '^Host.*' "$config_file" |\ + awk '{for (i=2; i<=NF; i++) print $i}' |\ + sort |\ + uniq |\ + grep -v '^*' |\ + sed -e 's/\.*\*$//' + )) + + # Add hosts to the global array + _ssh_hosts+=("${hosts[@]}") + + # Handle Include directives by reading the files they reference + local includes=($(egrep '^Include ' "$config_file" | awk '{print $2}')) + + # Loop through each included file or pattern + for include in "${includes[@]}"; do + + # Resolve relative paths and handle wildcards + for file in $(eval echo $include); do + parse_ssh_config "$file" + done + done + fi + } + + + _ssh_hosts=() + # Start parsing from the main SSH config file + _ssh_configfile="$HOME/.ssh/config" + parse_ssh_config "$_ssh_configfile" + _final_hosts=($(sort <<< "${_ssh_hosts[@]}" |\ + uniq |\ + grep -v '^*' |\ + sed -e 's/\.*\*$//' + )) + + zstyle ':completion:*:hosts' hosts $_final_hosts unset _ssh_hosts + unset _final_hosts fi unset _ssh_configfile