flood_tide_gen/gen/
gen_src_help.rs

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    //
26    sss.push_str_ary(&[
27        r#"// WARN: This file is auto generated by "#,
28        env!("CARGO_PKG_NAME"),
29        "\n",
30    ]);
31    //
32    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    //
44    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    //
52    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    //
66    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    //
74    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    //
82    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    //
90    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    //
98    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    //
159    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    //
293    #[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}