# Bash tab-completion for GStreamer. -*- shell-script -*- # Put this in /etc/bash_completion.d/ _gst_inspect() { local _gst_version=1.0 local cur cword prev words _gst_init_completion [[ "$cur" == "=" ]] && cur= [[ "$cur" =~ -.*=*$ ]] && prev="${cur%%=*}" cur="${cur#*=}" _gst_common_options || return COMPREPLY=( $(compgen \ -W "$(_gst_parse_help gst-inspect-$_gst_version) \ $(_gst_plugins) $(_gst_elements)" \ -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace 2>/dev/null } && complete -F _gst_inspect gst-inspect-1.0 _gst_launch() { local _gst_version=1.0 local cur cword prev words _gst_init_completion local curtype option element property _gst_launch_parse _gst_common_options || return COMPREPLY=( $(_gst_launch_compgen) ) [[ $COMPREPLY == *= ]] && compopt -o nospace 2>/dev/null } && complete -o default -F _gst_launch gst-launch-1.0 _gst_common_options() { if [[ -n "$curtype" ]]; then # Called from _gst_launch [[ $curtype == optionval ]] || return 0 else # Called from _gst_inspect local option="$prev" fi case "$option" in --gst-debug-level) COMPREPLY=( $(compgen -W "0 1 2 3 4 5" -- "$cur") );; --gst-debug) # TODO: comma-separated list of category_name:level pairs. ;; --gst-plugin-path) # TODO: support multiple (colon-separated) paths. COMPREPLY=( $(compgen -d -- "$cur") );; --gst-plugin-load) # TODO: comma-separated list of plugins (files?). ;; *) return 0;; esac return 1 # No need to attempt further completions. } _gst_launch_compgen() { case $curtype in option) compgen \ -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" ;; --exclude) ;; # TODO: comma-separated list of status information types. esac ;; \!) compgen -W '!' -- "$cur" ;; property) compgen -W "$(_gst_properties $element) ! " -- "$cur" ;; propertyval) compgen -W "$(_gst_property_values $element $property)" -- "$cur" ;; esac } _gst_plugins() { gst-inspect-$_gst_version 2>/dev/null | grep -v 'Total count' | awk -F': +' '{print $1}' | uniq } _gst_elements() { gst-inspect-$_gst_version 2>/dev/null | grep -v 'Total count' | awk -F': +' '{print $2}' } _gst_properties() { local element="$1" gst-inspect-$_gst_version "$element" 2>/dev/null | sed -n '/^Element Properties:$/,$ p' | awk '/^ [a-z]/ { print $1 "=" }' } _gst_property_values() { local element=$1 property=$2 gst-inspect-$_gst_version $element 2>/dev/null | awk " /^Element Properties:\$/ { inproperties = 1; next; } inproperties && /^ $property / { inproperty = 1; next; } inproperty && /^ *Boolean/ { printf \"true\nfalse\n\"; exit; } inproperty && /^ *Enum/ { inenum = 1; next; } inenum && /^ *\([0-9]+\): / { print \$2; next; } inproperty && /^ [a-z]/ { exit; }" } # Walks over $words, sets $curtype to the string: # # 'option' if $cur is an option or flag like "-a" or "--abc". # 'optionval' if $cur is the value of an option # (which will be set in $option). # 'element' if $cur is a GStreamer element name. # '!' if $cur is '!'. # 'property' if $cur is the name of a property of a GStreamer element # (which will be set in $element). # 'propertyval' if $cur is the value of an element's property # (which will be set in $element and $property, respectively). # # ($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. # # See test cases in tests/misc/test-gstreamer-completion.sh in the # gstreamer source repository. # _gst_launch_parse() { local i next state curtype= i=1 state=start while [[ $i -le $cword ]]; do next="${words[i]}" # Note that COMP_WORDBREAKS by default includes "=" and ":". case "$state,$next" in start,-*=*) curtype=optionval option="${next%%=*}" state=start;; start,-*) curtype=option option="$next" state=option;; start,) curtype=option-or-element;; start,*) curtype=element element="$next" state=element;; option,=) curtype=optionval state=option=;; option,*) _gst_takes_arg "$option" && curtype=optionval state=start || # re-evaluate without incrementing i: { curtype= state=start; continue; } ;; option=,*) curtype=optionval state=start;; element,\!) curtype='!' state='!';; \!,*) curtype=element element="$next" state=element;; element,*=) curtype=propertyval property="${next%=}" state=property=;; element,*=*) curtype=propertyval property="${next%%=*}" state=element;; element,*) curtype=property property="$next" state=property;; property,=) curtype=propertyval state=property=;; property=,*) curtype=propertyval state=element;; esac i=$((i + 1)) done cur="${cur#*=}" } _gst_takes_arg() { case "$1" in -o|--output|--gst-debug-level|--gst-debug) true;; --gst-plugin-path|--gst-plugin-load|--exclude) true;; *) 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 }