Name Description Size
ext.rs 9611
lib.rs Minimal, flexible command-line parser As opposed to a declarative parser, this processes arguments as a stream of tokens. As lexing a command-line is not context-free, we rely on the caller to decide how to interpret the arguments. # Examples ```rust use std::path::PathBuf; use std::ffi::OsStr; type BoxedError = Box<dyn std::error::Error + Send + Sync>; #[derive(Debug)] struct Args { paths: Vec<PathBuf>, color: Color, verbosity: usize, } #[derive(Debug)] enum Color { Always, Auto, Never, } impl Color { fn parse(s: Option<&OsStr>) -> Result<Self, BoxedError> { let s = s.map(|s| s.to_str().ok_or(s)); match s { Some(Ok("always")) | Some(Ok("")) | None => { Ok(Color::Always) } Some(Ok("auto")) => { Ok(Color::Auto) } Some(Ok("never")) => { Ok(Color::Never) } Some(invalid) => { Err(format!("Invalid value for `--color`, {invalid:?}").into()) } } } } fn parse_args( raw: impl IntoIterator<Item=impl Into<std::ffi::OsString>> ) -> Result<Args, BoxedError> { let mut args = Args { paths: Vec::new(), color: Color::Auto, verbosity: 0, }; let raw = clap_lex::RawArgs::new(raw); let mut cursor = raw.cursor(); raw.next(&mut cursor); // Skip the bin while let Some(arg) = raw.next(&mut cursor) { if arg.is_escape() { args.paths.extend(raw.remaining(&mut cursor).map(PathBuf::from)); } else if arg.is_stdio() { args.paths.push(PathBuf::from("-")); } else if let Some((long, value)) = arg.to_long() { match long { Ok("verbose") => { if let Some(value) = value { return Err(format!("`--verbose` does not take a value, got `{value:?}`").into()); } args.verbosity += 1; } Ok("color") => { args.color = Color::parse(value)?; } _ => { return Err( format!("Unexpected flag: --{}", arg.display()).into() ); } } } else if let Some(mut shorts) = arg.to_short() { while let Some(short) = shorts.next_flag() { match short { Ok('v') => { args.verbosity += 1; } Ok('c') => { let value = shorts.next_value_os(); args.color = Color::parse(value)?; } Ok(c) => { return Err(format!("Unexpected flag: -{c}").into()); } Err(e) => { return Err(format!("Unexpected flag: -{}", e.to_string_lossy()).into()); } } } } else { args.paths.push(PathBuf::from(arg.to_value_os().to_owned())); } } Ok(args) } let args = parse_args(["bin", "--hello", "world"]); println!("{args:?}"); ``` 15499