getopt2 0.1.0-beta.12

Zero dependency strict command line argument parser
Documentation
getopt2 - strict command line argument parser for Rust
======================================================
*Version 0.1.0* [MIT Licensed](https://spdx.org/licenses/MIT.html)

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://spdx.org/licenses/MIT.html)
[![Crates.io Version](https://img.shields.io/crates/v/getopt2.svg)](https://crates.io/crates/getopt2)
[![MSRV Crates.io](https://img.shields.io/crates/msrv/getopt2?logo=rust&label=MSRV&labelColor=orange)](https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html)
[![Safe Rust](https://img.shields.io/badge/Rust-safe-brightgreen.svg)](https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html)
[![dependency status](https://deps.rs/repo/gitlab/hsn10/getopt2/status.svg)](https://deps.rs/repo/gitlab/hsn10/getopt2)
[![Documentation](https://docs.rs/getopt2/badge.svg)](https://docs.rs/getopt2)
[![Downloads](https://img.shields.io/crates/d/getopt2)](https://crates.io/crates/getopt2/versions)
[![](https://tokei.rs/b1/gitlab/hsn10/getopt2?category=code)](https://github.com/XAMPPRocky/tokei)

Features
--------

1. Simple argument parsing rules:
    1. Unrecognised options or options with required value missing
       are parsed as positional arguments.
    1. No multiple options without an argument grouping together ("-abc") allowed.
    1. No attaching value to the option without space ("-aValue").
1. GNU argument parsing rules by default. Options can be anywhere in command line before "--"
1. POSIX parsing rules activated by "+" extension or by setting the POSIXLY_CORRECT
   environment variable.
   In POSIX mode first non option stops option parsing. ("+a:")
1. Double dash "--" support. Anything after "--" is not treated as options.
    1. If double dash follows an option with required argument, its used as option value, not a separator.
    1. If double dash follows an option with optional argument, its parsed as separator.
1. Optional arguments support extension "::".
    1. Original the "::" limitation:
    1. The GNU "a::" syntax only supports the option value being immediately attached
       to the flag (-aValue1). It does not support a space ("-a Value1").
    1. Because *getopt2* do not supports attached values, space is used
       for optional argument value separation.
1. Compatibility with ":" extension - allow to use "?" as option character.
   Can be combined with POSIX mode as "+:".

### Code quality

1. [MSRV 1.56]https://blog.rust-lang.org/2021/10/21/Rust-1.56.0/, accessible from entire *Rust 2021 Edition*.
1. Based on [getopt3 crate]https://crates.io/crates/getopt3.
1. Small code size. 270 LOC.
1. Zero dependencies.
1. No `unsafe` Rust.
1. Runs on *stable 2021 Edition Rust*.
1. 100 unit tests, 7 integration tests, and 7 doc tests.

Usage
-----

#### 1. Create getopt instance

  let g = **getopt2::new**(_arguments_, _optstring_)

  getopt2::new constructor arguments:

  1. _arguments_ command line arguments. Can be anything what can be converted to
                   Iterator over String. You can use `std::env::args()` but you need to skip first
                   argument because its executable name. It can be done manually by `.skip(1)`
                   or by calling `hideBin` utility function which strips its first argument.
  2. _optstring_ is a anything providing `AsRef <str>`.
        *optstring* is containing the legitimate option characters.
        1.  Valid option characters are alphanumeric plus '?'.
        1.  If such a character is followed by a colon, the option requires an
            argument.
        1.  If character is followed by a double collon, argument is
            optional.
        1.  space is used for argument separation on command line.
        1.  if *optstring* starts with "+" parsing is done in POSIX mode.

#####  Returned value:

  1. Function returns `Result <getopt>`.
  2. `Result` wraps parsing errors and *getopt* structure.
  3. Parsing can fail *only if* optstring is invalid.
  4. If required argument is missing function *new()* won't fail.
     Call *validate()* on parsed result for optional strict argument checking.

#### 2. Check parsed options

  *getopt* structure returned by constructor has following public members:
  1. _arguments_ : `Vec <String>` command line arguments with options removed.
  2. _options_map_ : `HashMap <char, argument>` map of recognized options.
     Maps option character to *argument enum* with values (YES, NO, OPTIONAL).
  3. _options_ : `HashMap <char, String>` options parsed.
     If option do not have argument, it is mapped to empty "" `String`,
     otherwise it is mapped to its argument as `String`.

  Structure *getopt* supports `IntoIterator` and can transform itself into `Iterator`
  over supplied command line arguments.
  It supports consuming itself or use self immutable reference for enumerating arguments.

  *getopt.iter()* returns `Iterator` over pub field _arguments_ without consuming itself.

  *getopt.len()* returns number of command line arguments.
  It's convience shortcut for *getopt.arguments.len()*.

  *getopt.get()* returns value of command line option.
  It's convience shortcut for *getopt.options.get()*.

  *getopt.has()* returns if option got supplied on command line.
  It's convience shortcut for *getopt.options.contains_key()*.

  *getopt\[usize\]* returns nth command line argument.
  It is a convenience shortcut for *getopt.arguments.index()*.

  *getopt.is_empty()* returns if any *arguments* were supplied on command line.
  It is a convenience shortcut for *getopt.arguments.is_empty()*.

#### 3. Optional - Check if correct options were provided

  You can run strict parse checks by calling *validate(getopt)* function.

  This function returns back `Result` with supplied *getopt instance* on success or
  error as `String`. It can detect if unknown options were encountered or
  required arguments are missing.

Example
-------

```rust
  use std::env::args;
  use getopt2::hideBin;

  let rc = getopt2::new(hideBin(args()), "ab:c");
  if let Ok(g) = rc {
     // command line options parsed sucessfully
     if let Some(arg) = g.options.get(&'b') {
        // handle b argument stored in arg
     };
  };
```
#### Reference

1. [POSIX getopt]https://pubs.opengroup.org/onlinepubs/9799919799/functions/getopt.html function.
1. [GNU libc getopt]https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html function.
1. [OpenBSD getopt]https://man.openbsd.org/getopt.3 function.
1. [FreeBSD getopt]https://man.freebsd.org/cgi/man.cgi?query=getopt&apropos=0&sektion=3&arch=default&format=html function.

#### Implemented getopt extensions

1. GNU getopt parsing rules:
   1. Options can be anywhere in command line before --
   1. double dash (--) support. Anything after -- is not treated as options.
   1. double dash is *eaten by getopt*, not visible to user as argument.
1. POSIX extension in the *getopt* function where the argument string
   specification can start with a colon (:). When the option string begins with
   a colon, it modifies the behavior of getopt to handle error cases differently.
   Specifically, it suppresses the default error messages that getopt prints
   when it encounters an unrecognized option or a missing argument,
   and it returns ":" instead of "?" for these error cases. This allows using "?" as
   option because its possible to spot difference unknown option and "-?" option.
   1. Extension is implemented in way that "?" as option is always supported.
      ":" at start of option string is fully optional and have no effect on
      activating this extension.
1. Two colons in optstring (::) indicates that the argument is optional.
   This is an extension not covered by POSIX.
1. In GNU getopt, if the option string (optstring) begins with a plus (+) character,
   it triggers POSIX-compatible parsing. This means that the first non-option
   argument will stop option parsing, similar to how setting the POSIXLY_CORRECT
   environment variable behaves. Double dash is still supported in this mode.

#### Crates getopt2 and getopt3 compared

Following table compares crates [getopt3](https://crates.io/crates/getopt3) and
[getopt2](https://crates.io/crates/getopt2).

Both crates parse command line
arguments and have almost identical API. Both parsers won't fail parsing unless *optstring*
is invalid.

Only API difference is that
public struct getopt member _options_map_ is defined as `HashMap <char, argument>` in *getopt2*
while in *getopt3* it is `HashMap <char, bool>`.

Main difference between both parsers is that [getopt2](https://crates.io/crates/getopt2)
turns unrecognised options or options with mandatory argument missing into
positional arguments.

| Feature                 |   getopt2    |   getopt3     |
| :------                 | :------      | :---------    |
| *GNU* parsing mode      | supported    | supported     |
| *POSIX* parsing mode    | supported    | not supported |
| *double dash* separator | supported    | supported     |
| *optional* arguments    | supported    | not supported |
| getopt (:) extension    | always active | always active |
| value can follow option -aValue | not supported | supported |
| grouping multiple options -abc | not supported | supported |
| parsing never fails unless *optstring* is invalid | yes | yes |
| *validate()* for strict checks | yes | yes |
| unknown options | turned into arguments | kept as options |