From 9e2c98b74713f2e9efb2b662530b92deff033ee4 Mon Sep 17 00:00:00 2001 From: Xithrius <15021300+Xithrius@users.noreply.github.com> Date: Sat, 1 Oct 2022 17:34:42 -0700 Subject: [PATCH] Clap 4.0 (#227) --- .github/workflows/greetings.yml | 20 -------- Cargo.lock | 51 +++++++------------- Cargo.toml | 18 +++---- src/handlers/args.rs | 83 ++++++++++++++++++++++++--------- src/handlers/config.rs | 30 +++++++++++- src/handlers/data.rs | 2 +- src/ui/mod.rs | 2 +- src/utils/text.rs | 32 +++++++------ 8 files changed, 133 insertions(+), 105 deletions(-) delete mode 100644 .github/workflows/greetings.yml diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml deleted file mode 100644 index 48eec48..0000000 --- a/.github/workflows/greetings.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Greetings - -on: - pull_request: - branches: [ main ] - issues: - branches: [ main ] - -jobs: - greeting: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/first-interaction@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - issue-message: 'Thank you for the issue! This issue will be addressed in a reasonable amount of time.' - pr-message: 'Thank you for the pull request! This contribution will be addressed in a reasonable amount of time.' diff --git a/Cargo.lock b/Cargo.lock index b1455a2..00f22de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,26 +120,24 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.20" +version = "4.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" +checksum = "0a1af219c3e254a8b4649d6ddaef886b2015089f35f2ac5e1db31410c0566ab8" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap", "once_cell", "strsim", "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.18" +version = "4.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +checksum = "cd114ae53ce5a0670f43d2f169c1cd26c69b4896b0c121900cf1e4d06d67316c" dependencies = [ "heck", "proc-macro-error", @@ -150,9 +148,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ "os_str_bytes", ] @@ -527,12 +525,6 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "heck" version = "0.4.0" @@ -568,16 +560,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" -dependencies = [ - "autocfg", - "hashbrown", -] - [[package]] name = "instant" version = "0.1.12" @@ -960,9 +942,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] @@ -1269,9 +1251,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" dependencies = [ "smawk", "unicode-linebreak", @@ -1320,9 +1302,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.20.0" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57aec3cfa4c296db7255446efb4928a6be304b431a806216105542a67b6ca82e" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -1330,7 +1312,6 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", @@ -1492,15 +1473,15 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "utf8parse" diff --git a/Cargo.toml b/Cargo.toml index eae0548..9ea107e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,17 +15,17 @@ categories = ["command-line-utilities"] [dependencies] crossterm = "0.25.0" tui = { version = "0.19.0", default-features = false, features = [ "crossterm" ] } -tokio = { version = "1.20.0", features = [ "full" ] } -clap = { version = "3.2.13", features = [ "derive", "cargo" ] } -serde = { version = "1.0.140", features = [ "derive" ] } -serde_json = "1.0.82" -unicode-width = "0.1.9" -unicode-segmentation = "1.9.0" -chrono = "0.4" +tokio = { version = "1.21.1", features = [ "full" ] } +clap = { version = "4.0.7", features = [ "derive", "cargo" ] } +serde = { version = "1.0.144", features = [ "derive" ] } +serde_json = "1.0.85" +unicode-width = "0.1.10" +unicode-segmentation = "1.10.0" +chrono = "0.4.22" irc = "0.15.0" -futures = "0.3.21" +futures = "0.3.24" toml = "0.5.9" -textwrap = "0.15.0" +textwrap = "0.15.1" rustyline = "10.0.0" lazy_static = "1.4.0" fuzzy-matcher = "0.3.7" diff --git a/src/handlers/args.rs b/src/handlers/args.rs index dc38e32..386d948 100644 --- a/src/handlers/args.rs +++ b/src/handlers/args.rs @@ -1,47 +1,87 @@ -use std::str::FromStr; +use clap::{builder::PossibleValue, Parser}; -use clap::Parser; +use crate::handlers::config::{Alignment, CompleteConfig, Palette, Theme}; -use crate::handlers::config::{CompleteConfig, Palette, Theme}; +impl clap::ValueEnum for Alignment { + fn value_variants<'a>() -> &'a [Self] { + &[Self::Left, Self::Center, Self::Right] + } -#[derive(Parser)] + fn to_possible_value<'a>(&self) -> Option { + Some(PossibleValue::new(match self { + Self::Left => "left", + Self::Center => "center", + Self::Right => "right", + })) + } +} + +impl clap::ValueEnum for Palette { + fn value_variants<'a>() -> &'a [Self] { + &[Self::Pastel, Self::Vibrant, Self::Warm, Self::Cool] + } + + fn to_possible_value<'a>(&self) -> Option { + Some(PossibleValue::new(match self { + Self::Pastel => "pastel", + Self::Vibrant => "vibrant", + Self::Warm => "warm", + Self::Cool => "cool", + })) + } +} + +impl clap::ValueEnum for Theme { + fn value_variants<'a>() -> &'a [Self] { + &[Self::Dark, Self::Light] + } + + fn to_possible_value<'a>(&self) -> Option { + Some(PossibleValue::new(match self { + Self::Light => "light", + _ => "dark", + })) + } +} + +#[derive(Parser, Debug)] #[clap(rename_all = "kebab-case")] #[clap(author, version, about)] /// Twitch chat in the terminal pub struct Cli { /// The streamer's name - #[clap(short, long)] + #[arg(short, long)] pub channel: Option, /// File to log to - #[clap(short, long)] + #[arg(short, long)] pub log_file: Option, /// If debug logs should be shown - #[clap(short, long)] + #[arg(short, long)] pub verbose: bool, /// The delay in milliseconds between terminal updates - #[clap(short, long)] + #[arg(short, long)] pub tick_delay: Option, /// The maximum amount of messages to be stored - #[clap(short, long)] + #[arg(short, long)] pub max_messages: Option, /// Show the date/time - #[clap(short, long, possible_values = &["true", "false"])] - pub date_shown: Option, + #[arg(short, long)] + pub date_shown: bool, /// Maximum length for Twitch usernames - #[clap(short = 'u', long)] + #[arg(short = 'u', long)] pub max_username_length: Option, /// Username column alignment - #[clap(short = 'a', long, possible_values = &["left", "center", "right"])] - pub username_alignment: Option, + #[arg(short = 'a', long)] + pub username_alignment: Option, /// Username color palette - #[clap(short, long, possible_values = &["pastel", "vibrant", "warm", "cool"])] + #[arg(short, long)] pub palette: Option, /// Twitch badges support - #[clap(short, long)] + #[arg(short, long)] pub badges: bool, /// The theme of the terminal - #[clap(long, possible_values = &["dark", "light"])] - pub theme: Option, + #[arg(long)] + pub theme: Option, } pub fn merge_args_into_config(config: &mut CompleteConfig, args: Cli) { @@ -64,9 +104,8 @@ pub fn merge_args_into_config(config: &mut CompleteConfig, args: Cli) { } // Frontend arguments - if let Some(date_shown) = args.date_shown { - config.frontend.date_shown = matches!(date_shown.as_str(), "true"); - } + config.frontend.date_shown = args.date_shown; + if let Some(maximum_username_length) = args.max_username_length { config.frontend.maximum_username_length = maximum_username_length; } @@ -78,6 +117,6 @@ pub fn merge_args_into_config(config: &mut CompleteConfig, args: Cli) { } config.frontend.badges = args.badges; if let Some(theme) = args.theme { - config.frontend.theme = Theme::from_str(theme.as_str()).unwrap(); + config.frontend.theme = theme; } } diff --git a/src/handlers/config.rs b/src/handlers/config.rs index 54126d6..0be38a5 100644 --- a/src/handlers/config.rs +++ b/src/handlers/config.rs @@ -84,7 +84,7 @@ pub struct FrontendConfig { /// The maximum length of a Twitch username. pub maximum_username_length: u16, /// Which side the username should be aligned to. - pub username_alignment: String, + pub username_alignment: Alignment, /// The color palette. pub palette: Palette, /// Show Title with time and channel. @@ -129,7 +129,7 @@ impl Default for FrontendConfig { date_shown: true, date_format: "%a %b %e %T %Y".to_string(), maximum_username_length: 26, - username_alignment: "right".to_string(), + username_alignment: Alignment::default(), palette: Palette::default(), title_shown: true, margin: 0, @@ -141,6 +141,32 @@ impl Default for FrontendConfig { } } +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum Alignment { + Left, + Center, + Right, +} + +impl Default for Alignment { + fn default() -> Self { + Self::Right + } +} + +impl FromStr for Alignment { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s { + "left" => Ok(Self::Left), + "center" => Ok(Self::Center), + _ => Ok(Self::Right), + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "lowercase")] pub enum Palette { diff --git a/src/handlers/data.rs b/src/handlers/data.rs index e880f33..280faee 100644 --- a/src/handlers/data.rs +++ b/src/handlers/data.rs @@ -176,7 +176,7 @@ impl Data { let mut cell_vector = vec![ Cell::from(align_text( &self.author, - frontend_config.username_alignment.as_str(), + frontend_config.username_alignment, frontend_config.maximum_username_length, )) .style(if self.system { diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 75b517a..da1eb43 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -76,7 +76,7 @@ impl<'a, 'b, 'c, T: Backend> WindowAttributes<'a, 'b, 'c, T> { pub fn draw_ui(frame: &mut Frame, app: &mut App, config: &CompleteConfig) { let username_column_title = align_text( "Username", - &config.frontend.username_alignment, + config.frontend.username_alignment, config.frontend.maximum_username_length, ); diff --git a/src/utils/text.rs b/src/utils/text.rs index c0b6816..577c757 100644 --- a/src/utils/text.rs +++ b/src/utils/text.rs @@ -6,7 +6,9 @@ use tui::{style::Style, text::Span}; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; -pub fn align_text(text: &str, alignment: &str, maximum_length: u16) -> String { +use crate::handlers::config::Alignment; + +pub fn align_text(text: &str, alignment: Alignment, maximum_length: u16) -> String { assert!( maximum_length >= 1, "Parameter of 'maximum_length' cannot be below 1." @@ -20,13 +22,13 @@ pub fn align_text(text: &str, alignment: &str, maximum_length: u16) -> String { } match alignment { - "right" => format!("{}{}", " ".repeat(maximum_length as usize - dw), text), - "center" => { + Alignment::Right => format!("{}{}", " ".repeat(maximum_length as usize - dw), text), + Alignment::Center => { let side_spaces = " ".repeat(((maximum_length / 2) - (((dw / 2) as f32).floor() as u16)) as usize); format!("{}{}{}", side_spaces, text, side_spaces) } - _ => text.to_string(), + Alignment::Left => text.to_string(), } } @@ -122,35 +124,35 @@ mod tests { #[test] #[should_panic(expected = "Parameter of 'maximum_length' cannot be below 1.")] fn test_text_align_maximum_length() { - align_text("", "left", 0); + align_text("", Alignment::Left, 0); } #[test] fn test_text_align_left() { - assert_eq!(align_text("a", "left", 10), "a".to_string()); - assert_eq!(align_text("a", "left", 1), "a".to_string()); + assert_eq!(align_text("a", Alignment::Left, 10), "a".to_string()); + assert_eq!(align_text("a", Alignment::Left, 1), "a".to_string()); } #[test] fn test_text_align_right() { assert_eq!( - align_text("a", "right", 10), + align_text("a", Alignment::Right, 10), format!("{}{}", " ".repeat(9), "a") ); - assert_eq!(align_text("a", "right", 1), "a".to_string()); - assert_eq!(align_text("你好", "right", 5), " 你好"); - assert_eq!(align_text("👑123", "right", 6), " 👑123"); + assert_eq!(align_text("a", Alignment::Right, 1), "a".to_string()); + assert_eq!(align_text("你好", Alignment::Right, 5), " 你好"); + assert_eq!(align_text("👑123", Alignment::Right, 6), " 👑123"); } #[test] fn test_text_align_center() { assert_eq!( - align_text("a", "center", 11), + align_text("a", Alignment::Center, 11), format!("{}{}{}", " ".repeat(5), "a", " ".repeat(5)) ); - assert_eq!(align_text("a", "center", 1), "a".to_string()); - assert_eq!(align_text("你好", "center", 6), " 你好 "); - assert_eq!(align_text("👑123", "center", 7), " 👑123 "); + assert_eq!(align_text("a", Alignment::Center, 1), "a".to_string()); + assert_eq!(align_text("你好", Alignment::Center, 6), " 你好 "); + assert_eq!(align_text("👑123", Alignment::Center, 7), " 👑123 "); } #[test]