You've already forked uutils-args
mirror of
https://github.com/uutils/uutils-args.git
synced 2026-06-10 16:13:08 -07:00
add options_first argument for the arguments attribute
This commit is contained in:
committed by
Sylvestre Ledru
parent
50bd56675b
commit
5c7bf4e3a7
@@ -13,6 +13,7 @@ pub struct ArgumentsAttr {
|
||||
pub file: Option<String>,
|
||||
pub exit_code: i32,
|
||||
pub parse_echo_style: bool,
|
||||
pub options_first: bool,
|
||||
}
|
||||
|
||||
impl Default for ArgumentsAttr {
|
||||
@@ -23,6 +24,7 @@ impl Default for ArgumentsAttr {
|
||||
file: None,
|
||||
exit_code: 1,
|
||||
parse_echo_style: false,
|
||||
options_first: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +57,9 @@ impl ArgumentsAttr {
|
||||
"parse_echo_style" => {
|
||||
args.parse_echo_style = true;
|
||||
}
|
||||
"options_first" => {
|
||||
args.options_first = true;
|
||||
}
|
||||
_ => return Err(meta.error("unrecognized argument for arguments attribute")),
|
||||
};
|
||||
Ok(())
|
||||
|
||||
+15
-1
@@ -67,6 +67,20 @@ pub fn arguments(input: TokenStream) -> TokenStream {
|
||||
quote!(parser.next()?)
|
||||
};
|
||||
|
||||
// If options_first is set and we find the first positional argument, we
|
||||
// immediately return all of them.
|
||||
let positional = if arguments_attr.options_first {
|
||||
quote!(
|
||||
// Unwrap is fine because this is called when we have just parsed a
|
||||
// value and therefore are not partially within an option.
|
||||
let mut values = parser.raw_args().unwrap().collect::<Vec<OsString>>();
|
||||
values.insert(0, value);
|
||||
Ok(Some(::uutils_args::Argument::MultiPositional(values)))
|
||||
)
|
||||
} else {
|
||||
quote!(Ok(Some(::uutils_args::Argument::Positional(value))))
|
||||
};
|
||||
|
||||
let expanded = quote!(
|
||||
impl #impl_generics Arguments for #name #ty_generics #where_clause {
|
||||
const EXIT_CODE: i32 = #exit_code;
|
||||
@@ -91,7 +105,7 @@ pub fn arguments(input: TokenStream) -> TokenStream {
|
||||
match arg {
|
||||
lexopt::Arg::Short(short) => { #short },
|
||||
lexopt::Arg::Long(long) => { #long },
|
||||
lexopt::Arg::Value(value) => { Ok(Some(::uutils_args::Argument::Positional(value))) },
|
||||
lexopt::Arg::Value(value) => { #positional },
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ pub enum Argument<T: Arguments> {
|
||||
Help,
|
||||
Version,
|
||||
Positional(OsString),
|
||||
MultiPositional(Vec<OsString>),
|
||||
Custom(T),
|
||||
}
|
||||
|
||||
@@ -143,6 +144,9 @@ impl<T: Arguments> ArgumentIter<T> {
|
||||
Argument::Positional(arg) => {
|
||||
self.positional_arguments.push(arg);
|
||||
}
|
||||
Argument::MultiPositional(args) => {
|
||||
self.positional_arguments.extend(args);
|
||||
}
|
||||
Argument::Custom(arg) => return Ok(Some(arg)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::ffi::OsString;
|
||||
|
||||
use uutils_args::{Arguments, Options};
|
||||
|
||||
#[test]
|
||||
fn timeout_like() {
|
||||
// The timeout coreutil has -v and a command argument
|
||||
#[derive(Arguments)]
|
||||
#[arguments(options_first)]
|
||||
enum Arg {
|
||||
#[arg("-v", "--verbose")]
|
||||
Verbose,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Settings {
|
||||
verbose: bool,
|
||||
}
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, arg: Arg) {
|
||||
match arg {
|
||||
Arg::Verbose => self.verbose = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (settings, command) = Settings::default()
|
||||
.parse(["timeout", "-v", "10", "foo", "-v"])
|
||||
.unwrap();
|
||||
|
||||
assert!(settings.verbose);
|
||||
assert_eq!(
|
||||
command,
|
||||
vec![
|
||||
OsString::from("10"),
|
||||
OsString::from("foo"),
|
||||
OsString::from("-v")
|
||||
]
|
||||
);
|
||||
|
||||
let (settings, command) = Settings::default()
|
||||
.parse(["timeout", "10", "foo", "-v"])
|
||||
.unwrap();
|
||||
|
||||
assert!(!settings.verbose);
|
||||
assert_eq!(
|
||||
command,
|
||||
vec![
|
||||
OsString::from("10"),
|
||||
OsString::from("foo"),
|
||||
OsString::from("-v")
|
||||
]
|
||||
);
|
||||
|
||||
let (settings, command) = Settings::default()
|
||||
.parse(["timeout", "--", "10", "-v"])
|
||||
.unwrap();
|
||||
|
||||
assert!(!settings.verbose);
|
||||
assert_eq!(command, vec![OsString::from("10"), OsString::from("-v")]);
|
||||
}
|
||||
Reference in New Issue
Block a user