]>
Commit | Line | Data |
---|---|---|
f38ab8af | 1 | # perf bash and zsh completion |
b2441318 | 2 | # SPDX-License-Identifier: GPL-2.0 |
98a4179c | 3 | |
c3fb6717 RR |
4 | # Taken from git.git's completion script. |
5 | __my_reassemble_comp_words_by_ref() | |
6 | { | |
7 | local exclude i j first | |
8 | # Which word separators to exclude? | |
9 | exclude="${1//[^$COMP_WORDBREAKS]}" | |
10 | cword_=$COMP_CWORD | |
11 | if [ -z "$exclude" ]; then | |
12 | words_=("${COMP_WORDS[@]}") | |
13 | return | |
14 | fi | |
15 | # List of word completion separators has shrunk; | |
16 | # re-assemble words to complete. | |
17 | for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do | |
18 | # Append each nonempty word consisting of just | |
19 | # word separator characters to the current word. | |
20 | first=t | |
21 | while | |
22 | [ $i -gt 0 ] && | |
23 | [ -n "${COMP_WORDS[$i]}" ] && | |
24 | # word consists of excluded word separators | |
25 | [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ] | |
26 | do | |
27 | # Attach to the previous token, | |
28 | # unless the previous token is the command name. | |
29 | if [ $j -ge 2 ] && [ -n "$first" ]; then | |
30 | ((j--)) | |
31 | fi | |
32 | first= | |
33 | words_[$j]=${words_[j]}${COMP_WORDS[i]} | |
34 | if [ $i = $COMP_CWORD ]; then | |
35 | cword_=$j | |
36 | fi | |
37 | if (($i < ${#COMP_WORDS[@]} - 1)); then | |
38 | ((i++)) | |
39 | else | |
40 | # Done. | |
41 | return | |
42 | fi | |
43 | done | |
44 | words_[$j]=${words_[j]}${COMP_WORDS[i]} | |
45 | if [ $i = $COMP_CWORD ]; then | |
46 | cword_=$j | |
47 | fi | |
48 | done | |
49 | } | |
50 | ||
1312c8a8 YS |
51 | # Define preload_get_comp_words_by_ref="false", if the function |
52 | # __perf_get_comp_words_by_ref() is required instead. | |
53 | preload_get_comp_words_by_ref="true" | |
54 | ||
55 | if [ $preload_get_comp_words_by_ref = "true" ]; then | |
56 | type _get_comp_words_by_ref &>/dev/null || | |
57 | preload_get_comp_words_by_ref="false" | |
58 | fi | |
59 | [ $preload_get_comp_words_by_ref = "true" ] || | |
60 | __perf_get_comp_words_by_ref() | |
c3fb6717 RR |
61 | { |
62 | local exclude cur_ words_ cword_ | |
63 | if [ "$1" = "-n" ]; then | |
64 | exclude=$2 | |
65 | shift 2 | |
66 | fi | |
67 | __my_reassemble_comp_words_by_ref "$exclude" | |
68 | cur_=${words_[cword_]} | |
69 | while [ $# -gt 0 ]; do | |
70 | case "$1" in | |
71 | cur) | |
72 | cur=$cur_ | |
73 | ;; | |
74 | prev) | |
75 | prev=${words_[$cword_-1]} | |
76 | ;; | |
77 | words) | |
78 | words=("${words_[@]}") | |
79 | ;; | |
80 | cword) | |
81 | cword=$cword_ | |
82 | ;; | |
83 | esac | |
84 | shift | |
85 | done | |
86 | } | |
87 | ||
1312c8a8 YS |
88 | # Define preload__ltrim_colon_completions="false", if the function |
89 | # __perf__ltrim_colon_completions() is required instead. | |
90 | preload__ltrim_colon_completions="true" | |
91 | ||
92 | if [ $preload__ltrim_colon_completions = "true" ]; then | |
93 | type __ltrim_colon_completions &>/dev/null || | |
94 | preload__ltrim_colon_completions="false" | |
95 | fi | |
96 | [ $preload__ltrim_colon_completions = "true" ] || | |
97 | __perf__ltrim_colon_completions() | |
ae0c1f99 NK |
98 | { |
99 | if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then | |
100 | # Remove colon-word prefix from COMPREPLY items | |
30079d1d | 101 | local colon_word=${1%"${1##*:}"} |
ae0c1f99 NK |
102 | local i=${#COMPREPLY[*]} |
103 | while [[ $((--i)) -ge 0 ]]; do | |
104 | COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} | |
105 | done | |
106 | fi | |
107 | } | |
108 | ||
12f9dd50 RR |
109 | __perfcomp () |
110 | { | |
111 | COMPREPLY=( $( compgen -W "$1" -- "$2" ) ) | |
112 | } | |
113 | ||
37e72c31 RR |
114 | __perfcomp_colon () |
115 | { | |
116 | __perfcomp "$1" "$2" | |
1312c8a8 YS |
117 | if [ $preload__ltrim_colon_completions = "true" ]; then |
118 | __ltrim_colon_completions $cur | |
119 | else | |
120 | __perf__ltrim_colon_completions $cur | |
121 | fi | |
37e72c31 RR |
122 | } |
123 | ||
67afff48 YS |
124 | __perf_prev_skip_opts () |
125 | { | |
126 | local i cmd_ cmds_ | |
127 | ||
128 | let i=cword-1 | |
eee200a6 | 129 | cmds_=$($cmd $1 --list-cmds) |
67afff48 YS |
130 | prev_skip_opts=() |
131 | while [ $i -ge 0 ]; do | |
eee200a6 YS |
132 | if [[ ${words[i]} == $1 ]]; then |
133 | return | |
134 | fi | |
67afff48 YS |
135 | for cmd_ in $cmds_; do |
136 | if [[ ${words[i]} == $cmd_ ]]; then | |
137 | prev_skip_opts=${words[i]} | |
138 | return | |
139 | fi | |
140 | done | |
141 | ((i--)) | |
142 | done | |
143 | } | |
6fdd9cb7 | 144 | |
2cf025e6 | 145 | __perf_main () |
98a4179c | 146 | { |
2cf025e6 | 147 | local cmd |
98a4179c | 148 | |
6e0dc374 | 149 | cmd=${words[0]} |
2cf025e6 | 150 | COMPREPLY=() |
98a4179c | 151 | |
67afff48 YS |
152 | # Skip options backward and find the last perf command |
153 | __perf_prev_skip_opts | |
35c2fde1 | 154 | # List perf subcommands or long options |
e003ce54 | 155 | if [ -z $prev_skip_opts ]; then |
35c2fde1 | 156 | if [[ $cur == --* ]]; then |
7335399a | 157 | cmds=$($cmd --list-opts) |
35c2fde1 NK |
158 | else |
159 | cmds=$($cmd --list-cmds) | |
35c2fde1 | 160 | fi |
7335399a | 161 | __perfcomp "$cmds" "$cur" |
6fdd9cb7 YS |
162 | # List possible events for -e option |
163 | elif [[ $prev == @("-e"|"--event") && | |
164 | $prev_skip_opts == @(record|stat|top) ]]; then | |
74cd5815 JY |
165 | |
166 | local cur1=${COMP_WORDS[COMP_CWORD]} | |
167 | local raw_evts=$($cmd list --raw-dump) | |
168 | local arr s tmp result | |
169 | ||
170 | if [[ "$cur1" == */* && ${cur1#*/} =~ ^[A-Z] ]]; then | |
171 | OLD_IFS="$IFS" | |
172 | IFS=" " | |
173 | arr=($raw_evts) | |
174 | IFS="$OLD_IFS" | |
175 | ||
176 | for s in ${arr[@]} | |
177 | do | |
178 | if [[ "$s" == *cpu/* ]]; then | |
179 | tmp=${s#*cpu/} | |
180 | result=$result" ""cpu/"${tmp^^} | |
181 | else | |
182 | result=$result" "$s | |
183 | fi | |
184 | done | |
185 | ||
34c16db0 | 186 | evts=${result}" "$(ls /sys/bus/event_source/devices/cpu/events) |
74cd5815 | 187 | else |
34c16db0 | 188 | evts=${raw_evts}" "$(ls /sys/bus/event_source/devices/cpu/events) |
74cd5815 JY |
189 | fi |
190 | ||
34c16db0 JY |
191 | if [[ "$cur1" == , ]]; then |
192 | __perfcomp_colon "$evts" "" | |
193 | else | |
194 | __perfcomp_colon "$evts" "$cur1" | |
195 | fi | |
02fde323 YS |
196 | else |
197 | # List subcommands for perf commands | |
6fdd9cb7 YS |
198 | if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched| |
199 | |data|help|script|test|timechart|trace) ]]; then | |
67afff48 | 200 | subcmds=$($cmd $prev_skip_opts --list-cmds) |
02fde323 YS |
201 | __perfcomp_colon "$subcmds" "$cur" |
202 | fi | |
203 | # List long option names | |
204 | if [[ $cur == --* ]]; then | |
eee200a6 YS |
205 | subcmd=$prev_skip_opts |
206 | __perf_prev_skip_opts $subcmd | |
207 | subcmd=$subcmd" "$prev_skip_opts | |
02fde323 YS |
208 | opts=$($cmd $subcmd --list-opts) |
209 | __perfcomp "$opts" "$cur" | |
210 | fi | |
98a4179c | 211 | fi |
2cf025e6 RR |
212 | } |
213 | ||
f38ab8af RR |
214 | if [[ -n ${ZSH_VERSION-} ]]; then |
215 | autoload -U +X compinit && compinit | |
216 | ||
217 | __perfcomp () | |
218 | { | |
219 | emulate -L zsh | |
220 | ||
221 | local c IFS=$' \t\n' | |
222 | local -a array | |
223 | ||
224 | for c in ${=1}; do | |
225 | case $c in | |
226 | --*=*|*.) ;; | |
227 | *) c="$c " ;; | |
228 | esac | |
229 | array[${#array[@]}+1]="$c" | |
230 | done | |
231 | ||
232 | compset -P '*[=:]' | |
233 | compadd -Q -S '' -a -- array && _ret=0 | |
234 | } | |
235 | ||
236 | __perfcomp_colon () | |
237 | { | |
238 | emulate -L zsh | |
239 | ||
240 | local cur_="${2-$cur}" | |
241 | local c IFS=$' \t\n' | |
242 | local -a array | |
243 | ||
244 | if [[ "$cur_" == *:* ]]; then | |
245 | local colon_word=${cur_%"${cur_##*:}"} | |
246 | fi | |
247 | ||
248 | for c in ${=1}; do | |
249 | case $c in | |
250 | --*=*|*.) ;; | |
251 | *) c="$c " ;; | |
252 | esac | |
253 | array[$#array+1]=${c#"$colon_word"} | |
254 | done | |
255 | ||
256 | compset -P '*[=:]' | |
257 | compadd -Q -S '' -a -- array && _ret=0 | |
258 | } | |
259 | ||
260 | _perf () | |
261 | { | |
262 | local _ret=1 cur cword prev | |
263 | cur=${words[CURRENT]} | |
264 | prev=${words[CURRENT-1]} | |
265 | let cword=CURRENT-1 | |
266 | emulate ksh -c __perf_main | |
267 | let _ret && _default && _ret=0 | |
268 | return _ret | |
269 | } | |
270 | ||
271 | compdef _perf perf | |
272 | return | |
273 | fi | |
274 | ||
2cf025e6 RR |
275 | type perf &>/dev/null && |
276 | _perf() | |
277 | { | |
74cd5815 JY |
278 | if [[ "$COMP_WORDBREAKS" != *,* ]]; then |
279 | COMP_WORDBREAKS="${COMP_WORDBREAKS}," | |
280 | export COMP_WORDBREAKS | |
281 | fi | |
282 | ||
5d4fd9c8 JY |
283 | if [[ "$COMP_WORDBREAKS" == *:* ]]; then |
284 | COMP_WORDBREAKS="${COMP_WORDBREAKS/:/}" | |
285 | export COMP_WORDBREAKS | |
286 | fi | |
287 | ||
2cf025e6 | 288 | local cur words cword prev |
1312c8a8 | 289 | if [ $preload_get_comp_words_by_ref = "true" ]; then |
74cd5815 | 290 | _get_comp_words_by_ref -n =:, cur words cword prev |
1312c8a8 | 291 | else |
74cd5815 | 292 | __perf_get_comp_words_by_ref -n =:, cur words cword prev |
1312c8a8 | 293 | fi |
2cf025e6 | 294 | __perf_main |
98a4179c | 295 | } && |
7b6c48e1 RR |
296 | |
297 | complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \ | |
298 | || complete -o default -o nospace -F _perf perf |