| # perf bash and zsh completion | 
 | # SPDX-License-Identifier: GPL-2.0 | 
 |  | 
 | # Taken from git.git's completion script. | 
 | __my_reassemble_comp_words_by_ref() | 
 | { | 
 | 	local exclude i j first | 
 | 	# Which word separators to exclude? | 
 | 	exclude="${1//[^$COMP_WORDBREAKS]}" | 
 | 	cword_=$COMP_CWORD | 
 | 	if [ -z "$exclude" ]; then | 
 | 		words_=("${COMP_WORDS[@]}") | 
 | 		return | 
 | 	fi | 
 | 	# List of word completion separators has shrunk; | 
 | 	# re-assemble words to complete. | 
 | 	for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do | 
 | 		# Append each nonempty word consisting of just | 
 | 		# word separator characters to the current word. | 
 | 		first=t | 
 | 		while | 
 | 			[ $i -gt 0 ] && | 
 | 			[ -n "${COMP_WORDS[$i]}" ] && | 
 | 			# word consists of excluded word separators | 
 | 			[ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ] | 
 | 		do | 
 | 			# Attach to the previous token, | 
 | 			# unless the previous token is the command name. | 
 | 			if [ $j -ge 2 ] && [ -n "$first" ]; then | 
 | 				((j--)) | 
 | 			fi | 
 | 			first= | 
 | 			words_[$j]=${words_[j]}${COMP_WORDS[i]} | 
 | 			if [ $i = $COMP_CWORD ]; then | 
 | 				cword_=$j | 
 | 			fi | 
 | 			if (($i < ${#COMP_WORDS[@]} - 1)); then | 
 | 				((i++)) | 
 | 			else | 
 | 				# Done. | 
 | 				return | 
 | 			fi | 
 | 		done | 
 | 		words_[$j]=${words_[j]}${COMP_WORDS[i]} | 
 | 		if [ $i = $COMP_CWORD ]; then | 
 | 			cword_=$j | 
 | 		fi | 
 | 	done | 
 | } | 
 |  | 
 | # Define preload_get_comp_words_by_ref="false", if the function | 
 | # __perf_get_comp_words_by_ref() is required instead. | 
 | preload_get_comp_words_by_ref="true" | 
 |  | 
 | if [ $preload_get_comp_words_by_ref = "true" ]; then | 
 | 	type _get_comp_words_by_ref &>/dev/null || | 
 | 	preload_get_comp_words_by_ref="false" | 
 | fi | 
 | [ $preload_get_comp_words_by_ref = "true" ] || | 
 | __perf_get_comp_words_by_ref() | 
 | { | 
 | 	local exclude cur_ words_ cword_ | 
 | 	if [ "$1" = "-n" ]; then | 
 | 		exclude=$2 | 
 | 		shift 2 | 
 | 	fi | 
 | 	__my_reassemble_comp_words_by_ref "$exclude" | 
 | 	cur_=${words_[cword_]} | 
 | 	while [ $# -gt 0 ]; do | 
 | 		case "$1" in | 
 | 		cur) | 
 | 			cur=$cur_ | 
 | 			;; | 
 | 		prev) | 
 | 			prev=${words_[$cword_-1]} | 
 | 			;; | 
 | 		words) | 
 | 			words=("${words_[@]}") | 
 | 			;; | 
 | 		cword) | 
 | 			cword=$cword_ | 
 | 			;; | 
 | 		esac | 
 | 		shift | 
 | 	done | 
 | } | 
 |  | 
 | # Define preload__ltrim_colon_completions="false", if the function | 
 | # __perf__ltrim_colon_completions() is required instead. | 
 | preload__ltrim_colon_completions="true" | 
 |  | 
 | if [ $preload__ltrim_colon_completions = "true" ]; then | 
 | 	type __ltrim_colon_completions &>/dev/null || | 
 | 	preload__ltrim_colon_completions="false" | 
 | fi | 
 | [ $preload__ltrim_colon_completions = "true" ] || | 
 | __perf__ltrim_colon_completions() | 
 | { | 
 | 	if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then | 
 | 		# Remove colon-word prefix from COMPREPLY items | 
 | 		local colon_word=${1%"${1##*:}"} | 
 | 		local i=${#COMPREPLY[*]} | 
 | 		while [[ $((--i)) -ge 0 ]]; do | 
 | 			COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} | 
 | 		done | 
 | 	fi | 
 | } | 
 |  | 
 | __perfcomp () | 
 | { | 
 | 	COMPREPLY=( $( compgen -W "$1" -- "$2" ) ) | 
 | } | 
 |  | 
 | __perfcomp_colon () | 
 | { | 
 | 	__perfcomp "$1" "$2" | 
 | 	if [ $preload__ltrim_colon_completions = "true" ]; then | 
 | 		__ltrim_colon_completions $cur | 
 | 	else | 
 | 		__perf__ltrim_colon_completions $cur | 
 | 	fi | 
 | } | 
 |  | 
 | __perf_prev_skip_opts () | 
 | { | 
 | 	local i cmd_ cmds_ | 
 |  | 
 | 	let i=cword-1 | 
 | 	cmds_=$($cmd $1 --list-cmds) | 
 | 	prev_skip_opts=() | 
 | 	while [ $i -ge 0 ]; do | 
 | 		if [[ ${words[i]} == $1 ]]; then | 
 | 			return | 
 | 		fi | 
 | 		for cmd_ in $cmds_; do | 
 | 			if [[ ${words[i]} == $cmd_ ]]; then | 
 | 				prev_skip_opts=${words[i]} | 
 | 				return | 
 | 			fi | 
 | 		done | 
 | 		((i--)) | 
 | 	done | 
 | } | 
 |  | 
 | __perf_main () | 
 | { | 
 | 	local cmd | 
 |  | 
 | 	cmd=${words[0]} | 
 | 	COMPREPLY=() | 
 |  | 
 | 	# Skip options backward and find the last perf command | 
 | 	__perf_prev_skip_opts | 
 | 	# List perf subcommands or long options | 
 | 	if [ -z $prev_skip_opts ]; then | 
 | 		if [[ $cur == --* ]]; then | 
 | 			cmds=$($cmd --list-opts) | 
 | 		else | 
 | 			cmds=$($cmd --list-cmds) | 
 | 		fi | 
 | 		__perfcomp "$cmds" "$cur" | 
 | 	# List possible events for -e option | 
 | 	elif [[ $prev == @("-e"|"--event") && | 
 | 		$prev_skip_opts == @(record|stat|top) ]]; then | 
 |  | 
 | 		local cur1=${COMP_WORDS[COMP_CWORD]} | 
 | 		local raw_evts=$($cmd list --raw-dump) | 
 | 		local arr s tmp result | 
 |  | 
 | 		if [[ "$cur1" == */* && ${cur1#*/} =~ ^[A-Z] ]]; then | 
 | 			OLD_IFS="$IFS" | 
 | 			IFS=" " | 
 | 			arr=($raw_evts) | 
 | 			IFS="$OLD_IFS" | 
 |  | 
 | 			for s in ${arr[@]} | 
 | 			do | 
 | 				if [[ "$s" == *cpu/* ]]; then | 
 | 					tmp=${s#*cpu/} | 
 | 					result=$result" ""cpu/"${tmp^^} | 
 | 				else | 
 | 					result=$result" "$s | 
 | 				fi | 
 | 			done | 
 |  | 
 | 			evts=${result}" "$(ls /sys/bus/event_source/devices/cpu/events) | 
 | 		else | 
 | 			evts=${raw_evts}" "$(ls /sys/bus/event_source/devices/cpu/events) | 
 | 		fi | 
 |  | 
 | 		if [[ "$cur1" == , ]]; then | 
 | 			__perfcomp_colon "$evts" "" | 
 | 		else | 
 | 			__perfcomp_colon "$evts" "$cur1" | 
 | 		fi | 
 | 	else | 
 | 		# List subcommands for perf commands | 
 | 		if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched| | 
 | 			|data|help|script|test|timechart|trace) ]]; then | 
 | 			subcmds=$($cmd $prev_skip_opts --list-cmds) | 
 | 			__perfcomp_colon "$subcmds" "$cur" | 
 | 		fi | 
 | 		# List long option names | 
 | 		if [[ $cur == --* ]];  then | 
 | 			subcmd=$prev_skip_opts | 
 | 			__perf_prev_skip_opts $subcmd | 
 | 			subcmd=$subcmd" "$prev_skip_opts | 
 | 			opts=$($cmd $subcmd --list-opts) | 
 | 			__perfcomp "$opts" "$cur" | 
 | 		fi | 
 | 	fi | 
 | } | 
 |  | 
 | if [[ -n ${ZSH_VERSION-} ]]; then | 
 | 	autoload -U +X compinit && compinit | 
 |  | 
 | 	__perfcomp () | 
 | 	{ | 
 | 		emulate -L zsh | 
 |  | 
 | 		local c IFS=$' \t\n' | 
 | 		local -a array | 
 |  | 
 | 		for c in ${=1}; do | 
 | 			case $c in | 
 | 			--*=*|*.) ;; | 
 | 			*) c="$c " ;; | 
 | 			esac | 
 | 			array[${#array[@]}+1]="$c" | 
 | 		done | 
 |  | 
 | 		compset -P '*[=:]' | 
 | 		compadd -Q -S '' -a -- array && _ret=0 | 
 | 	} | 
 |  | 
 | 	__perfcomp_colon () | 
 | 	{ | 
 | 		emulate -L zsh | 
 |  | 
 | 		local cur_="${2-$cur}" | 
 | 		local c IFS=$' \t\n' | 
 | 		local -a array | 
 |  | 
 | 		if [[ "$cur_" == *:* ]]; then | 
 | 			local colon_word=${cur_%"${cur_##*:}"} | 
 | 		fi | 
 |  | 
 | 		for c in ${=1}; do | 
 | 			case $c in | 
 | 			--*=*|*.) ;; | 
 | 			*) c="$c " ;; | 
 | 			esac | 
 | 			array[$#array+1]=${c#"$colon_word"} | 
 | 		done | 
 |  | 
 | 		compset -P '*[=:]' | 
 | 		compadd -Q -S '' -a -- array && _ret=0 | 
 | 	} | 
 |  | 
 | 	_perf () | 
 | 	{ | 
 | 		local _ret=1 cur cword prev | 
 | 		cur=${words[CURRENT]} | 
 | 		prev=${words[CURRENT-1]} | 
 | 		let cword=CURRENT-1 | 
 | 		emulate ksh -c __perf_main | 
 | 		let _ret && _default && _ret=0 | 
 | 		return _ret | 
 | 	} | 
 |  | 
 | 	compdef _perf perf | 
 | 	return | 
 | fi | 
 |  | 
 | type perf &>/dev/null && | 
 | _perf() | 
 | { | 
 | 	if [[ "$COMP_WORDBREAKS" != *,* ]]; then | 
 | 		COMP_WORDBREAKS="${COMP_WORDBREAKS}," | 
 | 		export COMP_WORDBREAKS | 
 | 	fi | 
 |  | 
 | 	if [[ "$COMP_WORDBREAKS" == *:* ]]; then | 
 | 		COMP_WORDBREAKS="${COMP_WORDBREAKS/:/}" | 
 | 		export COMP_WORDBREAKS | 
 | 	fi | 
 |  | 
 | 	local cur words cword prev | 
 | 	if [ $preload_get_comp_words_by_ref = "true" ]; then | 
 | 		_get_comp_words_by_ref -n =:, cur words cword prev | 
 | 	else | 
 | 		__perf_get_comp_words_by_ref -n =:, cur words cword prev | 
 | 	fi | 
 | 	__perf_main | 
 | } && | 
 |  | 
 | complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \ | 
 | 	|| complete -o default -o nospace -F _perf perf |