Skip to content

Instantly share code, notes, and snippets.

@Chovin
Last active January 3, 2024 07:17
Show Gist options
  • Save Chovin/b3551a88efc8b1e1b51bdeecdd0002ac to your computer and use it in GitHub Desktop.
Save Chovin/b3551a88efc8b1e1b51bdeecdd0002ac to your computer and use it in GitHub Desktop.
ssh config autocomplete
# # https://thevaluable.dev/zsh-completion-guide-examples/
zstyle ':completion:*:*:*:*:descriptions' format '%F{green}-- %d --%f'
zstyle ':completion:*' menu select
# zstyle ':completion:*' file-list all
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
# # Allow for autocomplete to be case insensitive
# # zstyle ':completion:*' matcher-list '' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' \
# '+l:|?=** r:|?=**'
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
# Define custom SSH autocompletion function
_ssh_completion() {
hosts=()
# ssh config
local CONFIG_FILE=~/.ssh/config
if [ -r $CONFIG_FILE ] ; then
# grabs Host name and ip assuming ip is on the next line
# getline puts the next line into $0
# output is list (Host1a Host1b:ip Host2:ip)
# so we need to fill in the ip of configs with multiple host names
local raw_hosts=(`awk '/^Host [A-Za-z]+/ {$1="";p=$0;getline;printf("%s:%s",p,$2)}' $CONFIG_FILE`)
local len=${#raw_hosts[@]}
local prev_ip=""
for (( i=${len}; i>0; i--))
do
local item="${raw_hosts[$i]}"
# split on :
local parts=(${(s/:/)item})
local ip="${parts[2]}"
if [[ -z "${ip}" ]] ; then
ip="${prev_ip}"
fi
prev_ip="${ip}"
# name:description
hosts[$i]="${parts[1]}:${ip}"
done
fi
_describe 'SSH config' hosts
# tunnels for tun alias
if [ -r $CONFIG_FILE ] ; then
hosts=(`awk '/^#Tunnel [A-Za-z]+/ {printf("%s:%s|%s",$2,$3,$4)}' $CONFIG_FILE`)
local len=${#hosts[@]}
for (( i=${len}; i>0; i--))
do
local item="${hosts[$i]}"
local parts=(${(s/|/)item})
hosts[$i]="${parts[1]} ${parts[2]}"
done
fi
_describe 'tun tunnels' hosts
if [[ -r ~/.ssh/known_hosts ]]; then
# ${var//word_to_replace/sub}
hosts=( ${${${${${(f)"$(cat ~/.ssh/known_hosts{,2} || true)"}%%\ *}//\[/}//\]/}%%,*}) 2>/dev/null
local len=${#hosts[@]}
for (( i=${len}; i>0; i--))
do
local item="${hosts[$i]}"
local parts=(${(s/:/)item})
local port="${parts[2]}"
if [[ ! -z "${port}" ]] ; then
hosts[$i]="${parts[1]}:-p ${port}"
fi
done
fi
# _describe 'known_hosts' hosts
# _wanted hosts expl 'known_hosts' compadd -a hosts
}
compdef _ssh_completion ssh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment