comp.zsh 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #compdef %[1]s
  2. compdef _%[1]s %[1]s
  3. # Copyright 2013-2023 The Cobra Authors
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. # zsh completion for %-36[1]s -*- shell-script -*-
  17. __%[1]s_debug()
  18. {
  19. local file="$BASH_COMP_DEBUG_FILE"
  20. if [[ -n ${file} ]]; then
  21. echo "$*" >> "${file}"
  22. fi
  23. }
  24. _%[1]s()
  25. {
  26. local shellCompDirectiveError=%[3]d
  27. local shellCompDirectiveNoSpace=%[4]d
  28. local shellCompDirectiveNoFileComp=%[5]d
  29. local shellCompDirectiveFilterFileExt=%[6]d
  30. local shellCompDirectiveFilterDirs=%[7]d
  31. local shellCompDirectiveKeepOrder=%[8]d
  32. local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder
  33. local -a completions
  34. __%[1]s_debug "\n========= starting completion logic =========="
  35. __%[1]s_debug "CURRENT: ${CURRENT}, words[*]: ${words[*]}"
  36. # The user could have moved the cursor backwards on the command-line.
  37. # We need to trigger completion from the $CURRENT location, so we need
  38. # to truncate the command-line ($words) up to the $CURRENT location.
  39. # (We cannot use $CURSOR as its value does not work when a command is an alias.)
  40. words=("${=words[1,CURRENT]}")
  41. __%[1]s_debug "Truncated words[*]: ${words[*]},"
  42. lastParam=${words[-1]}
  43. lastChar=${lastParam[-1]}
  44. __%[1]s_debug "lastParam: ${lastParam}, lastChar: ${lastChar}"
  45. # For zsh, when completing a flag with an = (e.g., %[1]s -n=<TAB>)
  46. # completions must be prefixed with the flag
  47. setopt local_options BASH_REMATCH
  48. if [[ "${lastParam}" =~ '-.*=' ]]; then
  49. # We are dealing with a flag with an =
  50. flagPrefix="-P ${BASH_REMATCH}"
  51. fi
  52. # Prepare the command to obtain completions
  53. requestComp="${words[1]} %[2]s ${words[2,-1]}"
  54. if [ "${lastChar}" = "" ]; then
  55. # If the last parameter is complete (there is a space following it)
  56. # We add an extra empty parameter so we can indicate this to the go completion code.
  57. __%[1]s_debug "Adding extra empty parameter"
  58. requestComp="${requestComp} \"\""
  59. fi
  60. __%[1]s_debug "About to call: eval ${requestComp}"
  61. # Use eval to handle any environment variables and such
  62. out=$(eval ${requestComp} 2>/dev/null)
  63. __%[1]s_debug "completion output: ${out}"
  64. # Extract the directive integer following a : from the last line
  65. local lastLine
  66. while IFS='\n' read -r line; do
  67. lastLine=${line}
  68. done < <(printf "%%s\n" "${out[@]}")
  69. __%[1]s_debug "last line: ${lastLine}"
  70. if [ "${lastLine[1]}" = : ]; then
  71. directive=${lastLine[2,-1]}
  72. # Remove the directive including the : and the newline
  73. local suffix
  74. (( suffix=${#lastLine}+2))
  75. out=${out[1,-$suffix]}
  76. else
  77. # There is no directive specified. Leave $out as is.
  78. __%[1]s_debug "No directive found. Setting do default"
  79. directive=0
  80. fi
  81. __%[1]s_debug "directive: ${directive}"
  82. __%[1]s_debug "completions: ${out}"
  83. __%[1]s_debug "flagPrefix: ${flagPrefix}"
  84. if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
  85. __%[1]s_debug "Completion received error. Ignoring completions."
  86. return
  87. fi
  88. while IFS='\n' read -r comp; do
  89. if [ -n "$comp" ]; then
  90. # If requested, completions are returned with a description.
  91. # The description is preceded by a TAB character.
  92. # For zsh's _describe, we need to use a : instead of a TAB.
  93. # We first need to escape any : as part of the completion itself.
  94. comp=${comp//:/\\:}
  95. local tab="$(printf '\t')"
  96. comp=${comp//$tab/:}
  97. __%[1]s_debug "Adding completion: ${comp}"
  98. completions+=${comp}
  99. lastComp=$comp
  100. fi
  101. done < <(printf "%%s\n" "${out[@]}")
  102. if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
  103. __%[1]s_debug "Activating nospace."
  104. noSpace="-S ''"
  105. fi
  106. if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then
  107. __%[1]s_debug "Activating keep order."
  108. keepOrder="-V"
  109. fi
  110. if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
  111. # File extension filtering
  112. local filteringCmd
  113. filteringCmd='_files'
  114. for filter in ${completions[@]}; do
  115. if [ ${filter[1]} != '*' ]; then
  116. # zsh requires a glob pattern to do file filtering
  117. filter="\*.$filter"
  118. fi
  119. filteringCmd+=" -g $filter"
  120. done
  121. filteringCmd+=" ${flagPrefix}"
  122. __%[1]s_debug "File filtering command: $filteringCmd"
  123. _arguments '*:filename:'"$filteringCmd"
  124. elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
  125. # File completion for directories only
  126. local subdir
  127. subdir="${completions[1]}"
  128. if [ -n "$subdir" ]; then
  129. __%[1]s_debug "Listing directories in $subdir"
  130. pushd "${subdir}" >/dev/null 2>&1
  131. else
  132. __%[1]s_debug "Listing directories in ."
  133. fi
  134. local result
  135. _arguments '*:dirname:_files -/'" ${flagPrefix}"
  136. result=$?
  137. if [ -n "$subdir" ]; then
  138. popd >/dev/null 2>&1
  139. fi
  140. return $result
  141. else
  142. __%[1]s_debug "Calling _describe"
  143. if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then
  144. __%[1]s_debug "_describe found some completions"
  145. # Return the success of having called _describe
  146. return 0
  147. else
  148. __%[1]s_debug "_describe did not find completions."
  149. __%[1]s_debug "Checking if we should do file completion."
  150. if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
  151. __%[1]s_debug "deactivating file completion"
  152. # We must return an error code here to let zsh know that there were no
  153. # completions found by _describe; this is what will trigger other
  154. # matching algorithms to attempt to find completions.
  155. # For example zsh can match letters in the middle of words.
  156. return 1
  157. else
  158. # Perform file completion
  159. __%[1]s_debug "Activating file completion"
  160. # We must return the result of this command, so it must be the
  161. # last command, or else we must store its result to return it.
  162. _arguments '*:filename:_files'" ${flagPrefix}"
  163. fi
  164. fi
  165. fi
  166. }
  167. # don't run the completion function when being source-ed or eval-ed
  168. if [ "$funcstack[1]" = "_%[1]s" ]; then
  169. _%[1]s
  170. fi