_cargo 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. #compdef cargo
  2. autoload -U regexp-replace
  3. _cargo() {
  4. local curcontext="$curcontext" ret=1
  5. local -a command_scope_spec common parallel features msgfmt triple target registry
  6. local -a state line state_descr # These are set by _arguments
  7. typeset -A opt_args
  8. common=(
  9. '(-q --quiet)*'{-v,--verbose}'[use verbose output]'
  10. '(-q --quiet -v --verbose)'{-q,--quiet}'[no output printed to stdout]'
  11. '-Z+[pass unstable (nightly-only) flags to cargo]: :_cargo_unstable_flags'
  12. '--frozen[require that Cargo.lock and cache are up to date]'
  13. '--locked[require that Cargo.lock is up to date]'
  14. '--color=[specify colorization option]:coloring:(auto always never)'
  15. '(- 1 *)'{-h,--help}'[show help message]'
  16. )
  17. # leading items in parentheses are an exclusion list for the arguments following that arg
  18. # See: http://zsh.sourceforge.net/Doc/Release/Completion-System.html#Completion-Functions
  19. # - => exclude all other options
  20. # 1 => exclude positional arg 1
  21. # * => exclude all other args
  22. # +blah => exclude +blah
  23. _arguments -s -S -C $common \
  24. '(- 1 *)--list[list installed commands]' \
  25. '(- 1 *)--explain=[provide a detailed explanation of an error message]:error code' \
  26. '(- 1 *)'{-V,--version}'[show version information]' \
  27. '(+beta +nightly)+stable[use the stable toolchain]' \
  28. '(+stable +nightly)+beta[use the beta toolchain]' \
  29. '(+stable +beta)+nightly[use the nightly toolchain]' \
  30. '1: :_cargo_cmds' \
  31. '*:: :->args'
  32. # These flags are mutually exclusive specifiers for the scope of a command; as
  33. # they are used in multiple places without change, they are expanded into the
  34. # appropriate command's `_arguments` where appropriate.
  35. command_scope_spec=(
  36. '(--bin --example --test --lib)--bench=[specify benchmark name]: :_cargo_benchmark_names'
  37. '(--bench --bin --test --lib)--example=[specify example name]:example name'
  38. '(--bench --example --test --lib)--bin=[specify binary name]:binary name'
  39. '(--bench --bin --example --test)--lib=[specify library name]:library name'
  40. '(--bench --bin --example --lib)--test=[specify test name]:test name'
  41. )
  42. parallel=(
  43. '(-j --jobs)'{-j+,--jobs=}'[specify number of parallel jobs]:jobs [# of CPUs]'
  44. )
  45. features=(
  46. '(--all-features)--features=[specify features to activate]:feature'
  47. '(--features)--all-features[activate all available features]'
  48. "--no-default-features[don't build the default features]"
  49. )
  50. msgfmt='--message-format=[specify error format]:error format [human]:(human json short)'
  51. triple='--target=[specify target triple]:target triple'
  52. target='--target-dir=[specify directory for all generated artifacts]:directory:_directories'
  53. manifest='--manifest-path=[specify path to manifest]:path:_directories'
  54. registry='--registry=[specify registry to use]:registry'
  55. case $state in
  56. args)
  57. curcontext="${curcontext%:*}-${words[1]}:"
  58. case ${words[1]} in
  59. bench)
  60. _arguments -s -A "^--" $common $parallel $features $msgfmt $triple $target $manifest \
  61. "${command_scope_spec[@]}" \
  62. '--all-targets[benchmark all targets]' \
  63. "--no-run[compile but don't run]" \
  64. '(-p --package)'{-p+,--package=}'[specify package to run benchmarks for]:package:_cargo_package_names' \
  65. '--exclude=[exclude packages from the benchmark]:spec' \
  66. '--no-fail-fast[run all benchmarks regardless of failure]' \
  67. '1: :_guard "^-*" "bench name"' \
  68. '*:args:_default'
  69. ;;
  70. build)
  71. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  72. '--all-targets[equivalent to specifying --lib --bins --tests --benches --examples]' \
  73. "${command_scope_spec[@]}" \
  74. '(-p --package)'{-p+,--package=}'[specify package to build]:package:_cargo_package_names' \
  75. '--release[build in release mode]' \
  76. '--build-plan[output the build plan in JSON]' \
  77. ;;
  78. check)
  79. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  80. '--all-targets[equivalent to specifying --lib --bins --tests --benches --examples]' \
  81. "${command_scope_spec[@]}" \
  82. '(-p --package)'{-p+,--package=}'[specify package to check]:package:_cargo_package_names' \
  83. '--release[check in release mode]' \
  84. ;;
  85. clean)
  86. _arguments -s -S $common $triple $target $manifest \
  87. '(-p --package)'{-p+,--package=}'[specify package to clean]:package:_cargo_package_names' \
  88. '--release[clean release artifacts]' \
  89. '--doc[clean just the documentation directory]'
  90. ;;
  91. doc)
  92. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  93. '--no-deps[do not build docs for dependencies]' \
  94. '--document-private-items[include non-public items in the documentation]' \
  95. '--open[open docs in browser after the build]' \
  96. '(-p --package)'{-p+,--package=}'[specify package to document]:package:_cargo_package_names' \
  97. '--release[build artifacts in release mode, with optimizations]' \
  98. ;;
  99. fetch)
  100. _arguments -s -S $common $triple $manifest
  101. ;;
  102. fix)
  103. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  104. "${command_scope_spec[@]}" \
  105. '--broken-code[fix code even if it already has compiler errors]' \
  106. '--edition[fix in preparation for the next edition]' \
  107. '--edition-idioms[fix warnings to migrate to the idioms of an edition]' \
  108. '--allow-no-vcs[fix code even if a VCS was not detected]' \
  109. '--allow-dirty[fix code even if the working directory is dirty]' \
  110. '--allow-staged[fix code even if the working directory has staged changes]'
  111. ;;
  112. generate-lockfile)
  113. _arguments -s -S $common $manifest
  114. ;;
  115. git-checkout)
  116. _arguments -s -S $common \
  117. '--reference=:reference' \
  118. '--url=:url:_urls'
  119. ;;
  120. help)
  121. _cargo_cmds
  122. ;;
  123. init)
  124. _arguments -s -S $common $registry \
  125. '--lib[use library template]' \
  126. '--edition=[specify edition to set for the crate generated]:edition:(2015 2018)' \
  127. '--vcs=[initialize a new repo with a given VCS]:vcs:(git hg pijul fossil none)' \
  128. '--name=[set the resulting package name]:name' \
  129. '1:path:_directories'
  130. ;;
  131. install)
  132. _arguments -s -S $common $parallel $features $triple $registry \
  133. '(-f --force)'{-f,--force}'[force overwriting of existing crates or binaries]' \
  134. '--bin=[only install the specified binary]:binary' \
  135. '--branch=[branch to use when installing from git]:branch' \
  136. '--debug[build in debug mode instead of release mode]' \
  137. '--example=[install the specified example instead of binaries]:example' \
  138. '--git=[specify URL from which to install the crate]:url:_urls' \
  139. '--path=[local filesystem path to crate to install]: :_directories' \
  140. '--rev=[specific commit to use when installing from git]:commit' \
  141. '--root=[directory to install packages into]: :_directories' \
  142. '--tag=[tag to use when installing from git]:tag' \
  143. '--vers=[version to install from crates.io]:version' \
  144. '--list[list all installed packages and their versions]' \
  145. '*: :_guard "^-*" "crate"'
  146. ;;
  147. locate-project)
  148. _arguments -s -S $common $manifest
  149. ;;
  150. login)
  151. _arguments -s -S $common $registry \
  152. '*: :_guard "^-*" "token"'
  153. ;;
  154. metadata)
  155. _arguments -s -S $common $features $manifest \
  156. "--no-deps[output information only about the root package and don't fetch dependencies]" \
  157. '--format-version=[specify format version]:version [1]:(1)'
  158. ;;
  159. new)
  160. _arguments -s -S $common $registry \
  161. '--lib[use library template]' \
  162. '--vcs:initialize a new repo with a given VCS:(git hg none)' \
  163. '--name=[set the resulting package name]'
  164. ;;
  165. owner)
  166. _arguments -s -S $common $registry \
  167. '(-a --add)'{-a,--add}'[specify name of a user or team to invite as an owner]:name' \
  168. '--index=[specify registry index]:index' \
  169. '(-l --list)'{-l,--list}'[list owners of a crate]' \
  170. '(-r --remove)'{-r,--remove}'[specify name of a user or team to remove as an owner]:name' \
  171. '--token=[specify API token to use when authenticating]:token' \
  172. '*: :_guard "^-*" "crate"'
  173. ;;
  174. package)
  175. _arguments -s -S $common $parallel $features $triple $target $manifest \
  176. '(-l --list)'{-l,--list}'[print files included in a package without making one]' \
  177. '--no-metadata[ignore warnings about a lack of human-usable metadata]' \
  178. '--allow-dirty[allow dirty working directories to be packaged]' \
  179. "--no-verify[don't build to verify contents]"
  180. ;;
  181. pkgid)
  182. _arguments -s -S $common $manifest \
  183. '(-p --package)'{-p+,--package=}'[specify package to get ID specifier for]:package:_cargo_package_names' \
  184. '*: :_guard "^-*" "spec"'
  185. ;;
  186. publish)
  187. _arguments -s -S $common $parallel $features $triple $target $manifest $registry \
  188. '--index=[specify registry index]:index' \
  189. '--allow-dirty[allow dirty working directories to be packaged]' \
  190. "--no-verify[don't verify the contents by building them]" \
  191. '--token=[specify token to use when uploading]:token' \
  192. '--dry-run[perform all checks without uploading]'
  193. ;;
  194. read-manifest)
  195. _arguments -s -S $common $manifest
  196. ;;
  197. run)
  198. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  199. '--example=[name of the bin target]:name' \
  200. '--bin=[name of the bin target]:name' \
  201. '(-p --package)'{-p+,--package=}'[specify package with the target to run]:package:_cargo_package_names' \
  202. '--release[build in release mode]' \
  203. '*: :_default'
  204. ;;
  205. rustc)
  206. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  207. '(-p --package)'{-p+,--package=}'[specify package to build]:package:_cargo_package_names' \
  208. '--profile=[specify profile to build the selected target for]:profile' \
  209. '--release[build artifacts in release mode, with optimizations]' \
  210. "${command_scope_spec[@]}" \
  211. '*: : _dispatch rustc rustc -default-'
  212. ;;
  213. rustdoc)
  214. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  215. '--document-private-items[include non-public items in the documentation]' \
  216. '--open[open the docs in a browser after the operation]' \
  217. '(-p --package)'{-p+,--package=}'[specify package to document]:package:_cargo_package_names' \
  218. '--release[build artifacts in release mode, with optimizations]' \
  219. "${command_scope_spec[@]}" \
  220. '*: : _dispatch rustdoc rustdoc -default-'
  221. ;;
  222. search)
  223. _arguments -s -S $common $registry \
  224. '--index=[specify registry index]:index' \
  225. '--limit=[limit the number of results]:results [10]' \
  226. '*: :_guard "^-*" "query"'
  227. ;;
  228. test)
  229. _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \
  230. '--test=[test name]: :_cargo_test_names' \
  231. '--no-fail-fast[run all tests regardless of failure]' \
  232. '--no-run[compile but do not run]' \
  233. '(-p --package)'{-p+,--package=}'[package to run tests for]:package:_cargo_package_names' \
  234. '--all[test all packages in the workspace]' \
  235. '--release[build artifacts in release mode, with optimizations]' \
  236. '1: :_cargo_test_names' \
  237. '(--doc --bin --example --test --bench)--lib[only test library]' \
  238. '(--lib --bin --example --test --bench)--doc[only test documentation]' \
  239. '(--lib --doc --example --test --bench)--bin=[binary name]' \
  240. '(--lib --doc --bin --test --bench)--example=[example name]' \
  241. '(--lib --doc --bin --example --bench)--test=[test name]' \
  242. '(--lib --doc --bin --example --test)--bench=[benchmark name]' \
  243. '*: :_default'
  244. ;;
  245. uninstall)
  246. _arguments -s -S $common \
  247. '(-p --package)'{-p+,--package=}'[specify package to uninstall]:package:_cargo_package_names' \
  248. '--bin=[only uninstall the specified binary]:name' \
  249. '--root=[directory to uninstall packages from]: :_files -/' \
  250. '*:crate:_cargo_installed_crates -F line'
  251. ;;
  252. update)
  253. _arguments -s -S $common $manifest \
  254. '--aggressive=[force dependency update]' \
  255. "--dry-run[don't actually write the lockfile]" \
  256. '(-p --package)'{-p+,--package=}'[specify package to update]:package:_cargo_package_names' \
  257. '--precise=[update single dependency to precise release]:release'
  258. ;;
  259. verify-project)
  260. _arguments -s -S $common $manifest
  261. ;;
  262. version)
  263. _arguments -s -S $common
  264. ;;
  265. yank)
  266. _arguments -s -S $common $registry \
  267. '--vers=[specify yank version]:version' \
  268. '--undo[undo a yank, putting a version back into the index]' \
  269. '--index=[specify registry index to yank from]:registry index' \
  270. '--token=[specify API token to use when authenticating]:token' \
  271. '*: :_guard "^-*" "crate"'
  272. ;;
  273. *)
  274. # allow plugins to define their own functions
  275. if ! _call_function ret _cargo-${words[1]}; then
  276. # fallback on default completion for unknown commands
  277. _default && ret=0
  278. fi
  279. (( ! ret ))
  280. ;;
  281. esac
  282. ;;
  283. esac
  284. }
  285. _cargo_unstable_flags() {
  286. local flags
  287. flags=( help ${${${(M)${(f)"$(_call_program flags cargo -Z help)"}:#*--*}/ #-- #/:}##*-Z } )
  288. _describe -t flags 'unstable flag' flags
  289. }
  290. _cargo_installed_crates() {
  291. local expl
  292. _description crates expl 'crate'
  293. compadd "$@" "$expl[@]" - ${${${(f)"$(cargo install --list)"}:# *}%% *}
  294. }
  295. _cargo_cmds() {
  296. local -a commands
  297. # This uses Parameter Expansion Flags, which are a built-in Zsh feature.
  298. # See more: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags
  299. # and http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion
  300. #
  301. # # How this work?
  302. #
  303. # First it splits the result of `cargo --list` at newline, then it removes the first line.
  304. # Then it removes indentation (4 whitespaces) before each items. (Note the x## pattern [1]).
  305. # Then it replaces those spaces between item and description with a `:`
  306. #
  307. # [1]: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org#patterns
  308. commands=( ${${${(M)"${(f)$(_call_program commands cargo --list)}":# *}/ ##/}/ ##/:} )
  309. _describe -t commands 'command' commands
  310. }
  311. #FIXME: Disabled until fixed
  312. #gets package names from the manifest file
  313. _cargo_package_names() {
  314. _message -e packages package
  315. }
  316. # Extracts the values of "name" from the array given in $1 and shows them as
  317. # command line options for completion
  318. _cargo_names_from_array() {
  319. # strip json from the path
  320. local manifest=${${${"$(cargo locate-project)"}%\"\}}##*\"}
  321. if [[ -z $manifest ]]; then
  322. return 0
  323. fi
  324. local last_line
  325. local -a names;
  326. local in_block=false
  327. local block_name=$1
  328. names=()
  329. while read -r line; do
  330. if [[ $last_line == "[[$block_name]]" ]]; then
  331. in_block=true
  332. else
  333. if [[ $last_line =~ '\s*\[\[.*' ]]; then
  334. in_block=false
  335. fi
  336. fi
  337. if [[ $in_block == true ]]; then
  338. if [[ $line =~ '\s*name\s*=' ]]; then
  339. regexp-replace line '^\s*name\s*=\s*|"' ''
  340. names+=( "$line" )
  341. fi
  342. fi
  343. last_line=$line
  344. done < "$manifest"
  345. _describe "$block_name" names
  346. }
  347. #Gets the test names from the manifest file
  348. _cargo_test_names() {
  349. _cargo_names_from_array "test"
  350. }
  351. #Gets the bench names from the manifest file
  352. _cargo_benchmark_names() {
  353. _cargo_names_from_array "bench"
  354. }
  355. _cargo