# 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 { local cur="$1" prefix="$2" local cur_prefix fmri fmri_list="" local exact_mode pattern if [[ "$cur" == $prefix* ]] { [[ "$cur" == $prefix ]] && setglobal cur = '"/'" setglobal pattern = ""$cur*"" setglobal exact_mode = '1' } else { setglobal pattern = ""$prefix*/$cur*"" } setglobal cur_prefix = $(cur%"${cur##*/}") for fmri in [$[svcs -H -o FMRI $pattern !2 >/dev/null]] { local fmri_part_list fmri_part if [[ -z "$exact_mode" ]] { setglobal 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"; setglobal IFS = '"/'"; set -- $fmri; setglobal IFS = $OIFS match $Argc { with 1 setglobal fmri_part_list = "" $1"" with 2 setglobal fmri_part_list = "" $2 $1/$2"" with 3 setglobal fmri_part_list = "" $3 $2/$3 $1/$2/$3"" with 4 setglobal fmri_part_list = "" $4 $3/$4 $2/$3/$4 $1/$2/$3/$4"" } } else { setglobal 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 local first_part=$(fmri_part#$cur_prefix) setglobal first_part = "$cur_prefix$(first_part%%/*)" [[ "$first_part" != "$fmri_part" ]] && setglobal first_part = '"/'" setglobal 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 local 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 :) local colonprefixes=$(cur%"${cur##*:}") local i=$(#COMPREPLY[*]) while test $shExpr('--i') -ge 0 { compat array-assign COMPREPLY '$i' $(COMPREPLY[$i]#"$colonprefixes") } } proc _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" ]] { 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