Skip to content

Commit f95c5ff

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

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

src/cargo/util/command_prelude.rs

+33-2
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;
@@ -155,7 +156,11 @@ pub trait CommandExt: Sized {
155156
) -> Self {
156157
self.arg_targets_lib_bin_example(lib, bin, bins, example, examples)
157158
._arg(flag("tests", tests).help_heading(heading::TARGET_SELECTION))
158-
._arg(optional_multi_opt("test", "NAME", test).help_heading(heading::TARGET_SELECTION))
159+
._arg(
160+
optional_multi_opt("test", "NAME", test)
161+
.help_heading(heading::TARGET_SELECTION)
162+
.add(clap_complete::ArgValueCandidates::new(get_test_candidates)),
163+
)
159164
._arg(flag("benches", benches).help_heading(heading::TARGET_SELECTION))
160165
._arg(
161166
optional_multi_opt("bench", "NAME", bench).help_heading(heading::TARGET_SELECTION),
@@ -1027,6 +1032,32 @@ pub fn lockfile_path(
10271032
return Ok(Some(path));
10281033
}
10291034

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

0 commit comments

Comments
 (0)