Crate xflags[−][src]
This crates provides a procedural macro for parsing command line arguments.
It is intended for use in development tools, so it emphasizes fast compile times and convenience at the expense of features.
If you need something more fancy, consider using
clap
instead.
Example
mod flags { use std::path::PathBuf; xflags::xflags! { src "./examples/basic.rs" cmd my-command required path: PathBuf { optional -v, --verbose } } // generated start // The following code is generated by `xflags` macro. // Run `env UPDATE_XFLAGS=1 cargo build` to regenerate. #[derive(Debug)] pub struct MyCommand { pub path: PathBuf, pub verbose: bool, } impl MyCommand { pub const HELP: &'static str = Self::HELP_; pub fn from_env() -> xflags::Result<Self> { Self::from_env_() } pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> { Self::from_vec_(args) } } // generated end } fn main() { let flags = flags::MyCommand::from_env(); println!("{:#?}", flags); }
To make the macro less opaque, xflag
can generate struct
describing the
CLI in-place. To disable this behavior, omit the src
attribute.
xflags correctly handles non-utf8 arguments.
Syntax Reference
The cmd keyword introduces a command that accepts positional arguments and switches.
xflags::xflags! { cmd command-name { } }
Switches are specified inside the curly braces. Long names (--switch
) are
mandatory, short names (-s
) are optional. Each switch can be optional,
required, or repeated. Dashes are allowed in switch names.
xflags::xflags! { cmd switches { optional -h, --help repeated --verbose required --pass-me } }
Switches can also take values. If the value type is OsString
or PathBuf
,
it is created directly from the underlying argument. Otherwise, FromStr
is
used for parsing
use std::{path::PathBuf, ffi::OsString}; xflags::xflags! { cmd switches-with-values { optional --config path: PathBuf repeated --data val: OsString optional -j, --jobs n: u32 } }
Positional arguments are specified before the opening curly brace:
use std::{path::PathBuf, ffi::OsString}; xflags::xflags! { cmd positional-arguments required program: PathBuf repeated args: OsString { } }
Nesting cmd is allowed:
xflags::xflags! { src "./examples/subcommands.rs" cmd app { repeated -v, --verbose cmd foo { optional -s, --switch } cmd bar {} } } // generated start // The following code is generated by `xflags` macro. // Run `env UPDATE_XFLAGS=1 cargo build` to regenerate. #[derive(Debug)] pub struct App { pub verbose: u32, pub subcommand: AppCmd, } #[derive(Debug)] pub enum AppCmd { Foo(Foo), Bar(Bar), } #[derive(Debug)] pub struct Foo { pub switch: bool, } #[derive(Debug)] pub struct Bar { } impl App { pub const HELP: &'static str = Self::HELP_; pub fn from_env() -> xflags::Result<Self> { Self::from_env_() } pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> { Self::from_vec_(args) } } // generated end
To make subcommand name optional use the default keyword to mark a subcommand to select if no subcommand name is passed. The name of the default subcommand affects only the name of the generated Rust struct, it can’t be specified explicitly on the command line.
xflags::xflags! { cmd app { repeated -v, --verbose default cmd foo { optional -s, --switch } cmd bar {} } }
Commands, arguments, and switches can documented. Doc comments become a part of generated help:
mod flags { use std::path::PathBuf; xflags::xflags! { /// Run basic system diagnostics. cmd healthck /// Optional configuration file. optional config: PathBuf { /// Verbosity level, can be repeated multiple times. repeated -v, --verbose /// Print the help message. optional -h, --help } } } fn main() { match flags::Healthck::from_env() { Ok(flags) => { if flags.help { println!("{}", flags::Healthck::HELP); return; } run_checks(flags.config, flags.verbose); } Err(err) => { eprintln!("{}", err); } } }
The src keyword controlls how the code generation works. If it is
absent, xflags
acts as a typical procedure macro, which generates a bunch
of structs and impls.
If the src keyword is present, it should specify the path to the file
with xflags!
invocation. The path should be relative to the directory with
Cargo.toml. The macro then will avoid generating the structs. Instead, if
the UPDATE_XFLAGS
environmental variable is set, the macro will write them
directly to the specified file.
By convention, xflag!
macro should be invoked from the flags
submodule.
The flags::
preffix should be used to refer to command names. Additional
validation logic can go to the flags
module:
mod flags { xflags::xflags! { cmd my-command { repeated -v, --verbose optional -q, --quiet } } impl MyCommand { fn validate(&self) -> xflags::Result<()> { if self.quiet && self.verbose > 0 { return Err(xflags::Error::new( "`-q` and `-v` can't be specified at the same time" )); } Ok(()) } } }
Macros
xflags | Generates a parser for command line arguments from a DSL. |
Structs
Error | This type represents an error that can occur during command line argument parsing. |
Type Definitions
Result |