Skip to content

Commit

Permalink
feat: Add custom completer for completing target triple
Browse files Browse the repository at this point in the history
  • Loading branch information
shannmu committed Sep 17, 2024
1 parent e7ca9be commit 63ef141
Showing 1 changed file with 60 additions and 2 deletions.
62 changes: 60 additions & 2 deletions src/cargo/util/command_prelude.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::core::compiler::{BuildConfig, MessageFormat, TimingOutput};
use crate::core::resolver::CliFeatures;
use crate::core::{Edition, Workspace};
use crate::core::{shell, Edition, Workspace};
use crate::ops::lockfile::LOCKFILE_NAME;
use crate::ops::registry::RegistryOrIndex;
use crate::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
Expand All @@ -19,6 +19,7 @@ use cargo_util_schemas::manifest::ProfileName;
use cargo_util_schemas::manifest::RegistryName;
use cargo_util_schemas::manifest::StringOrVec;
use clap::builder::UnknownArgumentValueParser;
use home::cargo_home_with_cwd;
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::path::PathBuf;
Expand Down Expand Up @@ -261,7 +262,8 @@ pub trait CommandExt: Sized {
};
self._arg(
optional_multi_opt("target", "TRIPLE", target)
.help_heading(heading::COMPILATION_OPTIONS),
.help_heading(heading::COMPILATION_OPTIONS)
.add(clap_complete::ArgValueCandidates::new(get_target_triples)),
)
._arg(unsupported_short_arg)
}
Expand Down Expand Up @@ -1027,6 +1029,62 @@ pub fn lockfile_path(
return Ok(Some(path));
}

fn get_target_triples() -> Vec<clap_complete::CompletionCandidate> {
let mut candidates = Vec::new();

if is_rustup() {
if let Ok(targets) = get_target_triples_from_rustup() {
candidates.extend(targets);
}
} else {
if let Ok(targets) = get_target_triples_from_rustc() {
candidates.extend(targets);
}
}

candidates
}

fn get_target_triples_from_rustup() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {
let output = std::process::Command::new("rustup")
.arg("target")
.arg("list")
.output()?;

if !output.status.success() {
return Ok(vec![]);
}

let stdout = String::from_utf8(output.stdout)?;

Ok(stdout
.lines()
.map(|line| {
let target = line.split_once(' ');
match target {
None => clap_complete::CompletionCandidate::new(line.to_owned()).hide(true),
Some((target, _installed)) => clap_complete::CompletionCandidate::new(target),
}
})
.collect())
}

fn get_target_triples_from_rustc() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {
let cwd = std::env::current_dir()?;
let gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);
let ws = Workspace::new(&find_root_manifest_for_wd(&PathBuf::from(&cwd))?, &gctx);

let rustc = gctx.load_global_rustc(ws.as_ref().ok())?;

let (stdout, _stderr) =
rustc.cached_output(rustc.process().arg("--print").arg("target-list"), 0)?;

Ok(stdout
.lines()
.map(|line| clap_complete::CompletionCandidate::new(line.to_owned()))
.collect())
}

#[track_caller]
pub fn ignore_unknown<T: Default>(r: Result<T, clap::parser::MatchesError>) -> T {
match r {
Expand Down

0 comments on commit 63ef141

Please sign in to comment.