perf-completion.sh 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. # perf bash and zsh completion
  2. # Taken from git.git's completion script.
  3. __my_reassemble_comp_words_by_ref()
  4. {
  5. local exclude i j first
  6. # Which word separators to exclude?
  7. exclude="${1//[^$COMP_WORDBREAKS]}"
  8. cword_=$COMP_CWORD
  9. if [ -z "$exclude" ]; then
  10. words_=("${COMP_WORDS[@]}")
  11. return
  12. fi
  13. # List of word completion separators has shrunk;
  14. # re-assemble words to complete.
  15. for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
  16. # Append each nonempty word consisting of just
  17. # word separator characters to the current word.
  18. first=t
  19. while
  20. [ $i -gt 0 ] &&
  21. [ -n "${COMP_WORDS[$i]}" ] &&
  22. # word consists of excluded word separators
  23. [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
  24. do
  25. # Attach to the previous token,
  26. # unless the previous token is the command name.
  27. if [ $j -ge 2 ] && [ -n "$first" ]; then
  28. ((j--))
  29. fi
  30. first=
  31. words_[$j]=${words_[j]}${COMP_WORDS[i]}
  32. if [ $i = $COMP_CWORD ]; then
  33. cword_=$j
  34. fi
  35. if (($i < ${#COMP_WORDS[@]} - 1)); then
  36. ((i++))
  37. else
  38. # Done.
  39. return
  40. fi
  41. done
  42. words_[$j]=${words_[j]}${COMP_WORDS[i]}
  43. if [ $i = $COMP_CWORD ]; then
  44. cword_=$j
  45. fi
  46. done
  47. }
  48. # Define preload_get_comp_words_by_ref="false", if the function
  49. # __perf_get_comp_words_by_ref() is required instead.
  50. preload_get_comp_words_by_ref="true"
  51. if [ $preload_get_comp_words_by_ref = "true" ]; then
  52. type _get_comp_words_by_ref &>/dev/null ||
  53. preload_get_comp_words_by_ref="false"
  54. fi
  55. [ $preload_get_comp_words_by_ref = "true" ] ||
  56. __perf_get_comp_words_by_ref()
  57. {
  58. local exclude cur_ words_ cword_
  59. if [ "$1" = "-n" ]; then
  60. exclude=$2
  61. shift 2
  62. fi
  63. __my_reassemble_comp_words_by_ref "$exclude"
  64. cur_=${words_[cword_]}
  65. while [ $# -gt 0 ]; do
  66. case "$1" in
  67. cur)
  68. cur=$cur_
  69. ;;
  70. prev)
  71. prev=${words_[$cword_-1]}
  72. ;;
  73. words)
  74. words=("${words_[@]}")
  75. ;;
  76. cword)
  77. cword=$cword_
  78. ;;
  79. esac
  80. shift
  81. done
  82. }
  83. # Define preload__ltrim_colon_completions="false", if the function
  84. # __perf__ltrim_colon_completions() is required instead.
  85. preload__ltrim_colon_completions="true"
  86. if [ $preload__ltrim_colon_completions = "true" ]; then
  87. type __ltrim_colon_completions &>/dev/null ||
  88. preload__ltrim_colon_completions="false"
  89. fi
  90. [ $preload__ltrim_colon_completions = "true" ] ||
  91. __perf__ltrim_colon_completions()
  92. {
  93. if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
  94. # Remove colon-word prefix from COMPREPLY items
  95. local colon_word=${1%"${1##*:}"}
  96. local i=${#COMPREPLY[*]}
  97. while [[ $((--i)) -ge 0 ]]; do
  98. COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
  99. done
  100. fi
  101. }
  102. __perfcomp ()
  103. {
  104. COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
  105. }
  106. __perfcomp_colon ()
  107. {
  108. __perfcomp "$1" "$2"
  109. if [ $preload__ltrim_colon_completions = "true" ]; then
  110. __ltrim_colon_completions $cur
  111. else
  112. __perf__ltrim_colon_completions $cur
  113. fi
  114. }
  115. __perf_prev_skip_opts ()
  116. {
  117. local i cmd_ cmds_
  118. let i=cword-1
  119. cmds_=$($cmd $1 --list-cmds)
  120. prev_skip_opts=()
  121. while [ $i -ge 0 ]; do
  122. if [[ ${words[i]} == $1 ]]; then
  123. return
  124. fi
  125. for cmd_ in $cmds_; do
  126. if [[ ${words[i]} == $cmd_ ]]; then
  127. prev_skip_opts=${words[i]}
  128. return
  129. fi
  130. done
  131. ((i--))
  132. done
  133. }
  134. __perf_main ()
  135. {
  136. local cmd
  137. cmd=${words[0]}
  138. COMPREPLY=()
  139. # Skip options backward and find the last perf command
  140. __perf_prev_skip_opts
  141. # List perf subcommands or long options
  142. if [ -z $prev_skip_opts ]; then
  143. if [[ $cur == --* ]]; then
  144. cmds=$($cmd --list-opts)
  145. else
  146. cmds=$($cmd --list-cmds)
  147. fi
  148. __perfcomp "$cmds" "$cur"
  149. # List possible events for -e option
  150. elif [[ $prev == @("-e"|"--event") &&
  151. $prev_skip_opts == @(record|stat|top) ]]; then
  152. evts=$($cmd list --raw-dump)
  153. __perfcomp_colon "$evts" "$cur"
  154. else
  155. # List subcommands for perf commands
  156. if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched|
  157. |data|help|script|test|timechart|trace) ]]; then
  158. subcmds=$($cmd $prev_skip_opts --list-cmds)
  159. __perfcomp_colon "$subcmds" "$cur"
  160. fi
  161. # List long option names
  162. if [[ $cur == --* ]]; then
  163. subcmd=$prev_skip_opts
  164. __perf_prev_skip_opts $subcmd
  165. subcmd=$subcmd" "$prev_skip_opts
  166. opts=$($cmd $subcmd --list-opts)
  167. __perfcomp "$opts" "$cur"
  168. fi
  169. fi
  170. }
  171. if [[ -n ${ZSH_VERSION-} ]]; then
  172. autoload -U +X compinit && compinit
  173. __perfcomp ()
  174. {
  175. emulate -L zsh
  176. local c IFS=$' \t\n'
  177. local -a array
  178. for c in ${=1}; do
  179. case $c in
  180. --*=*|*.) ;;
  181. *) c="$c " ;;
  182. esac
  183. array[${#array[@]}+1]="$c"
  184. done
  185. compset -P '*[=:]'
  186. compadd -Q -S '' -a -- array && _ret=0
  187. }
  188. __perfcomp_colon ()
  189. {
  190. emulate -L zsh
  191. local cur_="${2-$cur}"
  192. local c IFS=$' \t\n'
  193. local -a array
  194. if [[ "$cur_" == *:* ]]; then
  195. local colon_word=${cur_%"${cur_##*:}"}
  196. fi
  197. for c in ${=1}; do
  198. case $c in
  199. --*=*|*.) ;;
  200. *) c="$c " ;;
  201. esac
  202. array[$#array+1]=${c#"$colon_word"}
  203. done
  204. compset -P '*[=:]'
  205. compadd -Q -S '' -a -- array && _ret=0
  206. }
  207. _perf ()
  208. {
  209. local _ret=1 cur cword prev
  210. cur=${words[CURRENT]}
  211. prev=${words[CURRENT-1]}
  212. let cword=CURRENT-1
  213. emulate ksh -c __perf_main
  214. let _ret && _default && _ret=0
  215. return _ret
  216. }
  217. compdef _perf perf
  218. return
  219. fi
  220. type perf &>/dev/null &&
  221. _perf()
  222. {
  223. local cur words cword prev
  224. if [ $preload_get_comp_words_by_ref = "true" ]; then
  225. _get_comp_words_by_ref -n =: cur words cword prev
  226. else
  227. __perf_get_comp_words_by_ref -n =: cur words cword prev
  228. fi
  229. __perf_main
  230. } &&
  231. complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
  232. || complete -o default -o nospace -F _perf perf