forked from luck/tmp_suning_uos_patched
74cd5815d9
perf has perf-completion.sh to define command line auto-completion in bash/zsh. For record/stat -e it works for single events, but isn't working when specifying multiple events with comma. It would be very useful if it could be fixed to make it easier by supporting multiple events, comma separated. With this patch, the result can be like this: 1. Support the events returned from 'perf list --raw-dump' root@skl:/tmp# perf stat -e cpu/cache<TAB> cpu/cache-misses/ cpu/cache-references/ root@skl:/tmp# perf stat -e cpu/cache-misses/,cpu/branch-<TAB> cpu/branch-instructions/ cpu/branch-misses/ root@skl:/tmp# perf stat -e cpu/cache-misses/,cpu/branch-i<TAB> root@skl:/tmp# perf stat -e cpu/cache-misses/,cpu/branch-instructions/ 2. Support the events listed in /sys/bus/event_source/devices/cpu/events root@skl:/tmp# perf stat -e cycle<TAB> cycle_activity.cycles_l1d_miss cycle_activity.stalls_l3_miss cycle_activity.cycles_l2_miss cycle_activity.stalls_mem_any cycle_activity.cycles_l3_miss cycle_activity.stalls_total cycle_activity.cycles_mem_any cycles-ct cycle_activity.stalls_l1d_miss cycles-t cycle_activity.stalls_l2_miss root@skl:/tmp# perf stat -e cycles-<TAB> cycles-ct cycles-t root@skl:/tmp# perf stat -e cycles-t,cpu/c<TAB> cpu/cache-misses/ cpu/cpu-cycles/ cpu/cycles-t/ cpu/cache-references/ cpu/cycles-ct/ root@skl:/tmp# perf stat -e cycles-t,cpu/cache-<TAB> cpu/cache-misses/ cpu/cache-references/ root@skl:/tmp# perf stat -e cycles-t,cpu/cache-misses/ 3. Support the uppercase event which is with prefix "cpu/" root@skl:/tmp# perf stat -e cpu/c<TAB> cpu/cache-misses/ cpu/cpu-cycles/ cpu/cycles-t/ cpu/cache-references/ cpu/cycles-ct/ root@skl:/tmp# perf stat -e cpu/cache-misses/,cpu/C<TAB> cpu/CACHE-MISSES/ cpu/CPU-CYCLES/ cpu/CYCLES-T/ cpu/CACHE-REFERENCES/ cpu/CYCLES-CT/ root@skl:/tmp# perf stat -e cpu/cache-misses/,cpu/CACHE-REFERENCES/ Note that: a) This patch only supports bash. b) It doesn't support the cases like {},{} or {...,...}. Signed-off-by: Jin Yao <yao.jin@linux.intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kan Liang <kan.liang@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1513848370-8098-1-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
290 lines
6.0 KiB
Bash
290 lines
6.0 KiB
Bash
# 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
|
|
|
|
__perfcomp_colon "$evts" "$cur1"
|
|
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
|
|
|
|
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
|