dsl_cli_core/help/
cli.rs

1use crate::{Cli, CliCommand};
2
3impl Cli {
4    pub fn show_help(&self, command_name: String) {
5        // This might not exist if the command name is cli. Otherwise it will be a valid command.
6        let cmd_def = self.commands.iter().find(|cmd| cmd.name == command_name);
7
8        let mut cmds_info = Vec::new();
9        let mut args_info = Vec::new();
10        let mut opts_info = Vec::new();
11
12        match cmd_def {
13            Some(cmd_def) => {
14                args_info = cmd_def.args_info();
15                opts_info = cmd_def.opts_info();
16            }
17            None => {}
18        }
19
20        if command_name == "cli" {
21            cmds_info = self
22                .commands
23                .iter()
24                .map(|cmd| cmd.info())
25                .collect::<Vec<(String, String)>>();
26            cmds_info.push((
27                String::from("help [command]"),
28                String::from("Show help for a command"),
29            ));
30        }
31
32        let args_max_width = args_info
33            .iter()
34            .map(|(name, _)| name.len())
35            .max()
36            .unwrap_or(0);
37        let opts_max_width = opts_info
38            .iter()
39            .map(|(name, _)| name.len())
40            .max()
41            .unwrap_or(0);
42        let cmds_max_width = cmds_info
43            .iter()
44            .map(|(name, _)| name.len())
45            .max()
46            .unwrap_or(0);
47        let max_width = args_max_width.max(opts_max_width).max(cmds_max_width) + 2;
48
49        // Display Usage
50        match cmd_def {
51            Some(cmd_def) => {
52                println!();
53                let mut usage_string = String::new();
54
55                usage_string.push_str(&self.executable_name);
56
57                if command_name != "cli" {
58                    usage_string.push_str(" ");
59                    usage_string.push_str(&command_name);
60                }
61
62                if !args_info.is_empty() {
63                    let args_string = " ".to_owned()
64                        + &args_info
65                            .iter()
66                            .map(|(name, _)| name.as_str())
67                            .collect::<Vec<&str>>()
68                            .join(" ");
69                    usage_string.push_str(&args_string);
70                }
71
72                if !opts_info.is_empty() {
73                    usage_string.push_str(" [options]");
74                }
75
76                println!("Usage: {}", usage_string);
77            }
78            None => {}
79        }
80        // Display Description
81        match cmd_def {
82            Some(cmd_def) => {
83                let description = &cmd_def.description;
84
85                if let Some(description) = description {
86                    println!("{}", description)
87                } else {
88                    println!("No description available")
89                }
90            }
91            None => {}
92        }
93        // Display Arguments
94        if !args_info.is_empty() {
95            println!("\nArguments:");
96            for (name, description) in args_info {
97                let width = name.len();
98                let padding = " ".repeat(max_width - width);
99                println!("  {}{}{}", name, padding, description);
100            }
101        }
102        // Display Options
103        if !opts_info.is_empty() {
104            println!("\nOptions:");
105            for (name, description) in opts_info {
106                let width = name.len();
107                let padding = " ".repeat(max_width - width);
108                println!("  {}{}{}", name, padding, description);
109            }
110        }
111        // Display Commands
112        if !cmds_info.is_empty() {
113            println!("\nCommands:");
114            for (name, description) in cmds_info {
115                let width = name.len();
116                let padding = " ".repeat(max_width - width);
117                println!("  {}{}{}", name, padding, description);
118            }
119        }
120        println!();
121    }
122}