tools/gstreamer-completion: Bash 3.2 compatibility fixes
authorDavid Rothlisberger <david@rothlis.net>
Fri, 21 Dec 2012 08:56:26 +0000 (08:56 +0000)
committerStefan Sauer <ensonic@users.sf.net>
Mon, 29 Apr 2013 19:12:42 +0000 (21:12 +0200)
Compatible with bash 3.2; doesn't require the bash-completion package at
all (though the easiest way to install this script is still to install
bash-completion, and then drop this script into /etc/bash_completion.d).

Note that bash 3 doesn't break COMP_WORDS according to characters in
COMP_WORDBREAKS, so "property=val" looks like a single word, so this
won't complete property values (on bash 3). Similarly,
"--gst-debug-level=<TAB>" won't complete properly (on bash 3), but
"--gst-debug-level <TAB>" will.

For that reason, I now offer "--gst-debug-level" etc as completions
instead of "--gst-debug-level=".

Functions "_init_completion" and "_parse_help" were provided by the
bash-completion package >= 2.0; now I roll my own equivalent of
"_parse_help", and instead of "_init_completion" I use
"_get_comp_words_by_ref" which is available from bash-completion 1.2
onwards. If the bash-completion package isn't available at all I use
bash's raw facilities, at the expense of not completing properly when
the cursor is in the middle of a word.

The builtin "compopt" doesn't exist in bash 3; those users will just
have to live with the inconvenience of "property=" completing to
"property= " with a trailing space. Property values aren't completed
properly anyway on bash 3 (see above).

"[[ -v var ]]" to test whether a variable is set, also doesn't exist in
bash 3. Neither does ";;&" to fall through in a "case" statement.

In the unit tests:

* On my system (OS X), "#!/bin/bash" is bash 3.2, whereas
  "#!/usr/bin/env bash" is the 4.2 version I built myself.
* I have to initialise array variables like "expected=()", or bash 3
  treats "+=" as appending to an array already populated with one empty
  string.

tests/misc/test-gstreamer-completion.sh
tools/gstreamer-completion

index 6a22c0b..0f61367 100755 (executable)
@@ -1,9 +1,4 @@
-#!/usr/bin/env bash
-
-bashcomp=$(pkg-config --variable=prefix bash-completion
-                    )/share/bash-completion/bash_completion
-[ -f $bashcomp ] && . $bashcomp ||
-{ [ -f /etc/bash_completion ] && . /etc/bash_completion; }
+#!/bin/bash
 
 . $(dirname "$0")/../../tools/gstreamer-completion
 ret=0
@@ -16,8 +11,7 @@ test_gst_inspect_completion() {
     COMP_CWORD=$(( ${#COMP_WORDS[*]} - 1 ))
     COMP_LINE="${COMP_WORDS[*]}"
     COMP_POINT=${#COMP_LINE}
-
-    while [[ -n "$1" ]]; do expected+=("$1"); shift; done
+    expected=(); while [[ -n "$1" ]]; do expected+=("$1"); shift; done
 
     printf "test_gst_inspect_completion: '${COMP_WORDS[*]}'... "
     _gst_inspect
@@ -40,10 +34,11 @@ _assert_expected() {
 }
 
 # test_gst_inspect_completion <command line to complete> -- <expected completions>
-test_gst_inspect_completion '' -- --version --gst-debug-level= coreelements fakesrc
+test_gst_inspect_completion '' -- --version --gst-debug-level coreelements fakesrc
 test_gst_inspect_completion --ver -- --version
-test_gst_inspect_completion --gst-debug-le -- --gst-debug-level=
-test_gst_inspect_completion --gst-debug-level= -- 0 1 2 3 4 5
+test_gst_inspect_completion --gst-debug-le -- --gst-debug-level
+test_gst_inspect_completion --gst-debug-level '' -- 0 1 2 3 4 5
+test_gst_inspect_completion --gst-debug-level = -- 0 1 2 3 4 5
 test_gst_inspect_completion coreel -- coreelements
 test_gst_inspect_completion fake -- fakesrc fakesink
 test_gst_inspect_completion --version --gst-debug-level = 2 fake -- fakesrc fakesink
@@ -56,7 +51,7 @@ test_gst_launch_completion() {
     COMP_CWORD=$(( ${#COMP_WORDS[*]} - 1 ))
     COMP_LINE="${COMP_WORDS[*]}"
     COMP_POINT=${#COMP_LINE}
-    while [[ -n "$1" ]]; do expected+=("$1"); shift; done
+    expected=(); while [[ -n "$1" ]]; do expected+=("$1"); shift; done
 
     printf "test_gst_launch_completion: '${COMP_WORDS[*]}'... "
     _gst_launch
@@ -66,10 +61,10 @@ test_gst_launch_completion() {
 }
 
 # test_gst_launch_completion <command line to complete> -- <expected completions>
-test_gst_launch_completion '' -- --eos-on-shutdown --gst-debug-level= fakesrc fakesink
+test_gst_launch_completion '' -- --eos-on-shutdown --gst-debug-level fakesrc fakesink
 test_gst_launch_completion --mes -- --messages
-test_gst_launch_completion --gst-debug-le -- --gst-debug-level=
-test_gst_launch_completion --gst-debug-level -- --gst-debug-level=
+test_gst_launch_completion --gst-debug-le -- --gst-debug-level
+test_gst_launch_completion --gst-debug-level '' -- 0 1 2 3 4 5
 test_gst_launch_completion --gst-debug-level = -- 0 1 2 3 4 5
 test_gst_launch_completion fak -- fakesrc fakesink
 test_gst_launch_completion --messages fak -- fakesrc fakesink
@@ -85,6 +80,7 @@ test_gst_launch_parse() {
     words=(gst-launch)
     while [[ "$1" != -- ]]; do words+=("$1"); shift; done; shift
     cword=$(( ${#words[*]} - 1 ))
+    cur="${words[cword]}"
     local xcurtype="$1" xoption="$2" xelement="$3" xproperty="$4"
 
     printf "test_gst_launch_parse: '${words[*]}'... "
@@ -111,6 +107,7 @@ _assert() {
 test_gst_launch_parse '' -- option-or-element '' '' ''
 test_gst_launch_parse --mes -- option '' '' ''
 test_gst_launch_parse --messages -- option '' '' ''
+test_gst_launch_parse --gst-debug-level '' -- optionval --gst-debug-level '' ''
 test_gst_launch_parse --gst-debug-level = -- optionval --gst-debug-level '' ''
 test_gst_launch_parse fak -- element '' '' ''
 test_gst_launch_parse --messages fak -- element '' '' ''
index 4489f7d..b262b30 100644 (file)
@@ -4,12 +4,14 @@
 _gst_version=1.0
 
 _gst_inspect() {
-    local cur prev words cword split
-    _init_completion -n : -s || return
+    local cur cword prev words
+    _gst_init_completion
+    [[ "$cur" == "=" ]] && cur=
+
     _gst_common_options || return
 
     COMPREPLY=( $(compgen \
-        -W "$(_parse_help gst-inspect-$_gst_version --help-all) \
+        -W "$(_gst_parse_help gst-inspect-$_gst_version) \
             $(_gst_plugins) $(_gst_elements)" \
         -- "$cur") )
     [[ $COMPREPLY == *= ]] && compopt -o nospace 2>/dev/null
@@ -18,8 +20,7 @@ complete -F _gst_inspect gst-inspect-$_gst_version
 
 _gst_launch() {
     local cur cword prev words
-    _init_completion -n : || return
-
+    _gst_init_completion
     local curtype option element property
     _gst_launch_parse
     _gst_common_options || return
@@ -30,7 +31,7 @@ _gst_launch() {
 complete -o default -F _gst_launch gst-launch-$_gst_version
 
 _gst_common_options() {
-    if [[ -v curtype && -v option ]]; then  # Called from _gst_launch
+    if [[ -n "$curtype" ]]; then  # Called from _gst_launch
         [[ $curtype == optionval ]] || return 0
     else  # Called from _gst_inspect
         local option="$prev"
@@ -52,13 +53,17 @@ _gst_common_options() {
 
 _gst_launch_compgen() {
     case $curtype in
-        option|option-or-element)
+        option)
             compgen \
-                -W "$(_parse_help gst-launch-$_gst_version --help-all)" \
-                -- "$cur"
-            ;;&  # test next pattern too.
-        element|option-or-element)
+                -W "$(_gst_parse_help gst-launch-$_gst_version)" \
+                -- "$cur" ;;
+        element)
             compgen -W "$(_gst_elements)" -- "$cur" ;;
+        option-or-element)
+            compgen \
+                -W "$(_gst_parse_help gst-launch-$_gst_version) \
+                    $(_gst_elements)" \
+                -- "$cur" ;;
         optionval)
             case "$option" in
                 -o|--output) compgen -f -- "$cur" ;;
@@ -120,8 +125,7 @@ _gst_property_values() {
 # ($cur is the word currently being completed.)
 #
 # Before calling this function make sure that $curtype, $option, $element and
-# $property are local, and that $cur, $cword and $words have been initialised
-# by calling _init_completion.
+# $property are local, and that $cur, $cword and $words have been initialised.
 #
 # See test cases in tests/misc/test-gstreamer-completion.sh in the
 # gstreamer source repository.
@@ -161,3 +165,22 @@ _gst_takes_arg() {
         *) false;;
     esac
 }
+
+_gst_parse_help() {
+    $1 --help-all 2>&1 | grep -Eo -e '--[a-z-]+'
+}
+
+_gst_init_completion() {
+    if type _get_comp_words_by_ref &>/dev/null; then
+        # Available since bash-completion 1.2
+        _get_comp_words_by_ref cur cword prev words
+    else
+        # bash-completion not installed or too old. Use bash's raw facilities.
+        # This won't complete properly if the cursor is in the middle of a
+        # word.
+        cur="${COMP_WORDS[COMP_CWORD]}"
+        prev="${COMP_WORDS[COMP_CWORD-1]}"
+        cword=$COMP_CWORD
+        words=("${COMP_WORDS[@]}")
+    fi
+}