summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreddy Vulto <fvulto@gmail.com>2010-03-14 11:07:13 +0100
committerFreddy Vulto <fvulto@gmail.com>2010-03-14 11:07:13 +0100
commitbdca37a7bfdad428a072b71b7ec67b69bcc254a8 (patch)
treedd9457421c4031a7456688cf79a53ed3586ad412
parentf8bafe285e7d20fdd82f77289059dd18f78312c2 (diff)
downloadbash-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_completion87
-rw-r--r--test/unit/_get_comp_words_by_ref.exp57
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