summaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorTimofei Bredov <12125537+rebrendov@users.noreply.github.com>2023-09-17 18:15:04 +0300
committerGitHub <noreply@github.com>2023-09-18 00:15:04 +0900
commitedfdcc8cee31e227a5f7eda9c1faa4893757645c (patch)
treebc608c1a782057a87a0fec09c9597038d475b646 /shell
parent3982c9a552c7000bf1e4dbc667291bb6e64b4228 (diff)
Basic context-aware completion for ssh command (#3424)
Co-authored-by: Junegunn Choi <junegunn.c@gmail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/completion.bash37
-rw-r--r--shell/completion.zsh33
2 files changed, 52 insertions, 18 deletions
diff --git a/shell/completion.bash b/shell/completion.bash
index 9474ea03..c1a319b9 100644
--- a/shell/completion.bash
+++ b/shell/completion.bash
@@ -280,13 +280,33 @@ _fzf_proc_completion_post() {
awk '{print $2}'
}
+__fzf_list_hosts() {
+ command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2> /dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?%]') \
+ <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
+ <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
+ awk -v "user=$1" '{if (length($2) > 0) {print user $2}}' | sort -u
+}
+
_fzf_host_completion() {
- _fzf_complete +m -- "$@" < <(
- command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2> /dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?%]') \
- <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
- <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
- awk '{if (length($2) > 0) {print $2}}' | sort -u
- )
+ _fzf_complete +m -- "$@" < <(__fzf_list_hosts "")
+}
+
+# Values for $1 $2 $3 are described here
+# https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html
+# > the first argument ($1) is the name of the command whose arguments are being completed,
+# > the second argument ($2) is the word being completed,
+# > and the third argument ($3) is the word preceding the word being completed on the current command line.
+_fzf_complete_ssh() {
+ case $3 in
+ -i|-F|-E)
+ _fzf_path_completion "$@"
+ ;;
+ *)
+ local user=
+ [[ "$2" =~ '@' ]] && user="${2%%@*}@"
+ _fzf_complete +m -- "$@" < <(__fzf_list_hosts "$user")
+ ;;
+ esac
}
_fzf_var_completion() {
@@ -351,6 +371,9 @@ for cmd in $d_cmds; do
__fzf_defc "$cmd" _fzf_dir_completion "-o nospace -o dirnames"
done
+# ssh
+__fzf_defc ssh _fzf_complete_ssh "-o default -o bashdefault"
+
unset cmd d_cmds a_cmds
_fzf_setup_completion() {
@@ -376,7 +399,7 @@ _fzf_setup_completion() {
# Environment variables / Aliases / Hosts / Process
_fzf_setup_completion 'var' export unset printenv
_fzf_setup_completion 'alias' unalias
-_fzf_setup_completion 'host' ssh telnet
+_fzf_setup_completion 'host' telnet
_fzf_setup_completion 'proc' kill
fi
diff --git a/shell/completion.zsh b/shell/completion.zsh
index bb256d99..1b9d5594 100644
--- a/shell/completion.zsh
+++ b/shell/completion.zsh
@@ -215,21 +215,32 @@ _fzf_complete() {
command rm -f "$fifo"
}
+__fzf_list_hosts() {
+ setopt localoptions nonomatch
+ command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2> /dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?%]') \
+ <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
+ <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
+ awk -v "user=$1" '{if (length($2) > 0) {print user $2}}' | sort -u
+}
+
_fzf_complete_telnet() {
- _fzf_complete +m -- "$@" < <(
- command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0' |
- awk '{if (length($2) > 0) {print $2}}' | sort -u
- )
+ _fzf_complete +m -- "$@" < <(__fzf_list_hosts "")
}
+# The first and the only argument is the LBUFFER without the current word that contains the trigger.
+# The current word without the trigger is in the $prefix variable passed from the caller.
_fzf_complete_ssh() {
- _fzf_complete +m -- "$@" < <(
- setopt localoptions nonomatch
- command cat <(command tail -n +1 ~/.ssh/config ~/.ssh/config.d/* /etc/ssh/ssh_config 2> /dev/null | command grep -i '^\s*host\(name\)\? ' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}' | command grep -v '[*?%]') \
- <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
- <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
- awk '{if (length($2) > 0) {print $2}}' | sort -u
- )
+ local tokens=(${(z)1})
+ case ${tokens[-1]} in
+ -i|-F|-E)
+ _fzf_path_completion "$prefix" "$1"
+ ;;
+ *)
+ local user=
+ [[ $prefix =~ @ ]] && user="${prefix%%@*}@"
+ _fzf_complete +m -- "$@" < <(__fzf_list_hosts "$user")
+ ;;
+ esac
}
_fzf_complete_export() {