Skip to content

Commit aa5ab7a

Browse files
committed
Make it possible to use args in any order
1 parent 9b46b3d commit aa5ab7a

1 file changed

Lines changed: 74 additions & 4 deletions

File tree

src/cli.rs

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub type PanicHookInfo<'a> = std::panic::PanicInfo<'a>;
1616

1717
use anyhow::Context;
1818
use cargo_metadata::{camino::Utf8Path, semver::Version, Artifact, CrateType, MetadataCommand};
19-
use filetime::FileTime;
2019
use clap::Parser;
20+
use filetime::FileTime;
2121

2222
use crate::{
2323
cargo::{build_env, clang_target},
@@ -156,7 +156,6 @@ fn derive_ndk_path(shell: &mut Shell) -> Option<(PathBuf, String)> {
156156
highest_version_ndk_in_path(&ndk_dir).map(|path| (path, "standard location".to_string()))
157157
}
158158

159-
160159
fn default_ndk_dir() -> PathBuf {
161160
#[cfg(windows)]
162161
let dir = pathos::user::local_dir()
@@ -302,7 +301,6 @@ pub fn run_env(args: Vec<String>) -> anyhow::Result<()> {
302301
println!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
303302
std::process::exit(0);
304303
}
305-
306304

307305
let color = args
308306
.iter()
@@ -383,6 +381,78 @@ pub fn run_env(args: Vec<String>) -> anyhow::Result<()> {
383381
Ok(())
384382
}
385383

384+
/// Parse arguments that can appear both before and after the cargo subcommand
385+
fn parse_mixed_args(args: Vec<String>) -> anyhow::Result<Args> {
386+
use clap::CommandFactory;
387+
388+
let mut global_args = vec!["cargo-ndk".to_string()];
389+
let mut cargo_args = Vec::new();
390+
391+
// Skip the "ndk" subcommand name (always the first argument)
392+
let mut i = 1;
393+
394+
// Get all flags from the Args struct programmatically
395+
let cmd = Args::command();
396+
let mut global_flags = Vec::new();
397+
let mut value_flags = Vec::new();
398+
399+
for arg in cmd.get_arguments() {
400+
// Skip the cargo_args field since it's not a real flag
401+
if arg.get_id() == "cargo_args" {
402+
continue;
403+
}
404+
405+
if let Some(long) = arg.get_long() {
406+
let long_flag = format!("--{}", long);
407+
global_flags.push(long_flag.clone());
408+
409+
// Check if this flag takes a value (not a boolean flag)
410+
if arg.get_action().takes_values() {
411+
value_flags.push(long_flag);
412+
}
413+
}
414+
if let Some(short) = arg.get_short() {
415+
let short_flag = format!("-{}", short);
416+
global_flags.push(short_flag.clone());
417+
418+
// Check if this flag takes a value (not a boolean flag)
419+
if arg.get_action().takes_values() {
420+
value_flags.push(short_flag);
421+
}
422+
}
423+
}
424+
425+
while i < args.len() {
426+
let arg = &args[i];
427+
428+
// Check if this is a global flag
429+
if global_flags.contains(&arg.to_string()) {
430+
global_args.push(arg.clone());
431+
432+
// Check if this flag takes a value
433+
if value_flags.contains(&arg.to_string()) {
434+
if i + 1 < args.len() {
435+
i += 1;
436+
global_args.push(args[i].clone());
437+
}
438+
}
439+
} else {
440+
// This is a cargo arg
441+
cargo_args.push(arg.clone());
442+
}
443+
444+
i += 1;
445+
}
446+
447+
// Parse the extracted global args
448+
let mut parsed_args = Args::try_parse_from(&global_args)?;
449+
450+
// Set the cleaned cargo_args directly
451+
parsed_args.cargo_args = cargo_args;
452+
453+
Ok(parsed_args)
454+
}
455+
386456
pub fn run(args: Vec<String>) -> anyhow::Result<()> {
387457
// Check for help/version before parsing to avoid required arg errors
388458
if args.is_empty() || args.contains(&"--help".to_string()) || args.contains(&"-h".to_string()) {
@@ -445,7 +515,7 @@ pub fn run(args: Vec<String>) -> anyhow::Result<()> {
445515
.unwrap_or(BuildMode::Debug)
446516
};
447517

448-
let args = match Args::try_parse_from(&args) {
518+
let args = match parse_mixed_args(args) {
449519
Ok(args) => args,
450520
Err(e) => {
451521
shell.error(e)?;

0 commit comments

Comments
 (0)