cli: migrate from gumdrop to clap v3 (#379)

`gumdrop` was originally chosen for its minimalist set of dependencies,
but `clap` v3 has a slimmed down set of dependencies and better UX.
This commit is contained in:
Tony Arcieri (iqlusion)
2022-05-24 21:45:26 -06:00
committed by GitHub
parent bb80551324
commit fab9d25b0a
6 changed files with 120 additions and 102 deletions
+15 -80
View File
@@ -4,62 +4,25 @@ pub mod readers;
pub mod status;
use self::{readers::ReadersCmd, status::StatusCmd};
use crate::terminal::{self, STDOUT};
use gumdrop::Options;
use std::{
env,
io::{self, Write},
process::exit,
};
use termcolor::{ColorChoice, ColorSpec, WriteColor};
use crate::terminal;
use clap::Parser;
use std::{env, process::exit};
use termcolor::ColorChoice;
use yubikey::{Serial, YubiKey};
/// The `yubikey` CLI utility
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub struct YubiKeyCli {
/// Obtain help about the current command
#[options(short = "h", help = "print help message")]
pub help: bool,
/// Specify the serial number of the YubiKey to connect to
#[options(
short = "s",
long = "serial",
help = "serial number of the YubiKey to connect to"
)]
/// Serial number of the YubiKey to connect to
#[clap(short = 's', long = "serial")]
pub serial: Option<Serial>,
/// Subcommand to execute.
#[options(command)]
pub command: Option<Commands>,
#[clap(subcommand)]
pub command: Commands,
}
impl YubiKeyCli {
/// Print usage information
pub fn print_usage() -> io::Result<()> {
let mut stdout = STDOUT.lock();
stdout.reset()?;
let mut bold = ColorSpec::new();
bold.set_bold(true);
stdout.set_color(&bold)?;
writeln!(
stdout,
"{} {}",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
)?;
stdout.reset()?;
writeln!(stdout, "{}", env!("CARGO_PKG_AUTHORS"))?;
writeln!(stdout, "{}", env!("CARGO_PKG_DESCRIPTION").trim())?;
writeln!(stdout)?;
writeln!(stdout, "{}", Commands::usage())?;
Ok(())
}
/// Run the underlying command type or print usage info and exit
pub fn run(&self) {
// TODO(tarcieri): make this more configurable
@@ -70,10 +33,7 @@ impl YubiKeyCli {
env_logger::builder().format_timestamp(None).init();
}
match &self.command {
Some(cmd) => cmd.run(self.yubikey_init()),
None => Self::print_usage().unwrap(),
}
self.command.run(self.yubikey_init())
}
/// Initialize the YubiKey client driver
@@ -92,22 +52,18 @@ impl YubiKeyCli {
}
/// Subcommands of this application
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub enum Commands {
/// `help` subcommand
#[options(help = "show help for a command")]
Help(HelpOpts),
/// `version` subcommand
#[options(help = "display version information")]
#[clap(about = "display version information")]
Version(VersionOpts),
/// `readers` subcommand
#[options(help = "list detected readers")]
#[clap(about = "list detected readers")]
Readers(ReadersCmd),
/// `status` subcommand
#[options(help = "show yubikey status")]
#[clap(about = "show yubikey status")]
Status(StatusCmd),
}
@@ -115,7 +71,6 @@ impl Commands {
/// Run the given command
pub fn run(&self, yubikey: YubiKey) {
match self {
Commands::Help(help) => help.run(),
Commands::Version(version) => version.run(),
Commands::Readers(list) => list.run(),
Commands::Status(status) => status.run(yubikey),
@@ -123,28 +78,8 @@ impl Commands {
}
}
/// Help options
#[derive(Debug, Options)]
pub struct HelpOpts {
#[options(free, help = "subcommand to get help for")]
free: Vec<String>,
}
impl HelpOpts {
fn run(&self) {
if let Some(command) = self.free.first() {
if let Some(usage) = Commands::command_usage(command) {
println!("{}", usage);
exit(1);
}
}
println!("{}", Commands::usage());
}
}
/// Version options
#[derive(Debug, Options)]
#[derive(Debug, Parser)]
pub struct VersionOpts {}
impl VersionOpts {