From 33256db6dd4cd0789827d6eaecdbbdb3357ae77e Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Thu, 21 Feb 2019 11:08:59 +0100 Subject: [PATCH] src/cli/command.rs: simplify cli handler --- src/bin/catar.rs | 7 +-- src/bin/proxmox-backup-client.rs | 9 +-- src/bin/proxmox-backup-manager.rs | 7 +-- src/cli/command.rs | 93 +++++++++++++++++++------------ 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/src/bin/catar.rs b/src/bin/catar.rs index c6dc75af..f6639cb7 100644 --- a/src/bin/catar.rs +++ b/src/bin/catar.rs @@ -185,10 +185,5 @@ fn main() { .into() ); - if let Err(err) = run_cli_command(&cmd_def.into()) { - eprintln!("Error: {}", err); - print_cli_usage(); - std::process::exit(-1); - } - + run_cli_command(&cmd_def.into()); } diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index 1ade06c1..ee9c9ecf 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -236,12 +236,5 @@ fn main() { .insert("garbage-collect".to_owned(), garbage_collect_cmd_def.into()) .insert("list".to_owned(), list_cmd_def.into()); - if let Err(err) = run_cli_command(&cmd_def.into()) { - eprintln!("Error: {}", err); - if err.downcast::().is_ok() { - print_cli_usage(); - } - std::process::exit(-1); - } - + run_cli_command(&cmd_def.into()); } diff --git a/src/bin/proxmox-backup-manager.rs b/src/bin/proxmox-backup-manager.rs index 19aa3cd9..05e2af06 100644 --- a/src/bin/proxmox-backup-manager.rs +++ b/src/bin/proxmox-backup-manager.rs @@ -51,10 +51,5 @@ fn main() { .insert("datastore".to_owned(), datastore_commands()) .insert("garbage-collection".to_owned(), garbage_collection_commands()); - if let Err(err) = run_cli_command(&cmd_def.into()) { - eprintln!("Error: {}", err); - print_cli_usage(); - std::process::exit(-1); - } - + run_cli_command(&cmd_def.into()); } diff --git a/src/cli/command.rs b/src/cli/command.rs index 6d4081a1..b99c2588 100644 --- a/src/cli/command.rs +++ b/src/cli/command.rs @@ -2,7 +2,7 @@ use failure::*; use std::collections::HashMap; use std::collections::HashSet; -use serde_json::Value; +//use serde_json::Value; use crate::api_schema::*; use crate::api_schema::router::*; @@ -11,27 +11,39 @@ use super::environment::CliEnvironment; use super::getopts; -pub fn print_cli_usage() { +fn print_simple_usage(prefix: &str, _cli_cmd: &CliCommand, err: Error) { - eprintln!("Usage: TODO"); + eprintln!("Error: {}", err); + eprintln!("\nUsage: {} ", prefix); } -#[derive(Debug, Fail)] -#[fail(display = "Usage error: {}", _0)] -pub struct UsageError(Error); +fn handle_simple_command(prefix: &str, cli_cmd: &CliCommand, args: Vec) { -pub struct Invocation<'a>(&'a CliCommand, Value); - -fn handle_simple_command(cli_cmd: &CliCommand, args: Vec) -> Result { - - let (params, rest) = getopts::parse_arguments( - &args, &cli_cmd.arg_param, &cli_cmd.info.parameters)?; + let (params, rest) = match getopts::parse_arguments( + &args, &cli_cmd.arg_param, &cli_cmd.info.parameters) { + Ok((p, r)) => (p, r), + Err(err) => { + print_simple_usage(prefix, cli_cmd, err.into()); + std::process::exit(-1); + } + }; if !rest.is_empty() { - bail!("got additional arguments: {:?}", rest); + let err = format_err!("got additional arguments: {:?}", rest); + print_simple_usage(prefix, cli_cmd, err); + std::process::exit(-1); } - Ok(Invocation(cli_cmd, params)) + let mut rpcenv = CliEnvironment::new(); + + match (cli_cmd.info.handler)(params, &cli_cmd.info, &mut rpcenv) { + Ok(value) => { + println!("Result: {}", serde_json::to_string_pretty(&value).unwrap()); + } + Err(err) => { + eprintln!("Error: {}", err); + } + } } fn find_command<'a>(def: &'a CliCommandMap, name: &str) -> Option<&'a CommandLineInterface> { @@ -56,7 +68,14 @@ fn find_command<'a>(def: &'a CliCommandMap, name: &str) -> Option<&'a CommandLin None } -fn handle_nested_command(def: &CliCommandMap, mut args: Vec) -> Result { +fn print_nested_usage(prefix: &str, _def: &CliCommandMap, err: Error) { + + eprintln!("Error: {}", err); + eprintln!("\nUsage: {} ", prefix); + +} + +fn handle_nested_command(prefix: &str, def: &CliCommandMap, mut args: Vec) { if args.len() < 1 { let mut cmds: Vec<&String> = def.commands.keys().collect(); @@ -68,22 +87,30 @@ fn handle_nested_command(def: &CliCommandMap, mut args: Vec) -> Result cmd, - None => bail!("no such command '{}'", command), + None => { + let err = format_err!("no such command '{}'", command); + print_nested_usage(prefix, def, err); + std::process::exit(-1); + } }; + let new_prefix = format!("{} {}", prefix, command); + match sub_cmd { CommandLineInterface::Simple(cli_cmd) => { - handle_simple_command(cli_cmd, args) + handle_simple_command(&new_prefix, cli_cmd, args); } CommandLineInterface::Nested(map) => { - handle_nested_command(map, args) + handle_nested_command(&new_prefix, map, args); } } } @@ -248,30 +275,24 @@ pub fn print_bash_completion(def: &CommandLineInterface) { print_nested_completion(def, args); } -pub fn run_cli_command(def: &CommandLineInterface) -> Result<(), Error> { +pub fn run_cli_command(def: &CommandLineInterface) { - let args: Vec = std::env::args().skip(1).collect(); + let mut args = std::env::args(); + + let prefix = args.next().unwrap(); + let prefix = prefix.rsplit('/').next().unwrap(); // without path + + let args: Vec = args.collect(); if !args.is_empty() && args[0] == "bashcomplete" { print_bash_completion(def); - return Ok(()); + return; } - let invocation = match def { - CommandLineInterface::Simple(cli_cmd) => handle_simple_command(cli_cmd, args), - CommandLineInterface::Nested(map) => handle_nested_command(map, args), + match def { + CommandLineInterface::Simple(cli_cmd) => handle_simple_command(&prefix, cli_cmd, args), + CommandLineInterface::Nested(map) => handle_nested_command(&prefix, map, args), }; - - let mut rpcenv = CliEnvironment::new(); - - let res = match invocation { - Err(e) => return Err(UsageError(e).into()), - Ok(invocation) => (invocation.0.info.handler)(invocation.1, &invocation.0.info, &mut rpcenv)?, - }; - - println!("Result: {}", serde_json::to_string_pretty(&res).unwrap()); - - Ok(()) } pub type CompletionFunction = fn(&str) -> Vec;