summaryrefslogtreecommitdiffstats
path: root/completions/svcadm
blob: 5269c7bedbd67ab357f4c7c169d0d4cc1fd7e669 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# svcadm completion                                        -*- shell-script -*-
#
# Copyright 2006 Yann Rouillard <yann@opencsw.org>

#
# svcadm accept any complete FMRI or abbreviated 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 example, 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 ifs="$IFS"
            IFS="/"
            set -- $fmri
            IFS=$ifs
            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 through the list as we may have duplicate
        while ((i != 0)); do
            [[ ${COMPREPLY[i]} != "${COMPREPLY[i - 1]}" ]] && break
            ((i--))
        done
        if ((i == 0)); then
            _smf_complete_fmri "${COMPREPLY[0]}" "$prefix"
            return
        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-- > 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 [[ ! -v 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

# ex: filetype=sh