diff options
Diffstat (limited to 'bash-completion/addons/smf')
-rw-r--r-- | bash-completion/addons/smf | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/bash-completion/addons/smf b/bash-completion/addons/smf new file mode 100644 index 0000000..57ce673 --- /dev/null +++ b/bash-completion/addons/smf @@ -0,0 +1,174 @@ +# svcadm completion -*- shell-script -*- +# +# Copyright 2006 Yann Rouillard <yann@opencsw.org> + +# +# svcadm accept any complete FMRI or abreviated FMRI +# - a complete FMRI is svc:/foo/bar/bar/baz +# - abbreviated FMRI are foo/bar/bar/baz, bar/bar/baz, bar/baz or baz +# +# The goal of this function is to be able to propose all alternatives, +# but to not clutter the interface with all completions, we will only +# cut every completion alternative at the next slash. +# +# For exemple, if the user types <nothing><tab>, we will propose for svc://foo/bar/bar/baz +# the following completion: foo/, bar/ and baz +# If the user types <b><tab>, we will propose: bar/ and baz +# If the user types <bar/><tab>, we will propose: bar/bar/ and bar/baz +# +# By default, the function proproses only abbreviated completions except if the user already +# began to type svc:. In that case we will propose only the complete FMRI beginning with the +# pattern +# +_smf_complete_fmri () +{ + local cur="$1" prefix="$2" + local cur_prefix fmri fmri_list="" + local exact_mode pattern + + if [[ "$cur" == $prefix* ]]; then + [[ "$cur" == $prefix ]] && cur+="/" + pattern="$cur*" + exact_mode=1 + else + pattern="$prefix*/$cur*" + fi + + cur_prefix="${cur%"${cur##*/}"}" + + for fmri in $(svcs -H -o FMRI "$pattern" 2>/dev/null); do + local fmri_part_list fmri_part + if [[ -z "$exact_mode" ]]; then + fmri=${fmri#$prefix/} + + # we generate all possibles abbrevations for the FMRI + # no need to have a generic loop as we will have a finite + # number of components + local OIFS="$IFS"; IFS="/"; set -- $fmri; IFS="$OIFS" + case $# in + 1) fmri_part_list=" $1";; + 2) fmri_part_list=" $2 $1/$2";; + 3) fmri_part_list=" $3 $2/$3 $1/$2/$3";; + 4) fmri_part_list=" $4 $3/$4 $2/$3/$4 $1/$2/$3/$4";; + esac + else + fmri_part_list="$fmri" + fi + + # Here we make sure the completions begins with the pattern and + # we cut them at the first slash + for fmri_part in $fmri_part_list; do + [[ "$fmri_part" == $cur* ]] || continue + local first_part=${fmri_part#$cur_prefix} + first_part=$cur_prefix${first_part%%/*} + [[ "$first_part" != "$fmri_part" ]] && first_part+="/" + fmri_list+=" $first_part" + done + done + + COMPREPLY=( $fmri_list ) + + # here we want to detect if there only one completion proposed and that + # it ends with a slash. That means the users will still have to complete + # after, so we gain him one tab keystroke by immediately proposing the + # next completion alternatives + local i=${#COMPREPLY[*]} + if [[ $i -gt 0 ]] && [[ "${COMPREPLY[$((--i))]}" == */ ]]; then + # we have to iterate throught the list as we may have duplicate + while [[ $i -ne 0 ]]; do + [[ "${COMPREPLY[$i]}" != "${COMPREPLY[$((i - 1))]}" ]] && break + ((i--)) + done + if [[ $i -eq 0 ]]; then + _smf_complete_fmri "${COMPREPLY[0]}" "$prefix" + return 0 + fi + fi + + # Work-around bash_completion issue where bash interprets a colon + # as a separator, borrowed from maven completion code which borrowed + # it from darcs completion code :) + local colonprefixes=${cur%"${cur##*:}"} + local i=${#COMPREPLY[*]} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colonprefixes"} + done +} + +_svcadm () +{ + local cur prev words cword + _init_completion -n : || return + + local command_list="enable disable restart refresh clear mark milestone" + local command i + + for (( i=1; i < $cword; i++ )); do + if [[ ${words[i]} == @(enable|disable|restart|refresh|clear|mark|milestone) ]]; then + command=${words[i]} + fi + done + + if [[ -z "$command" ]]; then + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "-v" -- ${cur}) ) + else + COMPREPLY=( $(compgen -W "$command_list" -- ${cur}) ) + fi + else + if [[ ${cur} == -* ]]; then + case "$command" in + enable) + COMPREPLY=( $(compgen -W "-r -s -t" -- ${cur}) );; + disable) + COMPREPLY=( $(compgen -W "-s -t" -- ${cur}) );; + mark) + COMPREPLY=( $(compgen -W "-I -t" -- ${cur}) );; + milestone) + COMPREPLY=( $(compgen -W "-d" -- ${cur}) );; + esac + else + if [[ "$command" == "mark" ]] && [[ "$prev" != @(degraded|maintenance) ]]; then + COMPREPLY=( $(compgen -W "degraded maintenance" -- ${cur}) ) + elif [[ "$command" == "milestone" ]]; then + _smf_complete_fmri "${cur}" "svc:/milestone" + else + _smf_complete_fmri "${cur}" "svc:" + fi + fi + fi +} && +complete -F _svcadm svcadm + + +_svcs () { + local cur prev opts line + local svcs_cols="ctid desc fmri inst nsta nstate scope svc sta state stime" + COMPREPLY=() + + cur=${COMP_WORDS[COMP_CWORD]} + prev="${COMP_WORDS[COMP_CWORD-1]}" + line="${COMP_LINE}" + + case "$prev" in + -o|-s|-S) + COMPREPLY=($(compgen -W "$svcs_cols" -- "${cur##*,}")) + local existing_opts=$(expr "$cur" : '\(.*,\)') + if [[ -n "$existing_opts" ]]; then + COMPREPLY=( "${COMPREPLY[@]/#/${existing_opts}}" ) + fi + compopt -o nospace + return;; + esac + + if [[ $cur == -* ]]; then + COMPREPLY=($(compgen -W "-a -H -p -v -Z -z -o -s -S -d -D -R -l -L -v -x " -- "${cur}")) + else + _smf_complete_fmri "${cur}" "svc:" + fi + +} && +complete -F _svcs svcs + + +# ex: ts=4 sw=4 et filetype=sh |