gitignore_template_generator/parser/api.rs
1use std::ffi::OsString;
2
3use clap::ValueEnum;
4
5use crate::core::ProgramExit;
6pub use crate::parser::impls::ClapArgsParser;
7
8#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Default)]
9pub enum TimeoutUnit {
10 MILLISECOND,
11 #[default]
12 SECOND,
13}
14
15pub enum Action {
16 List,
17 RobustGenerate,
18 Generate,
19}
20
21pub struct CliOptionName {
22 pub short: &'static str,
23 pub long: &'static str,
24}
25
26/// Struct to gather cli args parsing result.
27///
28/// Used by [`crate::parser::ArgsParser`] implementations to store
29/// parsing result.
30#[derive(Debug, PartialEq, Default)]
31pub struct Args {
32 /// A non-empty list of gitignore template names.
33 ///
34 /// * Represented by the provided positional arguments, and required
35 /// unless any of `author`, `version` or `help` options are given.
36 /// * This field does not allow commas in any of its field.
37 pub template_names: Vec<String>,
38
39 /// The gitignore template generator service url.
40 ///
41 /// * Optional value represented by the cli option
42 /// [`crate::constant::cli_options::SERVER_URL`] that takes a string
43 /// value, and falling back to
44 /// [`crate::constant::template_manager::BASE_URL`] if not provided
45 /// in cli args.
46 pub server_url: String,
47
48 /// The gitignore template generator service endpoint uri.
49 ///
50 /// * Optional value represented by the cli option
51 /// [`crate::constant::cli_options::GENERATOR_URI`] that takes a string
52 /// value, and falling back to
53 /// [`crate::constant::template_manager::GENERATOR_URI`] if not provided in cli
54 /// args.
55 pub generator_uri: String,
56
57 /// The gitignore template lister service endpoint uri.
58 ///
59 /// * Optional value represented by the cli option
60 /// [`crate::constant::cli_options::LISTER_URI`] that takes a string
61 /// value, and falling back to
62 /// [`crate::constant::template_manager::LISTER_URI`] if not provided in cli
63 /// args.
64 pub lister_uri: String,
65
66 /// The boolean indicator of whether to display help infos or not.
67 ///
68 /// * Optional value represented by the cli option
69 /// [`crate::constant::cli_options::HELP`], and falling back to `false`
70 /// if not provided in cli args.
71 /// * Has precedence over version and author options if multiple are given
72 pub show_help: bool,
73
74 /// The boolean indicator of whether to display version infos or not.
75 ///
76 /// * Optional value represented by the cli option
77 /// [`crate::constant::cli_options::VERSION`], and falling back to
78 /// `false` if not provided in cli args.
79 /// * Has precedence over author option if multiple are given
80 pub show_version: bool,
81
82 /// The boolean indicator of whether to display author infos or not.
83 ///
84 /// * Optional value represented by the cli option
85 /// [`crate::constant::cli_options::AUTHOR`], and falling back to
86 /// `false` if not provided in cli args.
87 pub show_author: bool,
88
89 /// The boolean indicator of whether to display list of available templates
90 /// or not.
91 ///
92 /// * Optional value represented by the cli option
93 /// [`crate::constant::cli_options::LIST`], and falling back to
94 /// `false` if not provided in cli args.
95 pub show_list: bool,
96
97 /// The boolean indicator of whether to enable robust template check or not.
98 ///
99 /// Robust template check allow the script to handle template existence
100 /// check without reaching the generator endpoint.
101 ///
102 /// * Optional value represented by the cli option
103 /// [`crate::constant::cli_options::CHECK`], and falling back to
104 /// `false` if not provided in cli args.
105 pub check_template_names: bool,
106
107 /// The service call timeout.
108 ///
109 /// * Optional value represented by the cli option
110 /// [`crate::constant::cli_options::TIMEOUT`], and falling back to
111 /// [`crate::constant::template_manager::TIMEOUT`] if not provided in
112 /// cli args.
113 pub timeout: u64,
114
115 /// The timeout unit.
116 ///
117 /// * Optional value represented by the cli option
118 /// [`crate::constant::cli_options::TIMEOUT_UNIT`], and falling back to
119 /// [`crate::constant::template_manager::TIMEOUT_UNIT`] if not provided in
120 /// cli args.
121 pub timeout_unit: TimeoutUnit,
122}
123
124impl Args {
125 pub fn new() -> Self {
126 Self {
127 template_names: Vec::new(),
128 server_url: crate::constant::template_manager::BASE_URL.to_string(),
129 generator_uri: crate::constant::template_manager::GENERATOR_URI.to_string(),
130 lister_uri: crate::constant::template_manager::LISTER_URI.to_string(),
131 show_help: false,
132 show_version: false,
133 show_author: false,
134 show_list: false,
135 check_template_names: false,
136 timeout: crate::constant::template_manager::TIMEOUT_INT,
137 timeout_unit: crate::constant::template_manager::TIMEOUT_UNIT_ENUM,
138 }
139 }
140
141 pub fn to_action(&self) -> Action {
142 if self.show_list {
143 Action::List
144 } else if self.check_template_names {
145 Action::RobustGenerate
146 } else {
147 Action::Generate
148 }
149 }
150
151 /// Sets new value for `template_names` field.
152 ///
153 /// It needs to be called on struct instance and effectively mutates it.
154 ///
155 /// # Arguments
156 ///
157 /// * `template_names` - The new value to be assigned to `template_names`
158 /// field.
159 ///
160 /// # Returns
161 ///
162 /// The mutated borrowed instance.
163 pub fn with_template_names(mut self, template_names: Vec<String>) -> Self {
164 self.template_names = template_names;
165 self
166 }
167
168 /// Sets new value for `server_url` field.
169 ///
170 /// It needs to be called on struct instance and effectively mutates it.
171 ///
172 /// # Arguments
173 ///
174 /// * `server_url` - The new value to be assigned to `server_url`
175 /// field.
176 ///
177 /// # Returns
178 ///
179 /// The mutated borrowed instance.
180 pub fn with_server_url(mut self, server_url: &str) -> Self {
181 self.server_url = server_url.to_string();
182 self
183 }
184
185 /// Sets new value for `generator_uri` field.
186 ///
187 /// It needs to be called on struct instance and effectively mutates it.
188 ///
189 /// # Arguments
190 ///
191 /// * `generator_uri` - The new value to be assigned to
192 /// `generator_uri` field.
193 ///
194 /// # Returns
195 ///
196 /// The mutated borrowed instance.
197 pub fn with_generator_uri(mut self, generator_uri: &str) -> Self {
198 self.generator_uri = generator_uri.to_string();
199 self
200 }
201
202 /// Sets new value for `lister_uri` field.
203 ///
204 /// It needs to be called on struct instance and effectively mutates it.
205 ///
206 /// # Arguments
207 ///
208 /// * `lister_uri` - The new value to be assigned to `lister_uri` field.
209 ///
210 /// # Returns
211 ///
212 /// The mutated borrowed instance.
213 pub fn with_lister_uri(mut self, lister_uri: &str) -> Self {
214 self.lister_uri = lister_uri.to_string();
215 self
216 }
217
218 /// Sets new value for `show_list` field.
219 ///
220 /// It needs to be called on struct instance and effectively mutates it.
221 ///
222 /// # Arguments
223 ///
224 /// * `show_list` - The new value to be assigned to `show_list`
225 /// field.
226 ///
227 /// # Returns
228 ///
229 /// The mutated borrowed instance.
230 pub fn with_show_list(mut self, show_list: bool) -> Self {
231 self.show_list = show_list;
232 self
233 }
234
235 /// Sets new value for `check_template_names` field.
236 ///
237 /// It needs to be called on struct instance and effectively mutates it.
238 ///
239 /// # Arguments
240 ///
241 /// * `check_template_names` - The new value to be assigned to
242 /// `check_template_names` field.
243 ///
244 /// # Returns
245 ///
246 /// The mutated borrowed instance.
247 pub fn with_check_template_names(mut self, check_template_names: bool) -> Self {
248 self.check_template_names = check_template_names;
249 self
250 }
251
252 /// Sets new value for `timeout` field.
253 ///
254 /// It needs to be called on struct instance and effectively mutates it.
255 ///
256 /// # Arguments
257 ///
258 /// * `timeout` - The new value to be assigned to `timeout` field.
259 ///
260 /// # Returns
261 ///
262 /// The mutated borrowed instance.
263 pub fn with_timeout(mut self, timeout: u64) -> Self {
264 self.timeout = timeout;
265 self
266 }
267
268 /// Sets new value for `timeout_unit` field.
269 ///
270 /// It needs to be called on struct instance and effectively mutates it.
271 ///
272 /// # Arguments
273 ///
274 /// * `timeout_unit` - The new value to be assigned to `timeout_unit` field.
275 ///
276 /// # Returns
277 ///
278 /// The mutated borrowed instance.
279 pub fn with_timeout_unit(mut self, timeout_unit: TimeoutUnit) -> Self {
280 self.timeout_unit = timeout_unit;
281 self
282 }
283}
284
285/// Cli args parser trait to parse CLI args and return them in an [`Args`].
286///
287/// The produced Args instance needs to comply with constraints of each
288/// one of its fields (see fields doc in [`Args`] for more infos).
289pub trait ArgsParser {
290 /// Parses given cli args and return them as an [`Args`] instance.
291 ///
292 /// * First CLI args should be the binary name
293 /// * Rely on [`ArgsParser::try_parse`] method but additionally wrap
294 /// error handling logic
295 ///
296 /// # Arguments
297 ///
298 /// * `args` - The CLI args to be parsed. Typically retrieved from
299 /// [`std::env::args_os`].
300 ///
301 /// # Returns
302 ///
303 /// An owned instance of [`Args`] containing parsing result of given args.
304 fn parse(&self, args: impl IntoIterator<Item = OsString>) -> Args;
305
306 /// Parses given cli args and return them as an [`Args`] instance if no
307 /// error or early exit occurred.
308 ///
309 /// * First CLI args should be the binary name
310 /// * Version, author and help options are considered as early program
311 /// exit
312 /// * Returned Args complies with expected constraints (see fields doc
313 /// in [`Args`] for more infos)
314 ///
315 /// # Arguments
316 ///
317 /// * `args` - The CLI args to be parsed. Typically retrieved from
318 /// [`std::env::args_os`].
319 ///
320 /// # Returns
321 ///
322 /// A result containing an owned instance of [`Args`] if successful parsing,
323 /// or a [`ProgramExit`] if any error or early exit occurred (e.g. version/
324 /// author/help infos printing, invalid cli args...)
325 fn try_parse(&self, args: impl IntoIterator<Item = OsString>) -> Result<Args, ProgramExit>;
326}