docopt/
lib.rs

1//! Docopt for Rust. This implementation conforms to the
2//! [official description of Docopt](http://docopt.org/) and
3//! [passes its test suite](https://github.com/docopt/docopt/pull/201).
4//!
5//! This library is [on GitHub](https://github.com/docopt/docopt.rs).
6//!
7//! Fundamentally, Docopt is a command line argument parser. The detail that
8//! distinguishes it from most parsers is that the parser is derived from the
9//! usage string. Here's a simple example:
10//!
11//! ```rust
12//! use docopt::Docopt;
13//!
14//! // Write the Docopt usage string.
15//! const USAGE: &'static str = "
16//! Usage: cp [-a] <source> <dest>
17//!        cp [-a] <source>... <dir>
18//!
19//! Options:
20//!     -a, --archive  Copy everything.
21//! ";
22//!
23//! // The argv. Normally you'd just use `parse` which will automatically
24//! // use `std::env::args()`.
25//! let argv = || vec!["cp", "-a", "file1", "file2", "dest/"];
26//!
27//! // Parse argv and exit the program with an error message if it fails.
28//! let args = Docopt::new(USAGE)
29//!                   .and_then(|d| d.argv(argv().into_iter()).parse())
30//!                   .unwrap_or_else(|e| e.exit());
31//!
32//! // Now access your argv values. Synonyms work just fine!
33//! assert!(args.get_bool("-a") && args.get_bool("--archive"));
34//! assert_eq!(args.get_vec("<source>"), vec!["file1", "file2"]);
35//! assert_eq!(args.get_str("<dir>"), "dest/");
36//! assert_eq!(args.get_str("<dest>"), "");
37//! ```
38//!
39//! # Type based decoding
40//!
41//! Often, command line values aren't just strings or booleans---sometimes
42//! they are integers, or enums, or something more elaborate. Using the
43//! standard Docopt interface can be inconvenient for this purpose, because
44//! you'll need to convert all of the values explicitly. Instead, this crate
45//! provides a `Decoder` that converts an `ArgvMap` to your custom struct.
46//! Here is the same example as above using type based decoding:
47//!
48//! ```rust
49//! # fn main() {
50//! use docopt::Docopt;
51//! use serde::Deserialize;
52//!
53//! // Write the Docopt usage string.
54//! const USAGE: &'static str = "
55//! Usage: cp [-a] <source> <dest>
56//!        cp [-a] <source>... <dir>
57//!
58//! Options:
59//!     -a, --archive  Copy everything.
60//! ";
61//!
62//! #[derive(Deserialize)]
63//! struct Args {
64//!     arg_source: Vec<String>,
65//!     arg_dest: String,
66//!     arg_dir: String,
67//!     flag_archive: bool,
68//! }
69//!
70//! let argv = || vec!["cp", "-a", "file1", "file2", "dest/"];
71//! let args: Args = Docopt::new(USAGE)
72//!     .and_then(|d| d.argv(argv().into_iter()).deserialize())
73//!     .unwrap_or_else(|e| e.exit());
74//!
75//! // Now access your argv values.
76//! fn s(x: &str) -> String { x.to_string() }
77//! assert!(args.flag_archive);
78//! assert_eq!(args.arg_source, vec![s("file1"), s("file2")]);
79//! assert_eq!(args.arg_dir, s("dest/"));
80//! assert_eq!(args.arg_dest, s(""));
81//! # }
82//! ```
83//!
84//! # Command line arguments for `rustc`
85//!
86//! Here's an example with a subset of `rustc`'s command line arguments that
87//! shows more of Docopt and some of the benefits of type based decoding.
88//!
89//! ```rust
90//! # fn main() {
91//! # #![allow(non_snake_case)]
92//! use std::fmt;
93//!
94//! use serde::Deserialize;
95//!
96//! use docopt::Docopt;
97//!
98//! // Write the Docopt usage string.
99//! const USAGE: &'static str = "
100//! Usage: rustc [options] [--cfg SPEC... -L PATH...] INPUT
101//!        rustc (--help | --version)
102//!
103//! Options:
104//!     -h, --help         Show this message.
105//!     --version          Show the version of rustc.
106//!     --cfg SPEC         Configure the compilation environment.
107//!     -L PATH            Add a directory to the library search path.
108//!     --emit TYPE        Configure the output that rustc will produce.
109//!                        Valid values: asm, ir, bc, obj, link.
110//!     --opt-level LEVEL  Optimize with possible levels 0-3.
111//! ";
112//!
113//! #[derive(Deserialize)]
114//! struct Args {
115//!     arg_INPUT: String,
116//!     flag_emit: Option<Emit>,
117//!     flag_opt_level: Option<OptLevel>,
118//!     flag_cfg: Vec<String>,
119//!     flag_L: Vec<String>,
120//!     flag_help: bool,
121//!     flag_version: bool,
122//! }
123//!
124//! // This is easy. The decoder will automatically restrict values to
125//! // strings that match one of the enum variants.
126//! #[derive(Deserialize)]
127//! # #[derive(Debug, PartialEq)]
128//! enum Emit { Asm, Ir, Bc, Obj, Link }
129//!
130//! // This one is harder because we want the user to specify an integer,
131//! // but restrict it to a specific range. So we implement `Deserialize`
132//! // ourselves.
133//! # #[derive(Debug, PartialEq)]
134//! enum OptLevel { Zero, One, Two, Three }
135//! struct OptLevelVisitor;
136//!
137//! impl<'de> serde::de::Visitor<'de> for OptLevelVisitor {
138//!     type Value = OptLevel;
139//!
140//!     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
141//!         formatter.write_str("a number from range 0..3")
142//!     }
143//!
144//!     fn visit_u8<E>(self, n: u8) -> Result<Self::Value, E>
145//!         where E: serde::de::Error
146//!     {
147//!         Ok(match n {
148//!             0 => OptLevel::Zero, 1 => OptLevel::One,
149//!             2 => OptLevel::Two, 3 => OptLevel::Three,
150//!             n => {
151//!                 let err = format!(
152//!                     "Could not deserialize '{}' as opt-level.", n);
153//!                 return Err(E::custom(err));
154//!             }
155//!         })
156//!     }
157//! }
158//!
159//! impl<'de> serde::de::Deserialize<'de> for OptLevel {
160//!     fn deserialize<D>(d: D) -> Result<OptLevel, D::Error>
161//!         where D: serde::de::Deserializer<'de>
162//!     {
163//!         d.deserialize_u8(OptLevelVisitor)
164//!     }
165//! }
166//!
167//! let argv = || vec!["rustc", "-L", ".", "-L", "..", "--cfg", "a",
168//!                             "--opt-level", "2", "--emit=ir", "docopt.rs"];
169//! let args: Args = Docopt::new(USAGE)
170//!                         .and_then(|d| d.argv(argv().into_iter()).deserialize())
171//!                         .unwrap_or_else(|e| e.exit());
172//!
173//! // Now access your argv values.
174//! fn s(x: &str) -> String { x.to_string() }
175//! assert_eq!(args.arg_INPUT, "docopt.rs".to_string());
176//! assert_eq!(args.flag_L, vec![s("."), s("..")]);
177//! assert_eq!(args.flag_cfg, vec![s("a")]);
178//! assert_eq!(args.flag_opt_level, Some(OptLevel::Two));
179//! assert_eq!(args.flag_emit, Some(Emit::Ir));
180//! # }
181//! ```
182
183#![crate_name = "docopt"]
184#![doc(html_root_url = "http://burntsushi.net/rustdoc/docopt")]
185#![deny(missing_docs)]
186
187pub use crate::dopt::{ArgvMap, Deserializer, Docopt, Error, Value};
188
189macro_rules! werr(
190    ($($arg:tt)*) => ({
191        use std::io::{Write, stderr};
192        write!(&mut stderr(), $($arg)*).unwrap();
193    })
194);
195
196macro_rules! regex(
197    ($s:expr) => (regex::Regex::new($s).unwrap());
198);
199
200fn cap_or_empty<'t>(caps: &regex::Captures<'t>, name: &str) -> &'t str {
201    caps.name(name).map_or("", |m| m.as_str())
202}
203
204mod dopt;
205#[doc(hidden)]
206pub mod parse;
207mod synonym;
208#[cfg(test)]
209mod test;