cmder/parse/
options.rs

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}