# svcadm completion -*- shell-script -*- # # Copyright 2006 Yann Rouillard # # 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 , we will propose for svc://foo/bar/bar/baz # the following completion: foo/, bar/ and baz # If the user types , we will propose: bar/ and baz # If the user types , 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 # proc _smf_complete_fmri { var cur = $1, prefix = $2 var cur_prefix = '', fmri = '', fmri_list = ''"" var exact_mode = '', pattern = '' if [[ "$cur" == $prefix* ]] { [[ "$cur" == $prefix ]] && set cur = '"/'" set pattern = ""$cur*"" set exact_mode = '1' } else { set pattern = ""$prefix*/$cur*"" } set cur_prefix = $(cur%"${cur##*/}") for fmri in [$[svcs -H -o FMRI $pattern !2 >/dev/null]] { var fmri_part_list = '', fmri_part = '' if [[ -z "$exact_mode" ]] { set 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 var OIFS = $IFS; setglobal IFS = '"/'"; set -- $fmri; setglobal IFS = $OIFS match $Argc { with 1 set fmri_part_list = "" $1"" with 2 set fmri_part_list = "" $2 $1/$2"" with 3 set fmri_part_list = "" $3 $2/$3 $1/$2/$3"" with 4 set fmri_part_list = "" $4 $3/$4 $2/$3/$4 $1/$2/$3/$4"" } } else { set fmri_part_list = $fmri } # 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] { [[ "$fmri_part" == $cur* ]] || continue var first_part = $(fmri_part#$cur_prefix) set first_part = "$cur_prefix$(first_part%%/*)" [[ "$first_part" != "$fmri_part" ]] && set first_part = '"/'" set fmri_list = "" $first_part"" } } setglobal 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 var i = $(#COMPREPLY[*]) if [[ $i -gt 0 ]] && [[ "${COMPREPLY[$((--i))]}" == */ ]] { { [[ "${COMPREPLY[$i]}" != "${COMPREPLY[$((i - 1))]}" ]] && break sh-expr 'i--' } if [[ $i -eq 0 ]] { _smf_complete_fmri $(COMPREPLY[0]) $prefix return 0 } } # 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 :) var colonprefixes = $(cur%"${cur##*:}") var i = $(#COMPREPLY[*]) while test $shExpr('--i') -ge 0 { COMPREPLY[$i]=$(COMPREPLY[$i]#"$colonprefixes") } } proc _svcadm { var cur = '', prev = '', words = '', cword = '' _init_completion -n : || return var command_list = '"enable disable restart refresh clear mark milestone'" var 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" ]] { if [[ ${cur} == -* ]] { setglobal COMPREPLY = '( '$(compgen -W "-v" -- ${cur}) ) } else { setglobal COMPREPLY = '( '$(compgen -W "$command_list" -- ${cur}) ) } } else { if [[ ${cur} == -* ]] { match $command { with enable setglobal COMPREPLY = '( '$(compgen -W "-r -s -t" -- ${cur}) ) with disable setglobal COMPREPLY = '( '$(compgen -W "-s -t" -- ${cur}) ) with mark setglobal COMPREPLY = '( '$(compgen -W "-I -t" -- ${cur}) ) with milestone setglobal COMPREPLY = '( '$(compgen -W "-d" -- ${cur}) ) } } else { if [[ "$command" == "mark" ]] && [[ "$prev" != @(degraded|maintenance) ]] { setglobal COMPREPLY = '( '$(compgen -W "degraded maintenance" -- ${cur}) ) } elif [[ "$command" == "milestone" ]] { _smf_complete_fmri $(cur) "svc:/milestone" } else { _smf_complete_fmri $(cur) "svc:" } } } } && complete -F _svcadm svcadm # ex: ts=4 sw=4 et filetype=sh