treesap 0.1.0

A #[derive(Parser)] interface for sap
Documentation
  • Coverage
  • 100%
    1 out of 1 items documented1 out of 1 items with examples
  • Size
  • Source code size: 9.81 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.03 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 15s Average build duration of successful builds.
  • all releases: 15s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • tailwags/sap
    8 2 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • puppymati

treesap

A #[derive(Parser)] interface for sap

Crates.io Documentation License

treesap is a companion crate to sap that lets you declare your CLI arguments as a plain Rust struct instead of writing a manual parsing loop. Annotate your struct with #[derive(Parser)] and treesap generates a parse() method that calls into sap under the hood.

treesap is a work in progress. See the Status section for a precise breakdown of what is implemented today versus what is planned. For production-grade argument parsing, consider using sap directly until treesap reaches a stable feature set.

Status

Feature Status
#[derive(Parser)] on structs Implemented
bool fields as long flags Implemented
Short flag support (-v) Planned
Value-taking fields (String, u32, …) Planned
Option<T> fields (optional arguments) Planned
Required vs optional field distinction Planned
--help auto-generation Planned
--version auto-generation Planned
Subcommands Planned

Installation

Add both sap and treesap to your Cargo.toml:

[dependencies]
sap = "0.2.0"
treesap = "0.1.0"

Quick Start

Declare your arguments as a struct and derive Parser. Each bool field becomes a long flag whose name matches the field name exactly:

use treesap::Parser;

#[derive(Debug, Parser)]
struct Args {
    verbose: bool,
    dry_run: bool,
}

fn main() -> sap::Result<()> {
    let args = Args::parse()?;

    if args.verbose {
        println!("verbose mode enabled");
    }

    if args.dry_run {
        println!("dry-run: no changes will be made");
    }

    Ok(())
}

Running the program:

$ myprogram --verbose
verbose mode enabled

$ myprogram --verbose --dry-run
verbose mode enabled
dry-run: no changes will be made

What parse() does

The generated parse() method:

  1. Calls sap::Parser::from_env() to read std::env::args().
  2. Iterates over all arguments with forward().
  3. Matches each Argument::Long(name) against the field names in the struct.
  4. Returns Err for any unrecognised argument via sap::Argument::unexpected().
  5. Returns Ok(Self { … }) once all arguments are consumed.

Because parse() is generated by a proc-macro, the struct must be defined in a context where sap is also a direct dependency of your crate.

Current limitations

  • Only bool fields are supported. Any other field type will compile but produce incorrect behaviour (all fields are hardcoded to true when their flag appears).
  • #[arg(…)] and #[command(…)] attributes are accepted by the macro but not yet acted upon; short flags, custom flag names, and descriptions are silently ignored.
  • Fields are initialised with .unwrap(), so a missing flag causes a panic rather than a clean error. Make all fields optional by providing defaults until required-field handling is implemented.
  • Enums and unions are not supported (todo!() will panic at compile time).

Relationship to sap

treesap is a thin layer on top of sap. The generated parse() function is equivalent to what you would write by hand using sap::Parser. If treesap does not yet support a feature you need, you can drop down to sap directly:

use sap::{Parser, Argument};

fn main() -> sap::Result<()> {
    let mut parser = Parser::from_env()?;
    let mut verbose = false;
    let mut output = None;

    while let Some(arg) = parser.forward()? {
        match arg {
            Argument::Short('v') | Argument::Long("verbose") => verbose = true,
            Argument::Short('o') | Argument::Long("output") => {
                output = parser.value()?;
            }
            unknown => return Err(unknown.unexpected()),
        }
    }

    println!("verbose={verbose}, output={output:?}");
    Ok(())
}

See the sap README and sap documentation for the full API reference.

License

This project is licensed under the Apache-2.0 License. For more information, please see the LICENSE file.