revparse 3.0.4

GNU Style CLI Argument Parser, that's easy to use.
Documentation
# revparse
Compile time errors, fast parsing, easy usage.

## Usage
This argument parser works using the revparse! macro, into which you will write all the options:

`...` is just a placeholder.
```rust
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](#modname).

If you want a <mark>keyword</mark>, like fn as a flag (`--fn`), read [this](#how-to-use-a-keyword-as-a-flag).

### Quickstart
Here is a quick example, a more thorough explanation is below.
```rust
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);
}
```

## There's four different types of non positional arguments you can add:

### 1. long (`--some-arg`), short (`-s`), help message
```rust
[some_arg, 's', "help message"];
```
### 2. long (`--no-short`), help message
```rust
[no_short, "help message"];
```
### 3. long (`--value=VALUE`), short (`-v VALUE` / `-vVALUE`), help message, VALUE
`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.
```rust
[value, 'v', "help message", "VALUE"];
```
### 4. long (`--takes-val-no-short=SOME`), help message, SOME
```rust
[takes_val_no_short, "help message", "SOME"];
```

### All the above options together:
```rust
revparse! {
    [some_arg, 's', "help message"];
    [no_short, "help message"];
    [value, 'v', "help message", "VALUE"];
    [takes_val_no_short, "help message", "SOME"];
}
```
### How the help message would look like as of now:
```txt
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](#execname).

## Accessing the values

`new()` parses environmental args,
for tests you can use `custom_new()`, more about it [here](#custom-args-for-testing).
```rust
// 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):
```rust
Revparse {
    some_arg: false,
    no_short: false,
    value: None,
    takes_val_no_short: None,
}
```
<mark>The Arguments that take a value have the type:</mark>
```rust
Option<String>
```
If the flag was not given, the value will be `None`.

<mark>Those that don't take a value have the type:</mark>
```rust
bool
```
If the flag was not given, the value will be `false`, if it was, it will be `true`.

## Custom args for testing
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:
```rust
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

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:
```bash
program_name -- "----positional argument"
```

If you don't know what positional arguments are, read [this](https://betterdev.blog/command-line-arguments-anatomy-explained/).

There are five [settings](#settings) for positional arguments.
1. [Pos]#pos
2. [PosHelp]#poshelp
3. [PosMin]#posmin
4. [PosMax]#posmax
5. [PosInfinite]#posinfinite

### Get Positional Arguments
To get the positional arguments, the user entered you can use the `get_pos_args()` function.
```rust
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.
}
```

### Implementing this for GNU grep
```txt
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:
```rust
[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
```

## Settings
The Settings syntax is as follows
```rust
[SettingName => ...];
```
The following Settings exist:

\[[ExecName](#execname) => \<string literal\>\];

\[[Pos](#pos) => \<string literal\>\];

\[[PosHelp](#poshelp) => \<string literal\>\];

\[[PosMin](#posmin) => u64\];

\[[PosMax](#posmax) => u64\];

\[[PosInfinite](#posinfinite) => bool\];

\[[ModName](#modname) => \<identifier\>\];

### ExecName
The name of the executable. Needed for the help message.

Default: `program_name`

To change it to `revparse` for example:
```rust
[ExecName => "revparse"];
```

### Pos
Setting can be given multiple times.
Each `Pos` setting will be displayed in the "Usage message".

This:
```rust
[Pos => "SOME"];
[Pos => "ANOTHER"];
```
would be displayed like this:
```txt
Usage: program_name [OPTION]... SOME ANOTHER
```
and would raise the default of [PosMax](#posmax) to `2`, as [\[Pos => ...\];](#pos) was given twice.

[More](#positional-arguments)

### PosHelp
Help message for positional arguments.
For example
```rust
[PosHelp => "POS HELP MESSAGE"];
```
would be shown in the help message as:
```txt
Usage: program_name [OPTION]...
POS HELP MESSAGE

Options:
...
```
In case you wonder for what this is, [here is an example](#implementing-this-for-gnu-grep).

### PosMin
The minimum amount of [positional arguments](#positional-arguments) the user has to enter.

Default is `0`.

To force the user to enter `1` [positional argument](#positional-arguments):
```rust
[PosMin => 1];
```

### PosMax
The maximum amount of [positional arguments](#positional-arguments) the user has to enter.

Default is the amount of times
```rust
[Pos => "SOME"];
```
was used.

To change it to `5`, which would mean, that the user can't enter more than `5` [positional arguments](#positional-arguments):
```rust
[PosMax => 5];
```
This default can be overwritten with either [\[PosMax => ...\];](#posmax) or [\[PosInfinite => ...\];](#posinfinite).

### PosInfinite
If this is set to `true`,
```rust
[PosInfinite => true];
```
there will be no limit, on how much [positional arguments](#positional-arguments) the user can enter.

Default is `false`.

### ModName
Name of the module created by the `revparse!` macro.
Default is `revmod`.
If you want to change it to `example`:
```rust
[ModName => example];
```
`example` can't be a [keyword](https://doc.rust-lang.org/reference/keywords.html#keywords) and should not be written in quotes.

## How to use a keyword as a flag
To use a [keyword](https://doc.rust-lang.org/reference/keywords.html#keywords) as a flag, use a [raw identifier](https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html),
meaning that you need to add `r#` before the keyword.

Example with match:
```rust
[match, 'm', "help message"]; // compiler error
```
instead write this:
```rust
[r#match, 'm', "help message"]; // compiles
```
Don't worry, your flag will NOT be `--r#match`, but will work normally with `--match`.