sarge

Sarge is a simple, lightweight argument parser. It has two styles of argument: short (e.g. -h) and long (e.g. --help) (and both), and six different argument types: i64, u64, f64, String, bool, and Vec<T> where T: ArgumentType. It also supports using environment variables as arguments; in the event of a conflict, command-line.
Arguments are registered with an ArgumentParser, and when you're ready, ArgumentParser::parse. Parsing does two things: it sets the value of each argument, and returns a Vec<String> of the values not associated with an argument. Arguments can be created easily via the tag:: functions and registered with ArgumentParser::add, returning an ArgumentRef.
Arguments can be retrieved with ArgumentRef::get(self). Boolean arguments will always be Ok(true | false); other arguments may be Err(_) if they failed to parse, or were not provided.
Example:
use sarge::prelude::*;
fn main() {
let parser = ArgumentParser::new();
let help = parser.add(tag::both('h', "help")); let number = parser.add::<i64>(tag::long("number"));
let arguments = vec![
"my_program".to_string(),
"abc".to_string(),
"--number".to_string(),
"123".to_string(),
"def".to_string(),
];
let remainder = parser.parse_cli(&arguments, false).expect("Failed to parse arguments");
assert_eq!(
help.get(), Ok(false) );
assert_eq!(
number.get(),
Ok(123) );
assert_eq!(
remainder, vec![
"abc".to_string(),
"def".to_string(),
]
);
assert_eq!(
parser.binary(), Some("my_program".to_string())
);
}
Environment Variables
Sarge also supports using environment variables as arguments. This is automatically
done when you call parse, or you can use parse_env to pass the variables yourself.
It takes an Iterator<Item = (String, String)> as a reciever, the same type
std::env::args() returns.
Here's a quick example:
use sarge::prelude::*;
fn main() {
let parser = ArgumentParser::new();
let just_env = parser.add(tag::env("JUST_ENV"));
let both = parser.add(tag::long("cli-form").env("ENV_FORM"));
let cli_args = [
"test".to_string(),
"--cli-form=123".to_string(),
];
let env_args = [
("JUST_ENV".to_string(), "0".to_string()),
("ENV_FORM".to_string(), "456".to_string()),
].into_iter();
parser.parse_provided(&cli_args, env_args).unwrap();
assert_eq!(just_env.get(), Ok(false));
assert_eq!(both.get(), Ok(123i64));
}
Custom Types
Using the ArgumentType trait, you can implement your own types. Here's an
example (taken from src/test/custom_type.rs):
use sarge::{prelude::*, custom::*};
#[derive(Debug, PartialEq, Eq)]
struct MyCustomType(Vec<String>);
impl ArgumentType for MyCustomType {
type Error = ();
fn arg_type() -> ArgumentValueType {
ArgumentValueType::String
}
fn from_value(val: ArgumentValue) -> Result<Self, Self::Error> {
if let ArgumentValue::String(val) = val {
Ok(Self(val.split(' ').map(|s| s.to_string()).collect()))
} else {
Err(())
}
}
fn default_value() -> Option<Self> {
Some(MyCustomType(Vec::new()))
}
}
fn main() {
let parser = ArgumentParser::new();
let my_argument = parser.add::<MyCustomType>(tag::long("myarg"));
let arguments = [
"custom_type_test".to_string(),
"--myarg".to_string(),
"Hello World !".to_string(),
];
let _ = parser.parse_cli(&arguments, false).expect("failed to parse arguments");
assert_eq!(
my_argument.get(),
Ok(
MyCustomType(
vec![
"Hello".to_string(),
"World".to_string(),
"!".to_string(),
]
)
)
);
}