diff options
author | Freddy Vulto <fvulto@gmail.com> | 2010-03-14 11:07:13 +0100 |
---|---|---|
committer | Freddy Vulto <fvulto@gmail.com> | 2010-03-14 11:07:13 +0100 |
commit | bdca37a7bfdad428a072b71b7ec67b69bcc254a8 (patch) | |
tree | dd9457421c4031a7456688cf79a53ed3586ad412 | |
parent | f8bafe285e7d20fdd82f77289059dd18f78312c2 (diff) | |
download | bash-completion-bdca37a7bfdad428a072b71b7ec67b69bcc254a8.tar.gz |
Improve _get_comp_words_by_ref to return `words' and `cword'
Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
Available VARNAMES:
cur Return cur within varname "cur"
prev Return prev within varname "prev"
words Return words within varname "words"
cword Return cword within varname "cword"
Available OPTIONS:
-n EXCLUDE Characters out of $COMP_WORDBREAKS which should NOT be
considered word breaks. This is useful for things like scp
where we want to return host:path and not only path, so we
would pass the colon (:) as -n option in this case. Bash-3
doesn't do word splitting, so this ensures we get the same
word on both bash-3 and bash-4.
-c VARNAME Return cur within specified VARNAME
-p VARNAME Return prev within specified VARNAME
-w VARNAME Return words within specified VARNAME
-i VARNAME Return words within specified VARNAME
Example usage:
$ _get_comp_words_by_ref -n : cur prev
-rw-r--r-- | bash_completion | 87 | ||||
-rw-r--r-- | test/unit/_get_comp_words_by_ref.exp | 57 |
2 files changed, 112 insertions, 32 deletions
diff --git a/bash_completion b/bash_completion index 9418aacd..39488634 100644 --- a/bash_completion +++ b/bash_completion @@ -330,53 +330,83 @@ ___get_cword_at_cursor_by_ref() { # (For example, if the line is "ls foobar", # and the cursor is here --------> ^ # Also one is able to cross over possible wordbreak characters. -# Usage: _get_comp_words_by_ref [OPTIONS] VAR1 [VAR2 [VAR3]] +# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES] +# Available VARNAMES: +# cur Return cur within varname "cur" +# prev Return prev within varname "prev" +# words Return words within varname "words" +# cword Return cword within varname "cword" +# +# Available OPTIONS: +# -n EXCLUDE Characters out of $COMP_WORDBREAKS which should NOT be +# considered word breaks. This is useful for things like scp +# where we want to return host:path and not only path, so we +# would pass the colon (:) as -n option in this case. Bash-3 +# doesn't do word splitting, so this ensures we get the same +# word on both bash-3 and bash-4. +# -c VARNAME Return cur within specified VARNAME +# -p VARNAME Return prev within specified VARNAME +# -w VARNAME Return words within specified VARNAME +# -i VARNAME Return words within specified VARNAME +# # Example usage: # # $ _get_comp_words_by_ref -n : cur prev # -# Options: -n EXCLUDE Characters out of $COMP_WORDBREAKS which should NOT -# be considered word breaks. This is useful for things like scp where -# we want to return host:path and not only path, so we would pass the -# colon (:) as -n option in this case. Bash-3 doesn't do word splitting, -# so this ensures we get the same word on both bash-3 and bash-4. # @see __get_comp_words_by_ref _get_comp_words_by_ref() { # NOTE: The call to the main function __get_comp_words_by_ref() is wrapped - # to make collisions with local variable name less likely. - local __words __cword __cur __var __vars - __get_comp_words_by_ref __words __cword __cur __vars "$@" - set -- "${__vars[@]}" - eval $1=\$__cur - shift - for __var; do - ((__cword--)) - [[ ${__words[__cword]} ]] && eval $__var=\${__words[__cword]} - done + # to make collisions with local variable names less likely. + local __words __cword __cur + local __var_cur __var_prev __var_words __var_cword + + __get_comp_words_by_ref \ + __words __cword __cur \ + __var_cur __var_prev __var_words __var_cword "$@" + + [[ $__var_cur ]] && eval $__var_cur=\$__cur + [[ $__var_prev ]] && ((__cword)) && eval $__var_prev=\${__words[__cword - 1]} + [[ $__var_words ]] && eval $__var_words=\${__words[@]} + [[ $__var_cword ]] && eval $__var_cword=\$__cword + return 0 } -# @param $1 words Name of variable to return words to -# @param $2 cword Name of variable to return cword to -# @param $3 cur Name of variable to return current word to complete to -# @param $4 varnames Name of variable to return array of variable names to +# @param $1 words Name of variable to return words to +# @param $2 cword Name of variable to return cword to +# @param $3 cur Name of variable to return current word to complete to +# @param $4 var_cur Name of variable to return current word to complete to +# @param $5 var_prev Name of variable to return previous word to complete to +# @param $6 var_words Name of variable to return words to complete to +# @param $7 var_cword Name of variable to return index of words to complete to # @param $@ Arguments to _get_comp_words_by_ref() # @note Do not call this function directly but call `_get_comp_words_by_ref()' # instead to make variable name collisions less likely +# # @see _get_comp_words_by_ref() __get_comp_words_by_ref() { - local exclude flag i OPTIND=5 # Skip first four arguments - local cword words cur varnames=() - while getopts "n:" flag "$@"; do + local exclude flag i OPTIND=8 # Skip first seven arguments + local cword words cur + local var_cur var_cword var_prev var_words + + while getopts "c:i:n:p:w:" flag "$@"; do case $flag in + c) var_cur=$OPTARG ;; + i) var_cword=$OPTARG ;; n) exclude=$OPTARG ;; + p) var_prev=$OPTARG ;; + w) var_words=$OPTARG ;; esac done - varnames=( ${!OPTIND} ) - let "OPTIND += 1" while [[ $# -ge $OPTIND ]]; do - varnames+=( ${!OPTIND} ) + case ${!OPTIND} in + cur) var_cur=cur ;; + prev) var_prev=prev ;; + cword) var_cword=cword ;; + words) var_words=words ;; + *) echo "error: $FUNCNAME(): unknown argument: ${!OPTIND}" + esac let "OPTIND += 1" done @@ -385,7 +415,10 @@ __get_comp_words_by_ref() eval $1=\( \"\${words[@]}\" \) eval $2=\$cword eval $3=\$cur - eval $4=\( \"\${varnames[@]}\" \) + eval $4=\$var_cur + eval $5=\$var_prev + eval $6=\${var_words[@]} + eval $7=\$var_cword } diff --git a/test/unit/_get_comp_words_by_ref.exp b/test/unit/_get_comp_words_by_ref.exp index 67862b3a..1016d997 100644 --- a/test/unit/_get_comp_words_by_ref.exp +++ b/test/unit/_get_comp_words_by_ref.exp @@ -5,7 +5,10 @@ proc setup {} { proc teardown {} { - assert_bash_exec {unset COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS cur prev prev2} + assert_bash_exec { \ + unset COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS cur prev words cword \ + cur2 prev2 words2 cword2 \ + } # Delete 'COMP_WORDBREAKS' occupying two lines assert_env_unmodified { /COMP_WORDBREAKS=/{N @@ -46,8 +49,8 @@ sync_after_int set test "a b |"; # | = cursor position -set cmd {COMP_WORDS=(a b ''); COMP_CWORD=2; COMP_LINE='a b '; COMP_POINT=4; _get_comp_words_by_ref cur prev prev2; echo "$cur $prev $prev2"} -assert_bash_list {" b a"} $cmd $test +set cmd {COMP_WORDS=(a b ''); COMP_CWORD=2; COMP_LINE='a b '; COMP_POINT=4; _get_comp_words_by_ref cur prev; echo "$cur $prev"} +assert_bash_list {" b"} $cmd $test sync_after_int @@ -192,8 +195,8 @@ if {[lindex $::BASH_VERSINFO 0] <= 3} { }; # if append cmd {; COMP_LINE='a b c:'; COMP_POINT=6} assert_bash_exec $cmd $test -set cmd {_get_comp_words_by_ref -n : cur prev; echo "$cur $prev $prev2"} -assert_bash_list {"c: b a"} $cmd $test +set cmd {_get_comp_words_by_ref -n : cur prev; echo "$cur $prev"} +assert_bash_list {"c: b"} $cmd $test sync_after_int @@ -336,4 +339,48 @@ expect { sync_after_int +set test {unknown argument should raise error} +set cmd {_get_comp_words_by_ref dummy} +assert_bash_list {"error: __get_comp_words_by_ref(): unknown argument: dummy"} $cmd $test + + +sync_after_int + + +set test "a b| to all vars"; # | = cursor position +set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3} +assert_bash_exec $cmd +set cmd { \ + _get_comp_words_by_ref words cword prev cur; echo "${words[@]} $cword $cur $prev" \ +} +assert_bash_list {"a b 1 b a"} $cmd $test + + +sync_after_int + + +set test "a b| to alternate vars"; # | = cursor position +set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3;} +assert_bash_exec $cmd +set cmd {_get_comp_words_by_ref -c cur2 -p prev2 -w words2 -i cword2} +assert_bash_exec $cmd +set cmd {echo "$cur2 $prev2 ${words2[@]} $cword2"} +assert_bash_list {"b a a b 1"} $cmd $test + + +sync_after_int + + +set test "a b| to alternate vars"; # | = cursor position +set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3;} +assert_bash_exec $cmd +set cmd {_get_comp_words_by_ref -c cur2 -p prev2 -w words2 -i cword2} +assert_bash_exec $cmd +set cmd {echo "$cur2 $prev2 ${words2[@]} $cword2"} +assert_bash_list {"b a a b 1"} $cmd $test + + +sync_after_int + + teardown |