add csv formatter
This commit is contained in:
parent
91a99ed5ea
commit
5062a7b699
|
@ -63,6 +63,18 @@ version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -97,6 +109,28 @@ dependencies = [
|
||||||
"vec_map",
|
"vec_map",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "csv"
|
||||||
|
version = "1.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"csv-core",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "csv-core"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctor"
|
name = "ctor"
|
||||||
version = "0.1.20"
|
version = "0.1.20"
|
||||||
|
@ -204,6 +238,18 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.81"
|
version = "0.2.81"
|
||||||
|
@ -332,6 +378,12 @@ dependencies = [
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.25"
|
version = "0.6.25"
|
||||||
|
@ -354,6 +406,12 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.126"
|
version = "1.0.126"
|
||||||
|
@ -472,6 +530,7 @@ dependencies = [
|
||||||
"ansi_term 0.12.1",
|
"ansi_term 0.12.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"csv",
|
||||||
"dirs",
|
"dirs",
|
||||||
"itertools",
|
"itertools",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
|
|
|
@ -19,6 +19,7 @@ itertools = "0.10"
|
||||||
textwrap = "0.14"
|
textwrap = "0.14"
|
||||||
terminal_size = "0.1"
|
terminal_size = "0.1"
|
||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
|
csv = "1.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.7.2"
|
pretty_assertions = "0.7.2"
|
||||||
|
|
|
@ -33,6 +33,9 @@ pub enum Error {
|
||||||
#[error("IOError: {0}")]
|
#[error("IOError: {0}")]
|
||||||
IOError(#[from] std::io::Error),
|
IOError(#[from] std::io::Error),
|
||||||
|
|
||||||
|
#[error("CSV Error: {0}")]
|
||||||
|
CSVError(#[from] csv::Error),
|
||||||
|
|
||||||
#[error("Corrupted data found in the database: {0}")]
|
#[error("Corrupted data found in the database: {0}")]
|
||||||
CorruptedData(String),
|
CorruptedData(String),
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,13 @@ use crate::error;
|
||||||
use crate::models::Entry;
|
use crate::models::Entry;
|
||||||
|
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
pub mod csv;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Formatter {
|
pub enum Formatter {
|
||||||
Text,
|
Text,
|
||||||
|
Csv,
|
||||||
Custom(String),
|
Custom(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +34,7 @@ impl Formatter {
|
||||||
pub fn print_formatted<W: Write>(&self, entries: Vec<Entry>, out: &mut W, now: DateTime<Utc>, ids: bool, term_width: usize) -> error::Result<()> {
|
pub fn print_formatted<W: Write>(&self, entries: Vec<Entry>, out: &mut W, now: DateTime<Utc>, ids: bool, term_width: usize) -> error::Result<()> {
|
||||||
match &self {
|
match &self {
|
||||||
Formatter::Text => text::print_formatted(entries, out, now, ids, term_width)?,
|
Formatter::Text => text::print_formatted(entries, out, now, ids, term_width)?,
|
||||||
|
Formatter::Csv => csv::print_formatted(entries, out, ids)?,
|
||||||
Formatter::Custom(name) => {
|
Formatter::Custom(name) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use csv::Writer;
|
||||||
|
use chrono::SecondsFormat;
|
||||||
|
|
||||||
|
use crate::error::Result;
|
||||||
|
use crate::models::Entry;
|
||||||
|
|
||||||
|
pub fn print_formatted<W: Write>(entries: Vec<Entry>, out: &mut W, ids: bool) -> Result<()> {
|
||||||
|
let mut wtr = Writer::from_writer(out);
|
||||||
|
|
||||||
|
if ids {
|
||||||
|
wtr.write_record(&["id", "start", "end", "note", "sheet"])?;
|
||||||
|
} else {
|
||||||
|
wtr.write_record(&["start", "end", "note", "sheet"])?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in entries {
|
||||||
|
if ids {
|
||||||
|
wtr.write_record(&[
|
||||||
|
entry.id.to_string(),
|
||||||
|
entry.start.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||||
|
entry.end.map(|t| t.to_rfc3339_opts(SecondsFormat::Secs, true)).unwrap_or("".into()),
|
||||||
|
entry.note.unwrap_or("".into()),
|
||||||
|
entry.sheet,
|
||||||
|
])?;
|
||||||
|
} else {
|
||||||
|
wtr.write_record(&[
|
||||||
|
entry.start.to_rfc3339_opts(SecondsFormat::Secs, true),
|
||||||
|
entry.end.map(|t| t.to_rfc3339_opts(SecondsFormat::Secs, true)).unwrap_or("".into()),
|
||||||
|
entry.note.unwrap_or("".into()),
|
||||||
|
entry.sheet,
|
||||||
|
])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wtr.flush()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use chrono::{TimeZone, Utc};
|
||||||
|
|
||||||
|
use crate::test_utils::PrettyString;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_print_formatted() {
|
||||||
|
let entries = vec![
|
||||||
|
Entry::new_sample(1, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), Some(Utc.ymd(2021, 6, 30).and_hms(19, 0, 0))),
|
||||||
|
Entry::new_sample(2, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), None),
|
||||||
|
];
|
||||||
|
let mut out = Vec::new();
|
||||||
|
|
||||||
|
print_formatted(entries, &mut out, false).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("start,end,note,sheet
|
||||||
|
2021-06-30T18:12:34Z,2021-06-30T19:00:00Z,entry 1,default
|
||||||
|
2021-06-30T18:12:34Z,,entry 2,default
|
||||||
|
"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_print_formatted_ids() {
|
||||||
|
let entries = vec![
|
||||||
|
Entry::new_sample(1, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), Some(Utc.ymd(2021, 6, 30).and_hms(19, 0, 0))),
|
||||||
|
Entry::new_sample(2, Utc.ymd(2021, 6, 30).and_hms(18, 12, 34), None),
|
||||||
|
];
|
||||||
|
let mut out = Vec::new();
|
||||||
|
|
||||||
|
print_formatted(entries, &mut out, true).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("id,start,end,note,sheet
|
||||||
|
1,2021-06-30T18:12:34Z,2021-06-30T19:00:00Z,entry 1,default
|
||||||
|
2,2021-06-30T18:12:34Z,,entry 2,default
|
||||||
|
"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue