mithril_doc/
extract_clap_info.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use clap::{builder::StyledStr, Arg, Command};

use super::{FieldDoc, StructDoc};

/// Extract information of an command line argument.
fn extract_arg(arg: &Arg) -> FieldDoc {
    let parameter = arg.get_id().to_string();
    let short_option = arg.get_short().map_or("".into(), |c| format!("-{}", c));
    let long_option = arg.get_long().map_or("".into(), |c| format!("--{}", c));
    let env_variable = arg.get_env().map(|s| format!("{}", s.to_string_lossy()));
    let description = arg.get_help().map_or("-".into(), StyledStr::to_string);
    let default_value = if arg.get_default_values().iter().count() == 0 {
        None
    } else {
        Some(
            arg.get_default_values()
                .iter()
                .map(|s| format!("{}", s.to_string_lossy()))
                .collect::<Vec<String>>()
                .join(","),
        )
    };
    let example = None;

    FieldDoc {
        parameter,
        command_line_long: long_option,
        command_line_short: short_option,
        environment_variable: env_variable,
        description,
        default_value,
        example,
        is_mandatory: arg.is_required_set(),
    }
}

pub fn extract_parameters(cmd: &Command) -> StructDoc {
    StructDoc {
        data: cmd
            .get_arguments()
            .map(extract_arg)
            .collect::<Vec<FieldDoc>>(),
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use clap::{CommandFactory, Parser};

    #[derive(Parser, Debug, Clone)]
    #[command(version)]
    pub struct MyCommand {
        /// Run Mode
        #[clap(short, long, default_value = "dev")]
        run_mode: String,

        #[clap()]
        param_without_default: String,
    }

    #[test]
    fn test_extract_arg_info() {
        let command = MyCommand::command();
        let arg = command.get_arguments().next().unwrap();
        let parameter: FieldDoc = extract_arg(arg);

        assert_eq!("run_mode", parameter.parameter);
        assert_eq!("-r".to_string(), parameter.command_line_short);
        assert_eq!("--run-mode".to_string(), parameter.command_line_long);
        assert_eq!(Some("dev".to_string()), parameter.default_value);
        assert_eq!("Run Mode".to_string(), parameter.description);
        assert!(parameter.example.is_none());
        assert!(!parameter.is_mandatory);
    }

    #[test]
    fn test_extract_required_arg() {
        let command = MyCommand::command();
        let arg = command
            .get_arguments()
            .find(|arg| arg.get_id() == "param_without_default")
            .unwrap();
        let parameter: FieldDoc = extract_arg(arg);

        assert!(parameter.is_mandatory);
    }

    #[test]
    fn test_extract_command_info() {
        let command = MyCommand::command();
        let command_parameters: StructDoc = extract_parameters(&command);

        //assert_eq!(1, command_parameters.data.len());
        assert_eq!(
            "run_mode",
            command_parameters.data.first().unwrap().parameter
        );
        for arg in command.get_arguments() {
            println!("{} {}", arg.get_id(), arg.is_required_set());
        }
    }
}