Skip to content

Commit 435269b

Browse files
committed
feat: Add custom completer for completing target triple
1 parent e7ca9be commit 435269b

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

src/cargo/util/command_prelude.rs

+63-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, 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;
@@ -261,7 +262,8 @@ pub trait CommandExt: Sized {
261262
};
262263
self._arg(
263264
optional_multi_opt("target", "TRIPLE", target)
264-
.help_heading(heading::COMPILATION_OPTIONS),
265+
.help_heading(heading::COMPILATION_OPTIONS)
266+
.add(clap_complete::ArgValueCandidates::new(get_target_triples)),
265267
)
266268
._arg(unsupported_short_arg)
267269
}
@@ -1027,6 +1029,65 @@ pub fn lockfile_path(
10271029
return Ok(Some(path));
10281030
}
10291031

1032+
fn get_target_triples() -> Vec<clap_complete::CompletionCandidate> {
1033+
let mut candidates = Vec::new();
1034+
1035+
if is_rustup() {
1036+
if let Ok(targets) = get_target_triples_from_rustup() {
1037+
candidates.extend(targets);
1038+
}
1039+
} else {
1040+
if let Ok(targets) = get_target_triples_from_rustc() {
1041+
candidates.extend(targets);
1042+
}
1043+
}
1044+
1045+
candidates
1046+
}
1047+
1048+
fn get_target_triples_from_rustup() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {
1049+
let output = std::process::Command::new("rustup")
1050+
.arg("target")
1051+
.arg("list")
1052+
.output()?;
1053+
1054+
if !output.status.success() {
1055+
return Ok(vec![]);
1056+
}
1057+
1058+
let stdout = String::from_utf8(output.stdout)?;
1059+
1060+
Ok(stdout
1061+
.lines()
1062+
.map(|line| {
1063+
let target = line.split_once(' ');
1064+
match target {
1065+
None => clap_complete::CompletionCandidate::new(line.to_owned()).hide(true),
1066+
Some((target, _installed)) => clap_complete::CompletionCandidate::new(target),
1067+
}
1068+
})
1069+
.collect())
1070+
}
1071+
1072+
fn get_target_triples_from_rustc() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {
1073+
let cwd = std::env::current_dir()?;
1074+
let gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);
1075+
let ws = Workspace::new(&find_root_manifest_for_wd(&PathBuf::from(&cwd))?, &gctx);
1076+
1077+
let rustc = match ws {
1078+
Ok(ws) => gctx.load_global_rustc(Some(&ws))?,
1079+
Err(_) => gctx.load_global_rustc(None)?,
1080+
};
1081+
1082+
let (stdout, _stderr) =
1083+
rustc.cached_output(rustc.process().arg("--print").arg("target-list"), 0)?;
1084+
1085+
Ok(stdout
1086+
.lines()
1087+
.map(|line| clap_complete::CompletionCandidate::new(line.to_owned()))
1088+
.collect())
1089+
}
1090+
10301091
#[track_caller]
10311092
pub fn ignore_unknown<T: Default>(r: Result<T, clap::parser::MatchesError>) -> T {
10321093
match r {

0 commit comments

Comments
 (0)