Expand description
Derive-based argument parsing optimized for code size and conformance to the Fuchsia commandline tools specification
The public API of this library consists primarily of the FromArgs
derive and the from_env
function, which can be used to produce
a top-level FromArgs
type from the current program’s commandline
arguments.
Basic Example
use argh::FromArgs;
#[derive(FromArgs)]
/// Reach new heights.
struct GoUp {
/// whether or not to jump
#[argh(switch, short = 'j')]
jump: bool,
/// how high to go
#[argh(option)]
height: usize,
/// an optional nickname for the pilot
#[argh(option)]
pilot_nickname: Option<String>,
}
let up: GoUp = argh::from_env();
./some_bin --help
will then output the following:
Usage: cmdname [-j] --height <height> [--pilot-nickname <pilot-nickname>]
Reach new heights.
Options:
-j, --jump whether or not to jump
--height how high to go
--pilot-nickname an optional nickname for the pilot
--help display usage information
The resulting program can then be used in any of these ways:
./some_bin --height 5
./some_bin -j --height 5
./some_bin --jump --height 5 --pilot-nickname Wes
Switches, like jump
, are optional and will be set to true if provided.
Options, like height
and pilot_nickname
, can be either required,
optional, or repeating, depending on whether they are contained in an
Option
or a Vec
. Default values can be provided using the
#[argh(default = "<your_code_here>")]
attribute, and in this case an
option is treated as optional.
use argh::FromArgs;
fn default_height() -> usize {
5
}
#[derive(FromArgs)]
/// Reach new heights.
struct GoUp {
/// an optional nickname for the pilot
#[argh(option)]
pilot_nickname: Option<String>,
/// an optional height
#[argh(option, default = "default_height()")]
height: usize,
/// an optional direction which is "up" by default
#[argh(option, default = "String::from(\"only up\")")]
direction: String,
}
fn main() {
let up: GoUp = argh::from_env();
}
Custom option types can be deserialized so long as they implement the
FromArgValue
trait (automatically implemented for all FromStr
types).
If more customized parsing is required, you can supply a custom
fn(&str) -> Result<T, String>
using the from_str_fn
attribute:
#[derive(FromArgs)]
/// Goofy thing.
struct FiveStruct {
/// always five
#[argh(option, from_str_fn(always_five))]
five: usize,
}
fn always_five(_value: &str) -> Result<usize, String> {
Ok(5)
}
Positional arguments can be declared using #[argh(positional)]
.
These arguments will be parsed in order of their declaration in
the structure:
use argh::FromArgs;
#[derive(FromArgs, PartialEq, Debug)]
/// A command with positional arguments.
struct WithPositional {
#[argh(positional)]
first: String,
}
The last positional argument may include a default, or be wrapped in
Option
or Vec
to indicate an optional or repeating positional argument.
Subcommands are also supported. To use a subcommand, declare a separate
FromArgs
type for each subcommand as well as an enum that cases
over each command:
#[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
struct TopLevel {
#[argh(subcommand)]
nested: MySubCommandEnum,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum MySubCommandEnum {
One(SubCommandOne),
Two(SubCommandTwo),
}
#[derive(FromArgs, PartialEq, Debug)]
/// First subcommand.
#[argh(subcommand, name = "one")]
struct SubCommandOne {
#[argh(option)]
/// how many x
x: usize,
}
#[derive(FromArgs, PartialEq, Debug)]
/// Second subcommand.
#[argh(subcommand, name = "two")]
struct SubCommandTwo {
#[argh(switch)]
/// whether to fooey
fooey: bool,
}
You can also discover subcommands dynamically at runtime. To do this,
declare subcommands as usual and add a variant to the enum with the
dynamic
attribute. Instead of deriving FromArgs
, the value inside the
dynamic variant should implement DynamicSubCommand
.
#[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
struct TopLevel {
#[argh(subcommand)]
nested: MySubCommandEnum,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum MySubCommandEnum {
Normal(NormalSubCommand),
#[argh(dynamic)]
Dynamic(Dynamic),
}
#[derive(FromArgs, PartialEq, Debug)]
/// Normal subcommand.
#[argh(subcommand, name = "normal")]
struct NormalSubCommand {
#[argh(option)]
/// how many x
x: usize,
}
/// Dynamic subcommand.
#[derive(PartialEq, Debug)]
struct Dynamic {
name: String
}
impl DynamicSubCommand for Dynamic {
fn commands() -> &'static [&'static CommandInfo] {
static RET: OnceCell<Vec<&'static CommandInfo>> = OnceCell::new();
RET.get_or_init(|| {
let mut commands = Vec::new();
// argh needs the `CommandInfo` structs we generate to be valid
// for the static lifetime. We can allocate the structures on
// the heap with `Box::new` and use `Box::leak` to get a static
// reference to them. We could also just use a constant
// reference, but only because this is a synthetic example; the
// point of using dynamic commands is to have commands you
// don't know about until runtime!
commands.push(&*Box::leak(Box::new(CommandInfo {
name: "dynamic_command",
description: "A dynamic command",
})));
commands
})
}
fn try_redact_arg_values(
command_name: &[&str],
args: &[&str],
) -> Option<Result<Vec<String>, EarlyExit>> {
for command in Self::commands() {
if command_name.last() == Some(&command.name) {
// Process arguments and redact values here.
if !args.is_empty() {
return Some(Err("Our example dynamic command never takes arguments!"
.to_string().into()));
}
return Some(Ok(Vec::new()))
}
}
None
}
fn try_from_args(command_name: &[&str], args: &[&str]) -> Option<Result<Self, EarlyExit>> {
for command in Self::commands() {
if command_name.last() == Some(&command.name) {
if !args.is_empty() {
return Some(Err("Our example dynamic command never takes arguments!"
.to_string().into()));
}
return Some(Ok(Dynamic { name: command.name.to_string() }))
}
}
None
}
}
Structs
Information to display to the user about why a FromArgs
construction exited early.
Traits
Trait implemented by values returned from a dynamic subcommand handler.
A type which can be the receiver of a Flag
.
Types which can be constructed from a single commandline value.
Types which can be constructed from a set of commandline arguments.
A FromArgs
implementation that represents a single subcommand.
A FromArgs
implementation that can parse into one or more subcommands.
A top-level FromArgs
implementation that is not a subcommand.
Functions
Create a FromArgs
type from the current process’s env::args
.
Create a FromArgs
type from the current process’s env::args
.
Type Definitions
Information about a particular command used for output.
Derive Macros
Entrypoint for #[derive(FromArgs)]
.