diff --git a/bash_completion b/bash_completion index c881520a..f8b17b00 100644 --- a/bash_completion +++ b/bash_completion @@ -1036,7 +1036,7 @@ _user_at_host() { cur=`_get_cword` if [[ $cur == *@* ]]; then - _known_hosts + _known_hosts_real -h "$cur" else COMPREPLY=( $( compgen -u -- "$cur" ) ) fi @@ -1068,7 +1068,7 @@ _known_hosts() _known_hosts_real() { local configfile flag prefix - local cur curd ocur user suffix aliases global_kh user_kh hosts i host + local cur curd awkcur user suffix aliases global_kh user_kh hosts i host local -a kh khd config local IFS=$'\n' @@ -1083,8 +1083,6 @@ _known_hosts_real() esac done - ocur=$cur - [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@} kh=() @@ -1145,22 +1143,22 @@ _known_hosts_real() # If we have known_hosts files to use if [ ${#kh[@]} -gt 0 -o ${#khd[@]} -gt 0 -o -n "$configfile" ]; then # Escape slashes and dots in paths for awk - cur=${cur//\//\\\/} - cur=${cur//\./\\\.} - curd=$cur + awkcur=${cur//\//\\\/} + awkcur=${awkcur//\./\\\.} + curd=$awkcur - if [[ "$cur" == [0-9]*.* ]]; then + if [[ "$awkcur" == [0-9]*.* ]]; then # Digits followed by a dot - just search for that - cur="^$cur.*" - elif [[ "$cur" == [0-9]* ]]; then + awkcur="^$awkcur.*" + elif [[ "$awkcur" == [0-9]* ]]; then # Digits followed by no dot - search for digits followed # by a dot - cur="^$cur.*\." - elif [ -z "$cur" ]; then + awkcur="^$awkcur.*\." + elif [ -z "$awkcur" ]; then # A blank - search for a dot or an alpha character - cur="[a-z.]" + awkcur="[a-z.]" else - cur="^$cur" + awkcur="^$awkcur" fi if [ ${#kh[@]} -gt 0 ]; then @@ -1169,7 +1167,7 @@ _known_hosts_real() COMPREPLY=( $( awk 'BEGIN {FS=","} /^\s*[^|\#]/ {for (i=1; i<=2; ++i) { \ gsub(" .*$", "", $i); \ - if ($i ~ /'$cur'/) {print $i} \ + if ($i ~ /'$awkcur'/) {print $i} \ }}' "${kh[@]}" 2>/dev/null ) ) fi if [ ${#khd[@]} -gt 0 ]; then @@ -1178,7 +1176,7 @@ _known_hosts_real() # dont fork any processes, because in a cluster environment, # there can be hundreds of hostkeys for i in "${khd[@]}" ; do - if [[ "$i" == *key_22_$curd*.pub ]] && [ -r "$i" ] ; then + if [[ "$i" == *key_22_$awkcurd*.pub ]] && [ -r "$i" ] ; then host=${i/#*key_22_/} host=${host/%.pub/} COMPREPLY=( "${COMPREPLY[@]}" $host ) @@ -1188,12 +1186,12 @@ _known_hosts_real() # append any available aliases from config files if [ ${#config[@]} -gt 0 ] && [ -n "$aliases" ]; then local host_aliases=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\?['"$'\t '"']\+\([^#*?]*\)\(#.*\)\?$/\2/p' "${config[@]}" ) - hosts=$( compgen -W "$host_aliases" -- $ocur ) + hosts=$( compgen -W "$host_aliases" -- $cur ) COMPREPLY=( "${COMPREPLY[@]}" $hosts ) fi # Now add results of normal hostname completion - COMPREPLY=( "${COMPREPLY[@]}" $( compgen -A hostname -- $ocur ) ) + COMPREPLY=( "${COMPREPLY[@]}" $( compgen -A hostname -- $cur ) ) # apply suffix and prefix for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do diff --git a/test/completion/finger.exp b/test/completion/finger.exp new file mode 100644 index 00000000..cc77abe5 --- /dev/null +++ b/test/completion/finger.exp @@ -0,0 +1,6 @@ +source "lib/completions/finger.exp" + +# TODO: Dynamic loading of completions. After the tests have run a first time +# and real completion is installed, the tests can be run a second time. +# +# source "lib/completions/finger.exp" diff --git a/test/lib/completions/finger.exp b/test/lib/completions/finger.exp new file mode 100644 index 00000000..c49073a5 --- /dev/null +++ b/test/lib/completions/finger.exp @@ -0,0 +1,148 @@ +proc setup {} { + save_env +}; # setup() + + +proc teardown {} { + assert_env_unmodified +}; # teardown() + + +setup + + +set test "Tab should complete usernames" + + # Build string list of usernames, separated by regexp whitespace (\s+) + # Example string: user1\s+user2\s+user3 + +set users {} +foreach u [exec bash -c "compgen -A user"] { + # Escape special regexp characters (+) in username + regsub -all {([\+])} $u {\\\1} h + lappend users $u +}; # foreach +set users [lsort -ascii $users] +set users [join $users "\\s+"] + # Try completion +set cmd "finger " +send "$cmd\t" +set expected "^$cmd\r\n$users\r\n/@$cmd$" +expect { + -re $expected { pass "$test" } + -re /@ { unresolved "$test at prompt" } + default { unresolved "$test" } +}; # expect + + +sync_after_int + + +set test "Tab should complete partial username" + + # Build string list of usernames, starting with the character of the first + # username. Separate usernames by regexp whitespace (\s+) and 'plus' (+) + # prefix. Example string: \+user1\s+\+user2\s+\+user3 + +set users {} +set char "" +foreach u [exec bash -c "compgen -A user"] { + if {$char == ""} {set char [string range $u 0 0]} + # Only append username if starting with $char + if {[string range $u 0 0] == "$char"} { + # Escape possible special regexp characters (+) in username + regsub -all {([\+])} $u {\\\1} u + lappend users $u + }; # if +}; # foreach + # Try completion +set cmd "finger $char" +send "$cmd\t" +if {[llength $users] == 1} { + set expected "^finger $users" +} else { + set users [lsort -ascii $users] + set users [join $users "\\s+"] + set expected "^$cmd\r\n$users\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" + + # Build string list of hostnames, separated by regexp whitespace (\s+) + # Example string: host1\s+host2\s+host3 + +set hosts {} +foreach h [exec bash -c "compgen -A hostname"] { + # Escape special regexp characters (+) in hostname + regsub -all {([\+])} $h {\\\1} h + # Prefix hosts with username 'test@' + lappend hosts "test@$h" +}; # foreach + # Try completion +set cmd "finger test@" +send "$cmd\t" +if {[llength $hosts] == 1} { + set expected "^$cmd$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 partial hostname" + + # 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 {} +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 + # Prefix hosts with username 'test@' + lappend hosts "test@$h" + }; # if +}; # foreach + # Try completion +set cmd "finger test@$char" +send "$cmd\t" +if {[llength $hosts] == 1} { + set expected "^finger $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