xref: /aosp_15_r20/prebuilts/rust/linux-x86/1.80.1/etc/bash_completion.d/cargo (revision b40554a23088fb75aa6945dfe8e65169c8484da3)
1# 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 --workspace'
41	local opt_pkg='-p --package'
42	local opt_feat='-F --features --all-features --no-default-features'
43	local opt_mani='--manifest-path'
44	local opt_jobs='-j --jobs'
45	local opt_parallel="$opt_jobs --keep-going"
46	local opt_force='-f --force'
47	local opt_sync='-s --sync'
48	local opt_lock='--frozen --locked --offline'
49	local opt_targets="--lib --bin --bins --example --examples --test --tests --bench --benches --all-targets"
50
51	local opt___nocmd="$opt_common -V --version --list --explain"
52	local opt__add="$opt_common -p --package --features --default-features --no-default-features $opt_mani --optional --no-optional --rename --dry-run --path --git --branch --tag --rev --registry --dev --build --target --ignore-rust-version"
53	local opt__bench="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_targets --message-format --target --no-run --no-fail-fast --target-dir --ignore-rust-version"
54	local opt__build="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --ignore-rust-version"
55	local opt__b="$opt__build"
56	local opt__check="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --ignore-rust-version"
57	local opt__c="$opt__check"
58	local opt__clean="$opt_common $opt_pkg $opt_mani $opt_lock --target --release --doc --target-dir --profile"
59	local opt__clippy="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --no-deps --fix"
60	local opt__doc="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel --message-format --bin --bins --lib --target --open --no-deps --release --document-private-items --target-dir --profile --ignore-rust-version"
61	local opt__d="$opt__doc"
62	local opt__fetch="$opt_common $opt_mani $opt_lock --target"
63	local opt__fix="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_parallel $opt_targets $opt_lock --release --target --message-format --broken-code --edition --edition-idioms --allow-no-vcs --allow-dirty --allow-staged --profile --target-dir --ignore-rust-version"
64	local opt__generate_lockfile="$opt_common $opt_mani $opt_lock"
65	local opt__help="$opt_help"
66	local opt__init="$opt_common $opt_lock --bin --lib --name --vcs --edition --registry"
67	local opt__install="$opt_common $opt_feat $opt_parallel $opt_lock $opt_force --bin --bins --branch --debug --example --examples --git --list --path --rev --root --tag --version --registry --target --profile --no-track --ignore-rust-version"
68	local opt__locate_project="$opt_common $opt_mani $opt_lock --message-format --workspace"
69	local opt__login="$opt_common $opt_lock --registry"
70	local opt__metadata="$opt_common $opt_feat $opt_mani $opt_lock --format-version=1 --no-deps --filter-platform"
71	local opt__new="$opt_common $opt_lock --vcs --bin --lib --name --edition --registry"
72	local opt__owner="$opt_common $opt_lock -a --add -r --remove -l --list --index --token --registry"
73	local opt__package="$opt_common $opt_mani $opt_feat $opt_lock $opt_parallel --allow-dirty -l --list --no-verify --no-metadata --target --target-dir"
74	local opt__pkgid="$opt_common $opt_mani $opt_lock $opt_pkg"
75	local opt__publish="$opt_common $opt_mani $opt_feat $opt_lock $opt_parallel --allow-dirty --dry-run --token --no-verify --index --registry --target --target-dir"
76	local opt__read_manifest="$opt_help $opt_quiet $opt_verbose $opt_mani $opt_color $opt_lock --no-deps"
77	local opt__remove="$opt_common $opt_pkg $opt_lock $opt_mani --dry-run --dev --build --target"
78	local opt__rm="$opt__remove"
79	local opt__report="$opt_help $opt_verbose $opt_color future-incompat future-incompatibilities"
80	local opt__report__future_incompat="$opt_help $opt_verbose $opt_color $opt_pkg --id"
81	local opt__run="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel --message-format --target --bin --example --release --target-dir --profile --ignore-rust-version"
82	local opt__r="$opt__run"
83	local opt__rustc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets -L --crate-type --extern --message-format --profile --target --release --target-dir --ignore-rust-version"
84	local opt__rustdoc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --open --target-dir --profile --ignore-rust-version"
85	local opt__search="$opt_common $opt_lock --limit --index --registry"
86	local opt__test="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_targets --message-format --doc --target --no-run --release --no-fail-fast --target-dir --profile --ignore-rust-version"
87	local opt__t="$opt__test"
88	local opt__tree="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock --target -i --invert --prefix --no-dedupe --duplicates -d --charset -f --format -e --edges"
89	local opt__uninstall="$opt_common $opt_lock $opt_pkg --bin --root"
90	local opt__update="$opt_common $opt_mani $opt_lock $opt_pkg --aggressive --recursive --precise --dry-run"
91	local opt__vendor="$opt_common $opt_mani $opt_lock $opt_sync --no-delete --respect-source-config --versioned-dirs"
92	local opt__verify_project="$opt_common $opt_mani $opt_lock"
93	local opt__version="$opt_common $opt_lock"
94	local opt__yank="$opt_common $opt_lock --version --undo --index --token --registry"
95	local opt__libtest="--help --include-ignored --ignored --test --bench --list --logfile --nocapture --test-threads --skip -q --quiet --exact --color --format"
96
97	if [[ $cword -gt $dd_i ]]; then
98		# Completion after -- separator.
99		if [[ "${cmd}" = @(test|bench) ]]; then
100			COMPREPLY=( $( compgen -W "${opt__libtest}" -- "$cur" ) )
101		else
102			# Fallback to filename completion, useful with `cargo run`.
103			_filedir
104		fi
105	elif [[ $cword -le $cmd_i ]]; then
106		# Completion before or at the command.
107		if [[ "$cur" == -* ]]; then
108			COMPREPLY=( $( compgen -W "${opt___nocmd}" -- "$cur" ) )
109		elif [[ "$cur" == +* ]]; then
110			COMPREPLY=( $( compgen -W "$(_toolchains)" -- "$cur" ) )
111		else
112			_ensure_cargo_commands_cache_filled
113			COMPREPLY=( $( compgen -W "$__cargo_commands_cache" -- "$cur" ) )
114		fi
115	else
116		case "${prev}" in
117			--vcs)
118				COMPREPLY=( $( compgen -W "$vcs" -- "$cur" ) )
119				;;
120			--color)
121				COMPREPLY=( $( compgen -W "$color" -- "$cur" ) )
122				;;
123			--message-format)
124				COMPREPLY=( $( compgen -W "$msg_format" -- "$cur" ) )
125				;;
126			--manifest-path)
127				_filedir toml
128				;;
129			--bin)
130				COMPREPLY=( $( compgen -W "$(_bin_names)" -- "$cur" ) )
131				;;
132			--test)
133				COMPREPLY=( $( compgen -W "$(_test_names)" -- "$cur" ) )
134				;;
135			--bench)
136				COMPREPLY=( $( compgen -W "$(_benchmark_names)" -- "$cur" ) )
137				;;
138			--example)
139				COMPREPLY=( $( compgen -W "$(_get_examples)" -- "$cur" ) )
140				;;
141			--target)
142				COMPREPLY=( $( compgen -W "$(_get_targets)" -- "$cur" ) )
143				;;
144			--target-dir|--path)
145				_filedir -d
146				;;
147			help)
148				_ensure_cargo_commands_cache_filled
149				COMPREPLY=( $( compgen -W "$__cargo_commands_cache" -- "$cur" ) )
150				;;
151			*)
152				if [[ "$cmd" == "report" && "$prev" == future-incompat* ]]; then
153					local opt_var=opt__${cmd//-/_}__${prev//-/_}
154				else
155					local opt_var=opt__${cmd//-/_}
156				fi
157				if [[ -z "${!opt_var-}" ]]; then
158					# Fallback to filename completion.
159					_filedir
160				else
161					COMPREPLY=( $( compgen -W "${!opt_var}" -- "$cur" ) )
162				fi
163				;;
164		esac
165	fi
166
167	# compopt does not work in bash version 3
168
169	return 0
170} &&
171complete -F _cargo cargo
172
173__cargo_commands_cache=
174_ensure_cargo_commands_cache_filled(){
175	if [[ -z $__cargo_commands_cache ]]; then
176		__cargo_commands_cache="$(cargo --list 2>/dev/null | awk 'NR>1 {print $1}')"
177	fi
178}
179
180_locate_manifest(){
181	cargo locate-project --message-format plain 2>/dev/null
182}
183
184# Extracts the values of "name" from the array given in $1 and shows them as
185# command line options for completion
186_get_names_from_array()
187{
188	local manifest=$(_locate_manifest)
189	if [[ -z $manifest ]]; then
190		return 0
191	fi
192
193	local last_line
194	local -a names
195	local in_block=false
196	local block_name=$1
197	while read line
198	do
199		if [[ $last_line == "[[$block_name]]" ]]; then
200			in_block=true
201		else
202			if [[ $last_line =~ .*\[\[.* ]]; then
203				in_block=false
204			fi
205		fi
206
207		if [[ $in_block == true ]]; then
208			if [[ $line =~ .*name.*\= ]]; then
209				line=${line##*=}
210				line=${line%%\"}
211				line=${line##*\"}
212				names+=("$line")
213			fi
214		fi
215
216		last_line=$line
217	done < "$manifest"
218	echo "${names[@]}"
219}
220
221#Gets the bin names from the manifest file
222_bin_names()
223{
224	_get_names_from_array "bin"
225}
226
227#Gets the test names from the manifest file
228_test_names()
229{
230	_get_names_from_array "test"
231}
232
233#Gets the bench names from the manifest file
234_benchmark_names()
235{
236	_get_names_from_array "bench"
237}
238
239_get_examples(){
240	local manifest=$(_locate_manifest)
241	[ -z "$manifest" ] && return 0
242
243	local files=("${manifest%/*}"/examples/*.rs)
244	local names=("${files[@]##*/}")
245	local names=("${names[@]%.*}")
246	# "*" means no examples found
247	if [[ "${names[@]}" != "*" ]]; then
248		echo "${names[@]}"
249	fi
250}
251
252_get_targets(){
253	if command -v rustup >/dev/null 2>/dev/null; then
254	  rustup target list --installed
255	else
256	  rustc --print target-list
257	fi
258}
259
260_toolchains(){
261	local result=()
262	local toolchains=$(rustup toolchain list)
263	local channels="nightly|beta|stable|[0-9]\.[0-9]{1,2}\.[0-9]"
264	local date="[0-9]{4}-[0-9]{2}-[0-9]{2}"
265	while read line
266	do
267		# Strip " (default)"
268		line=${line%% *}
269		if [[ "$line" =~ ^($channels)(-($date))?(-.*) ]]; then
270			if [[ -z ${BASH_REMATCH[3]} ]]; then
271				result+=("+${BASH_REMATCH[1]}")
272			else
273				# channel-date
274				result+=("+${BASH_REMATCH[1]}-${BASH_REMATCH[3]}")
275			fi
276			result+=("+$line")
277		else
278			result+=("+$line")
279		fi
280	done <<< "$toolchains"
281	echo "${result[@]}"
282}
283
284# vim:ft=sh
285