tiempo-rs/src/commands/now.rs

160 lines
5.2 KiB
Rust

use std::convert::TryFrom;
use std::io::{BufRead, Write};
use clap::ArgMatches;
use crate::error::{Result, Error};
use crate::database::Database;
use crate::old::{entries_or_warning, warn_if_needed};
use crate::tabulate::{Tabulate, Col, Align::*};
use crate::formatters::text::format_duration;
use crate::io::Streams;
use super::{Command, Facts};
#[derive(Default)]
pub struct Args {
}
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(_matches: &'a ArgMatches) -> Result<Args> {
Ok(Args { })
}
}
pub struct NowCommand { }
impl<'a> Command<'a> for NowCommand {
type Args = Args;
fn handle<D, I, O, E>(_args: Self::Args, streams: &mut Streams<D, I, O, E>, facts: &Facts) -> Result<()>
where
D: Database,
I: BufRead,
O: Write,
E: Write,
{
let entries = streams.db.running_entries()?;
let (entries, needs_warning) = entries_or_warning(entries, &streams.db)?;
if entries.is_empty() {
streams.out.write_all(b"No running entries\n")?;
} else {
let current = streams.db.current_sheet()?;
let last = streams.db.last_sheet()?;
let mut tabs = Tabulate::with_columns(vec![
// indicator of current or prev sheet
Col::new().min_width(1).and_alignment(Right),
// sheet name
Col::new().min_width(9).and_alignment(Left),
// running time
Col::new().min_width(9).and_alignment(Right),
// activity
Col::new().min_width(0).and_alignment(Left),
]);
tabs.feed(vec!["", "Timesheet", "Running", "Activity"]);
tabs.separator(' ');
for entry in entries {
tabs.feed(vec![
if current == entry.sheet {
"*"
} else if last.as_ref() == Some(&entry.sheet) {
"-"
} else {
""
}.to_string(),
entry.sheet,
format_duration(facts.now - entry.start),
entry.note.unwrap_or_default(),
]);
}
streams.out.write_all(tabs.print(facts.env.stdout_is_tty).as_bytes())?;
}
warn_if_needed(&mut streams.err, needs_warning, &facts.env)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use chrono::{Utc, TimeZone, Local};
use pretty_assertions::assert_str_eq;
use crate::database::{SqliteDatabase, Database};
use super::*;
#[test]
fn list_sheets() {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap();
let facts = Facts::new().with_now(now);
streams.db.set_current_sheet("sheet2").unwrap();
streams.db.set_last_sheet("sheet4").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 1, 0, 0).unwrap()), None, "_archived").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 10,13, 55).unwrap()), None, "sheet1").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 7, 39, 18).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), Some(Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap()), None, "sheet3").unwrap();
streams.db.entry_insert(Utc.with_ymd_and_hms(2021, 1, 1, 12, 0, 0).unwrap(), None, Some("some".to_string()), "sheet4").unwrap();
NowCommand::handle(Default::default(), &mut streams, &facts).unwrap();
assert_str_eq!(&String::from_utf8_lossy(&streams.out), " Timesheet Running Activity
- sheet4 1:52:45 some
");
}
#[test]
fn old_database() {
let mut streams = Streams::fake(b"").with_db(
SqliteDatabase::from_path("assets/test_list_old_database.db").unwrap()
);
let now = Local.with_ymd_and_hms(2021, 7, 16, 11, 30, 45).unwrap();
let facts = Facts::new().with_now(now.with_timezone(&Utc));
NowCommand::handle(Default::default(), &mut streams, &facts).unwrap();
assert_str_eq!(&String::from_utf8_lossy(&streams.out), " Timesheet Running Activity
* default 0:10:24 que
");
assert_str_eq!(
String::from_utf8_lossy(&streams.err),
"[WARNING] You are using the old timetrap format, it is advised that you update your database using t migrate. To supress this warning set TIEMPO_SUPRESS_TIMETRAP_WARNING=1\n"
);
}
#[test]
fn with_no_running_entries_display_nicer_message() {
std::env::set_var("TZ", "CST+6");
let mut streams = Streams::fake(b"");
let now = Utc.with_ymd_and_hms(2021, 1, 1, 13, 52, 45).unwrap();
let facts = Facts::new().with_now(now);
NowCommand::handle(Default::default(), &mut streams, &facts).unwrap();
assert_str_eq!(&String::from_utf8_lossy(&streams.out), "No running entries
");
}
}