From a8aae547155d873dd0f94aa92b4fca524ce15797 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 1 Dec 2018 02:00:56 +1300 Subject: Overhaul ssh_config hosts completion --- bash/bash_completion.d/_ssh_config_hosts.bash | 62 +++++++++++++++++++-------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/bash/bash_completion.d/_ssh_config_hosts.bash b/bash/bash_completion.d/_ssh_config_hosts.bash index 8f45c412..c26457cf 100644 --- a/bash/bash_completion.d/_ssh_config_hosts.bash +++ b/bash/bash_completion.d/_ssh_config_hosts.bash @@ -1,22 +1,48 @@ # Complete ssh_config(5) hostnames _ssh_config_hosts() { - # Read hostnames from existent config files, no asterisks - local -a hosts - local config option value - for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do - [[ -e $config ]] || continue - while read -r option value _ ; do - [[ $option == Host ]] || continue - [[ $value != *'*'* ]] || continue - hosts[${#hosts[@]}]=$value - done < "$config" - done - - # Generate completion reply - local host - for host in "${hosts[@]}" ; do - [[ $host == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY[${#COMPREPLY[@]}]=$host - done + # Don't complete anything that wouldn't be in a valid hostname + case ${COMP_WORDS[COMP_CWORD]} in + *[!a-zA-Z0-9.-]*) return 1 ;; + esac + + # Iterate through words from a subshell + while read -r word ; do + [[ -n $word ]] || continue + COMPREPLY[${#COMPREPLY[@]}]=$word + done < <( + + # Check bind settings to see if we should match case insensitively + while read -r _ setting ; do + case $setting in + ('completion-ignore-case on') + shopt -qs nocasematch 2>/dev/null + break + ;; + esac + done < <(bind -v) + + # Iterate through SSH client config paths + for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do + [[ -e $config ]] || continue + + # Read Host options and their first value from file + while read -r option value _ ; do + [[ $option == Host ]] || continue + + # Check host value + case $value in + + # Don't complete with wildcard characters + (*'*'*) ;; + + # Found a match; print it + ("${COMP_WORDS[COMP_CWORD]}"*) + printf '%s\n' "$value" + ;; + esac + + done < "$config" + done + ) } -- cgit v1.2.3