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
//! Arg is simple command line argument parser, without any dependencies //! //! # Syntax //! //! ## Fields //! //! ### Arg //! //! - `short` - Specifies that it is flag with short switch. Optionally can be supplied with flag. //! - `long` - Specifies that it is flag with long switch. Optionally can be supplied with flag. //! - `default_value` - Specifies default value to use. Can be supplied with initialization expression as string. Otherwise uses Default trait. //! - `required` - Specifies whether argument is required. By default all arguments are optional. But booleans cannot be marked as `required` //! //! ### Types //! //! - Flag - is `bool` switch, automatically selected when `bool` is type of argument. Each time flag is supplied it results in `!previous_state` //! - Option - switch that accepts value. Used for any non-Vec type. Automatically overrides. //! - Multi Option - switch with `Vec<T>` type, which allows to accumulate multiple values of switch. //! - Argument - Plain argument that takes value. //! - Multi argument - Collection of arguments that accumulates into `Vec<T>`, there can be only one. //! //! ### Conversion //! //! By default all types, aside from `bool` flags use `FromStr::from_str` to parse value from string. //! //! ### Optional //! //! If type is `Option<T>` then argument is assumed to be optional, in which case it cannot be //! marked with `required` or `default_value` //! //! As result, not providing argument shall not fail parser. //! //! # Usage //! //! ```rust //! use arg::Args; //! //! #[derive(Args, Debug)] //! ///my_exe 0.1.0 //! ///About my program //! /// //! ///About my program //! struct MyArgs { //! #[arg(short, long)] //! ///About this flag //! flag: bool, //! //! #[arg(long = "verbose")] //! ///Verbose mode //! verbose: Option<bool>, //! //! #[arg(short = "v", long = "velocity", default_value = "42")] //! ///This is felocity. Default value is 42. //! speed: u32, //! //! #[arg(short = "g", long = "gps")] //! ///GPS coordinates. //! gps: Vec<u32>, //! //! ///To store path //! path: String, //! //! ///To store path 2 //! path2: String, //! //! ///To store rest of paths //! remain_paths: Vec<String>, //! } //! //! fn main() { //! match MyArgs::from_text("-v path1 path2") { //! Ok(args) => println!("args={:?}", args), //! Err(err) => println!("err={:?}", err), //! } //! } //! ``` //! #![no_std] #![warn(missing_docs)] #![cfg_attr(feature = "cargo-clippy", allow(clippy::style))] pub use arg_derive::*; mod split; pub use split::Split; use core::fmt; #[derive(PartialEq, Eq, Debug)] ///Parse errors pub enum ParseError<'a> { ///User requested help. HelpRequested, ///Too many arguments are specified. TooManyArgs, ///Argument is required, but missing /// ///Contains name of argument RequiredArgMissing(&'a str), ///Flag is specified, but value is missing. /// ///Contains full flag name. MissingValue(&'a str), ///Flag is specified with invalid value /// ///Contains full flag name and provided value. InvalidFlagValue(&'a str, &'a str), ///Argument is supplied with invalid vlaue /// ///Contains argument name and provided value. InvalidArgValue(&'a str, &'a str), ///Unknown flag is specified. UnknownFlag(&'a str) } impl<'a> ParseError<'a> { ///Returns whether help is requested pub fn is_help(&self) -> bool { match self { ParseError::HelpRequested => true, _ => false, } } } impl<'a> fmt::Display for ParseError<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParseError::HelpRequested => Ok(()), ParseError::TooManyArgs => write!(f, "Too many arguments are provided"), ParseError::RequiredArgMissing(arg) => write!(f, "Argument '{}' is required, but not provided", arg), ParseError::MissingValue(arg) => write!(f, "Flag '{}' is provided without value", arg), ParseError::InvalidFlagValue(arg, value) => write!(f, "Flag '{}' is provided with '{}' which is invalid", arg, value), ParseError::InvalidArgValue(arg, value) => write!(f, "Argument '{}' is provided with '{}' which is invalid", arg, value), ParseError::UnknownFlag(flag) => write!(f, "Unknown flag '{}' is provided", flag), } } } ///Describers command line argument parser pub trait Args: Sized { ///Help message for parser. const HELP: &'static str; ///Parses arguments from iterator of strings fn from_args<'a, T: IntoIterator<Item = &'a str>>(args: T) -> Result<Self, ParseError<'a>>; ///Parses arguments from string, which gets tokenized and passed to from. fn from_text<'a>(text: &'a str) -> Result<Self, ParseError<'a>> { Self::from_args(Split::from_str(text)) } }