From 0b19577ed94eae55ad80bd5b0a0583de7af82dcf Mon Sep 17 00:00:00 2001 From: Freddy Vulto Date: Sat, 13 Jun 2009 08:38:52 +0200 Subject: [PATCH] Added -h HOST option to _known_hosts_real Modified call to _known_hosts_real in ssh, vncviewer and xhost completions. --- bash_completion | 33 +++++----- contrib/ssh | 39 ++++++------ contrib/vncviewer | 8 +-- contrib/xhost | 23 ++----- test/lib/completions/xhost.exp | 112 +++++++++++++++++++++++++++++++++ 5 files changed, 156 insertions(+), 59 deletions(-) diff --git a/bash_completion b/bash_completion index d261d3e8..c881520a 100644 --- a/bash_completion +++ b/bash_completion @@ -1045,13 +1045,7 @@ _user_at_host() { } shopt -u hostcomplete && complete -F _user_at_host $nospace talk ytalk finger -# This function performs host completion based on ssh's known_hosts files, -# defaulting to standard host completion if they don't exist. -# -# Arguments: -a Use aliases -# -c Use `:' suffix -# -F configfile Use `configfile' for configuration settings -# -h host Complete on given host +# See: _known_hosts_real() _known_hosts() { local cur @@ -1062,19 +1056,30 @@ _known_hosts() _known_hosts_real "$@" } +# Helper function for completing _known_hosts. +# This function performs host completion based on ssh's known_hosts files, +# defaulting to standard host completion if they don't exist. +# Arguments: -a Use aliases +# -c Use `:' suffix +# -F configfile Use `configfile' for configuration settings +# -h hostname Use hostname to complete on +# -p PREFIX Use PREFIX +# Return: Completions are added to COMPREPLY[] _known_hosts_real() { - local configfile flag - local curd ocur user suffix aliases global_kh user_kh hosts i host + local configfile flag prefix + local cur curd ocur user suffix aliases global_kh user_kh hosts i host local -a kh khd config local IFS=$'\n' local OPTIND=1 - while getopts "acF:" flag "$@"; do + while getopts "acF:h:p:" flag "$@"; do case $flag in a) aliases='yes' ;; c) suffix=':' ;; - F) configfile="$OPTARG" ;; + F) configfile=$OPTARG ;; + h) cur=$OPTARG ;; + p) prefix=$OPTARG ;; esac done @@ -1190,17 +1195,15 @@ _known_hosts_real() # Now add results of normal hostname completion COMPREPLY=( "${COMPREPLY[@]}" $( compgen -A hostname -- $ocur ) ) - # apply suffix + # apply suffix and prefix for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do - COMPREPLY[i]=$user${COMPREPLY[i]}$suffix + COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix done elif [ -z "$configfile" ]; then # Just do normal hostname completion COMPREPLY=( $( compgen -A hostname -S "$suffix" -- $cur ) ) fi - [ $ocur ] && cur=$ocur || unset -v cur - return 0 } complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 \ diff --git a/contrib/ssh b/contrib/ssh index 627f9b02..8a9993a5 100644 --- a/contrib/ssh +++ b/contrib/ssh @@ -80,25 +80,22 @@ _ssh() -N -n -q -s -T -t -V -v -X -v -Y -y -b -b -c -D -e -F \ -i -L -l -m -O -o -p -R -S -w' -- $cur ) ) else - #if [ $COMP_CWORD -eq 1 ]; then - # Search COMP_WORDS for '-F configfile' argument - set -- "${COMP_WORDS[@]}" - while [ $# -gt 0 ]; do - if [ "${1:0:2}" = -F ]; then - if [ ${#1} -gt 2 ]; then - optconfigfile="$(dequote "$1")" - else - shift - [ "$1" ] && optconfigfile="$(dequote "-F$1")" - fi - break + # Search COMP_WORDS for '-F configfile' argument + set -- "${COMP_WORDS[@]}" + while [ $# -gt 0 ]; do + if [ "${1:0:2}" = -F ]; then + if [ ${#1} -gt 2 ]; then + optconfigfile="$(dequote "$1")" + else + shift + [ "$1" ] && optconfigfile="$(dequote "-F$1")" fi - shift - done - _known_hosts_real -a "$optconfigfile" - #else - COMPREPLY=( "${COMPREPLY[@]}" $( compgen -c -- $cur ) ) - #fi + break + fi + shift + done + _known_hosts_real -a "$optconfigfile" -h "$cur" + COMPREPLY=( "${COMPREPLY[@]}" $( compgen -c -- $cur ) ) fi return 0 @@ -145,7 +142,7 @@ _sftp() fi shift done - _known_hosts_real -a "$optconfigfile" + _known_hosts_real -a "$optconfigfile" -h "$cur" fi return 0 @@ -201,7 +198,7 @@ _scp() shift done - [[ "$cur" == */* ]] || _known_hosts_real -c -a "$optconfigfile" + [[ "$cur" == */* ]] || _known_hosts_real -c -a "$optconfigfile" -h "$cur" # This approach is used instead of _filedir to get a space appended # after local file/dir completions, and $nospace retained for others. @@ -234,7 +231,7 @@ _ssh_copy_id() { if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '-i' -- $cur ) ) else - _known_hosts_real -a + _known_hosts_real -a -h "$cur" fi return 0 diff --git a/contrib/vncviewer b/contrib/vncviewer index be9dc412..8cfdd987 100644 --- a/contrib/vncviewer +++ b/contrib/vncviewer @@ -41,7 +41,7 @@ _tightvncviewer() return 0 ;; -via) - _known_hosts + _known_hosts_real -h "$cur" return 0 ;; esac @@ -54,7 +54,7 @@ _tightvncviewer() -compresslevel -quality -nojpeg -nocursorshape \ -x11cursor' -- $cur ) ) else - _known_hosts + _known_hosts_real -h "$cur" fi } && complete -F _tightvncviewer tightvncviewer @@ -85,7 +85,7 @@ _xvnc4viewer() ;; # -via -[vV][iI][aA]) - _known_hosts + _known_hosts_real -h "$cur" return 0 ;; esac @@ -121,7 +121,7 @@ _xvnc4viewer() )" -- "$(echo "$cur" | tr [:upper:] [:lower:])" ) ) fi else - _known_hosts + _known_hosts_real -h "$cur" fi } && complete -F _xvnc4viewer xvnc4viewer diff --git a/contrib/xhost b/contrib/xhost index 04c12c22..fd21255f 100644 --- a/contrib/xhost +++ b/contrib/xhost @@ -6,27 +6,12 @@ have xhost && _xhost () { - local cur i - cur=`_get_cword` + local cur=`_get_cword` case "$cur" in - +*) - cur=${cur:1} - _known_hosts_real - for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do - COMPREPLY[i]=+${COMPREPLY[i]} - done - ;; - -*) - cur=${cur:1} - _known_hosts_real - for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do - COMPREPLY[i]=-${COMPREPLY[i]} - done - ;; - *) - _known_hosts_real - ;; + +*) _known_hosts_real -h "${cur:1}" -p+ ;; + -*) _known_hosts_real -h "${cur:1}" -p- ;; + *) _known_hosts_real -h "$cur" ;; esac return 0 diff --git a/test/lib/completions/xhost.exp b/test/lib/completions/xhost.exp index c6e8284a..d7f320d9 100644 --- a/test/lib/completions/xhost.exp +++ b/test/lib/completions/xhost.exp @@ -38,6 +38,44 @@ expect { sync_after_int +set test "Tab should complete partial hostname" + + # Build string list of hostnames, separated by regexp whitespace (\s+) + # Example string: host1\s+host2\s+host3 + +set hosts {} +set char "" +foreach h [exec bash -c "compgen -A hostname"] { + if {$char == ""} {set char [string range $h 0 0]} + # Only append hostname if starting with $char + if {[string range $h 0 0] == "$char"} { + # Escape special regexp characters (+) in hostname + regsub -all {([\+])} $h {\\\1} h + lappend hosts $h + }; # if +}; # foreach + # Try completion +set cmd "xhost $char" +send "$cmd\t" + # Escape possible special regexp characters (+) in cmd +regsub -all {([\+])} $cmd {\\\1} cmd +if {[llength $hosts] == 1} { + set expected "^xhost $hosts " +} else { + set hosts [lsort -ascii $hosts] + set hosts [join $hosts "\\s+"] + set expected "^$cmd\r\n$hosts\r\n/@$cmd$" +}; # if +expect { + -re $expected { pass "$test" } + -re /@ { unresolved "$test at prompt" } + default { unresolved "$test" } +}; # expect + + +sync_after_int + + set test "Tab should complete hostnames prefixed with +" # Build string list of hostnames, separated by regexp whitespace (\s+) and @@ -68,6 +106,44 @@ expect { sync_after_int +set test "Tab should complete partial hostname prefixed with +" + + # Build string list of hostnames, starting with the character of the first + # host. Separate hostnames by regexp whitespace (\s+) and 'plus' (+) + # prefix. Example string: \+host1\s+\+host2\s+\+host3 + +set hosts {} +foreach h [exec bash -c "compgen -A hostname"] { + if {$char == ""} {set char [string range $h 0 0]} + # Only append hostname if starting with $char + if {[string range $h 0 0] == "$char"} { + # Escape special regexp characters (+) in hostname + regsub -all {([\+])} $h {\\\1} h + lappend hosts $h + }; # if +}; # foreach + # Try completion +set cmd "xhost +$char" +send "$cmd\t" +if {[llength $hosts] == 1} { + set expected "^xhost \\+$hosts " +} else { + # Escape special regexp characters (+) in cmd + regsub -all {([\+])} $cmd {\\\1} cmd + set hosts [lsort -ascii $hosts] + set hosts [join $hosts "\\s+"] + set expected "^$cmd\r\n$hosts\r\n/@$cmd$" +}; # if +expect { + -re $expected { pass "$test" } + -re /@ { unresolved "$test at prompt" } + default { unresolved "$test" } +}; # expect + + +sync_after_int + + set test "Tab should complete hostnames prefixed with -" # Build string list of hostnames, separated by regexp whitespace (\s+) and @@ -96,4 +172,40 @@ expect { sync_after_int +set test "Tab should complete partial hostname prefixed with -" + + # Build string list of hostnames, starting with the character of the first + # host. Separate hostnames by regexp whitespace (\s+) and 'minus' (-) + # prefix. Example string: -host1\s+-host2\s+-host3 + +set hosts {} +foreach h [exec bash -c "compgen -A hostname"] { + if {$char == ""} {set char [string range $h 0 0]} + # Only append hostname if starting with $char + if {[string range $h 0 0] == "$char"} { + # Escape special regexp characters (+) in hostname + regsub -all {([\+])} $h {\\\1} h + lappend hosts $h + }; # if +}; # foreach + # Try completion +set cmd "xhost -$char" +send "$cmd\t" +if {[llength $hosts] == 1} { + set expected "^xhost -$hosts " +} else { + set hosts [lsort -ascii $hosts] + set hosts "-[join $hosts "\\s+-"]" + set expected "^$cmd\r\n$hosts\r\n/@$cmd$" +}; # if +expect { + -re $expected { pass "$test" } + -re /@ { unresolved "$test at prompt" } + default { unresolved "$test" } +}; # expect + + +sync_after_int + + teardown