An open API service indexing awesome lists of open source software.

https://github.com/tailwags/sap

🌿 A small, simple and sweet argument parser for Rust
https://github.com/tailwags/sap

args argument-parsing commandlineparser rust

Last synced: 5 months ago
JSON representation

🌿 A small, simple and sweet argument parser for Rust

Awesome Lists containing this project

README

          

# 🌿 Sap

_A small, simple and sweet argument parser for Rust_

[![Crates.io](https://img.shields.io/crates/v/sap.svg)](https://crates.io/crates/sap)
[![Documentation](https://docs.rs/sap/badge.svg)](https://docs.rs/sap)
[![License](https://img.shields.io/crates/l/sap.svg)](LICENSE)

Sap is a minimal, zero-dependency Unix command-line argument parser for Rust. It provides full control over argument parsing with an iterator-based API that handles GNU-style options while maintaining simplicity and flexibility.

## ✨ Features

- **GNU-style option parsing**: Support for short (`-a`), long (`--verbose`), and combined options (`-abc`)
- **Flexible value handling**: Options with values via `--name=value` or separate arguments
- **POSIX compliance**: Handle `--` separator and `-` (stdin) arguments correctly
- **Zero dependencies**: Pure Rust implementation with no external crates
- **Iterator-based**: Works with any `Iterator>` for maximum flexibility
- **Comprehensive error handling**: Descriptive error messages for invalid input

## 🚀 Quick Start

Add Sap to your `Cargo.toml`:

```toml
[dependencies]
sap = "0.0.5"
```

## 📖 Usage

### Basic Example

```rust
use sap::{Parser, Argument};

// Parse from command line arguments
let mut parser = Parser::from_env().unwrap();

while let Some(arg) = parser.forward().unwrap() {
match arg {
Argument::Short('v') => println!("Verbose mode enabled"),
Argument::Long("help") => println!("Help requested"),
Argument::Long("file") => {
if let Some(filename) = parser.value() {
println!("Processing file: {}", filename);
}
}
Argument::Value(val) => println!("Positional argument: {}", val),
Argument::Stdio => println!("Reading from stdin"),
}
}
```

### Parsing Custom Arguments

```rust
use sap::{Parser, Argument};

// Parse from any iterator of string-like values
let mut parser = Parser::from_arbitrary(["myprogram", "-v", "--file=input.txt"]).unwrap();

while let Some(arg) = parser.forward().unwrap() {
match arg {
Argument::Short('v') => println!("Verbose mode enabled"),
Argument::Long("file") => {
if let Some(filename) = parser.value() {
println!("Processing file: {}", filename);
}
}
Argument::Value(val) => println!("Positional argument: {}", val),
_ => {}
}
}
```

## 🎯 Argument Types

Sap recognizes four types of arguments:

- **`Argument::Short(char)`** - Short options like `-v`, `-x`, and combined ones like `-abc`
- **`Argument::Long(&str)`** - Long options like `--verbose`, `--file`, including values like `--file=foo.txt`
- **`Argument::Value(Cow)`** - Positional arguments and operands
- **`Argument::Stdio`** - The special `-` argument (stdin/stdout)

## 📚 Complete Example

Here's a more comprehensive example showing a typical CLI application:

```rust
use sap::{Parser, Argument, Result};

fn main() -> Result<()> {
let mut parser = Parser::from_env()?;
let mut verbose = false;
let mut output_file = None;
let mut input_files = Vec::new();

while let Some(arg) = parser.forward()? {
match arg {
Argument::Short('v') | Argument::Long("verbose") => {
verbose = true;
}
Argument::Short('h') | Argument::Long("help") => {
print_help(parser.name());
return Ok(());
}
Argument::Short('o') | Argument::Long("output") => {
output_file = parser.value();
if output_file.is_none() {
eprintln!("Error: --output requires a value");
std::process::exit(1);
}
}
Argument::Value(file) => {
input_files.push(file.into_owned());
}
Argument::Stdio => {
input_files.push("-".to_string());
}
unknown => {
eprintln!("Error: {}", unknown.into_error(parser.value()));
std::process::exit(1);
}
}
}

if verbose {
println!("Verbose mode enabled");
if let Some(ref output) = output_file {
println!("Output file: {}", output);
}
println!("Input files: {:?}", input_files);
}

Ok(())
}

fn print_help(program_name: &str) {
println!("Usage: {} [OPTIONS] [FILES...]", program_name);
println!("Options:");
println!(" -v, --verbose Enable verbose output");
println!(" -o, --output Specify output file");
println!(" -h, --help Show this help message");
}
```

## 🔍 Real-World Examples

For comprehensive examples of Sap in action, check out [**puppyutils**](https://github.com/puppyutils/puppyutils) - a collection of Unix utilities reimplemented in Rust. Sap was originally created as the argument parser for this project, so you'll find extensive real-world usage patterns.

## 🤝 Acknowledgments

Special thanks to [Esther](https://github.com/esther-ff) who wrote the original parser design for this library <3

## License

This project is licensed under the
[Apache-2.0 License](http://www.apache.org/licenses/LICENSE-2.0). For more
information, please see the [LICENSE](LICENSE) file.