perf-completion.sh 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. type _get_comp_words_by_ref &>/dev/null ||
  49. _get_comp_words_by_ref()
  50. {
  51. local exclude cur_ words_ cword_
  52. if [ "$1" = "-n" ]; then
  53. exclude=$2
  54. shift 2
  55. fi
  56. __my_reassemble_comp_words_by_ref "$exclude"
  57. cur_=${words_[cword_]}
  58. while [ $# -gt 0 ]; do
  59. case "$1" in
  60. cur)
  61. cur=$cur_
  62. ;;
  63. prev)
  64. prev=${words_[$cword_-1]}
  65. ;;
  66. words)
  67. words=("${words_[@]}")
  68. ;;
  69. cword)
  70. cword=$cword_
  71. ;;
  72. esac
  73. shift
  74. done
  75. }
  76. type __ltrim_colon_completions &>/dev/null ||
  77. __ltrim_colon_completions()
  78. {
  79. if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
  80. # Remove colon-word prefix from COMPREPLY items
  81. local colon_word=${1%"${1##*:}"}
  82. local i=${#COMPREPLY[*]}
  83. while [[ $((--i)) -ge 0 ]]; do
  84. COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
  85. done
  86. fi
  87. }
  88. __perfcomp ()
  89. {
  90. COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
  91. }
  92. __perfcomp_colon ()
  93. {
  94. __perfcomp "$1" "$2"
  95. __ltrim_colon_completions $cur
  96. }
  97. __perf_prev_skip_opts ()
  98. {
  99. local i cmd_ cmds_
  100. let i=cword-1
  101. cmds_=$($cmd $1 --list-cmds)
  102. prev_skip_opts=()
  103. while [ $i -ge 0 ]; do
  104. if [[ ${words[i]} == $1 ]]; then
  105. return
  106. fi
  107. for cmd_ in $cmds_; do
  108. if [[ ${words[i]} == $cmd_ ]]; then
  109. prev_skip_opts=${words[i]}
  110. return
  111. fi
  112. done
  113. ((i--))
  114. done
  115. }
  116. __perf_main ()
  117. {
  118. local cmd
  119. cmd=${words[0]}
  120. COMPREPLY=()
  121. # Skip options backward and find the last perf command
  122. __perf_prev_skip_opts
  123. # List perf subcommands or long options
  124. if [ $cword -eq 1 ]; then
  125. if [[ $cur == --* ]]; then
  126. cmds=$($cmd --list-opts)
  127. else
  128. cmds=$($cmd --list-cmds)
  129. fi
  130. __perfcomp "$cmds" "$cur"
  131. # List possible events for -e option
  132. elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
  133. evts=$($cmd list --raw-dump)
  134. __perfcomp_colon "$evts" "$cur"
  135. else
  136. # List subcommands for perf commands
  137. if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched) ]]; then
  138. subcmds=$($cmd $prev_skip_opts --list-cmds)
  139. __perfcomp_colon "$subcmds" "$cur"
  140. fi
  141. # List long option names
  142. if [[ $cur == --* ]]; then
  143. subcmd=$prev_skip_opts
  144. __perf_prev_skip_opts $subcmd
  145. subcmd=$subcmd" "$prev_skip_opts
  146. opts=$($cmd $subcmd --list-opts)
  147. __perfcomp "$opts" "$cur"
  148. fi
  149. fi
  150. }
  151. if [[ -n ${ZSH_VERSION-} ]]; then
  152. autoload -U +X compinit && compinit
  153. __perfcomp ()
  154. {
  155. emulate -L zsh
  156. local c IFS=$' \t\n'
  157. local -a array
  158. for c in ${=1}; do
  159. case $c in
  160. --*=*|*.) ;;
  161. *) c="$c " ;;
  162. esac
  163. array[${#array[@]}+1]="$c"
  164. done
  165. compset -P '*[=:]'
  166. compadd -Q -S '' -a -- array && _ret=0
  167. }
  168. __perfcomp_colon ()
  169. {
  170. emulate -L zsh
  171. local cur_="${2-$cur}"
  172. local c IFS=$' \t\n'
  173. local -a array
  174. if [[ "$cur_" == *:* ]]; then
  175. local colon_word=${cur_%"${cur_##*:}"}
  176. fi
  177. for c in ${=1}; do
  178. case $c in
  179. --*=*|*.) ;;
  180. *) c="$c " ;;
  181. esac
  182. array[$#array+1]=${c#"$colon_word"}
  183. done
  184. compset -P '*[=:]'
  185. compadd -Q -S '' -a -- array && _ret=0
  186. }
  187. _perf ()
  188. {
  189. local _ret=1 cur cword prev
  190. cur=${words[CURRENT]}
  191. prev=${words[CURRENT-1]}
  192. let cword=CURRENT-1
  193. emulate ksh -c __perf_main
  194. let _ret && _default && _ret=0
  195. return _ret
  196. }
  197. compdef _perf perf
  198. return
  199. fi
  200. type perf &>/dev/null &&
  201. _perf()
  202. {
  203. local cur words cword prev
  204. _get_comp_words_by_ref -n =: cur words cword prev
  205. __perf_main
  206. } &&
  207. complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
  208. || complete -o default -o nospace -F _perf perf