[ovs-dev] [RFC 1/2] ovs-vsctl-bashcomp: Avoid setting the COMP_WORDBREAKS.

Alex Wang alexw at nicira.com
Tue Mar 17 06:17:37 UTC 2015


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 ':' and '=' correctly
in the resulting completions.  Thusly, we need to remove those
completions.  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 <alexw at nicira.com>
---
 tests/completion.at               |   14 +++++++-------
 utilities/ovs-vsctl-bashcomp.bash |   18 +++++++++++++-----
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/tests/completion.at b/tests/completion.at
index d3b2800..0013efa 100644
--- a/tests/completion.at
+++ b/tests/completion.at
@@ -345,8 +345,8 @@ AT_SKIP_IF([test -z ${BASH_VERSION+x} || test ${BASH_VERSINFO[[0]]} -lt 4])
 OVS_VSWITCHD_START
 
 # complete ovs-vsctl --db=* [TAB]
-TMP="$(ovs-vsctl --commands | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n')
-$(ovs-vsctl --options | grep -- '--' | sed -e 's/=.*$/=/g')"
+TMP="$(ovs-vsctl --commands | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n' | sed -e 's/=//g')
+$(ovs-vsctl --options | grep -- '--' | sed -e 's/=.*$//g')"
 MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
 AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "--db=unix:$OVS_RUNDIR/db.sock "],
 [0], [dnl
@@ -405,7 +405,7 @@ AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "destroy Bridge br0 "],
 ${MATCH}
 ])
 # test +.  the first time, an argument is required, after that, it becomes '*'.
-TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | awk '/key.*value/ { print $1":"; next } { print $1; next }')"
+TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | awk '/key.*value/ { print $1; next } { print $1; next }')"
 MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
 AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 "],
 [0], [dnl
@@ -626,13 +626,13 @@ ${MATCH}
 # test: _ovs_vsctl_complete_column_optkey_value
 #
 # at first, we should complete on column.
-TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | awk '/key.*value/ { print $1":"; next } { print $1; next }')"
+TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | awk '/key.*value/ { print $1; next } { print $1; next }')"
 MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
 AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 "],
 [0], [dnl
 ${MATCH}
 ])
-MATCH="$(PREPARE_MATCH_NOSPACE(other_config:))"
+MATCH="$(PREPARE_MATCH_NOSPACE(other_config))"
 AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other"],
 [0], [dnl
 ${MATCH}
@@ -718,7 +718,7 @@ ${MATCH}
 # test 'add-port'
 # after specifying the new port name, we should complete on the column part
 # of '*COLUMN?:KEY=VALUE'.
-TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Port | awk '/key.*value/ { print $1":"; next } { print $1; next }')"
+TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Port | awk '/key.*value/ { print $1; next } { print $1; next }')"
 MATCH="$(PREPARE_MATCH_NOSPACE(${TMP} --))"
 AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add-port br0 new-port "],
 [0], [dnl
@@ -730,7 +730,7 @@ ${MATCH}
 # test: _ovs_vsctl_complete_dashdash
 #
 # after '--', there should be no global options available for completion.
-TMP="$(ovs-vsctl --commands | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n')"
+TMP="$(ovs-vsctl --commands | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n' | sed -e s/=//)"
 MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
 AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "init -- "],
 [0], [dnl
diff --git a/utilities/ovs-vsctl-bashcomp.bash b/utilities/ovs-vsctl-bashcomp.bash
index e79c6a2..1a8310b 100755
--- a/utilities/ovs-vsctl-bashcomp.bash
+++ b/utilities/ovs-vsctl-bashcomp.bash
@@ -36,7 +36,7 @@ _OVS_VSCTL_COMMANDS="$(_ovs_vsctl --commands)"
 
 # This doesn't complete on short arguments, so it filters them out.
 _OVS_VSCTL_OPTIONS="$(_ovs_vsctl --options | awk '/^--/ { print $0 }' \
-                      | sed -e 's/\(.*\)=ARG/\1=/')"
+                      | sed -e 's/\(.*\)=ARG/\1/')"
 IFS=$SAVE_IFS
 
 declare -A _OVS_VSCTL_PARSED_ARGS
@@ -89,6 +89,7 @@ _ovs_vsctl_bashcomp_localopt () {
     if [[ $result =~ "=" ]]; then
         options="NOSPACE"
     fi
+    result=$(echo "${result}" | sed -e s/=//)
     printf -- "${options}\nEO\n${result}"
 }
 
@@ -358,7 +359,7 @@ _ovs_vsctl_complete_column_optkey_value () {
             $_OVSDB_SERVER_LOCATION Open_vSwitch $table)
 
         result=$(printf "%s\n" "${columns}" \
-                 | awk '/key.*value/ { print $1":"; next }
+                 | awk '/key.*value/ { print $1; next }
                                      { print $1; next }' \
                  | _ovs_vsctl_check_startswith_string "$1" | sort | uniq)
     fi
@@ -627,7 +628,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 +646,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.
@@ -661,13 +668,11 @@ _ovs_vsctl_bashcomp () {
     _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
@@ -760,6 +765,9 @@ _ovs_vsctl_bashcomp () {
                 fi
                 printf "\n"
             else
+                # colon, equal sign will mess up the completion output, just
+                # deletes any completion with those signs.
+                completion="$(echo "${completion}" | sed -e '/:/d; /=/d')"
                 if [ "${_OVS_VSCTL_COMP_NOSPACE}" = "true" ]; then
                     compopt -o nospace
                     COMPREPLY=( $(compgen -W "${completion}" -- $word) )
-- 
1.7.9.5




More information about the dev mailing list