From 9c5b84d5fedc9f93e5363e9b06447e8421bdd599 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 6 Dec 2021 15:36:23 -0600 Subject: [PATCH] feat: Upgrate to clap3 --- Cargo.lock | 82 +++++++++++++++++++--- Cargo.toml | 7 +- src/bin/typos-cli/args.rs | 143 +++++++++++++++++++------------------- src/bin/typos-cli/main.rs | 13 ++-- 4 files changed, 151 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fedb034..f20efcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,11 +159,28 @@ dependencies = [ "atty", "bitflags", "strsim 0.8.0", - "textwrap", + "textwrap 0.11.0", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d17bf219fcd37199b9a29e00ba65dfb8cd5b2688b7297ec14ff829c40ac50ca9" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap 0.14.2", +] + [[package]] name = "clap-verbosity-flag" version = "0.3.2" @@ -174,6 +191,29 @@ dependencies = [ "structopt", ] +[[package]] +name = "clap-verbosity-flag" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1281ab1a7abc0f415a57cf6bc1f46282957ce0c5f2b3fe6b98ff3adf8e29b3" +dependencies = [ + "clap 3.0.0", + "log", +] + +[[package]] +name = "clap_derive" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b9752c030a14235a0bd5ef3ad60a1dcac8468c30921327fc8af36b20c790b9" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "codegenrs" version = "1.0.0" @@ -217,12 +257,12 @@ dependencies = [ [[package]] name = "concolor-clap" -version = "0.0.6" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb23c99e877c098e60ba3e84410153bfc311ac91b6ac7eabc0da0414ffa12e4" +checksum = "14b1e2c32ce41369500cb16afec166bb78f8044ab18264802e679aeec6871039" dependencies = [ + "clap 3.0.0", "concolor-control", - "structopt", ] [[package]] @@ -265,7 +305,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "itertools", @@ -889,6 +929,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "os_type" version = "2.3.0" @@ -1265,13 +1314,19 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ - "clap", + "clap 2.34.0", "lazy_static", "structopt-derive", ] @@ -1338,6 +1393,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + [[package]] name = "thiserror" version = "1.0.30" @@ -1454,8 +1515,8 @@ dependencies = [ "assert_fs", "atty", "bstr", - "clap", - "clap-verbosity-flag", + "clap 3.0.0", + "clap-verbosity-flag 0.4.0", "concolor-clap", "concolor-control", "content_inspector", @@ -1475,7 +1536,6 @@ dependencies = [ "proc-exit", "serde", "serde_json", - "structopt", "toml", "trycmd", "typed-arena", @@ -1536,8 +1596,8 @@ dependencies = [ name = "typos-vars-codegen" version = "1.3.0" dependencies = [ - "clap", - "clap-verbosity-flag", + "clap 2.34.0", + "clap-verbosity-flag 0.3.2", "codegenrs", "dictgen", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 771afb9..d8353c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,8 @@ typos-dict = { version = "^0.7", path = "crates/typos-dict", optional = true } typos-vars = { version = "^0.8", path = "crates/typos-vars", optional = true } unicase = "2.5" anyhow = "1.0" -structopt = "0.3" -clap = "2" -clap-verbosity-flag = "0.3" +clap = "3.0" +clap-verbosity-flag = "0.4" ignore = "0.4" serde = { version = "1.0", features = ["derive"] } toml = "0.5" @@ -75,7 +74,7 @@ env_logger = { version = "0.9", default-features = false, features = ["termcolor atty = "0.2.14" yansi = "0.5.0" concolor-control = { version = "0.0.7" } -concolor-clap = { version = "0.0.6", features = ["api_unstable"] } +concolor-clap = { version = "0.0.7", features = ["api_unstable"] } bstr = "0.2" once_cell = "1.2.0" ahash = "0.7" diff --git a/src/bin/typos-cli/args.rs b/src/bin/typos-cli/args.rs index 59b7dc8..540b73f 100644 --- a/src/bin/typos-cli/args.rs +++ b/src/bin/typos-cli/args.rs @@ -1,15 +1,13 @@ -use structopt::StructOpt; +use clap::Parser; use typos_cli::config; -arg_enum! { - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum Format { - Silent, - Brief, - Long, - Json, - } +#[derive(Debug, Copy, Clone, PartialEq, Eq, clap::ArgEnum)] +pub enum Format { + Silent, + Brief, + Long, + Json, } impl Format { @@ -39,109 +37,101 @@ impl Default for Format { } } -#[derive(Debug, StructOpt)] -#[structopt(rename_all = "kebab-case")] -#[structopt( - setting = structopt::clap::AppSettings::UnifiedHelpMessage, - setting = structopt::clap::AppSettings::DeriveDisplayOrder, - setting = structopt::clap::AppSettings::DontCollapseArgsInUsage, - setting = concolor_clap::color_choice(), +#[derive(Debug, Parser)] +#[clap(rename_all = "kebab-case")] +#[clap(about, author, version)] +#[clap( + setting = clap::AppSettings::DeriveDisplayOrder, + setting = clap::AppSettings::DontCollapseArgsInUsage, + color = concolor_clap::color_choice(), )] -#[structopt(group = structopt::clap::ArgGroup::with_name("mode").multiple(false))] +#[clap(group = clap::ArgGroup::new("mode").multiple(false))] pub(crate) struct Args { - #[structopt(parse(from_os_str), default_value = ".")] + #[clap(parse(from_os_str), default_value = ".")] /// Paths to check with `-` for stdin pub(crate) path: Vec, - #[structopt(short = "c", long = "config")] + #[clap(short = 'c', long = "config", parse(from_os_str))] /// Custom config file pub(crate) custom_config: Option, - #[structopt(long)] + #[clap(long)] /// Ignore implicit configuration files. pub(crate) isolated: bool, - #[structopt(long, group = "mode")] + #[clap(long, group = "mode")] /// Print a diff of what would change pub(crate) diff: bool, - #[structopt(long, short = "w", group = "mode")] + #[clap(long, short = 'w', group = "mode")] /// Write fixes out pub(crate) write_changes: bool, - #[structopt(long, group = "mode")] + #[clap(long, group = "mode")] /// Debug: Print each file that would be spellchecked. pub(crate) files: bool, - #[structopt(long, group = "mode")] + #[clap(long, group = "mode")] /// Debug: Print each identifier that would be spellchecked. pub(crate) identifiers: bool, - #[structopt(long, group = "mode")] + #[clap(long, group = "mode")] /// Debug: Print each word that would be spellchecked. pub(crate) words: bool, - #[structopt(long, group = "mode")] + #[clap(long, parse(from_os_str), group = "mode")] /// Write the current configuration to file with `-` for stdout pub(crate) dump_config: Option, - #[structopt(long, group = "mode")] + #[clap(long, group = "mode")] /// Show all supported file types. pub(crate) type_list: bool, - #[structopt( - long, - possible_values(&Format::variants()), - case_insensitive(true), - default_value("long") - )] + #[clap(long, arg_enum, ignore_case = true, default_value("long"))] pub(crate) format: Format, - #[structopt(short = "j", long = "threads", default_value = "0")] + #[clap(short = 'j', long = "threads", default_value = "0")] /// The approximate number of threads to use. pub(crate) threads: usize, - #[structopt(flatten)] + #[clap(flatten)] pub(crate) config: ConfigArgs, - #[structopt(flatten)] + #[clap(flatten)] pub(crate) color: concolor_clap::Color, - #[structopt(flatten)] + #[clap(flatten)] pub(crate) verbose: clap_verbosity_flag::Verbosity, } -#[derive(Debug, Clone, StructOpt)] -#[structopt(rename_all = "kebab-case")] +#[derive(Debug, Clone, clap::Args)] +#[clap(rename_all = "kebab-case")] pub(crate) struct FileArgs { - #[structopt(long, overrides_with("no-binary"))] + #[clap(long, overrides_with("no-binary"))] /// Search binary files. binary: bool, - #[structopt(long, overrides_with("binary"), hidden(true))] + #[clap(long, overrides_with("binary"), hide = true)] no_binary: bool, - #[structopt(long, overrides_with("check-filenames"))] + #[clap(long, overrides_with("check-filenames"))] /// Skip verifying spelling in file names. no_check_filenames: bool, - #[structopt(long, overrides_with("no-check-filenames"), hidden(true))] + #[clap(long, overrides_with("no-check-filenames"), hide = true)] check_filenames: bool, - #[structopt(long, overrides_with("check-files"))] + #[clap(long, overrides_with("check-files"))] /// Skip verifying spelling in files. no_check_files: bool, - #[structopt(long, overrides_with("no-check-files"), hidden(true))] + #[clap(long, overrides_with("no-check-files"), hide = true)] check_files: bool, - #[structopt(long, overrides_with("no-unicode"), hidden(true))] + #[clap(long, overrides_with("no-unicode"), hide = true)] unicode: bool, - #[structopt(long, overrides_with("unicode"))] + #[clap(long, overrides_with("unicode"))] /// Only allow ASCII characters in identifiers no_unicode: bool, - #[structopt( - long, - possible_values(&config::Locale::variants()), - )] + #[clap(long, possible_values(config::Locale::variants()))] pub(crate) locale: Option, } @@ -179,12 +169,12 @@ impl FileArgs { } } -#[derive(Debug, StructOpt)] -#[structopt(rename_all = "kebab-case")] +#[derive(Debug, clap::Args)] +#[clap(rename_all = "kebab-case")] pub(crate) struct ConfigArgs { - #[structopt(flatten)] + #[clap(flatten)] walk: WalkArgs, - #[structopt(flatten)] + #[clap(flatten)] overrides: FileArgs, } @@ -198,47 +188,47 @@ impl ConfigArgs { } } -#[derive(Debug, StructOpt)] -#[structopt(rename_all = "kebab-case")] +#[derive(Debug, clap::Args)] +#[clap(rename_all = "kebab-case")] pub(crate) struct WalkArgs { - #[structopt(long, name = "GLOB")] + #[clap(long, name = "GLOB")] /// Ignore files & directories matching the glob. exclude: Vec, - #[structopt(long, overrides_with("no-hidden"))] + #[clap(long, overrides_with("no-hidden"))] /// Search hidden files and directories. hidden: bool, - #[structopt(long, overrides_with("hidden"), hidden(true))] + #[clap(long, overrides_with("hidden"), hide = true)] no_hidden: bool, - #[structopt(long, overrides_with("ignore"))] + #[clap(long, overrides_with("ignore"))] /// Don't respect ignore files. no_ignore: bool, - #[structopt(long, overrides_with("no-ignore"), hidden(true))] + #[clap(long, overrides_with("no-ignore"), hide = true)] ignore: bool, - #[structopt(long, overrides_with("ignore-dot"))] + #[clap(long, overrides_with("ignore-dot"))] /// Don't respect .ignore files. no_ignore_dot: bool, - #[structopt(long, overrides_with("no-ignore-dot"), hidden(true))] + #[clap(long, overrides_with("no-ignore-dot"), hide = true)] ignore_dot: bool, - #[structopt(long, overrides_with("ignore-global"))] + #[clap(long, overrides_with("ignore-global"))] /// Don't respect global ignore files. no_ignore_global: bool, - #[structopt(long, overrides_with("no-ignore-global"), hidden(true))] + #[clap(long, overrides_with("no-ignore-global"), hide = true)] ignore_global: bool, - #[structopt(long, overrides_with("ignore-parent"))] + #[clap(long, overrides_with("ignore-parent"))] /// Don't respect ignore files in parent directories. no_ignore_parent: bool, - #[structopt(long, overrides_with("no-ignore-parent"), hidden(true))] + #[clap(long, overrides_with("no-ignore-parent"), hide = true)] ignore_parent: bool, - #[structopt(long, overrides_with("ignore-vcs"))] + #[clap(long, overrides_with("ignore-vcs"))] /// Don't respect ignore files in vcs directories. no_ignore_vcs: bool, - #[structopt(long, overrides_with("no-ignore-vcs"), hidden(true))] + #[clap(long, overrides_with("no-ignore-vcs"), hide = true)] ignore_vcs: bool, } @@ -285,6 +275,17 @@ fn resolve_bool_arg(yes: bool, no: bool) -> Option { (true, false) => Some(true), (false, true) => Some(false), (false, false) => None, - (_, _) => unreachable!("StructOpt should make this impossible"), + (_, _) => unreachable!("clap should make this impossible"), + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn verify_app() { + use clap::IntoApp; + Args::into_app().debug_assert() } } diff --git a/src/bin/typos-cli/main.rs b/src/bin/typos-cli/main.rs index cb2c636..7df73d7 100644 --- a/src/bin/typos-cli/main.rs +++ b/src/bin/typos-cli/main.rs @@ -1,10 +1,6 @@ -// 2015-edition macros. -#[macro_use] -extern crate clap; - use std::io::Write; -use structopt::StructOpt; +use clap::Parser; mod args; mod report; @@ -19,13 +15,14 @@ fn main() { fn run() -> proc_exit::ExitResult { // clap's `get_matches` uses Failure rather than Usage, so bypass it for `get_matches_safe`. - let args = match args::Args::from_args_safe() { + let args = match args::Args::try_parse() { Ok(args) => args, Err(e) if e.use_stderr() => { - return Err(proc_exit::Code::USAGE_ERR.with_message(e)); + let _ = e.print(); + return proc_exit::Code::USAGE_ERR.ok(); } Err(e) => { - writeln!(std::io::stdout(), "{}", e)?; + let _ = e.print(); return proc_exit::Code::SUCCESS.ok(); } };