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
use std::fmt::{Display, Formatter, Result}; #[derive(Debug, Clone)] pub struct Argument { pub name: Option<String>, pub default: Option<String>, pub value: Option<String>, pub arg_type: Option<String>, pub help: Option<String>, argument_type: ArgumentType, } #[derive(Debug, Clone)] enum ArgumentType { FunctionDefinition, FunctionCall { bare: bool, }, } #[cfg(test)] mod tests { mod definition { use Argument; #[test] fn it_prints_an_argument_with_no_default() { let arg = Argument::new("test", None, None, None); assert_eq!("test", format!("{}", arg)); } #[test] fn it_prints_an_argument_with_a_default() { let arg = Argument::new("test", Some(r#""value""#), None, None); assert_eq!(r#"test="value""#, format!("{}", arg)); } } mod bare_argument { use Argument; #[test] fn it_prints_an_argument() { let arg = Argument::bare("world"); assert_eq!("\"world\"", format!("{}", arg)); } } mod function_argument { use Argument; #[test] fn it_prints_an_argument() { let arg = Argument::input("name"); assert_eq!("name", format!("{}", arg)); } } } impl Argument { pub fn new<T: Display>(name: T, default: Option<T>, arg_type: Option<T>, help: Option<T>) -> Argument { Argument { name: Some(name.to_string()), default: default.map(|s| s.to_string()), value: None, arg_type: arg_type.map(|s| s.to_string()), help: help.map(|s| s.to_string()), argument_type: ArgumentType::FunctionDefinition, } } pub fn bare<T: Display>(value: T) -> Argument { Argument { name: None, default: None, value: Some(value.to_string()), arg_type: None, help: None, argument_type: ArgumentType::FunctionCall { bare: true }, } } pub fn input<T: Display>(name: T) -> Argument { Argument { name: Some(name.to_string()), default: None, value: None, arg_type: None, help: None, argument_type: ArgumentType::FunctionCall { bare: false }, } } pub fn has_help(&self) -> bool { self.help.is_some() } pub fn help_string(&self) -> String { if let Some(ref name) = self.name { let mut help = format!(":param {}:", name); if let Some(ref t) = self.arg_type { help.push_str(&format!(" {}", t)[..]); } if let Some(ref help_str) = self.help { help.push_str(&format!(" {}", help_str)[..]); } help } else { String::new() } } } impl Display for Argument { fn fmt(&self, f: &mut Formatter) -> Result { let mut output = String::new(); match self.argument_type { ArgumentType::FunctionDefinition => { if let Some(ref name) = self.name { output.push_str(&name[..]); } else { panic!("You must provide a name for a function definition's argument") } if let Some(ref default) = self.default { output.push_str(&format!("={}", default)[..]); } } ArgumentType::FunctionCall { bare: true } => { if let Some(ref value) = self.value { output.push_str(&format!("\"{}\"", value)[..]); } else { panic!("You must provide a value for a bare argument") } } ArgumentType::FunctionCall { bare: false } => { if let Some(ref name) = self.name { output.push_str(&format!("{}", name)[..]); } else { panic!("You must provide a name for a function call") } } } write!(f, "{}", output) } } #[derive(Debug, Clone)] pub struct KeywordArgument { pub keyword: String, pub argument: String, } impl KeywordArgument { pub fn new<T: Display>(name: T, arg: T) -> KeywordArgument { KeywordArgument { keyword: name.to_string(), argument: arg.to_string(), } } } impl Display for KeywordArgument { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{}={}", self.keyword, self.argument) } }