<p align="center">
<img src="https://raw.githubusercontent.com/LinuxProativo/flexiargs/refs/heads/master/logo.png" width="300"/>
</p>
<h1 align="center">FlexiArgs - Flexible Arguments Parser</h1>
<h3 align="center">โจ Minimalist, Flexible, and Ergonomic CLI Parsing.</h3>
<p align="center">
<img src="https://img.shields.io/badge/Platform-POSIX-FCC624?&logo=linux&style=flat-square"/>
<img src="https://img.shields.io/github/actions/workflow/status/LinuxProativo/flexiargs/rust.yml?label=Test&style=flat-square&logo=github"/>
<img src="https://img.shields.io/badge/RustC-1.85+-orange?style=flat-square&logo=rust"/>
<img src="https://img.shields.io/github/languages/code-size/LinuxProativo/flexiargs?style=flat-square&logo=rust&label=Code%20Size"/>
</p>
## ๐ Overview
`flexiargs` is a lightweight and dependency-friendly Rust crate designed for rule-based
command-line argument parsing without relying on macros, derive systems, or bloated
abstractions.
Instead of hiding behavior behind procedural magic, flexiargs provides a clean and
explicit API that allows developers to bind CLI arguments directly to variables while
retaining full control over parsing logic and application flow.
Built with simplicity and flexibility in mind, it gives you low-level control when
you need it, without sacrificing ergonomics. With flexiargs, you can easily manage:
- **โ๏ธ Parsing behavior and argument rules;**
- **โ
Validation and constraint handling;**
- **๐ฆ Unmatched or forwarded arguments;**
- **๐ Execution flow and command dispatching;**
- **๐งฉ Custom CLI architectures and dynamic behaviors;**
Unlike heavy CLI frameworks, flexiargs focuses on predictable behavior, small footprint,
and straightforward integration, making it ideal for projects where control and
portability matter. Perfect for:
- **๐ฆ Package managers;**
- **๐ ๏ธ System utilities;**
- **๐ฅ Installers and bootstrap tools;**
- **๐งฉ Embedded CLI environments;**
- **๐ Custom shell-like applications;**
- **๐งช Internal developer tooling;**
- **โก Lightweight standalone binaries;**
- **๐ Experimental runtime environments;**
## โจ Features
`flexiargs` is designed to keep CLI parsing simple, explicit, and predictable, without relying on macros or heavy abstractions. Instead of hiding behavior behind complex frameworks, it exposes clear rule-based control over how arguments are interpreted and processed.
* ๐งฉ **Simple rule-based parser API**
Defines parsing rules in a declarative way, without DSLs or code generation.
You have full control over how each argument is interpreted.
* ๐ซ **No procedural macros**
No dependency on `derive` or procedural macros. This reduces compile time,
avoids hidden behavior, and improves debugging clarity.
* ๐ **Supports short and long flags**
Full support for both short flags (`-v`, `-h`) and long flags
(`--verbose`, `--help`) for flexible CLI design.
* ๐ **Supports argument formats**
* `--flag=value`
Inline assignment for compact CLI usage.
* `--flag value`
Classic POSIX-style separation for readability in interactive usage.
* ๐ **Typed parsing with `FromStr`**
Automatically converts string inputs into Rust types using the `FromStr` trait,
ensuring type safety and reducing manual parsing code.
* โ ๏ธ **Automatic error formatting**
Parsing errors are automatically formatted in a clear and consistent way,
improving end-user feedback.
* ๐ **Optional and required arguments**
Explicit support for required and optional parameters, removing the need for
manual validation logic.
* ๐ **Multi-value collection**
Support for multiple values for the same flag (e.g. `--file a b c`), collected
into
typed containers.
* ๐ฅ **Positional argument passthrough**
Positional arguments can be captured or forwarded directly to subprocesses or
higher-level handlers.
* ๐ **Strict validation modes**
Enables strict parsing mode to reject unknown or malformed arguments, ideal for
robust tools and system utilities.
* ๐งต **Thread-safe shared settings (`RwLock`)**
Safe shared state across threads using `RwLock`, useful for concurrent CLI
applications or embedded runtimes.
* โก **Custom actions/callbacks**
Allows execution of custom callbacks during parsing for dynamic or
context-aware behavior.
* ๐ชถ **Minimal and dependency-light design**
Keeps the core lightweight with minimal dependencies, focusing on portability
and predictable behavior.
## ๐ฆ Installation
Add the crate to your `Cargo.toml`:
```toml
[dependencies]
flexiargs = "2.0"
```
## ๐ Public API
The crate intentionally exposes a very small API surface:
```rust
pub use messages::{invalid_arg, missing_arg};
pub use help::ArgHelp;
pub use options::ParserOptions;
pub use flexiargs::{Arg, NULL_PTR, parse_into_vars};
```
### ๐ช Main Entry Points
| `Arg` | Defines parsing rules |
| `parse_into_vars` | Executes parsing with `ParserOptions` |
| `ParserOptions` | Configuration for parsing behavior |
| `invalid_arg` | Standardized invalid argument error |
| `missing_arg` | Standardized missing parameter error |
## ๐ Quick Example
```rust
use flexiargs::{Arg, parse_into_vars, ParserOptions};
use std::collections::VecDeque;
let mut sync_mode = false;
let mut packages = Vec::new();
let mut cache_dir = String::new();
let mut config_file: Option<String> = None;
let mut use_overlay = true;
let opts = ParserOptions {
subcommand: "aports",
..Default::default()
};
let mut rules = [
Arg::bool(Some("-S"), "--sync", &mut sync_mode),
Arg::collect_list(None, "--pkgs", "packages", &mut packages),
Arg::value(None, "--cache-dir", "path", &mut cache_dir),
Arg::option(Some("-c"), "--config", "file", &mut config_file),
Arg::set(None, "--disable-overlay", false, &mut use_overlay),
];
let args = VecDeque::from(vec![
"-S".to_string(),
"wget".to_string(),
"curl".to_string(),
"--cache-dir=/tmp".to_string(),
"--disable-overlay".to_string()
]);
parse_into_vars(&mut rules, args, opts).ok();
drop(rules);
println!("Sync: {}", sync_mode);
println!("Packages: {:?}", packages);
println!("Cache dir: {}", cache_dir);
println!("Overlay enabled: {}", use_overlay);
```
## ๐ง Core Concepts
### ๐ Parsing Rules
Every CLI behavior is defined using an `Arg`.
Each rule describes:
- ๐ท๏ธ Accepted flags;
- โ๏ธ Parsing behavior;
- ๐ฏ Target variable;
- โ
Validation requirements;
Example:
```rust
Arg::bool(Some("-v"), "--verbose", &mut verbose)
```
## ๐งฑ Supported Rule Types
`flexiargs` is built around a small set of explicit rule types that define how command-line
input is interpreted, validated, and transformed. Instead of relying on implicit behavior
or hidden conventions, each rule type has a clear and predictable responsibility,
allowing you to compose CLI behavior in a controlled and deterministic way.
## ๐ฉ Boolean Flags
Sets a boolean to `true` when matched.
```rust
let mut verbose = false;
Arg::bool(Some("-v"), "--verbose", &mut verbose);
```
### โ
Supports
- `-v`
- `--verbose`
## ๐ข Typed Values
Parses values using `FromStr`.
```rust
let mut port: u16 = 0;
Arg::value(
Some("-p"),
"--port",
"port",
&mut port
);
```
### โ
Supports
- `--port 8080`
- `--port=8080`
- `-p 8080`
## โ Optional Values
Stores values in `Option<String>`.
```rust
let mut config: Option<String> = None;
Arg::option(
Some("-c"),
"--config",
"file",
&mut config
);
```
## ๐ง Fixed State Assignment
Assigns a predefined value when matched.
```rust
let mut overlay = true;
Arg::set(
None,
"--disable-overlay",
false,
&mut overlay
);
```
## ๐ Multi-Value Collection
Collects sequential positional values until another flag appears.
```rust
let mut packages = Vec::new();
Arg::collect_list(
None,
"--pkgs",
"packages",
&mut packages
);
```
### ๐งช Example
```bash
--pkgs wget curl git
```
### ๐ค Result
```rust
["wget", "curl", "git"]
```
## โก Custom Actions
Executes arbitrary logic.
```rust
Arg::action(
Some("-V"),
"--version",
|| {
println!("myapp 1.0");
}
);
```
### ๐ก Useful for
- ๐ Version output
- ๐ ๏ธ Custom handlers
- ๐ช Early exits
- ๐ Dynamic state manipulation
## โ Required Arguments
Arguments can be marked as essential:
```rust
Arg::value(
None,
"--root",
"path",
&mut root
).essential();
```
If no essential rule is matched:
```text
myapp: setup: no essential parameter specified
```
## ๐งต Thread-Safe Global State
flexiargs includes built-in support for shared application state using `RwLock`.
### ๐ฉ Shared Boolean Flags
```rust
use std::sync::RwLock;
static DEBUG: RwLock<bool> = RwLock::new(false);
Arg::rw_bool(
Some("-d"),
"--debug",
&DEBUG
);
```
### ๐ข Shared Typed Values
```rust
use std::sync::RwLock;
static PORT: RwLock<u16> = RwLock::new(8080);
Arg::rw_value(
None,
"--port",
"port",
&PORT
);
```
### ๐ง Shared Fixed Assignment
```rust
Arg::rw_set(
None,
"--production",
true,
&MODE
);
```
## ๐ Environment Variables
`flexiargs` supports documentation and parsing of environment variables,
allowing configuration via the environment.
```rust
Arg::env("ALPACK_ARCH", "Define the target architecture for rootfs"),
```
## ๐ Parsing
Parsing in flexiargs is explicit, deterministic, and fully rule-driven. Each step of
the parsing process is defined by clear rules that transform raw command-line input
into structured, validated, and typed data.
### ๐ฅ Basic Parsing
```rust
let opts = ParserOptions {
subcommand: "server",
..Default::default()
};
parse_into_vars(&mut rules, args, opts).ok()?;
```
## ๐ฆ ParseResult
The parser returns a `ParseResult`. This structure provides a clean,
streamlined interface for controlling your CLI's execution flow:
- โ
**Result Handling**: Encapsulates the success or failure of the parsing logic.
- ๐ **Automatic Help/Version**: Handles `--help`, `--version`, and `--help-all`
automatically, including output generation and exit state tracking.
- ๐ **Execution Flow**: Provides a fluent API to bridge the gap between
parsing and your main application logic.
### โ
.help_or_err()
The primary method to control execution flow. It automatically handles help
flags, returns errors if parsing failed, and indicates if the application
should exit after showing help.
```rust
match parse_into_vars(&mut rules, args, opts).help_or_err() {
Ok(true) => return Ok(()), // Help was shown, exit gracefully
Ok(false) => { /* Continue execution */ }
Err(e) => return Err(e), // Parsing error occurred
}
```
### ๐ .ok()
Extracts the raw parsing result, useful if you need to handle the
`Result<(), Box<dyn Error>>` manually without the built-in help/error logic.
```rust
parse_into_vars(&mut rules, args, opts).ok()?;
```
## ๐ Positional Arguments
The parser supports `--` to stop option parsing.
### ๐งช Example
```bash
myapp --verbose -- file1 file2
```
Everything after `--` becomes positional data.
## โ ๏ธ Error Messages
flexiargs provides standardized and human-readable errors automatically.
### โ Invalid arguments
```text
myapp: invalid argument '--unknown'
Use 'myapp --help' to see available options.
```
### โ Missing values
```text
myapp: setup: --port requires a <port>.
Usage: myapp setup --port <port>
```
## ๐ฏ Argument Matching
Rules in flexiargs define how input tokens are interpreted and matched against declared
CLI arguments. This matching system is flexible but explicit, allowing multiple naming
styles and aliasing strategies while keeping behavior predictable and rule-based.
Rules support:
- ๐ค Short flags;
- ๐ท๏ธ Long flags;
- ๐ Aliases via `|`;
- ๐งท Inline assignment;
### ๐งช Example
```rust
Arg::bool(
Some("-v"),
"--verbose|--debug",
&mut verbose
);
```
### โ
Support
- `-v`
- `--verbose`
- `--debug`
Argument matching in flexiargs is designed to be both flexible and explicit.
Instead of enforcing a single naming convention, it allows multiple identifiers
and aliases per argument while keeping resolution deterministic and rule-based.
## โ๏ธ ParserOptions
`ParserOptions` is the central configuration structure for `flexiargs`. It replaces
direct function parameters with a robust, extensible configuration object,
allowing you to fine-tune parsing behavior, validation rules, and context.
### ๐ Definition
```rust
pub struct ParserOptions<'a> {
/// The name of the subcommand being parsed, used for error messages.
pub subcommand: &'a str,
/// If true, unknown arguments will trigger an error.
pub strict: bool,
/// Rejects unmatched arguments up to a specific depth (if Some).
pub strict_level: Option<usize>,
/// If true, ignores help/version flags and treats them as standard arguments.
pub ignore_help: bool,
/// If true, suppresses parsing errors, allowing unmatched args to pass through.
pub passthrough: bool,
/// Fails the parsing process if no arguments were supplied.
pub require_args: bool,
/// A mutable reference to collect unmatched positional arguments.
pub collect_args: Option<&'a mut VecDeque<String>>,
/// A list of help rules for automated documentation.
pub help_rules: &'a [ArgHelp<'a>],
}
```
### ๐ก Why use ParserOptions?
- **Centralized Control:** Configure all parsing aspects (strictness, collection,
requirements) in one place before invoking `parse_into_vars`.
- **Cleaner API:** Keeps the `parse_into_vars` signature stable even as you add new features.
- **Fluent Setup:** Easily derive from `Default` and override only the fields you need.
### ๐ Usage Example
```rust
let mut remaining = VecDeque::new();
let opts = ParserOptions {
subcommand: "profile",
strict: true,
require_args: true,
collect_args: Some(&mut remaining),
..Default::default()
};
parse_into_vars(&mut rules, args, opts).help_or_err()?;
```
## ๐ค AutoHelp System
`flexiargs` provides an automated help generation system that maps your defined rules
and metadata into a structured, readable documentation output. Instead of maintaining
a separate manual, you define the application properties and command context directly
in your code.
### ๐ฆ App Properties
Defines the core metadata for the application, such as name, version, and a brief description.
```rust
ArgHelp::properties(
"ALPack",
"A flexible package manager utility",
"1.2.0"
);
```
### ๐ ๏ธ Subcommand Definition
Documents a subcommand. Use this to organize complex CLI tools into logical groups.
```rust
ArgHelp::subcommand(
None,
"profile",
"Manage system profiles"
);
```
### ๐ Argument Documentation
Documents a specific argument. You can add metadata strings (like `<DIR>`) to improve clarity.
```rust
ArgHelp::arg(
Some("-r"),
"--rootfs",
"Specify rootfs directory"
)
.meta("<DIR>");
```
### ๐ Environment Variable Documentation
Documents environment variables that influence the application behavior, ensuring they
appear in the generated help output.
```rust
ArgHelp::env(
"ALPACK_ARCH",
"Define the target architecture for rootfs"
);
```
### ๐ Contextual Grouping
Limits the visibility of an argument to specific subcommands. This is essential
when generating full help outputs with `--help-all`.
```rust
ArgHelp::arg(
Some("-c"),
"--config",
"Path to config file"
)
.context(&["profile", "setup"]);
```
## ๐ค Contributing
Contributions, improvements, and issue reports are welcome.
### ๐ง Possible Future Extensions
- ๐ Shell completion generation
## ๐ MIT License
This repository has scripts created to be free software.
Therefore, they can be distributed and/or modified within the terms of the ***MIT License***.
> ### See the [MIT License](LICENSE) file for details.
## ๐ฌ Contact & Support
* ๐ง **Email:** [m10ferrari1200@gmail.com](mailto:m10ferrari1200@gmail.com)
* ๐ง **Email:** [contatolinuxdicaspro@gmail.com](mailto:contatolinuxdicaspro@gmail.com)