blob: 793c5c0f21e06606c9c16062f8bb3223839a25c1 [file] [log] [blame]
Matthew Maurerbd398542019-09-05 16:25:08 -07001# Required for bash versions < 4.1
2# Default bash version is 3.2 on latest macOS. See #6874
3shopt -s extglob
4
5command -v cargo >/dev/null 2>&1 &&
6_cargo()
7{
8 local cur prev words cword
9 _get_comp_words_by_ref cur prev words cword
10
11 COMPREPLY=()
12
13 # Skip past - and + options to find the command.
14 local nwords=${#words[@]}
15 local cmd_i cmd dd_i
16 for (( cmd_i=1; cmd_i<$nwords; cmd_i++ ));
17 do
18 if [[ ! "${words[$cmd_i]}" =~ ^[+-] ]]; then
19 cmd="${words[$cmd_i]}"
20 break
21 fi
22 done
23 # Find the location of the -- separator.
24 for (( dd_i=1; dd_i<$nwords-1; dd_i++ ));
25 do
26 if [[ "${words[$dd_i]}" = "--" ]]; then
27 break
28 fi
29 done
30
31 local vcs='git hg none pijul fossil'
32 local color='auto always never'
33 local msg_format='human json short'
34
35 local opt_help='-h --help'
36 local opt_verbose='-v --verbose'
37 local opt_quiet='-q --quiet'
38 local opt_color='--color'
39 local opt_common="$opt_help $opt_verbose $opt_quiet $opt_color"
40 local opt_pkg_spec='-p --package --all --exclude'
41 local opt_pkg='-p --package'
42 local opt_feat='--features --all-features --no-default-features'
43 local opt_mani='--manifest-path'
44 local opt_jobs='-j --jobs'
45 local opt_force='-f --force'
46 local opt_test='--test --bench'
47 local opt_lock='--frozen --locked'
48 local opt_targets="--lib --bin --bins --example --examples --test --tests --bench --benches --all-targets"
49
50 local opt___nocmd="$opt_common -V --version --list --explain"
51 local opt__bench="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test $opt_targets --message-format --target --no-run --no-fail-fast --target-dir"
52 local opt__build="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test $opt_targets --message-format --target --release --target-dir"
53 local opt__check="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test $opt_targets --message-format --target --release --profile --target-dir"
54 local opt__clean="$opt_common $opt_pkg $opt_mani $opt_lock --target --release --doc --target-dir"
55 local opt__doc="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs --message-format --bin --bins --lib --target --open --no-deps --release --document-private-items --target-dir"
56 local opt__fetch="$opt_common $opt_mani $opt_lock"
57 local opt__fix="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_jobs $opt_targets $opt_lock --release --target --message-format --prepare-for --broken-code --edition --edition-idioms --allow-no-vcs --allow-dirty --allow-staged --profile --target-dir"
58 local opt__generate_lockfile="${opt__fetch}"
59 local opt__git_checkout="$opt_common $opt_lock --reference --url"
60 local opt__help="$opt_help"
61 local opt__init="$opt_common $opt_lock --bin --lib --name --vcs --edition --registry"
62 local opt__install="$opt_common $opt_feat $opt_jobs $opt_lock $opt_force --bin --bins --branch --debug --example --examples --git --list --path --rev --root --tag --version --registry --target"
63 local opt__locate_project="$opt_mani -h --help"
64 local opt__login="$opt_common $opt_lock --host --registry"
65 local opt__metadata="$opt_common $opt_feat $opt_mani $opt_lock --format-version=1 --no-deps"
66 local opt__new="$opt_common $opt_lock --vcs --bin --lib --name --edition --registry"
67 local opt__owner="$opt_common $opt_lock -a --add -r --remove -l --list --index --token --registry"
68 local opt__package="$opt_common $opt_mani $opt_feat $opt_lock $opt_jobs --allow-dirty -l --list --no-verify --no-metadata --target --target-dir"
69 local opt__pkgid="${opt__fetch} $opt_pkg"
70 local opt__publish="$opt_common $opt_mani $opt_feat $opt_lock $opt_jobs --allow-dirty --dry-run --host --token --no-verify --index --registry --target --target-dir"
71 local opt__read_manifest="$opt_help $opt_quiet $opt_verbose $opt_mani $opt_color "
72 local opt__run="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs --message-format --target --bin --example --release --target-dir"
73 local opt__rustc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test $opt_targets --message-format --profile --target --release --target-dir"
74 local opt__rustdoc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test $opt_targets --message-format --target --release --open --target-dir"
75 local opt__search="$opt_common $opt_lock --host --limit --index --limit --registry"
76 local opt__test="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test $opt_targets --message-format --doc --target --no-run --release --no-fail-fast --target-dir"
77 local opt__uninstall="$opt_common $opt_lock $opt_pkg_spec --bin --root"
78 local opt__update="$opt_common $opt_pkg_spec $opt_mani $opt_lock --aggressive --precise --dry-run"
79 local opt__verify_project="${opt__fetch}"
80 local opt__version="$opt_help $opt_verbose $opt_color"
81 local opt__yank="$opt_common $opt_lock --vers --undo --index --token --registry"
82 local opt__libtest="--help --include-ignored --ignored --test --bench --list --logfile --nocapture --test-threads --skip -q --quiet --exact --color --format"
83
84 if [[ $cword -gt $dd_i ]]; then
85 # Completion after -- separator.
86 if [[ "${cmd}" = @(test|bench) ]]; then
87 COMPREPLY=( $( compgen -W "${opt__libtest}" -- "$cur" ) )
88 else
89 # Fallback to filename completion, useful with `cargo run`.
90 _filedir
91 fi
92 elif [[ $cword -le $cmd_i ]]; then
93 # Completion before or at the command.
94 if [[ "$cur" == -* ]]; then
95 COMPREPLY=( $( compgen -W "${opt___nocmd}" -- "$cur" ) )
96 elif [[ "$cur" == +* ]]; then
97 COMPREPLY=( $( compgen -W "$(_toolchains)" -- "$cur" ) )
98 else
99 COMPREPLY=( $( compgen -W "$__cargo_commands" -- "$cur" ) )
100 fi
101 else
102 case "${prev}" in
103 --vcs)
104 COMPREPLY=( $( compgen -W "$vcs" -- "$cur" ) )
105 ;;
106 --color)
107 COMPREPLY=( $( compgen -W "$color" -- "$cur" ) )
108 ;;
109 --message-format)
110 COMPREPLY=( $( compgen -W "$msg_format" -- "$cur" ) )
111 ;;
112 --manifest-path)
113 _filedir toml
114 ;;
115 --bin)
116 COMPREPLY=( $( compgen -W "$(_bin_names)" -- "$cur" ) )
117 ;;
118 --test)
119 COMPREPLY=( $( compgen -W "$(_test_names)" -- "$cur" ) )
120 ;;
121 --bench)
122 COMPREPLY=( $( compgen -W "$(_benchmark_names)" -- "$cur" ) )
123 ;;
124 --example)
125 COMPREPLY=( $( compgen -W "$(_get_examples)" -- "$cur" ) )
126 ;;
127 --target)
128 COMPREPLY=( $( compgen -W "$(_get_targets)" -- "$cur" ) )
129 ;;
130 --target-dir)
131 _filedir -d
132 ;;
133 help)
134 COMPREPLY=( $( compgen -W "$__cargo_commands" -- "$cur" ) )
135 ;;
136 *)
137 local opt_var=opt__${cmd//-/_}
138 if [[ -z "${!opt_var}" ]]; then
139 # Fallback to filename completion.
140 _filedir
141 else
142 COMPREPLY=( $( compgen -W "${!opt_var}" -- "$cur" ) )
143 fi
144 ;;
145 esac
146 fi
147
148 # compopt does not work in bash version 3
149
150 return 0
151} &&
152complete -F _cargo cargo
153
154__cargo_commands=$(cargo --list 2>/dev/null | awk 'NR>1 {print $1}')
155
156_locate_manifest(){
157 local manifest=`cargo locate-project 2>/dev/null`
158 # regexp-replace manifest '\{"root":"|"\}' ''
159 echo ${manifest:9:${#manifest}-11}
160}
161
162# Extracts the values of "name" from the array given in $1 and shows them as
163# command line options for completion
164_get_names_from_array()
165{
166 local manifest=$(_locate_manifest)
167 if [[ -z $manifest ]]; then
168 return 0
169 fi
170
171 local last_line
172 local -a names
173 local in_block=false
174 local block_name=$1
175 while read line
176 do
177 if [[ $last_line == "[[$block_name]]" ]]; then
178 in_block=true
179 else
180 if [[ $last_line =~ .*\[\[.* ]]; then
181 in_block=false
182 fi
183 fi
184
185 if [[ $in_block == true ]]; then
186 if [[ $line =~ .*name.*\= ]]; then
187 line=${line##*=}
188 line=${line%%\"}
189 line=${line##*\"}
190 names+=($line)
191 fi
192 fi
193
194 last_line=$line
195 done < $manifest
196 echo "${names[@]}"
197}
198
199#Gets the bin names from the manifest file
200_bin_names()
201{
202 _get_names_from_array "bin"
203}
204
205#Gets the test names from the manifest file
206_test_names()
207{
208 _get_names_from_array "test"
209}
210
211#Gets the bench names from the manifest file
212_benchmark_names()
213{
214 _get_names_from_array "bench"
215}
216
217_get_examples(){
218 local manifest=$(_locate_manifest)
219 [ -z "$manifest" ] && return 0
220
221 local files=("${manifest%/*}"/examples/*.rs)
222 local names=("${files[@]##*/}")
223 local names=("${names[@]%.*}")
224 # "*" means no examples found
225 if [[ "${names[@]}" != "*" ]]; then
226 echo "${names[@]}"
227 fi
228}
229
230_get_targets(){
231 local result=()
232 local targets=$(rustup target list)
233 while read line
234 do
235 if [[ "$line" =~ default|installed ]]; then
236 result+=("${line%% *}")
237 fi
238 done <<< "$targets"
239 echo "${result[@]}"
240}
241
242_toolchains(){
243 local result=()
244 local toolchains=$(rustup toolchain list)
245 local channels="nightly|beta|stable|[0-9]\.[0-9]{1,2}\.[0-9]"
246 local date="[0-9]{4}-[0-9]{2}-[0-9]{2}"
247 while read line
248 do
249 # Strip " (default)"
250 line=${line%% *}
251 if [[ "$line" =~ ^($channels)(-($date))?(-.*) ]]; then
252 if [[ -z ${BASH_REMATCH[3]} ]]; then
253 result+=("+${BASH_REMATCH[1]}")
254 else
255 # channel-date
256 result+=("+${BASH_REMATCH[1]}-${BASH_REMATCH[3]}")
257 fi
258 result+=("+$line")
259 else
260 result+=("+$line")
261 fi
262 done <<< "$toolchains"
263 echo "${result[@]}"
264}
265
266# vim:ft=sh