Skip to content

Commit

Permalink
Fix required positional arguments (#38)
Browse files Browse the repository at this point in the history
`#[required]` and `#[positional]` can be used together.
  • Loading branch information
parasyte authored Feb 19, 2024
1 parent b645963 commit bc9ee3f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions onlyargs_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ categories = ["command-line-interface"]
license = "MIT"
exclude = [
"/compile_tests",
"/tests",
]

[lib]
Expand Down
13 changes: 12 additions & 1 deletion onlyargs_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,18 @@ pub fn derive_parser(input: TokenStream) -> TokenStream {
.collect::<String>();
let positional_ident = ast
.positional
.map(|opt| format!("{},", opt.name))
.map(|opt| {
if matches!(opt.property, ArgProperty::Positional { required: true }) {
format!(
r#"{}: {}.required("{arg}")?,"#,
opt.name,
opt.name,
arg = to_arg_name(&opt.name),
)
} else {
format!("{},", opt.name)
}
})
.unwrap_or_default();

let name = ast.name;
Expand Down
23 changes: 23 additions & 0 deletions onlyargs_derive/tests/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,26 @@ fn test_required_multivalue() -> Result<(), CliError> {

Ok(())
}

#[test]
fn test_required_positional() -> Result<(), CliError> {
#[derive(Debug, OnlyArgs)]
struct Args {
#[required]
#[positional]
rest: Vec<String>,
}

// Empty positional is not allowed.
assert!(matches!(
dbg!(Args::parse(vec![])),
Err(CliError::MissingRequired(name)) if name == "rest",
));

// At least one positional is required.
let args = Args::parse(["Bob"].into_iter().map(OsString::from).collect())?;

assert_eq!(args.rest, ["Bob"]);

Ok(())
}

0 comments on commit bc9ee3f

Please sign in to comment.