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
Generated
+98 -15
View File
@@ -105,6 +105,45 @@ dependencies = [
"inout", "inout",
] ]
[[package]]
name = "clap"
version = "3.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"lazy_static",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
dependencies = [
"os_str_bytes",
]
[[package]] [[package]]
name = "const-oid" name = "const-oid"
version = "0.7.1" version = "0.7.1"
@@ -332,24 +371,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "gumdrop" name = "hashbrown"
version = "0.8.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bc700f989d2f6f0248546222d9b4258f5b02a171a431f8285a81c08142629e3" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
"gumdrop_derive",
]
[[package]] [[package]]
name = "gumdrop_derive" name = "heck"
version = "0.8.1" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "729f9bd3449d77e7831a18abfb7ba2f99ee813dfd15b8c2167c9a54ba20aa99d" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
@@ -375,6 +406,16 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "indexmap"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "inout" name = "inout"
version = "0.1.3" version = "0.1.3"
@@ -511,6 +552,12 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "os_str_bytes"
version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435"
[[package]] [[package]]
name = "p256" name = "p256"
version = "0.11.0" version = "0.11.0"
@@ -613,6 +660,30 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.39" version = "1.0.39"
@@ -824,6 +895,12 @@ dependencies = [
"der 0.6.0", "der 0.6.0",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.1" version = "2.4.1"
@@ -859,6 +936,12 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.31" version = "1.0.31"
@@ -1018,8 +1101,8 @@ dependencies = [
name = "yubikey-cli" name = "yubikey-cli"
version = "0.6.0-pre" version = "0.6.0-pre"
dependencies = [ dependencies = [
"clap",
"env_logger", "env_logger",
"gumdrop",
"lazy_static", "lazy_static",
"log", "log",
"sha2 0.9.9", "sha2 0.9.9",
+1 -1
View File
@@ -15,7 +15,7 @@ edition = "2021"
rust-version = "1.56" rust-version = "1.56"
[dependencies] [dependencies]
gumdrop = "0.8" clap = { version = "3", features = ["derive"] }
env_logger = "0.9" env_logger = "0.9"
lazy_static = "1" lazy_static = "1"
log = "0.4" log = "0.4"
+2 -2
View File
@@ -8,9 +8,9 @@
unused_qualifications unused_qualifications
)] )]
use gumdrop::Options; use clap::Parser;
use yubikey_cli::commands::YubiKeyCli; use yubikey_cli::commands::YubiKeyCli;
fn main() { fn main() {
YubiKeyCli::parse_args_default_or_exit().run(); YubiKeyCli::parse().run()
} }
+15 -80
View File
@@ -4,62 +4,25 @@ pub mod readers;
pub mod status; pub mod status;
use self::{readers::ReadersCmd, status::StatusCmd}; use self::{readers::ReadersCmd, status::StatusCmd};
use crate::terminal::{self, STDOUT}; use crate::terminal;
use gumdrop::Options; use clap::Parser;
use std::{ use std::{env, process::exit};
env, use termcolor::ColorChoice;
io::{self, Write},
process::exit,
};
use termcolor::{ColorChoice, ColorSpec, WriteColor};
use yubikey::{Serial, YubiKey}; use yubikey::{Serial, YubiKey};
/// The `yubikey` CLI utility /// The `yubikey` CLI utility
#[derive(Debug, Options)] #[derive(Debug, Parser)]
pub struct YubiKeyCli { pub struct YubiKeyCli {
/// Obtain help about the current command /// Serial number of the YubiKey to connect to
#[options(short = "h", help = "print help message")] #[clap(short = 's', long = "serial")]
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"
)]
pub serial: Option<Serial>, pub serial: Option<Serial>,
/// Subcommand to execute. /// Subcommand to execute.
#[options(command)] #[clap(subcommand)]
pub command: Option<Commands>, pub command: Commands,
} }
impl YubiKeyCli { 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 /// Run the underlying command type or print usage info and exit
pub fn run(&self) { pub fn run(&self) {
// TODO(tarcieri): make this more configurable // TODO(tarcieri): make this more configurable
@@ -70,10 +33,7 @@ impl YubiKeyCli {
env_logger::builder().format_timestamp(None).init(); env_logger::builder().format_timestamp(None).init();
} }
match &self.command { self.command.run(self.yubikey_init())
Some(cmd) => cmd.run(self.yubikey_init()),
None => Self::print_usage().unwrap(),
}
} }
/// Initialize the YubiKey client driver /// Initialize the YubiKey client driver
@@ -92,22 +52,18 @@ impl YubiKeyCli {
} }
/// Subcommands of this application /// Subcommands of this application
#[derive(Debug, Options)] #[derive(Debug, Parser)]
pub enum Commands { pub enum Commands {
/// `help` subcommand
#[options(help = "show help for a command")]
Help(HelpOpts),
/// `version` subcommand /// `version` subcommand
#[options(help = "display version information")] #[clap(about = "display version information")]
Version(VersionOpts), Version(VersionOpts),
/// `readers` subcommand /// `readers` subcommand
#[options(help = "list detected readers")] #[clap(about = "list detected readers")]
Readers(ReadersCmd), Readers(ReadersCmd),
/// `status` subcommand /// `status` subcommand
#[options(help = "show yubikey status")] #[clap(about = "show yubikey status")]
Status(StatusCmd), Status(StatusCmd),
} }
@@ -115,7 +71,6 @@ impl Commands {
/// Run the given command /// Run the given command
pub fn run(&self, yubikey: YubiKey) { pub fn run(&self, yubikey: YubiKey) {
match self { match self {
Commands::Help(help) => help.run(),
Commands::Version(version) => version.run(), Commands::Version(version) => version.run(),
Commands::Readers(list) => list.run(), Commands::Readers(list) => list.run(),
Commands::Status(status) => status.run(yubikey), 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 /// Version options
#[derive(Debug, Options)] #[derive(Debug, Parser)]
pub struct VersionOpts {} pub struct VersionOpts {}
impl VersionOpts { impl VersionOpts {
+2 -2
View File
@@ -1,7 +1,7 @@
//! List detected readers //! List detected readers
use crate::terminal::STDOUT; use crate::terminal::STDOUT;
use gumdrop::Options; use clap::Parser;
use std::{ use std::{
io::{self, Write}, io::{self, Write},
process::exit, process::exit,
@@ -10,7 +10,7 @@ use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
use yubikey::{Context, Serial}; use yubikey::{Context, Serial};
/// The `readers` subcommand /// The `readers` subcommand
#[derive(Debug, Options)] #[derive(Debug, Parser)]
pub struct ReadersCmd {} pub struct ReadersCmd {}
impl ReadersCmd { impl ReadersCmd {
+2 -2
View File
@@ -1,7 +1,7 @@
//! Print device status //! Print device status
use crate::terminal::{print_cert_info, STDOUT}; use crate::terminal::{print_cert_info, STDOUT};
use gumdrop::Options; use clap::Parser;
use std::io::{self, Write}; use std::io::{self, Write};
use termcolor::{ColorSpec, StandardStreamLock, WriteColor}; use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
use yubikey::{piv::*, YubiKey}; use yubikey::{piv::*, YubiKey};
@@ -10,7 +10,7 @@ use yubikey::{piv::*, YubiKey};
const NONE_STR: &str = "<none>"; const NONE_STR: &str = "<none>";
/// The `status` subcommand /// The `status` subcommand
#[derive(Debug, Options)] #[derive(Debug, Parser)]
pub struct StatusCmd {} pub struct StatusCmd {}
impl StatusCmd { impl StatusCmd {