Crates.io | cli-command |
lib.rs | cli-command |
version | 0.1.0 |
created_at | 2025-09-15 07:49:02.916968+00 |
updated_at | 2025-09-15 07:49:02.916968+00 |
description | A lightweight and ergonomic command-line argument parser for Rust |
homepage | |
repository | https://gitlab.com/Efimster/cli-command |
max_upload_size | |
id | 1839562 |
size | 81,057 |
A lightweight, ergonomic command-line argument parser for Rust applications that prioritizes simplicity and performance with convenient macros for reduced boilerplate.
Perfect for developers who want CLI parsing without the complexity. While clap
is powerful, it's often overkill for simple applications. cli-command
fills the gap with a clean, intuitive API that's both lightweight and feature-rich.
cli_args!
macro eliminates boilerplate while maintaining type safetyFromStr
type out of the box๐ Minimal dependencies - Only 3 lightweight dependencies for macro support
๐ฏ Dual API design - Both method-based and macro-based interfaces
๐ง Flexible parsing - Supports both -
and --
argument prefixes
๐ Type conversion - Built-in support for common types
โก Error handling - Comprehensive error types with helpful messages
๐งช Well tested - Extensive test coverage
๐ Generic defaults - get_argument_or_default<T>()
works with any type
๐ Multiple values - Support for arguments with multiple parameters
๐จ Macro ergonomics - cli_args!
macro for boilerplate-free argument extraction
๐ญ Command matching - cli_match!
macro for clean command routing
Feature | cli-command | clap | pico-args | gumdrop |
---|---|---|---|---|
Dependencies | 3 | 20+ | 0 | 1 |
Binary Size | Minimal | Large | Minimal | Small |
Compile Time | Fast | Slow | Fast | Fast |
API Style | Method + Macro | Derive + Builder | Iterator-based | Derive |
Type Conversion | Built-in + Generic | Built-in | Manual | Built-in |
Error Messages | Helpful | Excellent | Basic | Good |
Learning Curve | Easy | Steep | Medium | Easy |
Macros Available | Optional | Yes | No | Yes |
When to choose cli-command:
use cli_command::{parse_command_line, Command};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse command line arguments
let cmd = parse_command_line()?;
// Get a simple argument
if let Some(port) = cmd.get_argument("port") {
println!("Port: {}", port);
}
// Get a required argument with type conversion
let threads: usize = cmd.get_argument_mandatory("threads")?;
println!("Threads: {}", threads);
// Get argument with default value (works with any FromStr type!)
let timeout: u64 = cmd.get_argument_or_default("timeout", 30)?;
let host: String = cmd.get_argument_or_default("host", "localhost".to_string())?;
let debug: bool = cmd.get_argument_or_default("debug", false)?;
println!("Timeout: {}, Host: {}, Debug: {}", timeout, host, debug);
Ok(())
}
Notice how get_argument_or_default<T>()
works with any type that implements FromStr
- no special handling needed! This generic approach makes the API both powerful and intuitive.
For even more ergonomic code, cli-command
provides convenient macros that eliminate boilerplate while maintaining the same performance:
cli_args!
MacroThe cli_args!
macro allows you to extract multiple arguments with defaults in a single expression:
use cli_command::{cli_args, parse_command_line};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Extract all arguments with defaults in one line!
let (port, host, workers, verbose) = cli_args!(
port: u16 = 8080,
host: String = "localhost".to_string(),
workers: usize = 4,
verbose: bool = false
);
println!("Server: {}:{} (workers: {}, verbose: {})", host, port, workers, verbose);
Ok(())
}
cli_match!
MacroThe cli_match!
macro provides clean command routing and automatically parses the command line:
use cli_command::{cli_match, cli_args};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// No need to manually parse command line - cli_match! does it automatically!
cli_match! {
"serve" => {
let (port, host) = cli_args!(
port: u16 = 8080,
host: String = "localhost".to_string()
);
start_server(port, host)
},
"build" => {
let (output, release) = cli_args!(
output: String = "dist".to_string(),
release: bool = false
);
build_project(output, release)
},
"help" => print_help(),
_ => {
eprintln!("Unknown command");
print_help();
Ok(())
}
}
}
parse_command_line()
manuallycli_match!
handles command parsing and routing automaticallyuse cli_command::{parse_command_line, Command};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cmd = parse_command_line()?;
match cmd.name.as_str() {
"serve" => {
let port: u16 = cmd.get_argument_or_default("port", 8080)?;
let host = cmd.get_argument_or_default("host", "localhost".to_string())?;
println!("Serving on {}:{}", host, port);
}
"build" => {
let output = cmd.get_argument_or_default("output", "dist".to_string())?;
let release = cmd.contains_argument("release");
println!("Building to {} (release: {})", output, release);
}
_ => {
println!("Unknown command: {}", cmd.name);
return Ok(());
}
}
Ok(())
}
use cli_command::{parse_command_line, Command};
use std::net::SocketAddr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cmd = parse_command_line()?;
// Parse server configuration
let addr: SocketAddr = cmd.get_argument_mandatory("bind")?;
let workers: usize = cmd.get_argument_or_default("workers", 4)?;
let max_connections: usize = cmd.get_argument_or_default("max-connections", 1000)?;
let enable_ssl = cmd.contains_argument("ssl");
println!("Server configuration:");
println!(" Address: {}", addr);
println!(" Workers: {}", workers);
println!(" Max connections: {}", max_connections);
println!(" SSL enabled: {}", enable_ssl);
Ok(())
}
pub struct Command {
pub name: String, // The command name (first non-flag argument)
pub arguments: HashMap<String, Box<[String]>>, // Parsed arguments
}
get_argument(name)
- Get first value of an argumentget_argument_nth_parameter(name, nth)
- Get nth value of an argumentget_argument_all(name)
- Get all values of an argumentcontains_argument(name)
- Check if argument existsget_argument_mandatory(name)
- Get first value, error if missingget_argument_nth_param_mandatory(name, nth)
- Get nth value, error if missingget_argument_mandatory_all(name)
- Get all values, error if missingget_argument_usize(name)
- Convert to usize
get_argument_mandatory_usize(name)
- Convert to usize
, error if missingget_argument_or_default(name, default)
- Get value or return defaultuse cli_command::{CliError, CliErrorKind};
match cmd.get_argument_mandatory("required_arg") {
Ok(value) => println!("Got: {}", value),
Err(CliError { kind: CliErrorKind::MissingArgument(arg), .. }) => {
eprintln!("Missing required argument: {}", arg);
}
Err(e) => eprintln!("Error: {}", e),
}
The parser supports standard Unix-style command line arguments:
# Command with arguments
myapp serve --port 8080 --host localhost --workers 4
# Multiple values for same argument
myapp build --input file1.rs file2.rs --output dist/
# Short and long forms
myapp -v --verbose --quiet
# Boolean flags (no value needed)
myapp --enable-feature --no-cache
cli-command
provides helpful error messages that guide users to solutions:
use cli_command::{CliError, CliErrorKind};
match cmd.get_argument_mandatory("required_arg") {
Ok(value) => println!("Got: {}", value),
Err(CliError { kind: CliErrorKind::MissingArgument(arg), .. }) => {
eprintln!("Missing required argument: {}", arg);
}
Err(e) => eprintln!("Error: {}", e),
}
MissingArgument
- Required argument not provided (with helpful usage hint)MissingParameter
- Required parameter at specific position not providedParseCommandLine
- General command line parsing errorInner
- Wrapped error from type conversionThe parser supports standard Unix-style command line arguments:
# Command with arguments
myapp serve --port 8080 --host localhost --workers 4
# Multiple values for same argument
myapp build --input file1.rs file2.rs --output dist/
# Short and long forms
myapp -v --verbose --quiet
# Boolean flags (no value needed)
myapp --enable-feature --no-cache
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
cli_args!
macro for ergonomic argument extractioncli_match!
macro for clean command routing