mirror of
https://github.com/Xithrius/twitch-tui.git
synced 2024-08-16 09:01:11 +03:00
Clap 4.0 (#227)
This commit is contained in:
parent
87d7b8892f
commit
9e2c98b747
20
.github/workflows/greetings.yml
vendored
20
.github/workflows/greetings.yml
vendored
@ -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.'
|
51
Cargo.lock
generated
51
Cargo.lock
generated
@ -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"
|
||||
|
18
Cargo.toml
18
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"
|
||||
|
@ -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<PossibleValue> {
|
||||
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<PossibleValue> {
|
||||
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<PossibleValue> {
|
||||
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<String>,
|
||||
/// File to log to
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long)]
|
||||
pub log_file: Option<String>,
|
||||
/// 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<u64>,
|
||||
/// The maximum amount of messages to be stored
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long)]
|
||||
pub max_messages: Option<usize>,
|
||||
/// Show the date/time
|
||||
#[clap(short, long, possible_values = &["true", "false"])]
|
||||
pub date_shown: Option<String>,
|
||||
#[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<u16>,
|
||||
/// Username column alignment
|
||||
#[clap(short = 'a', long, possible_values = &["left", "center", "right"])]
|
||||
pub username_alignment: Option<String>,
|
||||
#[arg(short = 'a', long)]
|
||||
pub username_alignment: Option<Alignment>,
|
||||
/// Username color palette
|
||||
#[clap(short, long, possible_values = &["pastel", "vibrant", "warm", "cool"])]
|
||||
#[arg(short, long)]
|
||||
pub palette: Option<Palette>,
|
||||
/// 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<String>,
|
||||
#[arg(long)]
|
||||
pub theme: Option<Theme>,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Self, Self::Err> {
|
||||
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 {
|
||||
|
@ -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 {
|
||||
|
@ -76,7 +76,7 @@ impl<'a, 'b, 'c, T: Backend> WindowAttributes<'a, 'b, 'c, T> {
|
||||
pub fn draw_ui<T: Backend>(frame: &mut Frame<T>, 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,
|
||||
);
|
||||
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user