clap Command Line Argument Parser

repository·master·Indexed 12 days ago

https://github.com/clap-rs/clap

A simple to use, efficient, and full-featured command-line argument parser for Rust. Version 4.6.6 provides both a declarative approach via the clap_derive macro-based API and a programmatic approach via the clap_builder API. The ecosystem includes clap_complete for shell completions (including Nushell), clap_mangen for generating ROFF man pages, and clap_lex for minimal command line lexical analysis.

Tokens
50.7K
Snippets
146
Records
184
Agent score
97%

What's inside clap

  1. Overview of clap

    master
    clap is a command-line argument parser for Rust. It allows you to create sophisticated command-line interfaces (CLIs) using either a declarative approach or a procedural approach (via derive macros).
  2. Use `clap_derive` for declarative CLI parsing

    master

    clap_derive provides procedural macros that allow you to define your command-line interface (CLI) by deriving the Parser trait on a struct or enum. This is the most ergonomic way to use clap, as it allows you to map CLI arguments directly to Rust data structures using attributes.

    For detailed usage, refer to the official documentation:

  3. Use the clap Builder API

    master

    The clap_builder package provides the Builder implementation for clap. This approach allows you to programmatically construct command-line argument parsers by calling methods on a Command object to define arguments, subcommands, and help text. This is an alternative to the clap_derive macro-based approach.

    For detailed API documentation, visit docs.rs/clap.

  4. Generate shell completions with `clap_complete`

    master
    clap_complete is a library used to generate shell completion scripts for command-line applications built with clap. It allows your users to benefit from tab-completion in their terminal by providing scripts tailored to specific shells.
  5. Generate man pages from `clap::Command` with `clap_mangen`

    master

    The clap_mangen crate allows you to generate ROFF man pages directly from a clap::Command instance. This is useful for generating documentation during the build process rather than requiring a runtime flag in your application.

    To use it in a build script (build.rs), follow these steps:

    1. Add clap_mangen to your [build-dependencies] in Cargo.toml.
    2. Use clap_mangen::Man::new(cmd) to create a man page generator from your command.
    3. Call .render(&mut buffer) to write the ROFF content into a byte buffer.
    4. Write the buffer to a file in the OUT_DIR (e.g., mybin.1).
    fn main() -> std::io::Result<()> {
        let out_dir = std::path::PathBuf::from(std::env::var_os("OUT_DIR").ok_or(std::io::ErrorKind::NotFound)?);
    
        let cmd = clap::Command::new("mybin")
            .arg(clap::arg!(-n --name <NAME>))
            .arg(clap::arg!(-c --count <NUM>));
    
        let man = clap_mangen::Man::new(cmd);
        let mut buffer: Vec<u8> = Default::default();
        man.render(&mut buffer)?;
    
        std::fs::write(out_dir.join("mybin.1"), buffer)?;
    
        Ok(())
    }
  6. Generate Nushell completions for clap CLIs

    master

    Use the clap_complete_nushell crate to generate Nushell-compatible completion scripts for your clap-based command-line applications. This is done by passing the Nushell type to the clap_complete::generate function.

    To implement this, you need to:

    1. Define your Command structure using clap.
    2. Import clap_complete::generate and clap_complete_nushell::Nushell.
    3. Call generate(Nushell, &mut cmd, "name", &mut io::stdout()) to output the completion script.
    use clap::{builder::PossibleValue, Arg, ArgAction, Command, ValueHint};
    use clap_complete::generate;
    use clap_complete_nushell::Nushell;
    use std::io;
    
    fn main() {
        let mut cmd = Command::new("myapp")
            .version("3.0")
            .propagate_version(true)
            .about("Tests completions")
            .arg(
                Arg::new("file")
                    .value_hint(ValueHint::FilePath)
                    .help("some input file"),
            )
            .arg(
                Arg::new("config")
                    .action(ArgAction::Count)
                    .help("some config file")
                    .short('c')
                    .visible_short_alias('C')
                    .long("config")
                    .visible_alias("conf"),
            )
            .arg(Arg::new("choice").value_parser(["first", "second"]))
            .subcommand(
                Command::new("test").about("tests things").arg(
                    Arg::new("case")
                        .long("case")
                        .action(ArgAction::Set)
                        .help("the case to test"),
                ),
            )
            .subcommand(
                Command::new("some_cmd")
                    .about("top level subcommand")
                    .subcommand(
                        Command::new("sub_cmd").about("sub-subcommand").arg(
                            Arg::new("config")
                                .long("config")
                                .action(ArgAction::Set)
                                .value_parser([PossibleValue::new("Lest quotes aren't escaped.")])
                                .help("the other case to test"),
                        ),
                    ),
            );
    
        generate(Nushell, &mut cmd, "myapp", &mut io::stdout());
    }
  7. Reviewing help output for CLI changes

    master

    When developing CLI tools, you can automate the review of help output to ensure changes are intentional. The pacman example uses a testing pattern where:

    1. Every command's long help is rendered.
    2. Each Markdown heading represents a complete command path.
    3. term_width(0) is used to prevent terminal-dependent line wrapping, ensuring consistent output.
    4. The output is compared against a snapshot using snapbox.

    To accept intentional changes to your help text, set the SNAPSHOTS environment variable to overwrite.

    SNAPSHOTS=overwrite
  8. Understand clap indices vs argv indices

    master

    The index_of(id) and indices_of(id) methods return indices that are similar to, but not exactly the same as, standard argv indices.

    Key Differences:

    • Flags: For flags (switches without values), the index refers to the occurrence of the switch itself.
    • Options: For options (switches with values), the index refers to the value provided, not the switch. For example, in -o val, the index recorded is for val.
    • Separation: Clap indices continue counting after arguments have been properly separated by the parser, whereas argv indices do not.
    • Delimiters: If a value is split by a value_delimiter, each resulting value receives its own distinct index.
    # use clap_builder as clap;
    # use clap::{Command, Arg, ArgAction};
    let m = Command::new("myapp")
        .arg(Arg::new("flag").short('f').action(ArgAction::SetTrue))
        .arg(Arg::new("option").short('o').action(ArgAction::Set))
        .get_matches_from(vec!["myapp", "-f", "-o", "val"]);
    
    // ARGV: [0:myapp, 1:-f, 2:-o, 3:val]
    // Clap:  [1:flag, 3:option]
    assert_eq!(m.index_of("flag"), Some(1));
    assert_eq!(m.index_of("option"), Some(3));