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