1use crate::ui::formatter::FormatGenerator;
2
3use super::Argument;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct CmderOption<'op> {
7 pub short: &'op str,
8 pub long: &'op str,
9 pub arguments: Vec<Argument>,
10 pub description: &'op str,
11 pub required: bool,
12 pub name: &'op str,
13}
14
15impl<'b> CmderOption<'b> {
16 pub fn new(name: &'b str) -> Self {
17 Self {
18 short: "",
19 name,
20 arguments: vec![],
21 description: "",
22 long: "",
23 required: false,
24 }
25 }
26
27 pub fn short(mut self, val: &'b str) -> Self {
28 self.short = val;
29 self
30 }
31
32 pub fn long(mut self, val: &'b str) -> Self {
33 self.long = val;
34 self
35 }
36
37 pub fn help(mut self, val: &'b str) -> Self {
38 self.description = val;
39 self
40 }
41
42 pub fn is_required(mut self, v: bool) -> Self {
43 self.required = v;
44 self
45 }
46
47 pub fn argument(mut self, val: &'b str) -> Self {
48 self.arguments.push(Argument::generate(val, None));
49 self
50 }
51
52 pub fn add_argument(mut self, a: Argument) -> Self {
53 self.arguments.push(a);
54 self
55 }
56
57 pub(crate) fn generate(short: &'b str, long: &'b str, desc: &'b str, args: &[&str]) -> Self {
58 let mut arguments = vec![];
59 for a in args.iter() {
60 arguments.push(Argument::generate(a, None))
61 }
62
63 Self {
64 short,
65 long,
66 description: desc,
67 arguments,
68 required: false,
69 name: "",
70 }
71 }
72}
73
74impl<'d> Default for CmderOption<'d> {
75 fn default() -> Self {
76 Self::generate("", "", "", &[])
77 }
78}
79
80pub(crate) fn resolve_option<'o>(list: &'o [CmderOption], val: String) -> Option<CmderOption<'o>> {
81 let mut flag = None;
82
83 let val = val.as_str();
84 for f in list {
85 if f.short == val || f.long == val {
86 flag = Some(f.clone());
87 }
88 }
89 flag
90}
91
92impl<'f> FormatGenerator for CmderOption<'f> {
93 fn generate(&self, ptrn: crate::ui::formatter::Pattern) -> (String, String) {
94 use crate::ui::formatter::Pattern;
95 match &ptrn {
96 Pattern::Custom(ptrn) => {
97 let base = &ptrn.flags_fmter;
98
99 let mut floating = String::from("");
100 let mut leading = base
101 .replace("{{short}}", self.short)
102 .replace("{{long}}", self.long);
103
104 if base.contains("{{args}}") && !self.arguments.is_empty() {
105 let mut value = String::new();
106
107 for a in &self.arguments {
108 value.push_str(&(a.literal));
109 value.push(' ');
110 }
111
112 leading = leading.replace("{{args}}", value.trim());
113 }
114
115 if base.contains("{{description}}") {
116 leading = leading.replace("{{description}}", self.description);
117 } else {
118 floating = self.description.into()
119 }
120
121 (leading, floating)
122 }
123 _ => {
124 let short: String = if !self.short.is_empty() {
125 format!("{},", self.short)
126 } else {
127 " ".into()
128 };
129
130 let args = if !self.arguments.is_empty() {
131 let mut raw = String::new();
132
133 for a in &self.arguments {
134 raw.push_str(&(a.literal));
135 raw.push(' ');
136 }
137
138 raw
139 } else {
140 "".into()
141 };
142
143 (
144 format!("{} {} {}", short, self.long, args),
145 self.description.into(),
146 )
147 }
148 }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154
155 use super::*;
156
157 #[test]
158 fn test_options_creation() {
159 let o = CmderOption::generate("-p", "--port", "Port flag", &[]);
160
161 assert_eq!(o.short, "-p");
162 assert_eq!(o.long, "--port");
163 assert_eq!(o.description, "Port flag");
164 assert_eq!(o.required, false);
165 assert_eq!(o.arguments, vec![]);
166 }
167}