-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.bash
185 lines (161 loc) · 5.31 KB
/
template.bash
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# bash completion for {{bc_namespace}}
#
# {{bc_namespace}} # all bash functions are prepended with "_{{bc_namespace}}_"
# {{bc_command}} # the bash-friendly name appended to the namespace
# {{bc_executable}} # the filename of the executable binary(s)
# Only get a list of valid completions when we've reached the last
# word. By incrementing 'iword' we have moved from the command/flag to
# the next word, the argument to that command/flag.
#
# _{{bc_namespace}}__docker_images() {
# commands=() flags=()
# iword=$(( ${iword} + 1 ))
#
# if (( ${iword} == ${cword} )); then
# commands=($(docker images))
# fi
# }
#
# If this is the last word, generate the list of valid arguments and
# append them without space after an '=' sign. By setting COMPREPLY
# here explicitly and returning '1' we exit the main loop without
# using the default completion handler.
#
# By using '"${words[0]}"' we call {{bc_command}}.
#
# _{{bc_namespace}}__docker_args() {
# commands=() flags=()
# iword=$(( ${iword} + 1 ))
#
# if (( ${iword} == ${cword} )); then
# COMPREPLY=($(compgen -W "$("${words[0]}" docker args)" -S= -- "${cur}"))
# _{{bc_namespace}}__nospace
# return 1
# fi
# }
#
# _{{bc_namespace}}__{{bc_command}}_build_all() {
# # by not checking for '-*' one does not need to type '-' to
# # complete these flags
# flags=(--build-arg --no-cache --base-image --help)
# flag_funcs=(
# --base-image####docker_images#--quiet
# --build-arg##docker_args
# )
# }
#
# _{{bc_namespace}}__{{bc_command}}_build() {
# if [[ "${word}" == -* ]]; then
# flags=(--help)
# else
# commands=(all)
# fi
# }
#
# _{{bc_namespace}}__{{bc_command}}() {
# if [[ "${word}" == -* ]]; then
# flags=(--help)
# else
# commands=(build clone)
# fi
# }
# completion function
#
# https://github.com/rakshasa/bash-completion-template
#
# NAMESPACE={{bc_namespace}}
# COMMAND={{bc_command}}
# EXECUTABLE="{{bc_executable}}"
_{{bc_namespace}}_{{bc_command}}() {
COMPREPLY=()
local cur prev words cword
_get_comp_words_by_ref -n : cur prev words cword
local commands flags arg_funcs
local command_current={{bc_command}} command_pos=0 iword=0 cskip=0
for (( iword=1; iword <= ${cword}; ++iword)); do
# Word is the current word being completed.
# Rword is the regexp pattern used when looking up arg_func.
local word=${words[iword]} rword=${words[iword]}
local completion_func=_{{bc_namespace}}__${command_current}
# Matching commands move the interpreter down a command layer while flags are handled in the same layer.
commands=() flags=() arg_funcs=()
if ! declare -F "${completion_func}" > /dev/null || ! ${completion_func}; then
# No conversion of '#' is done, the completion_func is responsible for cleaning up commands/flags.
return 0
fi
# Do not allow '#' in commands or flags.
if [[ "${word}" =~ '#' ]]; then
return 0
fi
if (( ${iword} == ${cword} )); then
# If non-empty word and no root commands are matched, include all aliased commands.
if [[ -z "${word}" ]] || [[ " ${commands[*]} " =~ \ ${word}([^# ]*)(#| ) ]]; then
commands=(${commands[@]//#[^ ]*/})
else
commands=(${commands[@]//#/ })
fi
# If non-empty word and no root flags are matched, include all aliased flags.
if [[ -z "${word}" ]] || [[ " ${flags[*]} " =~ \ ${word}([^# ]*)(#| ) ]]; then
flags=(${flags[@]//#[^ ]*/})
else
flags=(${flags[@]//#/ })
fi
break
fi
if [[ " ${commands[*]} " =~ " ${word} " ]]; then
# TODO: Allow aliases for commands.
command_current=${command_current}_${word//-/_}
command_pos=${iword}
elif [[ " ${flags[*]} " =~ \ ${word}(#| ) ]]; then
: # Always make your : mean :, and your ! mean !.
elif [[ " ${flags[*]} " =~ \ ([^ ]*)#${word}(#| ) ]] ; then
# Match current word or root flag.
rword="${rword}|${BASH_REMATCH[1]%%#*}"
else
return 0
fi
local arg_func=
local iarg=
for (( iarg=0; iarg < ${#arg_funcs[@]}; ++iarg )); do
if [[ "${arg_funcs[iarg]}" =~ ^(${rword})##([^$]*)$ ]]; then
arg_func="_{{bc_namespace}}__${BASH_REMATCH[2]//#/ }"
elif [[ "${arg_funcs[iarg]}" =~ ^(${rword})#([^$]*)$ ]]; then
arg_func="${BASH_REMATCH[2]//#/ }"
fi
done
if [[ -n "${arg_func}" ]] && ! ${arg_func}; then
return 0
fi
done
local compreply=("${commands[*]}" "${flags[*]}")
COMPREPLY=($(compgen -W "${compreply[*]}" -- "${cur}"))
return 0
}
_{{bc_namespace}}__time() {
_{{bc_namespace}}_{{bc_command}} "${@}"
#time _{{bc_namespace}}_{{bc_command}} "${@}"
}
complete -F _{{bc_namespace}}__time {{bc_executable}}
# helper functions
#
# arg_funcs+=(--foo##skip)
# arg_funcs+=(--bar#_{{bc_namespace}}__skip)
# arg_funcs+=(--baz##compgen#-o#default)
_{{bc_namespace}}__compgen() {
COMPREPLY=($(compgen $(printf "-o %s" "${@}")))
return 1
}
_{{bc_namespace}}__compopt() {
# compopt is not available in ancient bash versions (OSX)
# so only call it if it's available
type compopt &>/dev/null && compopt $(printf "-o %s" "${@}")
}
_{{bc_namespace}}__nospace() {
# compopt is not available in ancient bash versions (OSX)
# so only call it if it's available
type compopt &>/dev/null && compopt -o nospace
}
_{{bc_namespace}}__word_skip() {
commands=() flags=()
iword=$(( ${iword} + 1 ))
}