Data builder payload converted to string type

This commit is contained in:
Xithrius 2022-12-16 07:18:24 -08:00
parent 76dd136b28
commit 4ddaf5b733
No known key found for this signature in database
GPG Key ID: DADE524BA67AA52E
7 changed files with 47 additions and 143 deletions

4
Cargo.lock generated
View File

@ -1367,14 +1367,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"parking_lot 0.12.1",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.42.0",

View File

@ -15,7 +15,7 @@ categories = ["command-line-utilities"]
[dependencies]
crossterm = "0.25.0"
tui = { version = "0.19.0", default-features = false, features = [ "crossterm" ] }
tokio = { version = "1.23.0", features = [ "full" ] }
tokio = { version = "1.23.0", features = [ "rt", "macros", "rt-multi-thread" ] }
clap = { version = "4.0.29", features = [ "derive", "cargo" ] }
serde = { version = "1.0.149", features = [ "derive" ] }
serde_json = "1.0.89"

View File

@ -21,60 +21,24 @@ lazy_static! {
pub static ref FUZZY_FINDER: SkimMatcherV2 = SkimMatcherV2::default();
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub enum PayLoad {
Message(String),
Err(String),
}
#[derive(Debug, Copy, Clone)]
pub struct DataBuilder<'conf> {
pub date_format: &'conf str,
}
impl<'conf> DataBuilder<'conf> {
pub const fn new(date_format: &'conf str) -> Self {
DataBuilder { date_format }
}
pub fn user(user: String, message: String) -> Data {
Data {
time_sent: Local::now(),
author: user,
system: false,
payload: PayLoad::Message(message),
}
}
pub fn system(self, message: String) -> Data {
Data {
time_sent: Local::now(),
author: "System".to_string(),
system: true,
payload: PayLoad::Message(message),
}
}
pub fn twitch(self, message: String) -> Data {
Data {
time_sent: Local::now(),
author: "Twitch".to_string(),
system: true,
payload: PayLoad::Message(message),
}
}
}
#[derive(Debug, Clone)]
pub struct Data {
pub time_sent: DateTime<Local>,
pub author: String,
pub system: bool,
pub payload: PayLoad,
pub payload: String,
}
impl Data {
pub fn new(author: String, system: bool, payload: String) -> Self {
Self {
time_sent: Local::now(),
author,
system,
payload,
}
}
fn hash_username(&self, palette: &Palette) -> Color {
let hash = f64::from(
self.author
@ -104,11 +68,7 @@ impl Data {
username_highlight: Option<String>,
theme_style: Style,
) -> (Vec<Row>, u32) {
let message = if let PayLoad::Message(m) = &self.payload {
textwrap::fill(m.as_str(), limit)
} else {
panic!("Data.to_row() can only take an enum of PayLoad::Message.");
};
let message = textwrap::fill(self.payload.as_str(), limit);
let username_highlight_style = username_highlight.map_or_else(Style::default, |username| {
if Regex::new(format!("^.*{username}.*$").as_str())
@ -216,6 +176,29 @@ impl Data {
}
}
#[derive(Debug, Copy, Clone)]
pub struct DataBuilder<'conf> {
pub date_format: &'conf str,
}
impl<'conf> DataBuilder<'conf> {
pub const fn new(date_format: &'conf str) -> Self {
DataBuilder { date_format }
}
pub fn user(user: String, payload: String) -> Data {
Data::new(user, false, payload)
}
pub fn system(self, payload: String) -> Data {
Data::new("System".to_string(), true, payload)
}
pub fn twitch(self, payload: String) -> Data {
Data::new("Twitch".to_string(), true, payload)
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -223,13 +206,8 @@ mod tests {
#[test]
fn test_username_hash() {
assert_eq!(
Data {
time_sent: Local::now(),
author: "human".to_string(),
system: false,
payload: PayLoad::Message("beep boop".to_string()),
}
.hash_username(&Palette::Pastel),
Data::new("human".to_string(), false, "beep boop".to_string())
.hash_username(&Palette::Pastel),
Rgb(159, 223, 221)
);
}

View File

@ -50,7 +50,6 @@ impl Filters {
self.enabled = !self.enabled;
}
#[allow(dead_code)]
pub const fn reversed(&self) -> bool {
self.reversed
}

View File

@ -17,9 +17,9 @@ use tui::{backend::CrosstermBackend, Terminal};
use crate::{
handlers::{
app::{App, State},
app::App,
config::{CompleteConfig, CursorType},
data::{Data, DataBuilder, PayLoad},
data::Data,
user_input::{
events::{Config, Events, Key},
input::{handle_stateful_user_input, TerminalAction},
@ -114,21 +114,9 @@ pub async fn ui_driver(
terminal.clear().unwrap();
let date_format = config.frontend.date_format.clone();
let data_builder = DataBuilder::new(&date_format);
loop {
if let Ok(info) = rx.try_recv() {
match info.payload {
PayLoad::Message(_) => app.messages.push_front(info),
// If something such as a keypress failed, fallback to the normal state of the application.
PayLoad::Err(err) => {
app.state = State::Normal;
app.messages.push_front(data_builder.system(err));
}
}
app.messages.push_front(info);
// If scrolling is enabled, pad for more messages.
if app.scroll_offset > 0 {

View File

@ -16,7 +16,6 @@ use crate::{
handlers::{
app::{App, State},
config::CompleteConfig,
data::PayLoad,
},
utils::{
styles,
@ -144,10 +143,8 @@ pub fn draw_ui<T: Backend>(frame: &mut Frame<T>, app: &mut App, config: &Complet
let mut total_num_search_results = 0;
'outer: for data in &app.messages {
if let PayLoad::Message(msg) = data.payload.clone() {
if app.filters.contaminated(msg.as_str()) {
continue;
}
if app.filters.contaminated(data.payload.clone().as_str()) {
continue;
}
// Offsetting of messages for scrolling through said messages
@ -215,7 +212,11 @@ pub fn draw_ui<T: Backend>(frame: &mut Frame<T>, app: &mut App, config: &Complet
TitleStyle::Combined("Time", &current_time),
TitleStyle::Combined("Channel", config.twitch.channel.as_str()),
TitleStyle::Custom(Span::styled(
"Filter",
if app.filters.reversed() {
"retliF"
} else {
"Filter"
},
Style::default()
.add_modifier(Modifier::BOLD)
.fg(if app.filters.enabled() {

View File

@ -1,5 +1,3 @@
use std::vec::IntoIter;
use rustyline::line_buffer::LineBuffer;
use textwrap::core::display_width;
use tui::{style::Style, text::Span};
@ -35,31 +33,6 @@ pub fn align_text(text: &str, alignment: Alignment, maximum_length: u16) -> Stri
}
}
#[allow(dead_code)]
pub fn vector_column_max<T>(v: &[Vec<T>]) -> IntoIter<u16>
where
T: AsRef<str>,
{
assert!(
!v.is_empty(),
"Vector length should be greater than or equal to 1."
);
let column_max = |vec: &[Vec<T>], index: usize| -> u16 {
vec.iter().map(|v| v[index].as_ref().len()).max().unwrap() as u16
};
let column_amount = v[0].len();
let mut column_max_lengths: Vec<u16> = vec![];
for i in 0..column_amount {
column_max_lengths.push(column_max(v, i));
}
column_max_lengths.into_iter()
}
/// Acquiring the horizontal position of the cursor so it can be rendered visually.
pub fn get_cursor_position(line_buffer: &LineBuffer) -> usize {
line_buffer
@ -158,37 +131,6 @@ mod tests {
assert_eq!(align_text("👑123", Alignment::Center, 7), " 👑123 ");
}
#[test]
#[should_panic(expected = "Vector length should be greater than or equal to 1.")]
fn test_vector_column_max_empty_vector() {
let vec: Vec<Vec<String>> = vec![];
vector_column_max(&vec);
}
#[test]
fn test_vector_column_max_reference_strings() {
let vec = vec![vec!["", "s"], vec!["longer string", "lll"]];
let mut output_vec_all = vector_column_max(&vec);
assert_eq!(output_vec_all.next(), Some(13));
assert_eq!(output_vec_all.next(), Some(3));
}
#[test]
fn test_vector_column_max_strings() {
let vec = vec![
vec![String::new(), "another".to_string()],
vec![String::new(), "the last string".to_string()],
];
let mut output_vec_all = vector_column_max(&vec);
assert_eq!(output_vec_all.next(), Some(0));
assert_eq!(output_vec_all.next(), Some(15));
}
#[test]
fn test_get_cursor_position_with_single_byte_graphemes() {
let text = "never gonna give you up";