82 lines
2 KiB
Rust
82 lines
2 KiB
Rust
use chrono::{Local, TimeZone};
|
|
use comfy_table::{presets::UTF8_NO_BORDERS, ContentArrangement, Row, Table};
|
|
use libjens::api::{Category, Meme, User};
|
|
|
|
pub fn list_table() -> Table {
|
|
let mut table = Table::new();
|
|
|
|
table
|
|
.load_preset(UTF8_NO_BORDERS)
|
|
.set_content_arrangement(ContentArrangement::Dynamic);
|
|
|
|
table
|
|
}
|
|
|
|
pub trait TableHeader {
|
|
fn header() -> Row;
|
|
}
|
|
|
|
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", "ID"]);
|
|
|
|
/// a newtype wrapper to convert libjens types to table rows
|
|
pub struct JMTableEntry<T>(pub T);
|
|
|
|
impl From<JMTableEntry<User>> for Row {
|
|
fn from(e: JMTableEntry<User>) -> Self {
|
|
vec![e.0.name, e.0.id.unwrap_or_else(String::new)].into()
|
|
}
|
|
}
|
|
|
|
impl From<JMTableEntry<Category>> for Row {
|
|
fn from(e: JMTableEntry<Category>) -> Self {
|
|
vec![e.0.name, e.0.id].into()
|
|
}
|
|
}
|
|
|
|
impl From<JMTableEntry<Meme>> for Row {
|
|
fn from(e: JMTableEntry<Meme>) -> Self {
|
|
vec![
|
|
e.0.link,
|
|
e.0.category,
|
|
e.0.user,
|
|
Local
|
|
.timestamp(e.0.timestamp, 0)
|
|
.format("%F %R")
|
|
.to_string(),
|
|
e.0.id,
|
|
]
|
|
.into()
|
|
}
|
|
}
|
|
|
|
pub trait TableExt {
|
|
fn add_rows<T: Into<Row>>(&mut self, iter: impl IntoIterator<Item = T>) -> &mut Self;
|
|
|
|
fn type_header<T: TableHeader>(&mut self) -> &mut Self;
|
|
}
|
|
|
|
impl TableExt for Table {
|
|
fn add_rows<T: Into<Row>>(&mut self, iter: impl IntoIterator<Item = T>) -> &mut Self {
|
|
for i in iter.into_iter() {
|
|
self.add_row(i);
|
|
}
|
|
self
|
|
}
|
|
|
|
fn type_header<T: TableHeader>(&mut self) -> &mut Self {
|
|
self.set_header(T::header())
|
|
}
|
|
}
|