18c2ecf20Sopenharmony_ci# perf bash and zsh completion
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci# Taken from git.git's completion script.
58c2ecf20Sopenharmony_ci__my_reassemble_comp_words_by_ref()
68c2ecf20Sopenharmony_ci{
78c2ecf20Sopenharmony_ci	local exclude i j first
88c2ecf20Sopenharmony_ci	# Which word separators to exclude?
98c2ecf20Sopenharmony_ci	exclude="${1//[^$COMP_WORDBREAKS]}"
108c2ecf20Sopenharmony_ci	cword_=$COMP_CWORD
118c2ecf20Sopenharmony_ci	if [ -z "$exclude" ]; then
128c2ecf20Sopenharmony_ci		words_=("${COMP_WORDS[@]}")
138c2ecf20Sopenharmony_ci		return
148c2ecf20Sopenharmony_ci	fi
158c2ecf20Sopenharmony_ci	# List of word completion separators has shrunk;
168c2ecf20Sopenharmony_ci	# re-assemble words to complete.
178c2ecf20Sopenharmony_ci	for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
188c2ecf20Sopenharmony_ci		# Append each nonempty word consisting of just
198c2ecf20Sopenharmony_ci		# word separator characters to the current word.
208c2ecf20Sopenharmony_ci		first=t
218c2ecf20Sopenharmony_ci		while
228c2ecf20Sopenharmony_ci			[ $i -gt 0 ] &&
238c2ecf20Sopenharmony_ci			[ -n "${COMP_WORDS[$i]}" ] &&
248c2ecf20Sopenharmony_ci			# word consists of excluded word separators
258c2ecf20Sopenharmony_ci			[ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
268c2ecf20Sopenharmony_ci		do
278c2ecf20Sopenharmony_ci			# Attach to the previous token,
288c2ecf20Sopenharmony_ci			# unless the previous token is the command name.
298c2ecf20Sopenharmony_ci			if [ $j -ge 2 ] && [ -n "$first" ]; then
308c2ecf20Sopenharmony_ci				((j--))
318c2ecf20Sopenharmony_ci			fi
328c2ecf20Sopenharmony_ci			first=
338c2ecf20Sopenharmony_ci			words_[$j]=${words_[j]}${COMP_WORDS[i]}
348c2ecf20Sopenharmony_ci			if [ $i = $COMP_CWORD ]; then
358c2ecf20Sopenharmony_ci				cword_=$j
368c2ecf20Sopenharmony_ci			fi
378c2ecf20Sopenharmony_ci			if (($i < ${#COMP_WORDS[@]} - 1)); then
388c2ecf20Sopenharmony_ci				((i++))
398c2ecf20Sopenharmony_ci			else
408c2ecf20Sopenharmony_ci				# Done.
418c2ecf20Sopenharmony_ci				return
428c2ecf20Sopenharmony_ci			fi
438c2ecf20Sopenharmony_ci		done
448c2ecf20Sopenharmony_ci		words_[$j]=${words_[j]}${COMP_WORDS[i]}
458c2ecf20Sopenharmony_ci		if [ $i = $COMP_CWORD ]; then
468c2ecf20Sopenharmony_ci			cword_=$j
478c2ecf20Sopenharmony_ci		fi
488c2ecf20Sopenharmony_ci	done
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci# Define preload_get_comp_words_by_ref="false", if the function
528c2ecf20Sopenharmony_ci# __perf_get_comp_words_by_ref() is required instead.
538c2ecf20Sopenharmony_cipreload_get_comp_words_by_ref="true"
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciif [ $preload_get_comp_words_by_ref = "true" ]; then
568c2ecf20Sopenharmony_ci	type _get_comp_words_by_ref &>/dev/null ||
578c2ecf20Sopenharmony_ci	preload_get_comp_words_by_ref="false"
588c2ecf20Sopenharmony_cifi
598c2ecf20Sopenharmony_ci[ $preload_get_comp_words_by_ref = "true" ] ||
608c2ecf20Sopenharmony_ci__perf_get_comp_words_by_ref()
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	local exclude cur_ words_ cword_
638c2ecf20Sopenharmony_ci	if [ "$1" = "-n" ]; then
648c2ecf20Sopenharmony_ci		exclude=$2
658c2ecf20Sopenharmony_ci		shift 2
668c2ecf20Sopenharmony_ci	fi
678c2ecf20Sopenharmony_ci	__my_reassemble_comp_words_by_ref "$exclude"
688c2ecf20Sopenharmony_ci	cur_=${words_[cword_]}
698c2ecf20Sopenharmony_ci	while [ $# -gt 0 ]; do
708c2ecf20Sopenharmony_ci		case "$1" in
718c2ecf20Sopenharmony_ci		cur)
728c2ecf20Sopenharmony_ci			cur=$cur_
738c2ecf20Sopenharmony_ci			;;
748c2ecf20Sopenharmony_ci		prev)
758c2ecf20Sopenharmony_ci			prev=${words_[$cword_-1]}
768c2ecf20Sopenharmony_ci			;;
778c2ecf20Sopenharmony_ci		words)
788c2ecf20Sopenharmony_ci			words=("${words_[@]}")
798c2ecf20Sopenharmony_ci			;;
808c2ecf20Sopenharmony_ci		cword)
818c2ecf20Sopenharmony_ci			cword=$cword_
828c2ecf20Sopenharmony_ci			;;
838c2ecf20Sopenharmony_ci		esac
848c2ecf20Sopenharmony_ci		shift
858c2ecf20Sopenharmony_ci	done
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci# Define preload__ltrim_colon_completions="false", if the function
898c2ecf20Sopenharmony_ci# __perf__ltrim_colon_completions() is required instead.
908c2ecf20Sopenharmony_cipreload__ltrim_colon_completions="true"
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciif [ $preload__ltrim_colon_completions = "true" ]; then
938c2ecf20Sopenharmony_ci	type __ltrim_colon_completions &>/dev/null ||
948c2ecf20Sopenharmony_ci	preload__ltrim_colon_completions="false"
958c2ecf20Sopenharmony_cifi
968c2ecf20Sopenharmony_ci[ $preload__ltrim_colon_completions = "true" ] ||
978c2ecf20Sopenharmony_ci__perf__ltrim_colon_completions()
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
1008c2ecf20Sopenharmony_ci		# Remove colon-word prefix from COMPREPLY items
1018c2ecf20Sopenharmony_ci		local colon_word=${1%"${1##*:}"}
1028c2ecf20Sopenharmony_ci		local i=${#COMPREPLY[*]}
1038c2ecf20Sopenharmony_ci		while [[ $((--i)) -ge 0 ]]; do
1048c2ecf20Sopenharmony_ci			COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
1058c2ecf20Sopenharmony_ci		done
1068c2ecf20Sopenharmony_ci	fi
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci__perfcomp ()
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci__perfcomp_colon ()
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	__perfcomp "$1" "$2"
1178c2ecf20Sopenharmony_ci	if [ $preload__ltrim_colon_completions = "true" ]; then
1188c2ecf20Sopenharmony_ci		__ltrim_colon_completions $cur
1198c2ecf20Sopenharmony_ci	else
1208c2ecf20Sopenharmony_ci		__perf__ltrim_colon_completions $cur
1218c2ecf20Sopenharmony_ci	fi
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci__perf_prev_skip_opts ()
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	local i cmd_ cmds_
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	let i=cword-1
1298c2ecf20Sopenharmony_ci	cmds_=$($cmd $1 --list-cmds)
1308c2ecf20Sopenharmony_ci	prev_skip_opts=()
1318c2ecf20Sopenharmony_ci	while [ $i -ge 0 ]; do
1328c2ecf20Sopenharmony_ci		if [[ ${words[i]} == $1 ]]; then
1338c2ecf20Sopenharmony_ci			return
1348c2ecf20Sopenharmony_ci		fi
1358c2ecf20Sopenharmony_ci		for cmd_ in $cmds_; do
1368c2ecf20Sopenharmony_ci			if [[ ${words[i]} == $cmd_ ]]; then
1378c2ecf20Sopenharmony_ci				prev_skip_opts=${words[i]}
1388c2ecf20Sopenharmony_ci				return
1398c2ecf20Sopenharmony_ci			fi
1408c2ecf20Sopenharmony_ci		done
1418c2ecf20Sopenharmony_ci		((i--))
1428c2ecf20Sopenharmony_ci	done
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci__perf_main ()
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	local cmd
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	cmd=${words[0]}
1508c2ecf20Sopenharmony_ci	COMPREPLY=()
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	# Skip options backward and find the last perf command
1538c2ecf20Sopenharmony_ci	__perf_prev_skip_opts
1548c2ecf20Sopenharmony_ci	# List perf subcommands or long options
1558c2ecf20Sopenharmony_ci	if [ -z $prev_skip_opts ]; then
1568c2ecf20Sopenharmony_ci		if [[ $cur == --* ]]; then
1578c2ecf20Sopenharmony_ci			cmds=$($cmd --list-opts)
1588c2ecf20Sopenharmony_ci		else
1598c2ecf20Sopenharmony_ci			cmds=$($cmd --list-cmds)
1608c2ecf20Sopenharmony_ci		fi
1618c2ecf20Sopenharmony_ci		__perfcomp "$cmds" "$cur"
1628c2ecf20Sopenharmony_ci	# List possible events for -e option
1638c2ecf20Sopenharmony_ci	elif [[ $prev == @("-e"|"--event") &&
1648c2ecf20Sopenharmony_ci		$prev_skip_opts == @(record|stat|top) ]]; then
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci		local cur1=${COMP_WORDS[COMP_CWORD]}
1678c2ecf20Sopenharmony_ci		local raw_evts=$($cmd list --raw-dump)
1688c2ecf20Sopenharmony_ci		local arr s tmp result cpu_evts
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci		# aarch64 doesn't have /sys/bus/event_source/devices/cpu/events
1718c2ecf20Sopenharmony_ci		if [[ `uname -m` != aarch64 ]]; then
1728c2ecf20Sopenharmony_ci			cpu_evts=$(ls /sys/bus/event_source/devices/cpu/events)
1738c2ecf20Sopenharmony_ci		fi
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		if [[ "$cur1" == */* && ${cur1#*/} =~ ^[A-Z] ]]; then
1768c2ecf20Sopenharmony_ci			OLD_IFS="$IFS"
1778c2ecf20Sopenharmony_ci			IFS=" "
1788c2ecf20Sopenharmony_ci			arr=($raw_evts)
1798c2ecf20Sopenharmony_ci			IFS="$OLD_IFS"
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci			for s in ${arr[@]}
1828c2ecf20Sopenharmony_ci			do
1838c2ecf20Sopenharmony_ci				if [[ "$s" == *cpu/* ]]; then
1848c2ecf20Sopenharmony_ci					tmp=${s#*cpu/}
1858c2ecf20Sopenharmony_ci					result=$result" ""cpu/"${tmp^^}
1868c2ecf20Sopenharmony_ci				else
1878c2ecf20Sopenharmony_ci					result=$result" "$s
1888c2ecf20Sopenharmony_ci				fi
1898c2ecf20Sopenharmony_ci			done
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci			evts=${result}" "${cpu_evts}
1928c2ecf20Sopenharmony_ci		else
1938c2ecf20Sopenharmony_ci			evts=${raw_evts}" "${cpu_evts}
1948c2ecf20Sopenharmony_ci		fi
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci		if [[ "$cur1" == , ]]; then
1978c2ecf20Sopenharmony_ci			__perfcomp_colon "$evts" ""
1988c2ecf20Sopenharmony_ci		else
1998c2ecf20Sopenharmony_ci			__perfcomp_colon "$evts" "$cur1"
2008c2ecf20Sopenharmony_ci		fi
2018c2ecf20Sopenharmony_ci	else
2028c2ecf20Sopenharmony_ci		# List subcommands for perf commands
2038c2ecf20Sopenharmony_ci		if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched|
2048c2ecf20Sopenharmony_ci			|data|help|script|test|timechart|trace) ]]; then
2058c2ecf20Sopenharmony_ci			subcmds=$($cmd $prev_skip_opts --list-cmds)
2068c2ecf20Sopenharmony_ci			__perfcomp_colon "$subcmds" "$cur"
2078c2ecf20Sopenharmony_ci		fi
2088c2ecf20Sopenharmony_ci		# List long option names
2098c2ecf20Sopenharmony_ci		if [[ $cur == --* ]];  then
2108c2ecf20Sopenharmony_ci			subcmd=$prev_skip_opts
2118c2ecf20Sopenharmony_ci			__perf_prev_skip_opts $subcmd
2128c2ecf20Sopenharmony_ci			subcmd=$subcmd" "$prev_skip_opts
2138c2ecf20Sopenharmony_ci			opts=$($cmd $subcmd --list-opts)
2148c2ecf20Sopenharmony_ci			__perfcomp "$opts" "$cur"
2158c2ecf20Sopenharmony_ci		fi
2168c2ecf20Sopenharmony_ci	fi
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ciif [[ -n ${ZSH_VERSION-} ]]; then
2208c2ecf20Sopenharmony_ci	autoload -U +X compinit && compinit
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	__perfcomp ()
2238c2ecf20Sopenharmony_ci	{
2248c2ecf20Sopenharmony_ci		emulate -L zsh
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci		local c IFS=$' \t\n'
2278c2ecf20Sopenharmony_ci		local -a array
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci		for c in ${=1}; do
2308c2ecf20Sopenharmony_ci			case $c in
2318c2ecf20Sopenharmony_ci			--*=*|*.) ;;
2328c2ecf20Sopenharmony_ci			*) c="$c " ;;
2338c2ecf20Sopenharmony_ci			esac
2348c2ecf20Sopenharmony_ci			array[${#array[@]}+1]="$c"
2358c2ecf20Sopenharmony_ci		done
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci		compset -P '*[=:]'
2388c2ecf20Sopenharmony_ci		compadd -Q -S '' -a -- array && _ret=0
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	__perfcomp_colon ()
2428c2ecf20Sopenharmony_ci	{
2438c2ecf20Sopenharmony_ci		emulate -L zsh
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci		local cur_="${2-$cur}"
2468c2ecf20Sopenharmony_ci		local c IFS=$' \t\n'
2478c2ecf20Sopenharmony_ci		local -a array
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci		if [[ "$cur_" == *:* ]]; then
2508c2ecf20Sopenharmony_ci			local colon_word=${cur_%"${cur_##*:}"}
2518c2ecf20Sopenharmony_ci		fi
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci		for c in ${=1}; do
2548c2ecf20Sopenharmony_ci			case $c in
2558c2ecf20Sopenharmony_ci			--*=*|*.) ;;
2568c2ecf20Sopenharmony_ci			*) c="$c " ;;
2578c2ecf20Sopenharmony_ci			esac
2588c2ecf20Sopenharmony_ci			array[$#array+1]=${c#"$colon_word"}
2598c2ecf20Sopenharmony_ci		done
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci		compset -P '*[=:]'
2628c2ecf20Sopenharmony_ci		compadd -Q -S '' -a -- array && _ret=0
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	_perf ()
2668c2ecf20Sopenharmony_ci	{
2678c2ecf20Sopenharmony_ci		local _ret=1 cur cword prev
2688c2ecf20Sopenharmony_ci		cur=${words[CURRENT]}
2698c2ecf20Sopenharmony_ci		prev=${words[CURRENT-1]}
2708c2ecf20Sopenharmony_ci		let cword=CURRENT-1
2718c2ecf20Sopenharmony_ci		emulate ksh -c __perf_main
2728c2ecf20Sopenharmony_ci		let _ret && _default && _ret=0
2738c2ecf20Sopenharmony_ci		return _ret
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	compdef _perf perf
2778c2ecf20Sopenharmony_ci	return
2788c2ecf20Sopenharmony_cifi
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_citype perf &>/dev/null &&
2818c2ecf20Sopenharmony_ci_perf()
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	if [[ "$COMP_WORDBREAKS" != *,* ]]; then
2848c2ecf20Sopenharmony_ci		COMP_WORDBREAKS="${COMP_WORDBREAKS},"
2858c2ecf20Sopenharmony_ci		export COMP_WORDBREAKS
2868c2ecf20Sopenharmony_ci	fi
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if [[ "$COMP_WORDBREAKS" == *:* ]]; then
2898c2ecf20Sopenharmony_ci		COMP_WORDBREAKS="${COMP_WORDBREAKS/:/}"
2908c2ecf20Sopenharmony_ci		export COMP_WORDBREAKS
2918c2ecf20Sopenharmony_ci	fi
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	local cur words cword prev
2948c2ecf20Sopenharmony_ci	if [ $preload_get_comp_words_by_ref = "true" ]; then
2958c2ecf20Sopenharmony_ci		_get_comp_words_by_ref -n =:, cur words cword prev
2968c2ecf20Sopenharmony_ci	else
2978c2ecf20Sopenharmony_ci		__perf_get_comp_words_by_ref -n =:, cur words cword prev
2988c2ecf20Sopenharmony_ci	fi
2998c2ecf20Sopenharmony_ci	__perf_main
3008c2ecf20Sopenharmony_ci} &&
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_cicomplete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
3038c2ecf20Sopenharmony_ci	|| complete -o default -o nospace -F _perf perf
304