1use crate::ui::formatter::FormatGenerator;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct Argument {
5 pub name: String,
7
8 pub required: bool,
10
11 pub literal: String,
13
14 pub description: Option<String>,
16
17 pub variadic: bool,
19}
20
21impl Argument {
22 pub fn new(val: &str) -> Self {
23 Self {
24 name: val.into(),
25 required: false,
26 description: None,
27 literal: "".into(),
28 variadic: false,
29 }
30 }
31
32 pub fn generate(value: &str, description: Option<String>) -> Self {
34 let (name, required, variadic) = clean_arg(value.trim());
35
36 Self {
37 name,
38 required,
39 literal: value.to_string(),
40 description,
41 variadic,
42 }
43 }
44
45 pub fn help(mut self, val: &str) -> Self {
46 self.description = Some(val.into());
47 self
48 }
49
50 pub fn is_variadic(mut self, val: bool) -> Self {
51 self.variadic = val;
52 self
53 }
54
55 pub fn is_required(mut self, val: bool) -> Self {
56 self.required = val;
57 self
58 }
59}
60
61fn clean_arg(val: &str) -> (String, bool, bool) {
63 let delimiters;
64
65 let required = if val.starts_with('<') {
66 delimiters = vec!['<', '>'];
67 true
68 } else {
69 delimiters = vec!['[', ']'];
70 false
71 };
72
73 let mut name = val
74 .replace(delimiters[0], "")
75 .replace(delimiters[1], "")
76 .replace('-', "_");
77
78 let variadic = if name.ends_with("...") {
79 name = name.replace("...", "");
80 true
81 } else {
82 false
83 };
84
85 (name, required, variadic)
86}
87
88impl FormatGenerator for Argument {
89 fn generate(&self, ptrn: crate::ui::formatter::Pattern) -> (String, String) {
90 use crate::ui::formatter::Pattern;
91 match &ptrn {
92 Pattern::Custom(ptrn) => {
93 let base = &ptrn.args_fmter;
94
95 let mut floating = String::from("");
96 let mut leading = base
97 .replace("{{name}}", &self.name)
98 .replace("{{literal}}", &self.literal);
99
100 if base.contains("{{description}}") {
101 leading =
102 leading.replace("{{description}}", &self.description.clone().unwrap());
103 } else {
104 floating = self.description.clone().unwrap()
105 }
106
107 (leading, floating)
108 }
109 _ => (self.literal.clone(), self.description.clone().unwrap()),
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_arg_creation() {
120 let a = Argument::generate("<test-app>", Some("Dummy help str".into()));
121
122 assert!(a.required);
123 assert!(!a.variadic);
124 assert_eq!(a.name, "test_app");
125 assert_eq!(a.description, Some("Dummy help str".into()));
126 }
127}