aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2018-12-01 02:00:56 +1300
committerTom Ryder <tom@sanctum.geek.nz>2018-12-01 02:00:56 +1300
commita8aae547155d873dd0f94aa92b4fca524ce15797 (patch)
tree07cc4fe456795498a5f52f133d87b2ab90a3a164
parentUse more idiomatic short-circuit for -r in bashrc (diff)
downloaddotfiles-a8aae547155d873dd0f94aa92b4fca524ce15797.tar.gz
dotfiles-a8aae547155d873dd0f94aa92b4fca524ce15797.zip
Overhaul ssh_config hosts completion
-rw-r--r--bash/bash_completion.d/_ssh_config_hosts.bash62
1 files 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
+ )
}