From b004c4f1d59520e7b2965da25e8c58c9aa2fa924 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 21 Nov 2023 13:34:32 -0500 Subject: Bump clap to 4.4.8 --- Cargo.lock | 195 ++++++++++++++++++++++++++++++++++++++++++++++-------------- Cargo.toml | 2 +- src/main.rs | 195 ++++++++++++++++++++++++++++++++---------------------------- 3 files changed, 257 insertions(+), 135 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29219a1..1d83038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,23 +18,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", ] [[package]] @@ -81,25 +109,56 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.34.0" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "crc32fast" version = "1.3.2" @@ -250,13 +309,10 @@ dependencies = [ ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "image" @@ -540,9 +596,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -566,15 +622,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.50" @@ -613,16 +660,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "vec_map" -version = "0.8.2" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "wasi" @@ -658,6 +699,72 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/Cargo.toml b/Cargo.toml index 3b57b13..dd270a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] acap = "0.3.0" -clap = "2.34.0" +clap = { version = "4.4.8", features = ["derive"] } image = "0.24.7" rand = "0.8.5" rand_pcg = "0.3.1" diff --git a/src/main.rs b/src/main.rs index e9df476..204a582 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,8 @@ use crate::frontier::mean::MeanFrontier; use crate::frontier::min::MinFrontier; use crate::frontier::Frontier; -use clap::{self, clap_app, crate_authors, crate_name, crate_version}; +use clap::{ArgAction, CommandFactory, Parser, ValueEnum}; +use clap::error::ErrorKind; use image::{self, ColorType, ImageEncoder, ImageError, Rgba, RgbaImage}; use image::codecs::png::{CompressionType, FilterType, PngEncoder}; @@ -24,7 +25,6 @@ use std::error::Error; use std::io::{self, BufWriter, IsTerminal, Write}; use std::path::PathBuf; use std::process::exit; -use std::str::FromStr; use std::time::Instant; /// The color source specified on the command line. @@ -50,29 +50,107 @@ enum OrderArg { } /// The frontier implementation. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, ValueEnum)] enum FrontierArg { /// Pick a neighbor of the closest pixel so far. Min, /// Pick the pixel with the closest mean color of all its neighbors. Mean, /// Target the closest pixel on an image. + #[value(skip)] Image(PathBuf), } /// The color space to operate in. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)] enum ColorSpaceArg { /// sRGB space. + #[value(name = "RGB")] Rgb, /// CIE L*a*b* space. + #[value(name = "Lab")] Lab, /// CIE L*u*v* space. + #[value(name = "Luv")] Luv, /// Oklab space. + #[value(name = "Oklab")] Oklab, } +/// k-d forests. +#[derive(Debug, Parser)] +#[command(author, version, about, disable_help_flag = true)] +struct Cli { + /// Use all -bit colors. + #[arg(short, long, group = "source", value_name = "DEPTH", default_value = "24")] + bit_depth: Option, + /// use colors from the image. + #[arg(short, long, group = "source", value_name = "INPUT")] + input: Option, + + /// Sort colors by hue [default]. + #[arg(short = 's', long, group = "order", default_value_t = true)] + hue_sort: bool, + /// Randomize colors. + #[arg(short, long, group = "order")] + random: bool, + /// Place colors in Morton order (Z-order). + #[arg(short = 'M', long, group = "order")] + morton: bool, + /// Place colors in Hilbert curve order + #[arg(short = 'H', long, group = "order")] + hilbert: bool, + + /// Reduce artifacts by iterating through the colors in multiple stripes [default]. + #[arg(short = 't', long, group = "stripe?", default_value_t = true)] + stripe: bool, + /// Don't stripe. + #[arg(short = 'T', long, group = "stripe?")] + no_stripe: bool, + + /// Specify the selection mode. + #[arg(short = 'l', long, group = "frontier", value_name = "MODE", default_value = "min")] + selection: FrontierArg, + /// Place colors on the closest pixels of the image. + #[arg(short = 'g', long, group = "frontier", value_name = "TARGET")] + target: Option, + + /// Use the given color space. + #[arg(short, long, value_name = "SPACE", default_value = "Lab")] + color_space: ColorSpaceArg, + + /// The width of the generated image. + #[arg(short, long)] + width: Option, + /// The height of the generated image. + #[arg(short, long)] + height: Option, + + /// The x coordinate of the first pixel. + #[arg(short, value_name = "X")] + x0: Option, + /// The y coordinate of the first pixel. + #[arg(short, value_name = "Y")] + y0: Option, + + /// Generate frames of an animation. + #[arg(short, long)] + animate: bool, + + /// Save the image to . + #[arg(short, long, value_name = "PATH", default_value = "kd-forest.png")] + output: PathBuf, + + /// Seed the random number generator. + #[arg(short = 'e', long, default_value_t = 0)] + seed: u64, + + /// Print help. + #[arg(short = '?', long, action = ArgAction::Help)] + help: (), +} + /// Error type for this app. #[derive(Debug)] enum AppError { @@ -83,10 +161,7 @@ enum AppError { impl AppError { /// Create an error for an invalid argument. fn invalid_value(msg: &str) -> Self { - Self::ArgError(clap::Error::with_description( - msg, - clap::ErrorKind::InvalidValue, - )) + Self::ArgError(Cli::command().error(ErrorKind::InvalidValue, msg)) } /// Exit the program with this error. @@ -128,19 +203,6 @@ impl From for AppError { /// Result type for this app. type AppResult = Result; -/// Parse an argument into the appropriate type. -fn parse_arg(arg: Option<&str>) -> AppResult> -where - F: FromStr, - F::Err: Error, -{ - match arg.map(|s| s.parse()) { - Some(Ok(f)) => Ok(Some(f)), - Some(Err(e)) => Err(AppError::invalid_value(&e.to_string())), - None => Ok(None), - } -} - /// The parsed command line arguments. #[derive(Debug)] struct Args { @@ -160,49 +222,14 @@ struct Args { impl Args { fn parse() -> AppResult { - let args = clap_app!((crate_name!()) => - (version: crate_version!()) - (author: crate_authors!()) - (@setting ColoredHelp) - (@setting DeriveDisplayOrder) - (@setting UnifiedHelpMessage) - (@group source => - (@arg DEPTH: -b --("bit-depth") +takes_value "Use all DEPTH-bit colors") - (@arg INPUT: -i --input +takes_value "Use colors from the INPUT image") - ) - (@group order => - (@arg HUE: -s --hue-sort "Sort colors by hue [default]") - (@arg RANDOM: -r --random "Randomize colors") - (@arg MORTON: -M --morton "Place colors in Morton order (Z-order)") - (@arg HILBERT: -H --hilbert "Place colors in Hilbert curve order") - ) - (@group stripe => - (@arg STRIPE: -t --stripe "Reduce artifacts by iterating through the colors in multiple stripes [default]") - (@arg NOSTRIPE: -T --("no-stripe") "Don't stripe") - ) - (@group frontier => - (@arg MODE: -l --selection +takes_value possible_value[min mean] "Specify the selection mode") - (@arg TARGET: -g --target +takes_value "Place colors on the closest pixels of the TARGET image") - ) - (@arg SPACE: -c --("color-space") default_value("Lab") possible_value[RGB Lab Luv Oklab] "Use the given color space") - (@arg WIDTH: -w --width +takes_value "The width of the generated image") - (@arg HEIGHT: -h --height +takes_value "The height of the generated image") - (@arg X: -x +takes_value "The x coordinate of the first pixel") - (@arg Y: -y +takes_value "The y coordinate of the first pixel") - (@arg ANIMATE: -a --animate "Generate frames of an animation") - (@arg PATH: -o --output default_value("kd-forest.png") "Save the image to PATH") - (@arg SEED: -e --seed default_value("0") "Seed the random number generator") - ) - .get_matches_safe()?; + let args = Cli::try_parse()?; - let source = if let Some(input) = args.value_of("INPUT") { - SourceArg::Image(PathBuf::from(input)) + let source = if let Some(input) = args.input { + SourceArg::Image(input) } else { - let arg = args.value_of("DEPTH"); + let arg = args.bit_depth.unwrap(); let depths: Vec<_> = arg - .iter() - .map(|s| s.split(',')) - .flatten() + .split(',') .map(|n| n.parse().ok()) .collect(); @@ -216,62 +243,50 @@ impl Args { _ => { return Err(AppError::invalid_value( - &format!("invalid bit depth {}", arg.unwrap()), + &format!("invalid bit depth {}", arg), )); } }; if r > 8 || g > 8 || b > 8 { return Err(AppError::invalid_value( - &format!("bit depth of {} is too deep!", arg.unwrap()), + &format!("bit depth of {} is too deep!", arg), )); } SourceArg::AllRgb(r, g, b) }; - let order = if args.is_present("RANDOM") { + let order = if args.random { OrderArg::Random - } else if args.is_present("MORTON") { + } else if args.morton { OrderArg::Morton - } else if args.is_present("HILBERT") { + } else if args.hilbert { OrderArg::Hilbert } else { OrderArg::HueSort }; - let stripe = !args.is_present("NOSTRIPE") && order != OrderArg::Random; + let stripe = !args.no_stripe && order != OrderArg::Random; - let frontier = if let Some(target) = args.value_of("TARGET") { - FrontierArg::Image(PathBuf::from(target)) + let frontier = if let Some(target) = args.target { + FrontierArg::Image(target) } else { - match args.value_of("MODE") { - Some("min") | None => FrontierArg::Min, - Some("mean") => FrontierArg::Mean, - _ => unreachable!(), - } + args.selection }; - let space = match args.value_of("SPACE").unwrap() { - "RGB" => ColorSpaceArg::Rgb, - "Lab" => ColorSpaceArg::Lab, - "Luv" => ColorSpaceArg::Luv, - "Oklab" => ColorSpaceArg::Oklab, - _ => unreachable!(), - }; + let space = args.color_space; - let width = parse_arg(args.value_of("WIDTH"))?; - let height = parse_arg(args.value_of("HEIGHT"))?; - let x0 = parse_arg(args.value_of("X"))?; - let y0 = parse_arg(args.value_of("Y"))?; + let width = args.width; + let height = args.height; + let x0 = args.x0; + let y0 = args.y0; - let animate = args.is_present("ANIMATE"); + let animate = args.animate; - let output = args.value_of("PATH") - .map(PathBuf::from) - .unwrap(); + let output = args.output; - let seed = parse_arg(args.value_of("SEED"))?.unwrap_or(0); + let seed = args.seed; Ok(Self { source, -- cgit v1.2.3