gumdrop

repository·master·Indexed 42 days ago

https://github.com/murarth/gumdrop

A Rust option parser providing custom derive support for defining command-line interfaces. It allows developers to use the #[derive(Options)] procedural macro on structs and enums to automatically generate argument parsers, supporting subcommands, positional arguments, and customizable flags for short/long options, default values, and custom parsing functions. Version 0.8.1.

Tokens
3.3K
Snippets
7
Records
15
Agent score
4%

What's inside gumdrop

  1. Configure `ParsingStyle` for free arguments

    master

    The ParsingStyle enum controls how the parser treats "free" (non-option) arguments.

    • ParsingStyle::AllOptions: The default. The parser continues to look for options (like -o or --long) even after encountering free arguments.
    • ParsingStyle::StopAtFirstFree: Once the first non-option argument is encountered, all subsequent arguments are treated as free arguments, even if they look like options.
    use gumdrop::{Options, ParsingStyle};
    
    #[derive(Debug, Options)]
    struct MyOptions {
        #[options(help = "flag")]
        flag: bool,
        #[options(free)]
        free: Vec<String>,
    }
    
    // If args are ["foo", "-flag"]
    // AllOptions: flag=true, free=["foo", "-flag"]
    // StopAtFirstFree: flag=false, free=["foo", "-flag"]
  2. Use `derive(Options)` to generate argument parsers

    master

    The gumdrop_derive crate provides the #[derive(Options)] procedural macro. When applied to a struct or enum, it automatically generates an implementation of the gumdrop::Options trait, allowing you to parse command-line arguments into your data structures.

    Supported Types

    • Structs: Used to define a collection of options and positional arguments. Unit structs and tuple structs are not supported.
    • Enums: Used to define subcommands. Each variant must be a unary tuple variant (e.g., Variant(SubcommandOptions)).
    #[derive(gumdrop::Options)]
    struct MyOptions {
        #[options(help = "a help flag")]
        help: bool,
    }
  3. Implement subcommands using `enum`

    master

    To create a subcommand-based CLI, use #[derive(Options)] on an enum.

    1. The top-level struct must contain a field marked #[options(command)] that holds an Option<YourEnum>.
    2. Each variant in the enum should be a unary tuple variant containing a struct that implements Options.
    3. Command names are automatically generated from variant names (e.g., FooBar becomes foo-bar), but can be customized with #[options(name = "...")].

    Options defined in the top-level struct must appear before the subcommand name on the command line.

    use gumdrop::Options;
    
    #[derive(Debug, Options)]
    struct MyOptions {
        #[options(help = "be verbose")]
        verbose: bool,
    
        #[options(command)]
        command: Option<Command>,
    }
    
    #[derive(Debug, Options)]
    enum Command {
        #[options(help = "make stuff")]
        Make(MakeOpts),
        #[options(help = "install stuff")]
        Install(InstallOpts),
    }
    
    #[derive(Debug, Options)]
    struct MakeOpts {
        #[options(free)]
        free: Vec<String>,
    }
    
    #[derive(Debug, Options)]
    struct InstallOpts {
        #[options(help = "target directory")]
        dir: Option<String>,
    }
  4. Configure command-line options with `#[options]` attributes

    master

    In gumdrop, you can define subcommands and their specific options using the #[options] attribute on a struct. This attribute can be used on the main configuration struct or on nested subcommand structs.

    Supported attributes within #[options(...)] include:

    • name: Sets the name of the command.
    • help: Sets the help text for the command.

    Additionally, you can use #[doc = "..."] to provide documentation that gumdrop will use for help generation.

  5. Define CLI options with `derive(Options)`

    master

    Use the #[derive(Options)] macro on a struct to define command-line options. Each field in the struct represents an option or a free argument. Fields must have a Default implementation or an inline default value.

    Common Attributes:

    • #[options(free)]: Marks a field (usually a Vec<String>) to collect all non-option arguments.
    • #[options(help = "...")]: Provides a description for the help text.
    • #[options(meta = "...")]: Specifies a placeholder name (e.g., N) for the argument in the usage text.
    • #[options(count)]: Treats a boolean-like field as a counter (e.g., -vvv increments a u32 field).
    • #[options(short = "?", long = "...")]: Overrides the automatically generated short and long flag names.
    • #[options(no_short)] / #[options(no_long)]: Disables the short or long form of an option.
    • #[options(parse(try_from_str = "func"))]: Uses a function that returns Result<T, E> for custom parsing.
    • #[options(parse(from_str = "func"))]: Uses a function that always succeeds for custom transformation.
    use gumdrop::Options;
    
    #[derive(Debug, Options)]
    struct MyOptions {
        #[options(help = "print help message")]
        help: bool,
    
        #[options(help = "give a string argument")]
        string: Option<String>,
    
        #[options(help = "give a number", meta = "N")]
        number: Option<i32>,
    
        #[options(help = "list of items")]
        item: Vec<String>,
    
        #[options(count, help = "increase counter")]
        count: u32,
    
        #[options(free)]
        free: Vec<String>,
    }
    
    fn main() {
        let opts = MyOptions::parse_args_default_or_exit();
        println!("{:#?}", opts);
    }
  6. Parse arguments from the environment

    master

    Gumdrop provides helper functions to parse arguments directly from the process environment and handle errors or help requests automatically.

    • parse_args_default_or_exit(): The most common entry point. It uses the default ParsingStyle. If parsing fails, it prints the error to stderr and exits with code 2. If --help is requested, it prints usage and exits with code 0.
    • parse_args_or_exit(style): Same as above, but allows specifying a ParsingStyle.
    use gumdrop::Options;
    
    #[derive(Debug, Options)]
    struct MyOptions {
        #[options(help = "help")]
        help: bool,
    }
    
    fn main() {
        // Automatically handles --help and errors
        let opts = MyOptions::parse_args_default_or_exit();
    }
  7. The `Options` trait

    master

    The Options trait is the core interface for all CLI structures in gumdrop. It is typically implemented via #[derive(Options)].

    Key Methods:

    • parse<S: AsRef<str>>(parser: &mut Parser<S>) -> Result<Self, Error>: The low-level parsing logic.
    • parse_args<S: AsRef<str>>(args: &[S], style: ParsingStyle) -> Result<Self, Error>: Parses a slice of arguments with a specific style.
    • parse_args_default<S: AsRef<str>>(args: &[S]) -> Result<Self, Error>: Parses a slice of arguments using ParsingStyle::AllOptions.
    • usage() -> &'static str: Returns the usage string for the type.
    • self_usage() -> &'static str: Returns usage for the current instance (useful for subcommands).
    • command_list() -> Option<&'static str>: Returns a list of available commands.
    • command_name(&self) -> Option<&'static str>: Returns the name of the active command (for enums).
  8. Configure global command-line defaults

    master

    You can apply global settings to your entire parser using the #[options(...)] attribute on your main struct. These settings affect how all subsequent options are treated:

    • no_help_flag: Disables the automatic --help flag.
    • no_short: Disables short flags (e.g., -s) for all options.
    • no_long: Disables long flags (e.g., --short) for all options.
    • no_multi: Disables multi-value support (e.g., Vec<T>) for all options.
    • required: Makes all options required by default.
    • help = "...": Sets global help text.

    Example:

    #[derive(Options)]
    #[options(no_short, help = "My CLI Tool")]
    struct MyOpts {
        // ...
    }
  9. Configure struct fields with `#[options(...)]`

    master

    You can control how struct fields are parsed by adding #[options(...)] attributes.

    Field Attributes

    AttributeDescription
    commandMarks the field as a subcommand. Must be Option<T> where T: Options (usually an enum).
    help_flagMarks a bool field as a help flag. Fields named help get this automatically.
    no_help_flagPrevents an option from being treated as a help flag.
    countIncrements the field each time the option appears (e.g., -vvv increments a u32).
    freeMarks a field as a positional argument. Non-option arguments fill these in sequence. The final free field can be a Vec<T> to collect all remaining arguments.
    short = "?"Sets the short option character.
    no_shortDisables short option assignment for this field.
    long = "..."Sets the long option name.
    no_longDisables long option assignment for this field.
    default = "..."Provides a default value (parsed like an argument).
    default_exprProvides a default value as a Rust expression evaluated at compile time (requires default_expr feature).
    requiredCauses an error if the option is missing (unless a help_flag is present).
    multi = "..."Allows parsing an option multiple times using the specified method (e.g., push). Vec<T> fields are multi by default unless no_multi is used.
    no_multiInhibits automatic multi behavior for Vec<T> fields.
    not_requiredCancels a type-level required flag.
    help = "..."Sets the help text. Can also use doc comments.
    meta = "..."Sets the placeholder name shown in usage (e.g., --file <FILE>).
    parse(...)Specifies a custom parsing function. Supported types:
      parse(from_str = "...")fn(&str) -> T
      parse(try_from_str = "...")fn(&str) -> Result<T, E>
      parse(from_str)Uses From::from
      parse(try_from_str)Uses FromStr::from_str
  10. Customize type parsing with `from_str` and `try_from_str`

    master

    You can control how a field's string argument is converted into its target type using parsing attributes:

    • from_str = "path": Uses the specified function to convert the string argument. If no path is provided (from_str), it uses ::std::convert::From::from.
    • try_from_str = "path": Uses the specified function which returns a Result. If no path is provided (try_from_str), it defaults to ::std::str::FromStr::from_str.

    Example usage in an attribute:

    #[options(from_str = "my_custom_parser")]
    field: MyType,