Skip to content

Commit

Permalink
Merge pull request #82 from tertsdiepraam/new-positional
Browse files Browse the repository at this point in the history
New positional argument system
  • Loading branch information
tertsdiepraam authored Feb 5, 2024
2 parents 7304047 + 5c7bf4e commit 57af536
Show file tree
Hide file tree
Showing 10 changed files with 534 additions and 54 deletions.
5 changes: 5 additions & 0 deletions derive/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -23,6 +24,7 @@ impl Default for ArgumentsAttr {
file: None,
exit_code: 1,
parse_echo_style: false,
options_first: false,
}
}
}
Expand Down Expand Up @@ -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(())
Expand Down
16 changes: 15 additions & 1 deletion derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 },
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub enum ErrorKind {
UnexpectedOption(String, Vec<String>),

/// No more positional arguments were expected, but one was given anyway.
UnexpectedArgument(OsString),
UnexpectedArgument(String),

/// A value was passed to an option that didn't expect a value.
UnexpectedValue {
Expand Down Expand Up @@ -99,7 +99,7 @@ impl Display for ErrorKind {
Ok(())
}
ErrorKind::UnexpectedArgument(arg) => {
write!(f, "Found an invalid argument '{}'.", arg.to_string_lossy())
write!(f, "Found an invalid argument '{}'.", arg)
}
ErrorKind::UnexpectedValue { option, value } => {
write!(
Expand Down Expand Up @@ -144,7 +144,9 @@ impl From<lexopt::Error> for ErrorKind {
match other {
lexopt::Error::MissingValue { option } => Self::MissingValue { option },
lexopt::Error::UnexpectedOption(s) => Self::UnexpectedOption(s, Vec::new()),
lexopt::Error::UnexpectedArgument(s) => Self::UnexpectedArgument(s),
lexopt::Error::UnexpectedArgument(s) => {
Self::UnexpectedArgument(s.to_string_lossy().to_string())
}
lexopt::Error::UnexpectedValue { option, value } => {
Self::UnexpectedValue { option, value }
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

mod error;
pub mod internal;
pub mod positional;
mod value;

#[cfg(doc)]
Expand Down Expand Up @@ -64,6 +65,7 @@ pub enum Argument<T: Arguments> {
Help,
Version,
Positional(OsString),
MultiPositional(Vec<OsString>),
Custom(T),
}

Expand Down Expand Up @@ -142,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)),
}
}
Expand Down
Loading

0 comments on commit 57af536

Please sign in to comment.