From e5a51be87ecbd839c9821029cb0b701a983e39e7 Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Sun, 26 Dec 2021 14:12:36 +0100 Subject: [PATCH] improve tables and remove fzf nonsense --- cli/Cargo.toml | 8 ++- cli/src/commands/cats.rs | 17 +++-- cli/src/commands/list.rs | 55 +++------------- cli/src/commands/search.rs | 17 +++-- cli/src/commands/users.rs | 17 ++--- cli/src/main.rs | 6 +- cli/src/table.rs | 124 ++++++++++++++++++++++++++++--------- tokencracker/Cargo.toml | 12 ++-- 8 files changed, 139 insertions(+), 117 deletions(-) diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a2c3933..bea2e4b 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cli" -version = "1.0.0" +version = "1.1.0" authors = ["LordMZTE "] edition = "2018" license = "GPL-3.0" @@ -20,17 +20,19 @@ path = "src/main.rs" anyhow = "1.0.52" chrono = "0.4.19" clap = "2.34.0" +comfy-table = "5.0.0" env_logger = "0.9.0" fuzzy-matcher = "0.3.7" indicatif = "0.16.2" -libjens = { git = "https://tilera.xyz/git/LordMZTE/libjens.git", rev = "1.0.0" } +libjens = { git = "https://tilera.xyz/git/LordMZTE/libjens.git", rev = "1.0.1" } log = "0.4.14" opener = "0.5.0" reqwest = { version = "0.11.8", features = ["stream", "multipart"] } serde_json = "1.0.73" structopt = "0.3.25" -term-table = "1.3.2" term_size = "0.3.2" tokio = { version = "1.15.0", features = ["macros", "fs", "process", "rt-multi-thread"] } tokio-util = { version = "0.6.9", features = ["codec"] } url = "2.2.2" + +[features] diff --git a/cli/src/commands/cats.rs b/cli/src/commands/cats.rs index 1c8ee4d..ee5dbab 100644 --- a/cli/src/commands/cats.rs +++ b/cli/src/commands/cats.rs @@ -1,18 +1,17 @@ -use crate::table::{self, AsTableRow}; -use libjens::JMClient; +use crate::table::{list_table, JMTableEntry, TableExt}; +use libjens::{api::Category, JMClient}; pub async fn run(client: &JMClient) -> anyhow::Result<()> { // clone required, because for sorting the immutable reference will not work let mut cats = client.get_cats().await?.as_ref().clone(); cats.sort_by(|a, b| a.id.cmp(&b.id)); - let mut table = table::list_table(); - - for cat in &cats { - table.add_row(cat.as_table_row()); - } - - println!("{}", table.render()); + println!( + "{}", + list_table() + .type_header::() + .add_rows(cats.into_iter().map(JMTableEntry)) + ); Ok(()) } diff --git a/cli/src/commands/list.rs b/cli/src/commands/list.rs index 8e36158..e5fd6e7 100644 --- a/cli/src/commands/list.rs +++ b/cli/src/commands/list.rs @@ -1,21 +1,15 @@ -use anyhow::{Context, Result}; -use std::{ - io::Write, - process::{Command, Stdio}, -}; - use crate::{ - table::{self, AsTableRow}, + table::{list_table, JMTableEntry, TableExt}, util, }; -use libjens::{util::MemeSorting, JMClient}; +use anyhow::Result; +use libjens::{api::Meme, util::MemeSorting, JMClient}; pub async fn run( client: &JMClient, cat: Option, user: Option, sorting: Option, - fzf: bool, ) -> Result<()> { // This needs to be done so both users, memes and categories will be requested // at once @@ -47,43 +41,12 @@ pub async fn run( s.sort_with(&mut memes); } - let mut table = table::list_table(); - - for m in memes.iter() { - table.add_row(m.as_table_row()); - } - - let table_str = table.render(); - - if fzf { - let mut child = Command::new("fzf") - .args(&["--delimiter", "\\t", "--with-nth", "2"]) - .stdout(Stdio::piped()) - .stdin(Stdio::piped()) - .spawn() - .context("Failed to spawn FZF")?; - let stdin = child.stdin.as_mut().context("could not get FZF stdin")?; - - for (idx, line) in table_str.lines().enumerate() { - stdin - .write(format!("{}\t{}\n", idx, line).as_bytes()) - .context("Failed to write to FZF")?; - } - - let out = child.wait_with_output()?; - let out_str = String::from_utf8(out.stdout).context("FZF output is invalid UTF-8")?; - let idx = out_str - .split('\t') - .next() - .and_then(|s| s.parse::().ok()) - .context("Failed to parse FZF output")?; - let meme = memes - .get(idx) - .context("Falied to retrieve meme FZF returned")?; - println!("{}", meme.link); - } else { - println!("{}", table_str); - } + println!( + "{}", + list_table() + .type_header::() + .add_rows(memes.into_iter().cloned().map(JMTableEntry)) + ); Ok(()) } diff --git a/cli/src/commands/search.rs b/cli/src/commands/search.rs index 80b6d68..f1bb128 100644 --- a/cli/src/commands/search.rs +++ b/cli/src/commands/search.rs @@ -3,10 +3,10 @@ use log::info; use std::io::Write; use crate::{ - table::{self, AsTableRow}, + table::{list_table, JMTableEntry, TableExt}, util, }; -use libjens::JMClient; +use libjens::{api::Meme, JMClient}; pub async fn run( client: &JMClient, @@ -53,14 +53,11 @@ pub async fn run( matches.sort_by(|a, b| b.1.cmp(&a.1)); let res = match (firsturl, cat) { - (false, false) => { - let mut table = table::list_table(); - - for m in matches { - table.add_row(m.0.as_table_row()); - } - table.render().into_bytes() - }, + (false, false) => list_table() + .type_header::() + .add_rows(matches.into_iter().map(|(m, _)| JMTableEntry(m.clone()))) + .to_string() + .into_bytes(), (true, _) => matches .first() diff --git a/cli/src/commands/users.rs b/cli/src/commands/users.rs index 3352776..a17ab9a 100644 --- a/cli/src/commands/users.rs +++ b/cli/src/commands/users.rs @@ -1,16 +1,17 @@ -use crate::table::{self, AsTableRow}; use anyhow::Result; -use libjens::JMClient; +use libjens::{api::User, JMClient}; + +use crate::table::{list_table, JMTableEntry, TableExt}; pub async fn run(client: &JMClient) -> Result<()> { let users = client.get_users().await?; - let mut table = table::list_table(); - for u in &*users { - table.add_row(u.as_table_row()) - } - - println!("{}", table.render()); + println!( + "{}", + list_table() + .type_header::() + .add_rows(users.iter().cloned().map(JMTableEntry)) + ); Ok(()) } diff --git a/cli/src/main.rs b/cli/src/main.rs index f03af5e..c12c24b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -77,9 +77,6 @@ enum Cmd { help = "how to sort the results. can be id, user, category, timestamp or link" )] sort: Option, - - #[structopt(long, short, help = "search memes with FZF")] - fzf: bool, }, #[structopt(about = "Lists all users")] @@ -116,8 +113,7 @@ async fn main() -> Result<()> { category, user, sort, - fzf, - } => commands::list::run(&client, category, user, sort, fzf).await?, + } => commands::list::run(&client, category, user, sort).await?, Cmd::Users => commands::users::run(&client).await?, } diff --git a/cli/src/table.rs b/cli/src/table.rs index 03e4772..cbe4cfc 100644 --- a/cli/src/table.rs +++ b/cli/src/table.rs @@ -1,45 +1,109 @@ use chrono::{Local, TimeZone}; +use comfy_table::{presets::UTF8_NO_BORDERS, ContentArrangement, Row, Table}; use libjens::api::{Category, Meme, User}; -use term_table::{row::Row, table_cell::TableCell, Table, TableBuilder, TableStyle}; -/// returns an empty table with the correct format settings for lists -pub fn list_table<'a>() -> Table<'a> { - TableBuilder::new() - .style(TableStyle::simple()) - .separate_rows(false) - .has_top_boarder(false) - .has_bottom_boarder(false) - .build() +// pub trait AsTableRow { +// fn as_table_row(&self) -> term_table::row::Row; +//} +// impl AsTableRow for Category { +// fn as_table_row(&self) -> Row<'_> { +// Row::new(vec![TableCell::new(&self.id), TableCell::new(&self.name)]) +// } +//} +// impl AsTableRow for Meme { +// fn as_table_row(&self) -> Row<'_> { +// Row::new(vec![ +// TableCell::new(&self.link), +// TableCell::new(&self.category), +// TableCell::new(&self.user), +// TableCell::new(Local.timestamp(self.timestamp, 0).format("%F +// %R")), TableCell::new(&self.id), +// ]) +// } +//} +// impl AsTableRow for User { +// fn as_table_row(&self) -> Row<'_> { +// Row::new(vec![ +// TableCell::new(&self.name), +// TableCell::new(&self.get_id().map(String::as_ref).unwrap_or("[No +// ID]")), TableCell::new(&self.dayuploads), +// ]) +// } +//} + +pub fn list_table() -> Table { + let mut table = Table::new(); + + table + .load_preset(UTF8_NO_BORDERS) + .set_content_arrangement(ContentArrangement::Dynamic); + + table } -pub trait AsTableRow { - fn as_table_row(&self) -> term_table::row::Row; +pub trait TableHeader { + fn header() -> Row; } -impl AsTableRow for Category { - fn as_table_row(&self) -> Row<'_> { - Row::new(vec![TableCell::new(&self.id), TableCell::new(&self.name)]) +macro_rules! impl_table_header { + ($t:ident, $e:expr) => { + impl TableHeader for $t { + fn header() -> Row { + $e.into() + } + } + }; +} + +impl_table_header!(User, vec!["Name", "ID"]); +impl_table_header!(Category, vec!["Name", "ID"]); +impl_table_header!(Meme, vec!["Link", "Category", "User", "Timestamp"]); + +/// a newtype wrapper to convert libjens types to table rows +pub struct JMTableEntry(pub T); + +impl From> for Row { + fn from(e: JMTableEntry) -> Self { + vec![e.0.name, e.0.id.unwrap_or_else(String::new)].into() } } -impl AsTableRow for Meme { - fn as_table_row(&self) -> Row<'_> { - Row::new(vec![ - TableCell::new(&self.link), - TableCell::new(&self.category), - TableCell::new(&self.user), - TableCell::new(Local.timestamp(self.timestamp, 0).format("%F %R")), - TableCell::new(&self.id), - ]) +impl From> for Row { + fn from(e: JMTableEntry) -> Self { + vec![e.0.name, e.0.id].into() } } -impl AsTableRow for User { - fn as_table_row(&self) -> Row<'_> { - Row::new(vec![ - TableCell::new(&self.name), - TableCell::new(&self.get_id().map(String::as_ref).unwrap_or("[No ID]")), - TableCell::new(&self.dayuploads), - ]) +impl From> for Row { + fn from(e: JMTableEntry) -> Self { + vec![ + e.0.link, + e.0.category, + e.0.user, + Local + .timestamp(e.0.timestamp, 0) + .format("%F %R") + .to_string(), + ] + .into() + } +} + +pub trait TableExt { + fn add_rows>(&mut self, iter: impl IntoIterator) -> &mut Self; + + fn type_header(&mut self) -> &mut Self; +} + +impl TableExt for Table { + fn add_rows>(&mut self, iter: impl IntoIterator) -> &mut Self { + for i in iter.into_iter() { + self.add_row(i); + } + self + } + + fn type_header(&mut self) -> &mut Self { + self.set_header(T::header()) } } diff --git a/tokencracker/Cargo.toml b/tokencracker/Cargo.toml index b2c3f81..be0fede 100644 --- a/tokencracker/Cargo.toml +++ b/tokencracker/Cargo.toml @@ -16,10 +16,10 @@ name = "jmtoken" path = "src/main.rs" [dependencies] -anyhow = "1.0.34" -clap = "2.33.3" +anyhow = "1.0.52" +clap = "2.34.0" md5 = "0.7.0" -reqwest = "0.10.8" -serde = { version = "1.0.117", features = ["derive"] } -serde_json = "1.0.59" -tokio = { version = "~0.2", features = ["full"] } +reqwest = "0.11.8" +serde = { version = "1.0.132", features = ["derive"] } +serde_json = "1.0.73" +tokio = { version = "1.15.0", features = ["full"] }