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