diff --git a/proxmox-router/src/cli/command.rs b/proxmox-router/src/cli/command.rs index 8ae889f9..7a26ffb9 100644 --- a/proxmox-router/src/cli/command.rs +++ b/proxmox-router/src/cli/command.rs @@ -335,9 +335,10 @@ pub fn handle_command( result } -fn prepare_cli_command(def: &CommandLineInterface) -> (String, Vec) { - let mut args = std::env::args(); - +fn prepare_cli_command(def: &CommandLineInterface, mut args: A) -> (String, Vec) +where + A: Iterator, +{ let prefix = args.next().unwrap(); let prefix = prefix.rsplit('/').next().unwrap().to_string(); // without path @@ -379,12 +380,44 @@ fn prepare_cli_command(def: &CommandLineInterface) -> (String, Vec) { /// - ``printdoc``: Output ReST documentation. /// pub async fn run_async_cli_command>(def: C, rpcenv: CliEnvironment) { + run_async_cli_command_with_args(def, rpcenv, std::env::args()).await +} + +/// Helper to get arguments and invoke the command. +/// +/// This is the synchrounous version of run_async_cli_command. You can +/// pass an optional ``run`` function to execute async commands (else +/// async commands simply fail). +pub fn run_cli_command>( + def: C, + rpcenv: CliEnvironment, + run: Option Result>, +) { + run_cli_command_with_args(def, rpcenv, run, std::env::args()) +} + +/// Helper to get arguments and invoke the command (async). +/// +/// The first argument is assumed to be the program name, and is passed as ``prefix`` to +/// ``handle_command()``. +/// +/// This helper automatically add the help command, and two special +/// sub-command: +/// +/// - ``bashcomplete``: Output bash completions instead of running the command. +/// - ``printdoc``: Output ReST documentation. +/// +pub async fn run_async_cli_command_with_args(def: C, rpcenv: CliEnvironment, args: A) +where + C: Into, + A: IntoIterator, +{ let def = match def.into() { CommandLineInterface::Simple(cli_cmd) => CommandLineInterface::Simple(cli_cmd), CommandLineInterface::Nested(map) => CommandLineInterface::Nested(map.insert_help()), }; - let (prefix, args) = prepare_cli_command(&def); + let (prefix, args) = prepare_cli_command(&def, args.into_iter()); if handle_command_future(Arc::new(def), &prefix, args, rpcenv) .await @@ -399,17 +432,21 @@ pub async fn run_async_cli_command>(def: C, rpcenv /// This is the synchrounous version of run_async_cli_command. You can /// pass an optional ``run`` function to execute async commands (else /// async commands simply fail). -pub fn run_cli_command>( +pub fn run_cli_command_with_args( def: C, rpcenv: CliEnvironment, run: Option Result>, -) { + args: A, +) where + C: Into, + A: IntoIterator, +{ let def = match def.into() { CommandLineInterface::Simple(cli_cmd) => CommandLineInterface::Simple(cli_cmd), CommandLineInterface::Nested(map) => CommandLineInterface::Nested(map.insert_help()), }; - let (prefix, args) = prepare_cli_command(&def); + let (prefix, args) = prepare_cli_command(&def, args.into_iter()); if handle_command(Arc::new(def), &prefix, args, rpcenv, run).is_err() { std::process::exit(-1);