macro_rules! arg_parse { ( #[name($name:expr)] #[description($app_desc:expr)] $(#[$outer:meta])* $vis:vis struct $ArgStruct:ident { $( #[short($short_desc:expr), long($long_desc:expr), description($desc:expr)] $required_field:ident: $req_ty:ty, )* $( #[optional] #[short($opt_short_desc:expr), long($opt_long_desc:expr), description($opt_desc:expr)] $optional_field:ident: Option<$opt_ty:ty>, )* $( #[repeating] #[short($rep_short_desc:expr), long($rep_long_desc:expr), description($rep_desc:expr)] $repeating_field:ident: Vec<$rep_ty:ty>, )* $( #[subcommand($sc_name:expr)] $subcommand:ident: Option<$sc_ty:ty>, )* } ) => { ... }; }
Expand description
A macro that parses args. The goal is not to be a beautiful full-featured arg-parser, there are many projects which does that better. This is only supposed to supposed to support the minimum to create a CLI that takes arguments. There are Four kinds of arguments that are accepted:
- Required arguments, passed as
--longor-s(short) followed byargument. - Optional arguments, passed as
--longor-s(short) followed byargument, or not at all. - Repeating arguments, passed 0 or more times as
--longor-s(short) followed byargument. - Subcommands, passed as
command-name. I have a special distaste forproc_macros, regular macros are limited but can at least be expanded with relative ease, but it does come with limitations. One of those being the above fields having to be declared in order. Required always first, subcommands always last.
Some more requirements:
- Repeating arguments are always
Vec<T>. - Optional arguments are always
Option<T>. - Subcommands are always
Option<T> arg_parse!-structs need a#[name("")]-section, followed by a#[description("")]-section- All fields except subcommands need a
#[short(""), long(""), description("")]right above it. - Optional fields require a
#[optional]above the required 5. - Repeating arguments need a
#[repeating]above the required 5. - Subcommands need a
#[subcommand("")]right above it
Ex:
extern crate alloc;
use tiny_cli::arg_parse;
arg_parse!(
#[name("My nested command")]
#[description("Use this nested subcommand for fun and profit")]
pub struct NestedSc {
#[short("f"), long("field-1"), description("My first field")]
my_sc_field: String,
#[short("s"), long("sc-field"), description("My sc second field")]
my_other_sc_field: i64,
}
);
arg_parse!(
#[name("My first first level subcommand")]
#[description("Use this nested subcommand for fun and profit")]
pub struct ScOne {
#[short("h"), long("has-field"), description("My first field")]
my_sc_field: String,
#[subcommand("nested")]
nested: Option<NestedSc>,
}
);
arg_parse!(
#[name("My second first level subcommand")]
#[description("Use this nested subcommand for fun and profit")]
pub struct ScTwo {
#[optional]
#[short("h"), long("has-field"), description("My first field")]
opt_option: Option<String>,
#[repeating]
#[short("r"), long("rep-field"), description("My repeating field")]
rep_option: Vec<i32>,
}
);
arg_parse!(
#[name("My top level command")]
#[description("Use top level command with subcommands for fun and profit")]
pub struct Mc {
#[short("m"), long("my-field"), description("My first field")]
my_field: String,
#[subcommand("first-sub")]
subcommand_one: Option<ScOne>,
#[subcommand("second-sub")]
subcommand_two: Option<ScTwo>,
}
);