mirror of
https://github.com/nikolassv/bartib
synced 2024-12-11 04:32:27 +00:00
make grouped table output more readable
This commit is contained in:
parent
ad97302723
commit
964458007e
4 changed files with 106 additions and 43 deletions
45
Cargo.lock
generated
45
Cargo.lock
generated
|
@ -11,15 +11,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.42"
|
||||
|
@ -47,10 +38,10 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
|||
name = "bartib"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clap",
|
||||
"nu-ansi-term",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -79,7 +70,7 @@ version = "2.33.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0",
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
|
@ -88,6 +79,12 @@ dependencies = [
|
|||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.18"
|
||||
|
@ -97,12 +94,32 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccf5ce0705f83c8afb776d00fe071ab994148efdd8e060909c6614b0fe740af"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -122,6 +139,12 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
|
|
|
@ -11,4 +11,4 @@ chrono = "0.4"
|
|||
clap = "~2.33"
|
||||
thiserror = "1.0"
|
||||
anyhow = "1.0.42"
|
||||
ansi_term = "0.12.1"
|
||||
nu-ansi-term = "0.34.0"
|
|
@ -1,4 +1,4 @@
|
|||
use ansi_term::Colour;
|
||||
use nu_ansi_term::Color;
|
||||
use chrono::NaiveDate;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
|
@ -37,13 +37,24 @@ pub fn list_activities_grouped_by_date(activities: &[&activity::Activity]) {
|
|||
return;
|
||||
}
|
||||
|
||||
let activities_by_date = group_activities_by_date(activities);
|
||||
let mut activity_table = table::Table::new(vec![
|
||||
"Started".to_string(),
|
||||
"Stopped".to_string(),
|
||||
"Description".to_string(),
|
||||
"Project".to_string(),
|
||||
"Duration".to_string(),
|
||||
]);
|
||||
|
||||
for (date, activity_list) in activities_by_date {
|
||||
println!("{}", date);
|
||||
list_activities(&activity_list, false);
|
||||
println!();
|
||||
}
|
||||
group_activities_by_date(activities).iter()
|
||||
.map(|(date, activity_list)| create_activites_group(&format!("{}", date), activity_list.as_slice()))
|
||||
.for_each(|g| activity_table.add_group(g));
|
||||
|
||||
println!("\n{}", activity_table);
|
||||
}
|
||||
|
||||
fn create_activites_group(title: &str, activities: &[&activity::Activity]) -> table::Group {
|
||||
let rows = activities.iter().map(|a| get_activity_table_row(&a, false)).collect();
|
||||
table::Group::new(Some(title.to_string()), rows)
|
||||
}
|
||||
|
||||
// displays a table with running activities (no end time)
|
||||
|
@ -118,7 +129,7 @@ fn get_activity_table_row(activity: &&activity::Activity, with_start_dates: bool
|
|||
]);
|
||||
|
||||
if !activity.is_stopped() {
|
||||
new_row.set_color(Colour::Green);
|
||||
new_row.set_color(Color::Green.normal());
|
||||
}
|
||||
|
||||
new_row
|
||||
|
|
75
src/table.rs
75
src/table.rs
|
@ -1,13 +1,12 @@
|
|||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
use std::str;
|
||||
|
||||
use ansi_term::{Colour, Style};
|
||||
use nu_ansi_term::Style;
|
||||
|
||||
pub struct Row {
|
||||
content: Vec<String>,
|
||||
color: Option<Colour>,
|
||||
style: Option<Style>,
|
||||
}
|
||||
|
||||
pub struct Group {
|
||||
|
@ -25,12 +24,12 @@ impl Row {
|
|||
pub fn new(content: Vec<String>) -> Row {
|
||||
Row {
|
||||
content,
|
||||
color: None,
|
||||
style: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_color(&mut self, color: Colour) {
|
||||
self.color = Some(color);
|
||||
pub fn set_color(&mut self, style: Style) {
|
||||
self.style = Some(style);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,23 +52,31 @@ impl Table {
|
|||
self.rows.push(row);
|
||||
}
|
||||
|
||||
pub fn add_group(&mut self, group: Group) {
|
||||
self.groups.push(group);
|
||||
}
|
||||
|
||||
fn get_all_rows(&self) -> Vec<&Row> {
|
||||
self.groups.iter()
|
||||
.flat_map(|g| g.rows.as_slice())
|
||||
.chain(self.rows.as_slice())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_column_width(&self) -> Vec<usize> {
|
||||
let mut column_width: Vec<usize> = self.header.iter().map(|e| e.chars().count()).collect();
|
||||
|
||||
let mut i: usize;
|
||||
|
||||
for row in &self.rows {
|
||||
i = 0;
|
||||
|
||||
while let Some(w) = row.content.get(i) {
|
||||
if let Some(old_w) = column_width.get(i) {
|
||||
column_width[i] = cmp::max(w.chars().count(), *old_w);
|
||||
} else {
|
||||
column_width.push(w.chars().count());
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
for row in self.get_all_rows() {
|
||||
row.content.iter()
|
||||
.map(|cell| cell.chars().count())
|
||||
.enumerate()
|
||||
.for_each(|(i, char_count)| {
|
||||
if let Some(old_w) = column_width.get(i) {
|
||||
column_width[i] = cmp::max(char_count, *old_w);
|
||||
} else {
|
||||
column_width.push(char_count);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
column_width
|
||||
|
@ -84,15 +91,37 @@ impl fmt::Display for Table {
|
|||
writeln!(f)?;
|
||||
|
||||
for row in &self.rows {
|
||||
let style = row.color.map(|color| Style::new().fg(color));
|
||||
write_cells(f, &row.content, &column_width, style)?;
|
||||
writeln!(f)?;
|
||||
write_row(f, row, &column_width)?;
|
||||
}
|
||||
|
||||
for group in &self.groups {
|
||||
write_group(f, group, &column_width)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_group(f: &mut fmt::Formatter<'_>, group: &Group, column_width: &Vec<usize>) -> fmt::Result {
|
||||
let empty_string = "".to_string();
|
||||
let title = group.title.as_ref().unwrap_or(&empty_string);
|
||||
|
||||
writeln!(f)?;
|
||||
writeln!(f, "{}", Style::new().bold().paint(title))?;
|
||||
|
||||
for row in &group.rows {
|
||||
write_row(f, row, &column_width)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_row(f: &mut fmt::Formatter<'_>, row: &Row, column_width : &Vec<usize>) -> fmt::Result {
|
||||
write_cells(f, &row.content, &column_width, row.style)?;
|
||||
writeln!(f)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_cells<T: AsRef<str> + std::fmt::Display>(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
cells: &[T],
|
||||
|
|
Loading…
Reference in a new issue