Skip to content

Commit 521bd76

Browse files
authored
feat(complete): Added completion for --profile (#15308)
### What does this PR try to resolve? This attempts to complete the autocompleter for `cargo build --profile <TAB>`, it loads the built in profiles and the custom profile present in `Cargo.toml` and `.cargo/config.toml` if present when pressing TAB key, in the completion value it also adds an description inspired by [this](https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/job_queue/mod.rs#L805-L813) ![Screenshot from 2025-03-14 02-17-40](https://github.com/user-attachments/assets/6fc784a0-e3e7-4deb-9252-847d720894c1) Related to #14520
2 parents 6344cad + feb0e50 commit 521bd76

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

src/cargo/core/profiles.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,11 @@ impl Profiles {
391391
.get(name)
392392
.ok_or_else(|| anyhow::format_err!("profile `{}` is not defined", name))
393393
}
394+
395+
/// Returns an iterator over all profile names known to Cargo.
396+
pub fn profile_names(&self) -> impl Iterator<Item = InternedString> + '_ {
397+
self.by_name.keys().copied()
398+
}
394399
}
395400

396401
/// An object used for handling the profile hierarchy.

src/cargo/util/command_prelude.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::core::compiler::{
22
BuildConfig, CompileKind, MessageFormat, RustcTargetData, TimingOutput,
33
};
44
use crate::core::resolver::{CliFeatures, ForceAllTargets, HasDevUnits};
5-
use crate::core::{shell, Edition, Package, Target, TargetKind, Workspace};
5+
use crate::core::{profiles::Profiles, shell, Edition, Package, Target, TargetKind, Workspace};
66
use crate::ops::lockfile::LOCKFILE_NAME;
77
use crate::ops::registry::RegistryOrIndex;
88
use crate::ops::{self, CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
@@ -274,7 +274,11 @@ pub trait CommandExt: Sized {
274274
self._arg(
275275
opt("profile", profile)
276276
.value_name("PROFILE-NAME")
277-
.help_heading(heading::COMPILATION_OPTIONS),
277+
.help_heading(heading::COMPILATION_OPTIONS)
278+
.add(clap_complete::ArgValueCandidates::new(|| {
279+
let candidates = get_profile_candidates();
280+
candidates
281+
})),
278282
)
279283
}
280284

@@ -1118,6 +1122,53 @@ pub fn get_registry_candidates() -> CargoResult<Vec<clap_complete::CompletionCan
11181122
}
11191123
}
11201124

1125+
fn get_profile_candidates() -> Vec<clap_complete::CompletionCandidate> {
1126+
match get_workspace_profile_candidates() {
1127+
Ok(candidates) if !candidates.is_empty() => candidates,
1128+
// fallback to default profile candidates
1129+
_ => default_profile_candidates(),
1130+
}
1131+
}
1132+
1133+
fn get_workspace_profile_candidates() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {
1134+
let gctx = new_gctx_for_completions()?;
1135+
let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx)?;
1136+
let profiles = Profiles::new(&ws, InternedString::new("dev"))?;
1137+
1138+
let mut candidates = Vec::new();
1139+
for name in profiles.profile_names() {
1140+
let Ok(profile_instance) = Profiles::new(&ws, name) else {
1141+
continue;
1142+
};
1143+
let base_profile = profile_instance.base_profile();
1144+
1145+
let mut description = String::from(if base_profile.opt_level.as_str() == "0" {
1146+
"unoptimized"
1147+
} else {
1148+
"optimized"
1149+
});
1150+
1151+
if base_profile.debuginfo.is_turned_on() {
1152+
description.push_str(" + debuginfo");
1153+
}
1154+
1155+
candidates
1156+
.push(clap_complete::CompletionCandidate::new(&name).help(Some(description.into())));
1157+
}
1158+
1159+
Ok(candidates)
1160+
}
1161+
1162+
fn default_profile_candidates() -> Vec<clap_complete::CompletionCandidate> {
1163+
vec![
1164+
clap_complete::CompletionCandidate::new("dev").help(Some("unoptimized + debuginfo".into())),
1165+
clap_complete::CompletionCandidate::new("release").help(Some("optimized".into())),
1166+
clap_complete::CompletionCandidate::new("test")
1167+
.help(Some("unoptimized + debuginfo".into())),
1168+
clap_complete::CompletionCandidate::new("bench").help(Some("optimized".into())),
1169+
]
1170+
}
1171+
11211172
fn get_example_candidates() -> Vec<clap_complete::CompletionCandidate> {
11221173
get_targets_from_metadata()
11231174
.unwrap_or_default()

0 commit comments

Comments
 (0)