Skip to content

Commit ac5fc2e

Browse files
committed
feat: Add custom completer for completing example names
1 parent 468f150 commit ac5fc2e

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

src/cargo/util/command_prelude.rs

+40-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::core::compiler::{BuildConfig, MessageFormat, TimingOutput};
22
use crate::core::resolver::CliFeatures;
3-
use crate::core::{Edition, Workspace};
3+
use crate::core::{shell, Edition, Target, TargetKind, Workspace};
44
use crate::ops::lockfile::LOCKFILE_NAME;
55
use crate::ops::registry::RegistryOrIndex;
66
use crate::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
@@ -19,6 +19,7 @@ use cargo_util_schemas::manifest::ProfileName;
1919
use cargo_util_schemas::manifest::RegistryName;
2020
use cargo_util_schemas::manifest::StringOrVec;
2121
use clap::builder::UnknownArgumentValueParser;
22+
use home::cargo_home_with_cwd;
2223
use std::ffi::{OsStr, OsString};
2324
use std::path::Path;
2425
use std::path::PathBuf;
@@ -177,7 +178,10 @@ pub trait CommandExt: Sized {
177178
._arg(flag("examples", examples).help_heading(heading::TARGET_SELECTION))
178179
._arg(
179180
optional_multi_opt("example", "NAME", example)
180-
.help_heading(heading::TARGET_SELECTION),
181+
.help_heading(heading::TARGET_SELECTION)
182+
.add(clap_complete::ArgValueCandidates::new(
183+
get_example_candidates,
184+
)),
181185
)
182186
}
183187

@@ -192,7 +196,10 @@ pub trait CommandExt: Sized {
192196
._arg(flag("bins", bins).help_heading(heading::TARGET_SELECTION))
193197
._arg(
194198
optional_multi_opt("example", "NAME", example)
195-
.help_heading(heading::TARGET_SELECTION),
199+
.help_heading(heading::TARGET_SELECTION)
200+
.add(clap_complete::ArgValueCandidates::new(
201+
get_example_candidates,
202+
)),
196203
)
197204
._arg(flag("examples", examples).help_heading(heading::TARGET_SELECTION))
198205
}
@@ -201,7 +208,10 @@ pub trait CommandExt: Sized {
201208
self._arg(optional_multi_opt("bin", "NAME", bin).help_heading(heading::TARGET_SELECTION))
202209
._arg(
203210
optional_multi_opt("example", "NAME", example)
204-
.help_heading(heading::TARGET_SELECTION),
211+
.help_heading(heading::TARGET_SELECTION)
212+
.add(clap_complete::ArgValueCandidates::new(
213+
get_example_candidates,
214+
)),
205215
)
206216
}
207217

@@ -1027,6 +1037,32 @@ pub fn lockfile_path(
10271037
return Ok(Some(path));
10281038
}
10291039

1040+
fn get_example_candidates() -> Vec<clap_complete::CompletionCandidate> {
1041+
get_targets_from_metadata()
1042+
.unwrap_or_default()
1043+
.into_iter()
1044+
.filter_map(|target| match target.kind() {
1045+
TargetKind::ExampleBin => Some(clap_complete::CompletionCandidate::new(target.name())),
1046+
_ => None,
1047+
})
1048+
.collect::<Vec<_>>()
1049+
}
1050+
1051+
fn get_targets_from_metadata() -> CargoResult<Vec<Target>> {
1052+
let cwd = std::env::current_dir()?;
1053+
let gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);
1054+
let ws = Workspace::new(&find_root_manifest_for_wd(&cwd)?, &gctx)?;
1055+
1056+
let packages = ws.members().collect::<Vec<_>>();
1057+
1058+
let targets = packages
1059+
.into_iter()
1060+
.flat_map(|pkg| pkg.targets().into_iter().cloned())
1061+
.collect::<Vec<_>>();
1062+
1063+
Ok(targets)
1064+
}
1065+
10301066
#[track_caller]
10311067
pub fn ignore_unknown<T: Default>(r: Result<T, clap::parser::MatchesError>) -> T {
10321068
match r {

0 commit comments

Comments
 (0)