diff options
| author | Joel Klinghed <the_jk@spawned.biz> | 2024-04-24 21:37:17 +0200 |
|---|---|---|
| committer | Joel Klinghed <the_jk@spawned.biz> | 2024-04-24 21:37:17 +0200 |
| commit | 92742afc7724fd502d65f8056f245c2401d3ce07 (patch) | |
| tree | 947a874a22ae4be1c5d7bf05a021155ddbe8c7e3 | |
| parent | c0bf5db3c0c4052526d5234144346f3caf767ef9 (diff) | |
Detect arg parser to use
Switch Parser trait to an object safe trait so guess_parser can
return an boxed instance.
| -rw-r--r-- | src/args.rs | 29 | ||||
| -rw-r--r-- | src/main.rs | 31 |
2 files changed, 31 insertions, 29 deletions
diff --git a/src/args.rs b/src/args.rs index 0014d66..9f6fe3d 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,7 +1,8 @@ +#![allow(dead_code)] + use derive_builder::Builder; use std::collections::HashMap; -#[allow(dead_code)] pub enum ValueRequirement { None, Required(&'static str), @@ -96,7 +97,7 @@ pub trait Parser { fn run( &self, options: &mut Options, - args: impl IntoIterator<Item = String>, + args: &mut dyn Iterator<Item = String>, ) -> Result<Arguments, String>; fn print_help(&self, options: &Options); } @@ -128,16 +129,15 @@ impl Parser for LongOnlyParser { fn run( &self, options: &mut Options, - args: impl IntoIterator<Item = String>, + args: &mut dyn Iterator<Item = String>, ) -> Result<Arguments, String> { let mut ret = Vec::new(); - let mut args_iter = args.into_iter(); - let program = args_iter.next(); - while let Some(arg) = args_iter.next() { + let program = args.next(); + while let Some(arg) = args.next() { if arg.starts_with("-") { if arg == "--" { // All following arguments are just that. - while let Some(arg) = args_iter.next() { + while let Some(arg) = args.next() { ret.push(arg) } break; @@ -162,7 +162,7 @@ impl Parser for LongOnlyParser { } ValueRequirement::Required(_) => { if value.is_none() { - value = args_iter.next(); + value = args.next(); if value.is_none() { return Err(format!("option '{}' requires an argument", arg)); } @@ -206,16 +206,15 @@ impl Parser for ShortAndLongParser { fn run( &self, options: &mut Options, - args: impl IntoIterator<Item = String>, + args: &mut dyn Iterator<Item = String>, ) -> Result<Arguments, String> { let mut ret = Vec::new(); - let mut args_iter = args.into_iter(); - let program = args_iter.next(); - while let Some(arg) = args_iter.next() { + let program = args.next(); + while let Some(arg) = args.next() { if arg.starts_with("--") { if arg.len() == 2 { // All following arguments are just that. - while let Some(arg) = args_iter.next() { + while let Some(arg) = args.next() { ret.push(arg) } break; @@ -240,7 +239,7 @@ impl Parser for ShortAndLongParser { } ValueRequirement::Required(_) => { if value.is_none() { - value = args_iter.next(); + value = args.next(); if value.is_none() { return Err(format!("option '{}' requires an argument", arg)); } @@ -260,7 +259,7 @@ impl Parser for ShortAndLongParser { match option.value_req { ValueRequirement::None => {} ValueRequirement::Required(_) => { - value = args_iter.next(); + value = args.next(); if value.is_none() { return Err(format!("option requires an argument -- '{}", c)); } diff --git a/src/main.rs b/src/main.rs index 347e144..4cfbcc7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,18 @@ mod args; -use crate::args::Parser; use std::process::ExitCode; +fn guess_parser(args: &mut dyn Iterator<Item = String>) -> Box<dyn args::Parser> { + for arg in args { + if arg.len() > 2 && arg.starts_with("--") { + // --C.. can only be ShortAndLong + return Box::new(args::ShortAndLongParser::new()); + } + } + // TODO: Can we make more guesses? + Box::new(args::LongOnlyParser::new()) +} + fn parse_args() -> Result<bool, String> { let mut options = args::Options::new(); let help_idx = options.push( @@ -28,32 +38,25 @@ fn parse_args() -> Result<bool, String> { .build() .unwrap(), ); - let test_idx = options.push( - args::OptionBuilder::default() - .short('t') - .long("test") - .description("testing") - .value(args::ValueRequirement::Required("FILE")) - .build() - .unwrap(), - ); - let parser = args::ShortAndLongParser::new(); - let args = parser.run(&mut options, std::env::args())?; + let parser = guess_parser(&mut std::env::args()); + let maybe_args = parser.run(&mut options, &mut std::env::args()); + + // help is special, check for it even if parser#run returned error. let ref help = options[help_idx]; if help.is_set() { parser.print_help(&options); return Ok(true); } + + let args = maybe_args?; let ref version = options[version_idx]; if version.is_set() { println!("Version is 0.0.1"); return Ok(true); } let ref verbose = options[verbose_idx]; - let ref test = options[test_idx]; println!("verbose: {}", verbose.is_set()); - println!("test: {:?}", test.value()); println!("args: {:?}", args.args); Ok(false) } |
