_python-argcomplete 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #compdef -default-
  2. # argcomplete global completion loader for zsh and bash
  3. # Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors.
  4. # Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info.
  5. # Note: both the leading underscore in the name of this file and the first line (compdef) are required by zsh
  6. # In zsh, this file is autoloaded and used as the default completer (_default).
  7. # There are many other special contexts we don't want to override
  8. # (as would be the case with `#compdef -P *`).
  9. # https://zsh.sourceforge.io/Doc/Release/Completion-System.html
  10. # Copy of __expand_tilde_by_ref from bash-completion
  11. # ZSH implementation added
  12. __python_argcomplete_expand_tilde_by_ref () {
  13. if [ -n "${ZSH_VERSION-}" ]; then
  14. if [ "${(P)1[1]}" = "~" ]; then
  15. eval $1="${(P)1/#\~/$HOME}";
  16. fi
  17. else
  18. if [ "${!1:0:1}" = "~" ]; then
  19. if [ "${!1}" != "${!1//\/}" ]; then
  20. eval $1="${!1/%\/*}"/'${!1#*/}';
  21. else
  22. eval $1="${!1}";
  23. fi;
  24. fi
  25. fi
  26. }
  27. # Run something, muting output or redirecting it to the debug stream
  28. # depending on the value of _ARC_DEBUG.
  29. # If ARGCOMPLETE_USE_TEMPFILES is set, use tempfiles for IPC.
  30. __python_argcomplete_run() {
  31. if [[ -z "${ARGCOMPLETE_USE_TEMPFILES-}" ]]; then
  32. __python_argcomplete_run_inner "$@"
  33. return
  34. fi
  35. local tmpfile="$(mktemp)"
  36. _ARGCOMPLETE_STDOUT_FILENAME="$tmpfile" __python_argcomplete_run_inner "$@"
  37. local code=$?
  38. cat "$tmpfile"
  39. rm "$tmpfile"
  40. return $code
  41. }
  42. __python_argcomplete_run_inner() {
  43. if [[ -z "${_ARC_DEBUG-}" ]]; then
  44. "$@" 8>&1 9>&2 1>/dev/null 2>&1 </dev/null
  45. else
  46. "$@" 8>&1 9>&2 1>&9 2>&1 </dev/null
  47. fi
  48. }
  49. __python_argcomplete_upshift_bash_rematch() {
  50. if [[ -z "${ZSH_VERSION-}" ]]; then
  51. _BASH_REMATCH=( "" "${BASH_REMATCH[@]}" )
  52. else
  53. _BASH_REMATCH=( "${BASH_REMATCH[@]}" )
  54. fi
  55. }
  56. # This function scans the beginning of an executable file provided as the first
  57. # argument ($1) for certain indicators, specified by the second argument ($2),
  58. # or the "target". There are three possible targets: "interpreter",
  59. # "magic_string", and "easy_install". If the target is "interpreter", the
  60. # function matches the interpreter line, alongside any optional interpreter
  61. # arguments. If the target is "magic_string", a match is attempted for the
  62. # "PYTHON_ARGCOMPLETE_OK" magic string, indicating that the file should be run
  63. # to get completions. If the target is "easy_install", the function matches either
  64. # "PBR Generated" or any of the "EASY-INSTALL" scripts (either SCRIPT,
  65. # ENTRY-SCRIPT, or DEV-SCRIPT). In all cases, only the first kilobyte of
  66. # the file is searched. The regex matches are returned in BASH_REMATCH,
  67. # indexed starting at 1, regardless of the shell in use.
  68. __python_argcomplete_scan_head() {
  69. local file="$1"
  70. local target="$2"
  71. local REPLY
  72. if [[ -n "${ZSH_VERSION-}" ]]; then
  73. read -r -k 1024 -u 0 < "$file";
  74. else
  75. read -r -N 1024 < "$file"
  76. fi
  77. # Since ZSH does not support a -n option, we
  78. # trim all characters after the first line in both shells
  79. if [[ "$target" = "interpreter" ]]; then
  80. read -r <<< "$REPLY"
  81. fi
  82. local regex
  83. case "$target" in
  84. magic_string) regex='PYTHON_ARGCOMPLETE_OK' ;;
  85. easy_install) regex="(PBR Generated)|(EASY-INSTALL-(SCRIPT|ENTRY-SCRIPT|DEV-SCRIPT))" ;;
  86. asdf) regex="asdf exec " ;;
  87. interpreter) regex='^#!(.*)$' ;;
  88. esac
  89. local ret=""
  90. if [[ "$REPLY" =~ $regex ]]; then
  91. ret=1
  92. fi
  93. __python_argcomplete_upshift_bash_rematch
  94. [[ -n $ret ]]
  95. }
  96. __python_argcomplete_scan_head_noerr() {
  97. __python_argcomplete_scan_head "$@" 2>/dev/null
  98. }
  99. __python_argcomplete_which() {
  100. if [[ -n "${ZSH_VERSION-}" ]]; then
  101. whence -p "$@"
  102. else
  103. type -P "$@"
  104. fi
  105. }
  106. _python_argcomplete_global() {
  107. if [[ -n "${ZSH_VERSION-}" ]]; then
  108. # Store result of a regex match in the
  109. # BASH_REMATCH variable rather than MATCH
  110. setopt local_options BASH_REMATCH
  111. fi
  112. # 1-based version of BASH_REMATCH. Modifying BASH_REMATCH
  113. # directly causes older versions of Bash to exit
  114. local _BASH_REMATCH="";
  115. local executable=""
  116. # req_argv contains the arguments to the completion
  117. # indexed from 1 (regardless of the shell.) In Bash,
  118. # the zeroth index is empty
  119. local req_argv=()
  120. if [[ -z "${ZSH_VERSION-}" ]]; then
  121. executable=$1
  122. req_argv=( "" "${COMP_WORDS[@]:1}" )
  123. __python_argcomplete_expand_tilde_by_ref executable
  124. else
  125. executable="${words[1]}"
  126. __python_argcomplete_expand_tilde_by_ref executable
  127. req_argv=( "${words[@]:1}" )
  128. fi
  129. local ARGCOMPLETE=0
  130. if [[ "$executable" == python* ]] || [[ "$executable" == pypy* ]]; then
  131. if [[ "${req_argv[1]}" == -m ]]; then
  132. if __python_argcomplete_run "$executable" -m argcomplete._check_module "${req_argv[2]}"; then
  133. ARGCOMPLETE=3
  134. else
  135. return
  136. fi
  137. fi
  138. if [[ $ARGCOMPLETE == 0 ]]; then
  139. local potential_path="${req_argv[1]}"
  140. __python_argcomplete_expand_tilde_by_ref potential_path
  141. if [[ -f "$potential_path" ]] && __python_argcomplete_scan_head_noerr "$potential_path" magic_string; then
  142. req_argv[1]="$potential_path" # not expanded in __python_argcomplete_run
  143. ARGCOMPLETE=2
  144. else
  145. return
  146. fi
  147. fi
  148. elif __python_argcomplete_which "$executable" >/dev/null 2>&1; then
  149. local SCRIPT_NAME=$(__python_argcomplete_which "$executable")
  150. __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" interpreter
  151. if (__python_argcomplete_which pyenv && [[ "$SCRIPT_NAME" = $(pyenv root)/shims/* ]]) >/dev/null 2>&1; then
  152. local SCRIPT_NAME=$(pyenv which "$executable")
  153. fi
  154. if (__python_argcomplete_which asdf && __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" asdf) >/dev/null 2>&1; then
  155. local SCRIPT_NAME=$(asdf which "$executable")
  156. fi
  157. if __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" magic_string; then
  158. ARGCOMPLETE=1
  159. elif __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" interpreter; then
  160. __python_argcomplete_upshift_bash_rematch
  161. local interpreter="${_BASH_REMATCH[2]}"
  162. if [[ -n "${ZSH_VERSION-}" ]]; then
  163. interpreter=($=interpreter)
  164. else
  165. interpreter=($interpreter)
  166. fi
  167. if (__python_argcomplete_scan_head_noerr "$SCRIPT_NAME" easy_install \
  168. && "${interpreter[@]}" "$(__python_argcomplete_which python-argcomplete-check-easy-install-script)" "$SCRIPT_NAME") >/dev/null 2>&1; then
  169. ARGCOMPLETE=1
  170. elif __python_argcomplete_run "${interpreter[@]}" -m argcomplete._check_console_script "$SCRIPT_NAME"; then
  171. ARGCOMPLETE=1
  172. fi
  173. fi
  174. fi
  175. if [[ $ARGCOMPLETE != 0 ]]; then
  176. local IFS=$'\013'
  177. if [[ -n "${ZSH_VERSION-}" ]]; then
  178. local completions
  179. completions=($(IFS="$IFS" \
  180. COMP_LINE="$BUFFER" \
  181. COMP_POINT="$CURSOR" \
  182. _ARGCOMPLETE=$ARGCOMPLETE \
  183. _ARGCOMPLETE_SHELL="zsh" \
  184. _ARGCOMPLETE_SUPPRESS_SPACE=1 \
  185. __python_argcomplete_run "$executable" "${(@)req_argv[1, ${ARGCOMPLETE}-1]}"))
  186. local nosort=()
  187. local nospace=()
  188. if is-at-least 5.8; then
  189. nosort=(-o nosort)
  190. fi
  191. if [[ "${completions-}" =~ ([^\\]): && "${BASH_REMATCH[2]}" =~ [=/:] ]]; then
  192. nospace=(-S '')
  193. fi
  194. _describe "$executable" completions "${nosort[@]}" "${nospace[@]}"
  195. else
  196. COMPREPLY=($(IFS="$IFS" \
  197. COMP_LINE="$COMP_LINE" \
  198. COMP_POINT="$COMP_POINT" \
  199. COMP_TYPE="$COMP_TYPE" \
  200. _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" \
  201. _ARGCOMPLETE=$ARGCOMPLETE \
  202. _ARGCOMPLETE_SHELL="bash" \
  203. _ARGCOMPLETE_SUPPRESS_SPACE=1 \
  204. __python_argcomplete_run "$executable" "${req_argv[@]:1:${ARGCOMPLETE}-1}"))
  205. if [[ $? != 0 ]]; then
  206. unset COMPREPLY
  207. elif [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then
  208. compopt -o nospace
  209. fi
  210. fi
  211. elif [[ -n "${ZSH_VERSION-}" ]]; then
  212. _default
  213. else
  214. type -t _completion_loader | grep -q 'function' && _completion_loader "$@"
  215. fi
  216. }
  217. if [[ -z "${ZSH_VERSION-}" ]]; then
  218. complete -o default -o bashdefault -D -F _python_argcomplete_global
  219. else
  220. # -Uz is recommended for the use of functions supplied with the zsh distribution.
  221. # https://unix.stackexchange.com/a/214306
  222. autoload -Uz is-at-least
  223. # If this is being implicitly loaded because we placed it on fpath,
  224. # the comment at the top of this file causes zsh to invoke this script directly,
  225. # so we must explicitly call the global completion function.
  226. # Note $service should only ever be -default- because the comment at the top
  227. # registers this script as the default completer (#compdef -default-).
  228. if [[ $service == -default- ]]; then
  229. _python_argcomplete_global
  230. fi
  231. # If this has been executed directly (e.g. `eval "$(activate-global-python-argcomplete --dest=-)"`)
  232. # we need to explicitly call compdef to register the completion function.
  233. # If we have been implicitly loaded, we still call compdef as a slight optimisation
  234. # (there is no need to execute any top-level code more than once).
  235. compdef _python_argcomplete_global -default-
  236. fi