14 releases

new 0.2.1 Apr 24, 2024
0.2.0 Mar 18, 2024
0.1.3 Feb 22, 2024
0.0.7 Dec 26, 2023
0.0.4 Jul 5, 2023

#140 in Command-line interface

Download history 59/week @ 2024-01-08 29/week @ 2024-01-15 15/week @ 2024-01-22 44/week @ 2024-01-29 30/week @ 2024-02-05 29/week @ 2024-02-12 183/week @ 2024-02-19 72/week @ 2024-02-26 51/week @ 2024-03-04 119/week @ 2024-03-11 216/week @ 2024-03-18 164/week @ 2024-03-25 171/week @ 2024-04-01 108/week @ 2024-04-08 82/week @ 2024-04-15 241/week @ 2024-04-22

628 downloads per month
Used in 21 crates (3 directly)

ISC license

843 lines

Self-similar derive-based command line argument parsing, in the same genre as Clap-derive. It supports

  • Command line parsing
  • Help

This attempts to support parsing arbitrarily complex command line arguments. Like with Serde, you can combine structs, vecs, enums in any way you want. Just because you can doesn't mean you should.

$ # This is an example help output, sans light ansi styling
$ spagh set -h
Usage: spagh set > IDENTITY DATA

    IDENTITY: BACKED-IDENTITY-ARG       Identity to publish as
    DATA: <PATH> | -                    Data to publish.  Must be json in the structure `{KEY: {"ttl": MINUTES, "value": DATA}, ...}`


    An identity with its associated secret.

    local <PATH>                        A file containing a generated key
    card card                           PC/SC card with ED25519 key


    PCSC-ID: <STRING>                   Card to register, using id per pcscd (not identity id)
    PIN: <STRING>                       Card pin


Why or why not

Why this and not Clap?

  • This parses more complex data types, like vectors of sub-structures, or enums
  • It's more consistent
  • It has a super-simple interface (just #[derive(Aargvark)])

Why not this?

  • Some command line parsing conventions were discarded in order to simplify and maintain self-similarity. A lot of command line conventions are inconsistent or break down as you nest things, after all.
  • Quirky CLI parsing generally isn't supported: Some tricks (like -v -vv -vvv) break patterns and probably won't ever be implemented. (Other things just haven't been implemented yet due to lack of time)
  • Alpha

Conventions and usage

To add it to your project, run

cargo add aargvark

To parse command line arguments

  1. Define the data type you want to parse them into, like

    struct MyArgs {
      velociraptor: String,
      deadly: bool,
      color_pattern: Option<ColorPattern>,
  2. Vark it

    let args = aargvark::vark::<MyArgs>();

Optional fields in structs become optional (--long) arguments. If you want a bool long option that's enabled if the flag is specified (i.e. doesn't take a value), use Option<()>.

You can derive structs, enums, and tuples, and there are implementations for Vec, HashSet, most Ip and SocketAddr types, and PathBuf provided.

Some additional wrappers are provided for automatically loading (and parsing) files:

  • AargvarkFile<T>
  • AargvarkJson<T> requires feature serde_json
  • AargvarkYaml<T> requires feature serde_yaml

To parse your own types, implement AargvarkTrait, or if your type takes a single string argument you can implement AargvarkFromStr.

Advanced usage

  • Vecs

    Vec elements are space separated. The way vec parsing works is it attempts to parse as many elements as possible. When parsing one element fails, it rewinds to after it parsed the last successful element and proceeds from the next field after the vec.

  • Prevent recursion in help

    Add #[vark(break)] to a type, field, or variant to prevent recursing into any of the children. This is useful for subcommand enums - attach this to the enum and it will list the arguments but not the arguments' arguments (unless you do -h after specifying one on the command line).

  • Rename enum variants and option keys

    Add #[vark(name="x")] to a field.

  • Change placeholder (id) string

    Add #[vark(id="x")] to a field.


~366K SLoC