Skip to main content

noargs/
lib.rs

1//! Imperative command-line argument parser library with no dependencies, no macros, and no implicit I/O.
2//!
3//! # Features
4//!
5//! - Supports the following argument types:
6//!   - Positional arguments ([`Arg`])
7//!   - Named arguments with values ([`Opt`])
8//!   - Named arguments without values ([`Flag`])
9//!   - Subcommands ([`Cmd`])
10//! - Automatically generates help text
11//! - Simple and minimal interface due to its imperative nature (no complex DSL)
12//!
13//! # Examples
14//!
15//! The following code demonstrates the basic usage of `noargs`:
16//! ```
17//! fn main() -> noargs::Result<()> {
18//!     // Create `noargs::RawArgs` having the result of `std::env::args()`.
19//!     let mut args = noargs::raw_args();
20//!
21//!     // Set metadata for help
22//!     args.metadata_mut().app_name = env!("CARGO_PKG_NAME");
23//!     args.metadata_mut().app_description = env!("CARGO_PKG_DESCRIPTION");
24//!
25//!     // Handle well-known flags
26//!     if noargs::VERSION_FLAG.take(&mut args).is_present() {
27//!         println!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
28//!         return Ok(());
29//!     }
30//!     noargs::HELP_FLAG.take_help(&mut args);
31//!
32//!     // Handle application specific args
33//!     let foo: usize = noargs::opt("foo")
34//!         .default("1").take(&mut args).then(|o| o.value().parse())?;
35//!     let bar: bool = noargs::flag("bar")
36//!         .take(&mut args).is_present();
37//!     let baz: Option<String> = noargs::arg("[BAZ]")
38//!         .take(&mut args).present_and_then(|a| a.value().parse())?;
39//!
40//!     // Check unexpected args and build help text if need
41//!     if let Some(help) = args.finish()? {
42//!         print!("{help}");
43//!         return Ok(());
44//!     }
45//!
46//!     // Do application logic
47//!
48//!     Ok(())
49//! }
50//! ```
51//!
52//! For a fuller no-subcommand example (with common pitfalls), see `examples/basics.rs`.
53//! For repeated options / positional arrays, see `examples/arrays.rs`.
54//!
55//! The following example shows how to handle subcommands.
56//! For a fuller command-routing pattern, see `examples/subcommands.rs`.
57//! ```
58//! fn main() -> noargs::Result<()> {
59//!     let mut args = noargs::raw_args();
60//!     args.metadata_mut().app_name = env!("CARGO_PKG_NAME");
61//!     args.metadata_mut().app_description = env!("CARGO_PKG_DESCRIPTION");
62//!
63//!     // Handle well-known flags
64//!     if noargs::VERSION_FLAG.take(&mut args).is_present() {
65//!         println!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
66//!         return Ok(());
67//!     }
68//!     noargs::HELP_FLAG.take_help(&mut args);
69//!     # args.metadata_mut().help_mode = true;
70//!
71//!     // Handle subcommands
72//!     if noargs::cmd("start")
73//!         .doc("Start the service")
74//!         .take(&mut args)
75//!         .is_present()
76//!     {
77//!         let port: u16 = noargs::opt("port")
78//!             .short('p')
79//!             .default("8080")
80//!             .take(&mut args)
81//!             .then(|o| o.value().parse())?;
82//!
83//!         println!("Starting service on port {}", port);
84//!     } else if noargs::cmd("stop")
85//!         .doc("Stop the service")
86//!         .take(&mut args)
87//!         .is_present()
88//!     {
89//!         println!("Stopping service");
90//!     } else if let Some(help) = args.finish()? {
91//!         print!("{help}");
92//!     }
93//!
94//!     Ok(())
95//! }
96//! ```
97#![warn(missing_docs)]
98mod arg;
99mod args;
100mod cmd;
101mod error;
102mod flag;
103mod formatter;
104mod help;
105mod opt;
106
107pub use self::arg::{Arg, ArgSpec};
108pub use self::args::{Metadata, RawArgs};
109pub use self::cmd::{Cmd, CmdSpec};
110pub use self::error::Error;
111pub use self::flag::{Flag, FlagSpec};
112pub use self::opt::{Opt, OptSpec};
113
114/// A specialized [`std::result::Result`] type for the [`Error`] type.
115pub type Result<T> = std::result::Result<T, Error>;
116
117/// Makes an [`RawArgs`] instance initialized with command-line arguments.
118///
119/// This is a shorthand for `RawArgs::new(std::env::args())`.
120pub fn raw_args() -> RawArgs {
121    RawArgs::new(std::env::args())
122}
123
124/// Makes an [`ArgSpec`] instance with a specified name.
125///
126/// # Recommended Naming Convention
127///
128/// - Required: `<NAME>`
129/// - Optional: `[NAME]`
130/// - Zero or more: `[NAME]...`
131/// - One or more: `<NAME>...`
132pub const fn arg(name: &'static str) -> ArgSpec {
133    ArgSpec::new(name)
134}
135
136/// Makes an [`OptSpec`] instance with a specified name.
137pub const fn opt(name: &'static str) -> OptSpec {
138    OptSpec::new(name)
139}
140
141/// Makes a [`FlagSpec`] instance with a specified name.
142pub const fn flag(name: &'static str) -> FlagSpec {
143    FlagSpec::new(name)
144}
145
146/// Makes a [`CmdSpec`] instance with a specified name.
147pub const fn cmd(name: &'static str) -> CmdSpec {
148    CmdSpec::new(name)
149}
150
151/// Well-known flag (`--help, -h`) for printing help information.
152pub const HELP_FLAG: FlagSpec = flag("help")
153    .short('h')
154    .doc("Print help ('--help' for full help, '-h' for summary)");
155
156/// Well-known flag (`--version`) for printing version information.
157pub const VERSION_FLAG: FlagSpec = flag("version").doc("Print version");