From f586e34a50ea677ba778764862d26248571ec392 Mon Sep 17 00:00:00 2001 From: David Rothlisberger Date: Fri, 21 Dec 2012 08:56:26 +0000 Subject: [PATCH] tools/gstreamer-completion: Bash 3.2 compatibility fixes 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=" won't complete properly (on bash 3), but "--gst-debug-level " 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 | 27 ++++++-------- tools/gstreamer-completion | 49 ++++++++++++++++++------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/tests/misc/test-gstreamer-completion.sh b/tests/misc/test-gstreamer-completion.sh index 6a22c0b27f..0f613678cd 100755 --- a/tests/misc/test-gstreamer-completion.sh +++ b/tests/misc/test-gstreamer-completion.sh @@ -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 -- -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 -- -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 '' '' '' diff --git a/tools/gstreamer-completion b/tools/gstreamer-completion index 4489f7dac8..b262b301da 100644 --- a/tools/gstreamer-completion +++ b/tools/gstreamer-completion @@ -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 +}