diff --git a/CHANGES b/CHANGES index 05ac17aa..1c311bc1 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,9 @@ bash-completion (2.x) * Add "short" tarball extensions to unxz, unlzma etc completions. * Improve /etc/init.d/* and sqlite3 completions. + [ Freddy Vulto ] + * Added _tilde(), fix ~username completion (Alioth: #312613, Debian: #587095) + -- David Paleino Wed, 16 Jun 2010 17:53:22 +0200 bash-completion (1.2) diff --git a/bash_completion b/bash_completion index 53eea33f..e1e926b9 100644 --- a/bash_completion +++ b/bash_completion @@ -618,7 +618,7 @@ _filedir() { local i IFS=$'\t\n' xspec - __expand_tilde_by_ref cur + _tilde "$cur" || return 0 local -a toks local quoted tmp @@ -803,7 +803,26 @@ _available_interfaces() } +# Perform tilde (~) completion +# @return True (0) if completion needs further processing, +# False (> 0) if tilde is followed by a valid username, completions +# are put in COMPREPLY and no further processing is necessary. +_tilde() { + local result=0 + # Does $1 start with tilde (~) and doesn't contain slash (/)? + if [[ ${1:0:1} == "~" && $1 == ${1//\/} ]]; then + # Try generate username completions + COMPREPLY=( $( compgen -P '~' -u "${1#\~}" ) ) + result=${#COMPREPLY[@]} + fi + return $result +} + + # Expand variable starting with tilde (~) +# We want to expand ~foo/... to /home/foo/... to avoid problems when +# word-to-complete starting with a tilde is fed to commands and ending up +# quoted instead of expanded. # Only the first portion of the variable from the tilde up to the first slash # (~../) is expanded. The remainder of the variable, containing for example # a dollar sign variable ($) or asterisk (*) is not expanded. @@ -832,7 +851,7 @@ __expand_tilde_by_ref() { # becomes "~a". Double quotes allow eval. # 2: Remove * before the first slash (/), i.e. "~a/b" # becomes "b". Single quotes prevent eval. - # +-----1----+ +---2----+ + # +-----1----+ +---2----+ eval $1="${!1/%\/*}"/'${!1#*/}' else # No, $1 doesn't contain slash diff --git a/test/lib/completions/ls.exp b/test/lib/completions/ls.exp index 171f6e14..fa47f85b 100644 --- a/test/lib/completions/ls.exp +++ b/test/lib/completions/ls.exp @@ -19,4 +19,14 @@ if {[assert_exec {ls --help} "" "" "unsupported"]} { sync_after_int +set test "~part should complete to ~full" +assert_bash_exec {compgen -u} {} /@ users +find_unique_completion_pair $users part full +set cmd [format {ls ~%s} $part] +assert_complete "~$full/" $cmd $test + + +sync_after_int + + teardown diff --git a/test/unit/_tilde.exp b/test/unit/_tilde.exp new file mode 100644 index 00000000..54394cb8 --- /dev/null +++ b/test/unit/_tilde.exp @@ -0,0 +1,51 @@ +# @param string $part Reference to variable to hold partial unique username +# @param string $full Reference to variable to hold full unique username +proc setup {part full} { + upvar $part _part + upvar $full _full + + assert_bash_exec {compgen -u} {} /@ users + find_unique_completion_pair $users _part _full + save_env +} + + +proc teardown {} { + assert_env_unmodified { + /COMPREPLY=/d + } +} + + +setup part full + + +set test "function should run without errors" +assert_bash_exec {_tilde > /dev/null} $test + + +sync_after_int + + +set test "function should not pollute environment" +# NOTE: A possible environment pollution is detected by assert_env_modified() in teardown() +assert_bash_exec {foo() { local aa="~"; _tilde "$aa"; }; foo; unset foo} $test + + +sync_after_int + + +set test "~full should complete to ~full unmodified" +set cmd [format {_tilde "~%s"; printf "%%s" "${COMPREPLY[@]}"} $full] +assert_bash_list "~$full" $cmd $test + + +sync_after_int + + +set test "~part should complete to ~full" +set cmd [format {_tilde "~%s"; printf "%%s" "${COMPREPLY[@]}"} $part] +assert_bash_list "~$full" $cmd $test + + +teardown