Modifying $COMP_WORDBREAKS in completion script is not the recommended as it is a global variable and the modification could affect the behavior of other completion scripts. As a workaround, this commit uses the _get_comp_words_by_ref which allows user to exclude characters out of $COMP_WORDBREAKS and reassemble input command line. However, as a side effect, the bash completion module cannot handle characters defined in $COMP_WORDBREAKS (e.g. ':' and '=') correctly in the resulting completions. Thusly, we need to trim the colon-word and equal-word prefixes from reply. This will reduce the functionality of some fancy completions. For example, COLUMN?:KEY=VALUE will not complete on KEY and VALUE.
Signed-off-by: Alex Wang <al...@nicira.com> --- tests/completion.at | 14 +++++------ utilities/ovs-vsctl-bashcomp.bash | 49 ++++++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/tests/completion.at b/tests/completion.at index d3b2800..7006260 100644 --- a/tests/completion.at +++ b/tests/completion.at @@ -608,7 +608,7 @@ AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add Bridge br0 other_config ran [0], [dnl ${MATCH} ]) -MATCH="$(PREPARE_MATCH_NOSPACE(random_key=abc))" +MATCH="$(PREPARE_MATCH_NOSPACE(abc))" AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add Bridge br0 other_config random_key=abc"], [0], [dnl ${MATCH} @@ -638,14 +638,14 @@ AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other"], ${MATCH} ]) # then, with the ':' we should complete on key. -TMP="$(ovs-vsctl --no-heading --columns=other_config list Bridge br0 | tr -d '{\"}' | tr -s ', ' '\n' | cut -d'=' -f1 | xargs printf "other_config:%s\n")" +TMP="$(ovs-vsctl --no-heading --columns=other_config list Bridge br0 | tr -d '{\"}' | tr -s ', ' '\n' | cut -d'=' -f1)" MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))" AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other_config:"], [0], [dnl ${MATCH} ]) # finally, if user fill in some value, we should just complete on user input. -MATCH="$(PREPARE_MATCH_NOSPACE(other_config:random_val1=12345))" +MATCH="$(PREPARE_MATCH_NOSPACE(12345))" AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other_config:random_val1=12345"], [0], [dnl ${MATCH} @@ -677,17 +677,15 @@ AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-manager "], ${MATCH} ]) # filename completion on unix, punix. -MATCH="$(PREPARE_MATCH_NOSPACE(unix:testsuite.log))" +MATCH="$(PREPARE_MATCH_NOSPACE(testsuite.log))" AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-manager unix:test"], [0], [dnl ${MATCH} ]) -# no completion on other type, just return available types. -# in real environment, bash will not complete on anything. -MATCH="$(PREPARE_MATCH_NOSPACE(pssl: ptcp: punix: ssl: tcp: unix:))" +# no completion on other type. AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-manager ssl:something"], [0], [dnl -${MATCH} + ]) diff --git a/utilities/ovs-vsctl-bashcomp.bash b/utilities/ovs-vsctl-bashcomp.bash index e79c6a2..a2b56ad 100755 --- a/utilities/ovs-vsctl-bashcomp.bash +++ b/utilities/ovs-vsctl-bashcomp.bash @@ -604,6 +604,36 @@ _ovs_vsctl_process_messages () { fi } +# colon, equal sign will mess up the completion output, just +# removes the colon-word and equal-word prefix from COMPREPLY items. +# +# Implementation of this function refers to the __ltrim_colon_completions +# function defined in bash_completion module. +_ovs_vsctl_trim_compreply() { + local cur=$1 + + if [[ + "$cur" == *:* && "$COMP_WORDBREAKS" == *:* + ]]; then + local colon_word=${cur%${cur##*:}} + local i=${#COMPREPLY[*]} + cur=${cur##*:} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} + done + fi + + if [[ + "$cur" == *=* && "$COMP_WORDBREAKS" == *=* + ]]; then + local equal_word=${cur%${cur##*=}} + local i=${#COMPREPLY[*]} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$equal_word"} + done + fi +} + # The general strategy here is that the same functions that decide # completions can also capture the necessary context for later # completions. This means that there is no distinction between the @@ -627,7 +657,7 @@ _ovs_vsctl_process_messages () { # status of the function _ovs_vsctl_complete_argument represents where # it has determined that the next argument will be. _ovs_vsctl_bashcomp () { - local cur valid_globals cmd_args raw_cmd cmd_pos valid_globals valid_opts + local words cword valid_globals cmd_args raw_cmd cmd_pos valid_globals valid_opts local test="false" # Does not support BASH_VERSION < 4.0 @@ -645,6 +675,12 @@ _ovs_vsctl_bashcomp () { <<< "$tmp" export COMP_WORDS export COMP_CWORD="$((${#COMP_WORDS[@]}-1))" + else + # If not in test mode, reassembles the COMP_WORDS and COMP_CWORD + # using just space as word break. + _get_comp_words_by_ref -n "\"'><=;|&(:" -w words -i cword + COMP_WORDS=( "${words[@]}") + COMP_CWORD=${cword} fi # Extract the conf.db path. @@ -654,20 +690,18 @@ _ovs_vsctl_bashcomp () { fi # If having trouble accessing the database, return. - if ! _ovs_vsctl get-manager 2>/dev/null; then + if ! _ovs_vsctl get-manager 1>/dev/null 2>/dev/null; then return 1; fi _OVS_VSCTL_PARSED_ARGS=() _OVS_VSCTL_NEW_RECORDS=() cmd_pos=-1 - cur=${COMP_WORDS[COMP_CWORD]} valid_globals=true valid_opts=true valid_commands=true given_opts="" index=1 - export COMP_WORDBREAKS=" " for word in "${COMP_WORDS[@]:1:${COMP_CWORD}} "; do _OVS_VSCTL_COMP_NOSPACE=false local completion @@ -753,6 +787,12 @@ _ovs_vsctl_bashcomp () { completion="$(sort -u <<< "$(tr ' ' '\n' <<< ${completion})")" if [ $index -eq $COMP_CWORD ]; then if [ "$test" = "true" ]; then + # Simulates the _ovs_vsctl_trim_compreply. + if [[ + "$word" == *:* || "$word" == *=* + ]]; then + completion="$(sed -e 's/.*://; s/.*=//' <<< "${completion}")" + fi if [ "${_OVS_VSCTL_COMP_NOSPACE}" = "true" ]; then printf "%s" "$completion" | sed -e '/^$/d' else @@ -767,6 +807,7 @@ _ovs_vsctl_bashcomp () { compopt +o nospace COMPREPLY=( $(compgen -W "${completion}" -- $word) ) fi + _ovs_vsctl_trim_compreply "$word" fi fi index=$(($index+1)) -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev