]>
Commit | Line | Data |
---|---|---|
1819b194 DM |
1 | //! Tools to create command line parsers |
2 | //! | |
3 | //! This crate provides convenient helpers to create command line | |
4 | //! parsers using Schema definitions. | |
5 | //! | |
6 | //! ## Features | |
7 | //! | |
8 | //! - Use declarative API schema to define the CLI | |
9 | //! - Automatic parameter verification | |
10 | //! - Automatically generate documentation and manual pages | |
11 | //! - Automatically generate bash completion helpers | |
12 | //! - Ability to create interactive commands (using ``rustyline``) | |
13 | //! - Supports complex/nested commands | |
14 | ||
15 | mod environment; | |
16 | pub use environment::*; | |
17 | ||
18 | mod shellword; | |
19 | pub use shellword::*; | |
20 | ||
21 | mod format; | |
22 | pub use format::*; | |
23 | ||
24 | mod completion; | |
25 | pub use completion::*; | |
26 | ||
27 | mod getopts; | |
28 | pub use getopts::*; | |
29 | ||
30 | mod command; | |
31 | pub use command::*; | |
32 | ||
33 | mod readline; | |
34 | pub use readline::*; | |
35 | ||
36 | use std::collections::HashMap; | |
37 | ||
38 | use crate::ApiMethod; | |
39 | ||
40 | /// Completion function for single parameters. | |
41 | /// | |
42 | /// Completion functions gets the current parameter value, and should | |
43 | /// return a list of all possible values. | |
44 | pub type CompletionFunction = fn(&str, &HashMap<String, String>) -> Vec<String>; | |
45 | ||
46 | /// Define a simple CLI command. | |
47 | pub struct CliCommand { | |
48 | /// The Schema definition. | |
49 | pub info: &'static ApiMethod, | |
50 | /// Argument parameter list. | |
51 | /// | |
52 | /// Those parameters are expected to be passed as command line | |
53 | /// arguments in the specified order. All other parameters needs | |
54 | /// to be specified as ``--option <value>`` pairs. | |
55 | pub arg_param: &'static [&'static str], | |
56 | /// Predefined parameters. | |
57 | pub fixed_param: HashMap<&'static str, String>, | |
58 | /// Completion functions. | |
59 | /// | |
60 | /// Each parameter may have an associated completion function, | |
61 | /// which is called by the shell completion handler. | |
62 | pub completion_functions: HashMap<String, CompletionFunction>, | |
63 | } | |
64 | ||
65 | impl CliCommand { | |
1819b194 DM |
66 | /// Create a new instance. |
67 | pub fn new(info: &'static ApiMethod) -> Self { | |
68 | Self { | |
92ffe4c2 WB |
69 | info, |
70 | arg_param: &[], | |
1819b194 DM |
71 | fixed_param: HashMap::new(), |
72 | completion_functions: HashMap::new(), | |
73 | } | |
74 | } | |
75 | ||
76 | /// Set argument parameter list. | |
77 | pub fn arg_param(mut self, names: &'static [&'static str]) -> Self { | |
78 | self.arg_param = names; | |
79 | self | |
80 | } | |
81 | ||
82 | /// Set fixed parameters. | |
83 | pub fn fixed_param(mut self, key: &'static str, value: String) -> Self { | |
84 | self.fixed_param.insert(key, value); | |
85 | self | |
86 | } | |
87 | ||
88 | /// Set completion functions. | |
92ffe4c2 | 89 | pub fn completion_cb(mut self, param_name: &str, cb: CompletionFunction) -> Self { |
1819b194 DM |
90 | self.completion_functions.insert(param_name.into(), cb); |
91 | self | |
92 | } | |
93 | } | |
94 | ||
95 | /// Define nested CLI commands. | |
96 | pub struct CliCommandMap { | |
97 | /// Each command has an unique name. The map associates names with | |
98 | /// command definitions. | |
99 | pub commands: HashMap<String, CommandLineInterface>, | |
100 | } | |
101 | ||
102 | impl CliCommandMap { | |
1819b194 DM |
103 | /// Create a new instance. |
104 | pub fn new() -> Self { | |
92ffe4c2 WB |
105 | Self { |
106 | commands: HashMap::new(), | |
107 | } | |
1819b194 DM |
108 | } |
109 | ||
110 | /// Insert another command. | |
111 | pub fn insert<S: Into<String>>(mut self, name: S, cli: CommandLineInterface) -> Self { | |
112 | self.commands.insert(name.into(), cli); | |
113 | self | |
114 | } | |
115 | ||
116 | /// Insert the help command. | |
117 | pub fn insert_help(mut self) -> Self { | |
92ffe4c2 WB |
118 | self.commands |
119 | .insert(String::from("help"), help_command_def().into()); | |
1819b194 DM |
120 | self |
121 | } | |
122 | ||
123 | fn find_command(&self, name: &str) -> Option<(String, &CommandLineInterface)> { | |
1819b194 DM |
124 | if let Some(sub_cmd) = self.commands.get(name) { |
125 | return Some((name.to_string(), sub_cmd)); | |
126 | }; | |
127 | ||
128 | let mut matches: Vec<&str> = vec![]; | |
129 | ||
130 | for cmd in self.commands.keys() { | |
131 | if cmd.starts_with(name) { | |
92ffe4c2 WB |
132 | matches.push(cmd); |
133 | } | |
1819b194 DM |
134 | } |
135 | ||
92ffe4c2 WB |
136 | if matches.len() != 1 { |
137 | return None; | |
138 | } | |
1819b194 DM |
139 | |
140 | if let Some(sub_cmd) = self.commands.get(matches[0]) { | |
141 | return Some((matches[0].to_string(), sub_cmd)); | |
142 | }; | |
143 | ||
144 | None | |
145 | } | |
146 | } | |
147 | ||
148 | /// Define Complex command line interfaces. | |
149 | pub enum CommandLineInterface { | |
150 | Simple(CliCommand), | |
151 | Nested(CliCommandMap), | |
152 | } | |
153 | ||
154 | impl From<CliCommand> for CommandLineInterface { | |
155 | fn from(cli_cmd: CliCommand) -> Self { | |
92ffe4c2 | 156 | CommandLineInterface::Simple(cli_cmd) |
1819b194 DM |
157 | } |
158 | } | |
159 | ||
160 | impl From<CliCommandMap> for CommandLineInterface { | |
161 | fn from(list: CliCommandMap) -> Self { | |
162 | CommandLineInterface::Nested(list) | |
163 | } | |
164 | } |