1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-02-22 12:58:26 +00:00

refactor: Port to clap3

Ths does remove the specialization of version's description.  The way
this is done (internally through `mut_arg`) doesn't play well with
subcommands.  Clap tries to force this version of `version` into the
subcommand despite not being needed.  Clap v4 dramatically changes how
version customization works.

clap also does more error checks now to prevent programmer mistake, so
we can't have a conflict with an argument that is conditionally there,
so I swapped the condition.
This commit is contained in:
Ed Page 2022-09-01 15:41:07 -05:00 committed by David Peter
parent 49875d6ce7
commit 2323804f7e
5 changed files with 61 additions and 56 deletions

55
Cargo.lock generated
View File

@ -193,18 +193,28 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.34.0" version = "3.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
dependencies = [ dependencies = [
"ansi_term",
"atty", "atty",
"bitflags", "bitflags",
"clap_lex",
"indexmap",
"once_cell",
"strsim", "strsim",
"term_size", "termcolor",
"terminal_size",
"textwrap", "textwrap",
"unicode-width", ]
"vec_map",
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
] ]
[[package]] [[package]]
@ -715,6 +725,12 @@ dependencies = [
"pkg-config", "pkg-config",
] ]
[[package]]
name = "os_str_bytes"
version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.2" version = "0.11.2"
@ -1045,9 +1061,9 @@ checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
@ -1108,16 +1124,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "term_size"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.1.2" version = "1.1.2"
@ -1145,12 +1151,11 @@ checksum = "13a4ec180a2de59b57434704ccfad967f789b12737738798fa08798cd5824c16"
[[package]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.11.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
dependencies = [ dependencies = [
"term_size", "terminal_size",
"unicode-width",
] ]
[[package]] [[package]]
@ -1243,12 +1248,6 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"

View File

@ -77,10 +77,10 @@ default-features = false
features = ["parsing"] features = ["parsing"]
[dependencies.clap] [dependencies.clap]
version = "2.34" version = "3.2.20"
optional = true optional = true
default-features = false default-features = false
features = ["suggestions", "color", "wrap_help"] features = ["std", "suggestions", "color", "wrap_help", "cargo"]
[dev-dependencies] [dev-dependencies]
assert_cmd = "2.0.4" assert_cmd = "2.0.4"
@ -93,7 +93,7 @@ tempfile = "3.3.0"
nix = { version = "0.24.2", default-features = false, features = ["term"] } nix = { version = "0.24.2", default-features = false, features = ["term"] }
[build-dependencies] [build-dependencies]
clap = { version = "2.34", optional = true } clap = { version = "3.2.20", optional = true }
[profile.release] [profile.release]
lto = true lto = true

View File

@ -32,7 +32,7 @@ fn is_truecolor_terminal() -> bool {
} }
pub struct App { pub struct App {
pub matches: ArgMatches<'static>, pub matches: ArgMatches,
interactive_output: bool, interactive_output: bool,
} }
@ -49,7 +49,7 @@ impl App {
}) })
} }
fn matches(interactive_output: bool) -> Result<ArgMatches<'static>> { fn matches(interactive_output: bool) -> Result<ArgMatches> {
let args = if wild::args_os().nth(1) == Some("cache".into()) let args = if wild::args_os().nth(1) == Some("cache".into())
|| wild::args_os().any(|arg| arg == "--no-config") || wild::args_os().any(|arg| arg == "--no-config")
{ {

View File

@ -16,7 +16,7 @@ static VERSION: Lazy<String> = Lazy::new(|| {
} }
}); });
pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> { pub fn build_app(interactive_output: bool) -> ClapApp<'static> {
let clap_color_setting = if interactive_output && env::var_os("NO_COLOR").is_none() { let clap_color_setting = if interactive_output && env::var_os("NO_COLOR").is_none() {
AppSettings::ColoredHelp AppSettings::ColoredHelp
} else { } else {
@ -32,7 +32,6 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.setting(AppSettings::ArgsNegateSubcommands) .setting(AppSettings::ArgsNegateSubcommands)
.setting(AppSettings::AllowExternalSubcommands) .setting(AppSettings::AllowExternalSubcommands)
.setting(AppSettings::DisableHelpSubcommand) .setting(AppSettings::DisableHelpSubcommand)
.setting(AppSettings::VersionlessSubcommands)
.max_term_width(100) .max_term_width(100)
.about( .about(
"A cat(1) clone with wings.\n\n\ "A cat(1) clone with wings.\n\n\
@ -50,14 +49,16 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
"File(s) to print / concatenate. Use a dash ('-') or no argument at all \ "File(s) to print / concatenate. Use a dash ('-') or no argument at all \
to read from standard input.", to read from standard input.",
) )
.takes_value(true)
.multiple(true) .multiple(true)
.empty_values(false), .empty_values(false)
.allow_invalid_utf8(true),
) )
.arg( .arg(
Arg::with_name("show-all") Arg::with_name("show-all")
.long("show-all") .long("show-all")
.alias("show-nonprintable") .alias("show-nonprintable")
.short("A") .short('A')
.conflicts_with("language") .conflicts_with("language")
.help("Show non-printable characters (space, tab, newline, ..).") .help("Show non-printable characters (space, tab, newline, ..).")
.long_help( .long_help(
@ -70,9 +71,9 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
Arg::with_name("plain") Arg::with_name("plain")
.overrides_with("plain") .overrides_with("plain")
.overrides_with("number") .overrides_with("number")
.short("p") .short('p')
.long("plain") .long("plain")
.multiple(true) .multiple_occurrences(true)
.help("Show plain style (alias for '--style=plain').") .help("Show plain style (alias for '--style=plain').")
.long_help( .long_help(
"Only show plain style, no decorations. This is an alias for \ "Only show plain style, no decorations. This is an alias for \
@ -82,7 +83,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
) )
.arg( .arg(
Arg::with_name("language") Arg::with_name("language")
.short("l") .short('l')
.long("language") .long("language")
.overrides_with("language") .overrides_with("language")
.help("Set the language for syntax highlighting.") .help("Set the language for syntax highlighting.")
@ -97,7 +98,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("highlight-line") Arg::with_name("highlight-line")
.long("highlight-line") .long("highlight-line")
.short("H") .short('H')
.takes_value(true) .takes_value(true)
.number_of_values(1) .number_of_values(1)
.multiple(true) .multiple(true)
@ -120,6 +121,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.number_of_values(1) .number_of_values(1)
.multiple(true) .multiple(true)
.value_name("name") .value_name("name")
.allow_invalid_utf8(true)
.help("Specify the name to display for a file.") .help("Specify the name to display for a file.")
.long_help( .long_help(
"Specify the name to display for a file. Useful when piping \ "Specify the name to display for a file. Useful when piping \
@ -135,7 +137,8 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("diff") Arg::with_name("diff")
.long("diff") .long("diff")
.short("d") .short('d')
.conflicts_with("line-range")
.help("Only show lines that have been added/removed/modified.") .help("Only show lines that have been added/removed/modified.")
.long_help( .long_help(
"Only show lines that have been added/removed/modified with respect \ "Only show lines that have been added/removed/modified with respect \
@ -226,7 +229,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
Arg::with_name("number") Arg::with_name("number")
.long("number") .long("number")
.overrides_with("number") .overrides_with("number")
.short("n") .short('n')
.help("Show line numbers (alias for '--style=numbers').") .help("Show line numbers (alias for '--style=numbers').")
.long_help( .long_help(
"Only show line numbers, no other decorations. This is an alias for \ "Only show line numbers, no other decorations. This is an alias for \
@ -280,7 +283,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("force-colorization") Arg::with_name("force-colorization")
.long("force-colorization") .long("force-colorization")
.short("f") .short('f')
.conflicts_with("color") .conflicts_with("color")
.conflicts_with("decorations") .conflicts_with("decorations")
.overrides_with("force-colorization") .overrides_with("force-colorization")
@ -309,7 +312,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
) )
.arg( .arg(
Arg::with_name("no-paging") Arg::with_name("no-paging")
.short("P") .short('P')
.long("no-paging") .long("no-paging")
.alias("no-pager") .alias("no-pager")
.overrides_with("no-paging") .overrides_with("no-paging")
@ -334,7 +337,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
) )
.arg( .arg(
Arg::with_name("map-syntax") Arg::with_name("map-syntax")
.short("m") .short('m')
.long("map-syntax") .long("map-syntax")
.multiple(true) .multiple(true)
.takes_value(true) .takes_value(true)
@ -450,12 +453,11 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("line-range") Arg::with_name("line-range")
.long("line-range") .long("line-range")
.short("r") .short('r')
.multiple(true) .multiple(true)
.takes_value(true) .takes_value(true)
.number_of_values(1) .number_of_values(1)
.value_name("N:M") .value_name("N:M")
.conflicts_with("diff")
.help("Only print the lines from N to M.") .help("Only print the lines from N to M.")
.long_help( .long_help(
"Only print the specified range of lines for each file. \ "Only print the specified range of lines for each file. \
@ -470,14 +472,14 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("list-languages") Arg::with_name("list-languages")
.long("list-languages") .long("list-languages")
.short("L") .short('L')
.conflicts_with("list-themes") .conflicts_with("list-themes")
.help("Display all supported languages.") .help("Display all supported languages.")
.long_help("Display a list of supported languages for syntax highlighting."), .long_help("Display a list of supported languages for syntax highlighting."),
) )
.arg( .arg(
Arg::with_name("unbuffered") Arg::with_name("unbuffered")
.short("u") .short('u')
.long("unbuffered") .long("unbuffered")
.hidden_short_help(true) .hidden_short_help(true)
.long_help( .long_help(
@ -539,8 +541,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.hidden_short_help(true) .hidden_short_help(true)
.help("Show acknowledgements."), .help("Show acknowledgements."),
) )
.help_message("Print this help message.") .help_message("Print this help message.");
.version_message("Show version information.");
// Check if the current directory contains a file name cache. Otherwise, // Check if the current directory contains a file name cache. Otherwise,
// enable the 'bat cache' subcommand. // enable the 'bat cache' subcommand.
@ -553,7 +554,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("build") Arg::with_name("build")
.long("build") .long("build")
.short("b") .short('b')
.help("Initialize (or update) the syntax/theme cache.") .help("Initialize (or update) the syntax/theme cache.")
.long_help( .long_help(
"Initialize (or update) the syntax/theme cache by loading from \ "Initialize (or update) the syntax/theme cache by loading from \
@ -563,7 +564,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.arg( .arg(
Arg::with_name("clear") Arg::with_name("clear")
.long("clear") .long("clear")
.short("c") .short('c')
.help("Remove the cached syntax definitions and themes."), .help("Remove the cached syntax definitions and themes."),
) )
.group( .group(
@ -607,3 +608,8 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
) )
} }
} }
#[test]
fn verify_app() {
build_app(false).debug_assert();
}

View File

@ -293,11 +293,11 @@ fn run() -> Result<bool> {
} }
match app.matches.subcommand() { match app.matches.subcommand() {
("cache", Some(cache_matches)) => { Some(("cache", cache_matches)) => {
// If there is a file named 'cache' in the current working directory, // If there is a file named 'cache' in the current working directory,
// arguments for subcommand 'cache' are not mandatory. // arguments for subcommand 'cache' are not mandatory.
// If there are non-zero arguments, execute the subcommand cache, else, open the file cache. // If there are non-zero arguments, execute the subcommand cache, else, open the file cache.
if !cache_matches.args.is_empty() { if cache_matches.args_present() {
run_cache_subcommand(cache_matches)?; run_cache_subcommand(cache_matches)?;
Ok(true) Ok(true)
} else { } else {