1#[allow(deprecated)]
2use super::{GenBuffer, MetaType, OptStr, SrcHelpFlags, SrcHelpFlags0};
3use std::cmp::Ordering;
4
5#[allow(clippy::unnecessary_wraps)]
6#[allow(deprecated, dead_code)]
7#[deprecated(
8 since = "0.1.10",
9 note = "Please use the do_gen_src<F>() function instead"
10)]
11pub fn gen_src_help(
12 vec_optstr: &[OptStr],
13 vec_line: &[String],
14 out_flags: SrcHelpFlags,
15) -> anyhow::Result<String> {
16 Ok(gen_src_help0(vec_optstr, vec_line, out_flags.into()))
17}
18
19pub(crate) fn gen_src_help0(
20 vec_optstr: &[OptStr],
21 vec_line: &[String],
22 out_flags: SrcHelpFlags0,
23) -> String {
24 let mut sss = GenBuffer::with_capacity(4 * 1024);
25 sss.push_str_ary(&[
27 r#"// WARN: This file is auto generated by "#,
28 env!("CARGO_PKG_NAME"),
29 "\n",
30 ]);
31 if !out_flags.options_text {
33 sss += "/*\n";
34 }
35 sss += "const OPTIONS_TEXT: &str = r\"";
36 for line in vec_line {
37 sss.push_str_ary(&[line, "\n"]);
38 }
39 sss += "\";\n";
40 if !out_flags.options_text {
41 sss += "*/\n";
42 }
43 if !out_flags.cmd_op {
45 sss += "/*\n";
46 }
47 gen_src_cmd_opt(&mut sss, vec_optstr);
48 if !out_flags.cmd_op {
49 sss += "*/\n";
50 }
51 let vec_optstr_sorted = {
53 let mut target: Vec<&OptStr> = vec_optstr.iter().collect();
54 target.sort_by(|&a, &b| match a.lon.cmp(&b.lon) {
55 Ordering::Less => Ordering::Less,
56 Ordering::Greater => Ordering::Greater,
57 Ordering::Equal => match a.sho.cmp(&b.sho) {
58 Ordering::Less => Ordering::Less,
59 Ordering::Greater => Ordering::Greater,
60 Ordering::Equal => a.num.cmp(&b.num),
61 },
62 });
63 target
64 };
65 if !out_flags.opt_ary {
67 sss += "/*\n";
68 }
69 gen_src_opt_ary(&mut sss, &vec_optstr_sorted);
70 if !out_flags.opt_ary {
71 sss += "*/\n";
72 }
73 if !out_flags.opt_ary_sho_idx {
75 sss += "/*\n";
76 }
77 gen_src_opt_ary_sho_idx(&mut sss, &vec_optstr_sorted);
78 if !out_flags.opt_ary_sho_idx {
79 sss += "*/\n";
80 }
81 if !out_flags.cmd_opt_conf {
83 sss += "/*\n";
84 }
85 gen_src_struct_cmd_opt_conf(&mut sss, vec_optstr, &out_flags);
86 if !out_flags.cmd_opt_conf {
87 sss += "*/\n";
88 }
89 if !out_flags.value_to {
91 sss += "/*\n";
92 }
93 gen_src_value_to(&mut sss, vec_optstr);
94 if !out_flags.value_to {
95 sss += "*/\n";
96 }
97 sss.into_string()
99}
100
101fn gen_src_cmd_opt(sss: &mut GenBuffer, vec_optstr: &[OptStr]) {
102 *sss += r#"
103#[repr(u8)]
104#[derive(Debug, PartialEq, Eq)]
105enum CmdOp {
106"#;
107 for rec in vec_optstr.iter() {
108 sss.push_str_ary(&[" ", &rec.enum_s, ",\n"]);
109 }
110 *sss += "}\n";
111 *sss += r#"
112impl std::convert::From<u8> for CmdOp {
113 fn from(value: u8) -> Self {
114 unsafe { std::mem::transmute(value) }
115 }
116}
117impl CmdOp {
118 pub const fn to(self) -> OptNum {
119 self as OptNum
120 }
121}
122"#;
123}
124
125fn gen_src_opt_ary(sss: &mut GenBuffer, vec_optstr_sorted: &[&OptStr]) {
126 let s = r#"
127#[rustfmt::skip]
128const OPT_ARY: [Opt;"#;
129 *sss += &format!("{}{}] = [\n", s, vec_optstr_sorted.len());
130 for rec in vec_optstr_sorted.iter() {
131 *sss += " Opt { ";
132 if rec.sho.is_empty() {
133 *sss += "sho: 0u8, ";
134 } else {
135 *sss += &format!("sho: b'{}', ", rec.sho);
136 }
137 let s = "\"".to_string() + &rec.lon + "\",";
138 *sss += &format!("lon: {:-17}", s);
139 *sss += if rec.meta.is_empty() {
140 "has: Arg::No, "
141 } else {
142 "has: Arg::Yes, "
143 };
144 *sss += &format!("num: CmdOp::{}.to(), ", rec.enum_s);
145 *sss += "},\n";
146 }
147 *sss += "];\n";
148}
149
150fn gen_src_opt_ary_sho_idx(sss: &mut GenBuffer, vec_optstr_sorted: &[&OptStr]) {
151 let mut vec_optstr_sho_idx: Vec<(_, usize)> = vec_optstr_sorted
152 .iter()
153 .enumerate()
154 .filter(|(_, &o)| !o.sho.is_empty())
155 .map(|(i, &o)| (&o.sho, i))
156 .collect();
157 vec_optstr_sho_idx.sort_by(|a, b| a.0.cmp(b.0));
158 let s = r#"
160#[rustfmt::skip]
161const OPT_ARY_SHO_IDX: [(u8,usize);"#;
162 *sss += &format!("{}{}] = [\n", s, vec_optstr_sho_idx.len());
163 for elm in vec_optstr_sho_idx.iter() {
164 *sss += &format!("(b'{}',{}),", elm.0, elm.1);
165 }
166 *sss += "];\n";
167}
168
169fn gen_src_struct_cmd_opt_conf(
170 sss: &mut GenBuffer,
171 vec_optstr: &[OptStr],
172 out_flags: &SrcHelpFlags0,
173) {
174 if !out_flags.subcmd_opt_conf {
175 *sss += r#"
176#[derive(Debug, Default, PartialEq, Eq)]
177pub struct CmdOptConf {
178 pub prog_name: String,
179"#;
180 if out_flags.cmd_opt_conf_has_subcmd {
181 *sss += r#" pub subcmd: String,
182"#;
183 }
184 } else {
185 *sss += r#"
186#[derive(Debug, PartialEq, Eq)]
187pub struct SubCmdOptConf<'a> {
188 pub parent: &'a CmdOptConf,
189 pub prog_name: String,
190"#;
191 }
192 *sss += r#" //
193"#;
194 let mut have_help: bool = false;
195 let mut have_version: bool = false;
196 for rec in vec_optstr.iter() {
197 let v_type = if rec.is_vec {
198 if rec.is_opt {
199 format!("Vec<Option<{}>>", rec.meta_type.as_type_string())
200 } else {
201 format!("Vec<{}>", rec.meta_type.as_type_string())
202 }
203 } else if rec.is_opt {
204 format!("Option<{}>", rec.meta_type.as_type_string())
205 } else {
206 rec.meta_type.as_type_string().to_string()
207 };
208 *sss += &format!(" pub {}: {},\n", rec.field_s, v_type);
209 if rec.enum_s == "Help" {
210 have_help = true;
211 }
212 if rec.enum_s == "Version" {
213 have_version = true;
214 }
215 }
216 *sss += r#" //
217 pub arg_params: Vec<String>,
218}
219"#;
220 if out_flags.subcmd_opt_conf {
221 *sss += r#"
222impl<'a> SubCmdOptConf<'a> {
223 pub fn new(a_parent: &'a CmdOptConf, a_prog_name: String) -> SubCmdOptConf<'a> {
224 SubCmdOptConf {
225 parent: a_parent,
226 prog_name: a_prog_name,
227 //
228"#;
229 for rec in vec_optstr.iter() {
230 let v_init = "Default::default()".to_string();
231 *sss += &format!(" {}: {},\n", rec.field_s, v_init);
232 }
233 *sss += r#" //
234 arg_params: Vec::new(),
235 }
236 }
237}
238"#;
239 }
240 if out_flags.cmd_opt_conf_has_subcmd {
241 *sss += r#"
242impl flood_tide::SubCommand for CmdOptConf {
243 fn set_subcmd(&mut self, a_subcmd: String) {
244 self.subcmd = a_subcmd;
245 }
246}
247"#;
248 }
249 if !out_flags.subcmd_opt_conf {
250 *sss += r#"
251impl flood_tide::HelpVersion for CmdOptConf {
252 fn is_help(&self) -> bool {"#;
253 } else {
254 *sss += r#"
255impl<'a> flood_tide::HelpVersion for SubCmdOptConf<'a> {
256 fn is_help(&self) -> bool {"#;
257 }
258 if have_help {
259 *sss += r#"
260 self.flg_help"#;
261 } else {
262 *sss += r#"
263 false"#;
264 }
265 *sss += r#"
266 }
267 fn is_version(&self) -> bool {"#;
268 if have_version {
269 *sss += r#"
270 self.flg_version"#;
271 } else {
272 *sss += r#"
273 false"#;
274 }
275 *sss += r#"
276 }
277}
278"#;
279}
280
281fn gen_src_value_to(sss: &mut GenBuffer, vec_optstr: &[OptStr]) {
282 let mut vec_mt: Vec<&MetaType> = Vec::new();
283 for rec in vec_optstr.iter() {
284 let mt = &rec.meta_type;
285 if let MetaType::Bool = mt {
286 continue;
287 }
288 if !vec_mt.contains(&mt) {
289 vec_mt.push(mt);
290 }
291 }
292 #[allow(unused_assignments)]
294 let mut buf = String::new();
295 vec_mt.sort();
296 for mt in vec_mt.iter() {
297 let s = match mt {
298 MetaType::Bool => "",
299 MetaType::String => {
300 r#"
301fn value_to_string(nv: &NameVal<'_>) -> Result<String, OptParseError> {
302 match nv.val {
303 Some(x) => Ok(x.to_string()),
304 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
305 }
306}
307"#
308 }
309 MetaType::I8 => {
310 r#"
311fn value_to_i8(nv: &NameVal<'_>) -> Result<i8, OptParseError> {
312 match nv.val {
313 Some(x) => match x.parse::<i8>() {
314 Ok(d) => Ok(d),
315 Err(err) => Err(OptParseError::invalid_option_argument(
316 &nv.opt.lon_or_sho(),
317 &err.to_string(),
318 )),
319 },
320 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
321 }
322}
323"#
324 }
325 MetaType::I16 => {
326 r#"
327fn value_to_i16(nv: &NameVal<'_>) -> Result<i16, OptParseError> {
328 match nv.val {
329 Some(x) => match x.parse::<i16>() {
330 Ok(d) => Ok(d),
331 Err(err) => Err(OptParseError::invalid_option_argument(
332 &nv.opt.lon_or_sho(),
333 &err.to_string(),
334 )),
335 },
336 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
337 }
338}
339"#
340 }
341 MetaType::I32 => {
342 r#"
343fn value_to_i32(nv: &NameVal<'_>) -> Result<i32, OptParseError> {
344 match nv.val {
345 Some(x) => match x.parse::<i32>() {
346 Ok(d) => Ok(d),
347 Err(err) => Err(OptParseError::invalid_option_argument(
348 &nv.opt.lon_or_sho(),
349 &err.to_string(),
350 )),
351 },
352 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
353 }
354}
355"#
356 }
357 MetaType::I64 => {
358 r#"
359fn value_to_i64(nv: &NameVal<'_>) -> Result<i64, OptParseError> {
360 match nv.val {
361 Some(x) => match x.parse::<i64>() {
362 Ok(d) => Ok(d),
363 Err(err) => Err(OptParseError::invalid_option_argument(
364 &nv.opt.lon_or_sho(),
365 &err.to_string(),
366 )),
367 },
368 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
369 }
370}
371"#
372 }
373 MetaType::I128 => {
374 r#"
375fn value_to_i128(nv: &NameVal<'_>) -> Result<i128, OptParseError> {
376 match nv.val {
377 Some(x) => match x.parse::<i128>() {
378 Ok(d) => Ok(d),
379 Err(err) => Err(OptParseError::invalid_option_argument(
380 &nv.opt.lon_or_sho(),
381 &err.to_string(),
382 )),
383 },
384 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
385 }
386}
387"#
388 }
389 MetaType::U8 => {
390 r#"
391fn value_to_u8(nv: &NameVal<'_>) -> Result<u8, OptParseError> {
392 match nv.val {
393 Some(x) => match x.parse::<u8>() {
394 Ok(d) => Ok(d),
395 Err(err) => Err(OptParseError::invalid_option_argument(
396 &nv.opt.lon_or_sho(),
397 &err.to_string(),
398 )),
399 },
400 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
401 }
402}
403"#
404 }
405 MetaType::U16 => {
406 r#"
407fn value_to_u16(nv: &NameVal<'_>) -> Result<u16, OptParseError> {
408 match nv.val {
409 Some(x) => match x.parse::<u16>() {
410 Ok(d) => Ok(d),
411 Err(err) => Err(OptParseError::invalid_option_argument(
412 &nv.opt.lon_or_sho(),
413 &err.to_string(),
414 )),
415 },
416 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
417 }
418}
419"#
420 }
421 MetaType::U32 => {
422 r#"
423fn value_to_u32(nv: &NameVal<'_>) -> Result<u32, OptParseError> {
424 match nv.val {
425 Some(x) => match x.parse::<u32>() {
426 Ok(d) => Ok(d),
427 Err(err) => Err(OptParseError::invalid_option_argument(
428 &nv.opt.lon_or_sho(),
429 &err.to_string(),
430 )),
431 },
432 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
433 }
434}
435"#
436 }
437 MetaType::U64 => {
438 r#"
439fn value_to_u64(nv: &NameVal<'_>) -> Result<u64, OptParseError> {
440 match nv.val {
441 Some(x) => match x.parse::<u64>() {
442 Ok(d) => Ok(d),
443 Err(err) => Err(OptParseError::invalid_option_argument(
444 &nv.opt.lon_or_sho(),
445 &err.to_string(),
446 )),
447 },
448 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
449 }
450}
451"#
452 }
453 MetaType::U128 => {
454 r#"
455fn value_to_u128(nv: &NameVal<'_>) -> Result<u128, OptParseError> {
456 match nv.val {
457 Some(x) => match x.parse::<u128>() {
458 Ok(d) => Ok(d),
459 Err(err) => Err(OptParseError::invalid_option_argument(
460 &nv.opt.lon_or_sho(),
461 &err.to_string(),
462 )),
463 },
464 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
465 }
466}
467"#
468 }
469 MetaType::Isize => {
470 r#"
471fn value_to_isize(nv: &NameVal<'_>) -> Result<isize, OptParseError> {
472 match nv.val {
473 Some(x) => match x.parse::<isize>() {
474 Ok(d) => Ok(d),
475 Err(err) => Err(OptParseError::invalid_option_argument(
476 &nv.opt.lon_or_sho(),
477 &err.to_string(),
478 )),
479 },
480 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
481 }
482}
483"#
484 }
485 MetaType::Usize => {
486 r#"
487fn value_to_usize(nv: &NameVal<'_>) -> Result<usize, OptParseError> {
488 match nv.val {
489 Some(x) => match x.parse::<usize>() {
490 Ok(d) => Ok(d),
491 Err(err) => Err(OptParseError::invalid_option_argument(
492 &nv.opt.lon_or_sho(),
493 &err.to_string(),
494 )),
495 },
496 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
497 }
498}
499"#
500 }
501 MetaType::F32 => {
502 r#"
503fn value_to_f32(nv: &NameVal<'_>) -> Result<f32, OptParseError> {
504 match nv.val {
505 Some(x) => match x.parse::<f32>() {
506 Ok(d) => Ok(d),
507 Err(err) => Err(OptParseError::invalid_option_argument(
508 &nv.opt.lon_or_sho(),
509 &err.to_string(),
510 )),
511 },
512 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
513 }
514}
515"#
516 }
517 MetaType::F64 => {
518 r#"
519fn value_to_f64(nv: &NameVal<'_>) -> Result<f64, OptParseError> {
520 match nv.val {
521 Some(x) => match x.parse::<f64>() {
522 Ok(d) => Ok(d),
523 Err(err) => Err(OptParseError::invalid_option_argument(
524 &nv.opt.lon_or_sho(),
525 &err.to_string(),
526 )),
527 },
528 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
529 }
530}
531"#
532 }
533 MetaType::Path => {
534 r#"
535fn value_to_path(nv: &NameVal<'_>) -> Result<std::path::PathBuf, OptParseError> {
536 match nv.val {
537 Some(x) => Ok(std::path::PathBuf::from(x)),
538 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
539 }
540}
541"#
542 }
543 MetaType::Other(string) => {
544 buf = format!(
545 r#"
546fn value_to_{}(nv: &NameVal<'_>) -> Result<{}, OptParseError> {{
547 match nv.val {{
548 Some(s) => match FromStr::from_str(s) {{
549 Ok(x) => Ok(x),
550 Err(err) => Err(OptParseError::invalid_option_argument(
551 &nv.opt.lon_or_sho(),
552 &err.to_string(),
553 )),
554 }},
555 None => Err(OptParseError::missing_option_argument(&nv.opt.lon_or_sho())),
556 }}
557}}
558"#,
559 string,
560 mt.as_type_string(),
561 );
562 buf.as_str()
563 }
564 };
565 sss.push_str(s);
566 }
567}