]> git.proxmox.com Git - proxmox.git/blame - proxmox-router/src/cli/mod.rs
router: fix warning
[proxmox.git] / proxmox-router / src / cli / mod.rs
CommitLineData
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
41f3fdfe
WB
15use std::collections::HashMap;
16
17use crate::ApiMethod;
18
1819b194
DM
19mod environment;
20pub use environment::*;
21
22mod shellword;
23pub use shellword::*;
24
25mod format;
26pub use format::*;
27
ce53818e
DM
28mod text_table;
29pub use text_table::*;
30
1819b194 31mod completion;
1819b194 32
417b7159
DM
33mod completion_helpers;
34pub use completion_helpers::*;
35
1819b194
DM
36mod getopts;
37pub use getopts::*;
38
39mod command;
40pub use command::*;
41
42mod readline;
43pub use readline::*;
44
1819b194
DM
45/// Completion function for single parameters.
46///
47/// Completion functions gets the current parameter value, and should
48/// return a list of all possible values.
49pub type CompletionFunction = fn(&str, &HashMap<String, String>) -> Vec<String>;
50
32b8ae98
HL
51/// Initialize default logger for CLI binaries
52pub fn init_cli_logger(env_var_name: &str, default_log_level: &str) {
f5052400
FG
53 env_logger::Builder::from_env(
54 env_logger::Env::new().filter_or(env_var_name, default_log_level),
55 )
56 .write_style(env_logger::WriteStyle::Never)
57 .format_level(false)
58 .format_module_path(false)
59 .format_target(false)
60 .format_timestamp(None)
61 .init();
32b8ae98
HL
62}
63
1819b194
DM
64/// Define a simple CLI command.
65pub struct CliCommand {
66 /// The Schema definition.
67 pub info: &'static ApiMethod,
68 /// Argument parameter list.
69 ///
70 /// Those parameters are expected to be passed as command line
71 /// arguments in the specified order. All other parameters needs
72 /// to be specified as ``--option <value>`` pairs.
73 pub arg_param: &'static [&'static str],
74 /// Predefined parameters.
75 pub fixed_param: HashMap<&'static str, String>,
76 /// Completion functions.
77 ///
78 /// Each parameter may have an associated completion function,
79 /// which is called by the shell completion handler.
80 pub completion_functions: HashMap<String, CompletionFunction>,
81}
82
83impl CliCommand {
1819b194
DM
84 /// Create a new instance.
85 pub fn new(info: &'static ApiMethod) -> Self {
86 Self {
92ffe4c2
WB
87 info,
88 arg_param: &[],
1819b194
DM
89 fixed_param: HashMap::new(),
90 completion_functions: HashMap::new(),
91 }
92 }
93
94 /// Set argument parameter list.
95 pub fn arg_param(mut self, names: &'static [&'static str]) -> Self {
96 self.arg_param = names;
97 self
98 }
99
100 /// Set fixed parameters.
101 pub fn fixed_param(mut self, key: &'static str, value: String) -> Self {
102 self.fixed_param.insert(key, value);
103 self
104 }
105
106 /// Set completion functions.
92ffe4c2 107 pub fn completion_cb(mut self, param_name: &str, cb: CompletionFunction) -> Self {
1819b194
DM
108 self.completion_functions.insert(param_name.into(), cb);
109 self
110 }
111}
112
113/// Define nested CLI commands.
ee1a7cd6 114#[derive(Default)]
1819b194
DM
115pub struct CliCommandMap {
116 /// Each command has an unique name. The map associates names with
117 /// command definitions.
118 pub commands: HashMap<String, CommandLineInterface>,
e7cb1f20 119 pub aliases: Vec<(Vec<&'static str>, Vec<&'static str>)>,
d014c6f2
DM
120 /// List of options to suppress in generate_usage
121 pub usage_skip_options: &'static [&'static str],
1819b194
DM
122}
123
124impl CliCommandMap {
1819b194
DM
125 /// Create a new instance.
126 pub fn new() -> Self {
ee1a7cd6 127 Default::default()
1819b194
DM
128 }
129
130 /// Insert another command.
f1fcdff9 131 pub fn insert<C: Into<CommandLineInterface>>(mut self, name: &'static str, cli: C) -> Self {
bf7b939b 132 self.commands.insert(name.into(), cli.into());
1819b194
DM
133 self
134 }
135
b210ad69 136 pub fn alias(mut self, old: &'static [&'static str], new: &'static [&'static str]) -> Self {
e7cb1f20
DM
137 self.aliases.push((Vec::from(old), Vec::from(new)));
138 self
139 }
140
d014c6f2
DM
141 pub fn usage_skip_options(mut self, list: &'static [&'static str]) -> Self {
142 self.usage_skip_options = list;
143 self
144 }
145
1819b194
DM
146 /// Insert the help command.
147 pub fn insert_help(mut self) -> Self {
92ffe4c2
WB
148 self.commands
149 .insert(String::from("help"), help_command_def().into());
1819b194
DM
150 self
151 }
152
153 fn find_command(&self, name: &str) -> Option<(String, &CommandLineInterface)> {
1819b194
DM
154 if let Some(sub_cmd) = self.commands.get(name) {
155 return Some((name.to_string(), sub_cmd));
156 };
157
158 let mut matches: Vec<&str> = vec![];
159
160 for cmd in self.commands.keys() {
161 if cmd.starts_with(name) {
92ffe4c2
WB
162 matches.push(cmd);
163 }
1819b194
DM
164 }
165
92ffe4c2
WB
166 if matches.len() != 1 {
167 return None;
168 }
1819b194
DM
169
170 if let Some(sub_cmd) = self.commands.get(matches[0]) {
171 return Some((matches[0].to_string(), sub_cmd));
172 };
173
174 None
175 }
176}
177
178/// Define Complex command line interfaces.
179pub enum CommandLineInterface {
180 Simple(CliCommand),
181 Nested(CliCommandMap),
182}
183
184impl From<CliCommand> for CommandLineInterface {
185 fn from(cli_cmd: CliCommand) -> Self {
92ffe4c2 186 CommandLineInterface::Simple(cli_cmd)
1819b194
DM
187 }
188}
189
190impl From<CliCommandMap> for CommandLineInterface {
191 fn from(list: CliCommandMap) -> Self {
192 CommandLineInterface::Nested(list)
193 }
194}