diff --git a/proxmox/src/api/cli/command.rs b/proxmox/src/api/cli/command.rs index 89dfdf1e..b0431754 100644 --- a/proxmox/src/api/cli/command.rs +++ b/proxmox/src/api/cli/command.rs @@ -156,6 +156,8 @@ fn parse_nested_command<'a>( // Note: Avoid async recursive function, because current rust compiler cant handle that loop { + replace_aliases(args, &map.aliases); + if args.is_empty() { let mut cmds: Vec<&String> = map.commands.keys().collect(); cmds.sort(); @@ -173,6 +175,7 @@ fn parse_nested_command<'a>( return Err(format_err!("{}", err_msg)); } + let command = args.remove(0); let (_, sub_cmd) = match map.find_command(&command) { @@ -228,7 +231,7 @@ fn help_command( _info: &ApiMethod, _rpcenv: &mut dyn RpcEnvironment, ) -> Result { - let command: Vec = param["command"] + let mut command: Vec = param["command"] .as_array() .unwrap_or(&Vec::new()) .iter() @@ -239,6 +242,9 @@ fn help_command( HELP_CONTEXT.with(|ctx| match &*ctx.borrow() { Some(def) => { + if let CommandLineInterface::Nested(map) = def.as_ref() { + replace_aliases(&mut command, &map.aliases); + } print_help(def, String::from(""), &command, verbose); } None => { @@ -259,6 +265,26 @@ pub(crate) fn help_command_def() -> CliCommand { CliCommand::new(&API_METHOD_COMMAND_HELP).arg_param(&["command"]) } +fn replace_aliases( + args: &mut Vec, + aliases: &Vec<(Vec<&'static str>, Vec<&'static str>)>, +) { + for (old, new) in aliases { + if args.len() < old.len() { continue; } + if old[..] == args[..old.len()] { + let new_args: Vec = new.iter() + .map(|s| String::from(*s)).collect(); + let rest = args.split_off(old.len()); + args.truncate(0); + args.extend(new_args); + for arg in rest.iter() { + args.push(arg.clone()); + } + return; + } + } +} + /// Handle command invocation. /// /// This command gets the command line ``args`` and tries to invoke diff --git a/proxmox/src/api/cli/mod.rs b/proxmox/src/api/cli/mod.rs index 86e1d398..71ecd461 100644 --- a/proxmox/src/api/cli/mod.rs +++ b/proxmox/src/api/cli/mod.rs @@ -101,6 +101,7 @@ pub struct CliCommandMap { /// Each command has an unique name. The map associates names with /// command definitions. pub commands: HashMap, + pub aliases: Vec<(Vec<&'static str>, Vec<&'static str>)>, } impl CliCommandMap { @@ -115,6 +116,11 @@ impl CliCommandMap { self } + pub fn alias(mut self, old: &'static[&'static str], new: &'static[&'static str]) -> Self { + self.aliases.push((Vec::from(old), Vec::from(new))); + self + } + /// Insert the help command. pub fn insert_help(mut self) -> Self { self.commands