Compile time errors, fast parsing, easy usage.
This argument parser works using the revparse! macro, into which you will write all the options:
...
is just a placeholder.
use revparse::revparse;
revparse! {
[...];
[...];
[...];
}
revparse! {...}
should be written outside of any functions, as it creates a module called revmod
by default.
You can change the name of the module using the ModName setting.
If you want a keyword, like fn as a flag (--fn
), read this.
Here is a quick example, a more thorough explanation is below.
use revparse::revparse;
revparse! {
// arg is of type `bool`
[arg, 'a', "help message for --arg / -a"];
// underscores are shown as '-'.
// with_underscore is also of type `bool`
[with_underscore, 'w', "help message for --with-underscore / -w"];
// takes_val has the type `Option<String>`
[takes_val, 't', "help message for --takes-val=VAL", "VAL"];
}
fn main() {
let args = revmod::Revparse::new();
// In this case the user entered no arguments
assert_eq!(args.arg, false);
assert_eq!(args.with_underscore, false);
assert_eq!(args.takes_val, None);
}
[some_arg, 's', "help message"];
[no_short, "help message"];
VALUE
is for making the user understand what value you want him to enter.
For example FILE
would mean, the user should enter a filename.
[value, 'v', "help message", "VALUE"];
[takes_val_no_short, "help message", "SOME"];
revparse! {
[some_arg, 's', "help message"];
[no_short, "help message"];
[value, 'v', "help message", "VALUE"];
[takes_val_no_short, "help message", "SOME"];
}
Usage: program_name [OPTION]...
Options:
-h, --help display this help text and exit
-s, --some-arg help message
--no-short help message
-v, --value=VALUE help message
--takes-val-no-short=SOME help message
Of course "help message" isn't a very useful help message.
As you can see in the help message, it says program_name
, which probably isn't what you want.
You can change it using the ExecName setting.
new()
parses environmental args,
for tests you can use custom_new()
, more about it here.
// creates module revmod
revparse! {
[some_arg, 's', "help message"];
[no_short, "help message"];
[value, 'v', "help message", "VALUE"];
[takes_val_no_short, "help message", "SOME"];
}
fn main() {
let args = revmod::Revparse::new();
// args.some_arg => bool
// args.no_short => bool
// args.value => Option<String>
// args.takes_val_no_short => Option<String>
println!("{:#?}", args);
}
This would print (if the user entered no arguments):
Revparse {
some_arg: false,
no_short: false,
value: None,
takes_val_no_short: None,
}
The Arguments that take a value have the type:
Option<String>
If the flag was not given, the value will be None
.
Those that don't take a value have the type:
bool
If the flag was not given, the value will be false
, if it was, it will be true
.
You can use the custom_new()
function for testing your program with preset arguments.
custom_new()
takes impl Iterator<Item = String>
as a parameter.
So let's test the example above:
revparse! {
[some_arg, 's', "help message"];
[no_short, "help message"];
[value, 'v', "help message", "VALUE"];
[takes_val_no_short, "help message", "SOME"];
}
// helper function
fn iter_str(args: &[&str]) -> impl Iterator<Item = String> {
args.iter().map(|i| i.to_string())
}
fn main() {
let args = revmod::Revparse::custom_new(iter_str(&["exec", "--some-arg", "-vEXAMPLE_VALUE", "--takes-val-no-short", "some_value"]));
assert_eq!(args.some_arg, true); // was called
assert_eq!(args.no_short, false); // wasn't called
assert_eq!(args.value.unwrap(), "EXAMPLE_VALUE"); // If -v had not been called, args.value would be `None` and the program would panic.
assert_eq!(args.takes_val_no_short.unwrap(), "some_value");
// So let's test it with different args
let args = revmod::Revparse::custom_new(iter_str(&["exec", "-s", "--value=VAL", "--no-short"]));
assert_eq!(args.some_arg, true); // was called with "-s"
assert_eq!(args.no_short, true);
assert_eq!(args.value.unwrap(), "VAL");
assert_eq!(args.takes_val_no_short, None); // is None, since it wasn't called
}
positional arguments are arguments that do not start with a "-" or "--".
If the user wants to give a positional argument, that does in fact start with a "-", he can write a "--" before the positional argument like this:
program_name -- "----positional argument"
If you don't know what positional arguments are, read this.
There are five settings for positional arguments.
To get the positional arguments, the user entered you can use the get_pos_args()
function.
revparse! {
[PosMax => 5];
[PosMin => 1];
}
fn main() {
let mut args = revmod::Revparse::new();
let pos_args = args.get_pos_args();
let len = pos_args.len();
assert!(len <= 5 && len >= 1); // User has to enter beween 1 and 5 positional arguments.
}
Usage: grep [OPTION]... PATTERNS [FILE]...
Search for PATTERNS in each FILE.
Example: grep -i 'hello world' menu.h main.c
PATTERNS can contain multiple patterns separated by newlines.
To implement this, you would have to use these settings:
[PosHelp => "Search for PATTERNS in each FILE.\nExample: grep -i 'hello world' menu.h main.c\nPATTERNS can contain multiple patterns separated by newlines."];
[Pos => "PATTERNS"];
[Pos => "[FILE]..."];
[ExecName => "grep"];
[PosInfinite => true]; // grep has no limit for the amount of files you can enter.
[PosMin => 1]; // and forces you to enter a Pattern
The Settings syntax is as follows
[SettingName => ...];
The following Settings exist:
[ExecName => <string literal>];
[Pos => <string literal>];
[PosHelp => <string literal>];
[PosMin => u64];
[PosMax => u64];
[PosInfinite => bool];
[ModName => <identifier>];
The name of the executable. Needed for the help message.
Default: program_name
To change it to revparse
for example:
[ExecName => "revparse"];
Setting can be given multiple times.
Each Pos
setting will be displayed in the "Usage message".
This:
[Pos => "SOME"];
[Pos => "ANOTHER"];
would be displayed like this:
Usage: program_name [OPTION]... SOME ANOTHER
and would raise the default of PosMax to 2
, as [Pos => ...]; was given twice.
Help message for positional arguments. For example
[PosHelp => "POS HELP MESSAGE"];
would be shown in the help message as:
Usage: program_name [OPTION]...
POS HELP MESSAGE
Options:
...
In case you wonder for what this is, here is an example.
The minimum amount of positional arguments the user has to enter.
Default is 0
.
To force the user to enter 1
positional argument:
[PosMin => 1];
The maximum amount of positional arguments the user has to enter.
Default is the amount of times
[Pos => "SOME"];
was used.
To change it to 5
, which would mean, that the user can't enter more than 5
positional arguments:
[PosMax => 5];
This default can be overwritten with either [PosMax => ...]; or [PosInfinite => ...];.
If this is set to true
,
[PosInfinite => true];
there will be no limit, on how much positional arguments the user can enter.
Default is false
.
Name of the module created by the revparse!
macro.
Default is revmod
.
If you want to change it to example
:
[ModName => example];
example
can't be a keyword and should not be written in quotes.
To use a keyword as a flag, use a raw identifier,
meaning that you need to add r#
before the keyword.
Example with match:
[match, 'm', "help message"]; // compiler error
instead write this:
[r#match, 'm', "help message"]; // compiles
Don't worry, your flag will NOT be --r#match
, but will work normally with --match
.