Crate lexopt

source ·
Expand description

A pathologically simple command line argument parser.

Most argument parsers are declarative: you tell them what to parse, and they do it.

This one provides you with a stream of options and values and lets you figure out the rest.

Example

struct Args {
    thing: String,
    number: u32,
    shout: bool,
}

fn parse_args() -> Result<Args, lexopt::Error> {
    use lexopt::prelude::*;

    let mut thing = None;
    let mut number = 1;
    let mut shout = false;
    let mut parser = lexopt::Parser::from_env();
    while let Some(arg) = parser.next()? {
        match arg {
            Short('n') | Long("number") => {
                number = parser.value()?.parse()?;
            }
            Long("shout") => {
                shout = true;
            }
            Value(val) if thing.is_none() => {
                thing = Some(val.string()?);
            }
            Long("help") => {
                println!("Usage: hello [-n|--number=NUM] [--shout] THING");
                std::process::exit(0);
            }
            _ => return Err(arg.unexpected()),
        }
    }

    Ok(Args {
        thing: thing.ok_or("missing argument THING")?,
        number,
        shout,
    })
}

fn main() -> Result<(), lexopt::Error> {
    let args = parse_args()?;
    let mut message = format!("Hello {}", args.thing);
    if args.shout {
        message = message.to_uppercase();
    }
    for _ in 0..args.number {
        println!("{}", message);
    }
    Ok(())
}

Let’s walk through this:

  • We start parsing with Parser::from_env.
  • We call parser.next() in a loop to get all the arguments until they run out.
  • We match on arguments. Short and Long indicate an option.
  • To get the value that belongs to an option (like 10 in -n 10) we call parser.value().
  • Value indicates a free-standing argument.
    • if thing.is_none() is a useful pattern for positional arguments. If we already found thing we pass it on to another case.
    • It also contains an OsString.
      • The .string() method decodes it into a plain String.
  • If we don’t know what to do with an argument we use return Err(arg.unexpected()) to turn it into an error message.
  • Strings can be promoted to errors for custom error messages.

Modules

A small prelude for processing arguments.

Structs

A parser for command line arguments.
An iterator for the remaining raw arguments, returned by Parser::raw_args.
An iterator for multiple option-arguments, returned by Parser::values.

Enums

A command line argument found by Parser, either an option or a positional argument.
An error during argument parsing.

Traits

An optional extension trait with methods for parsing OsStrings.