diff --git a/Cargo.lock b/Cargo.lock index bd8f6e1..6580127 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -787,7 +787,7 @@ checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "streamd" -version = "0.2.2" +version = "0.2.1" dependencies = [ "chrono", "chrono-tz", diff --git a/Cargo.toml b/Cargo.toml index b4d48cb..9199c46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "streamd" -version = "0.2.2" +version = "0.2.1" edition = "2021" description = "Personal knowledge management and time-tracking CLI using @Tag annotations" license = "AGPL-3.0-only" diff --git a/flake.nix b/flake.nix index 38723ae..dbfaed7 100644 --- a/flake.nix +++ b/flake.nix @@ -103,6 +103,12 @@ package = toolchain; }; commitizen.enable = true; + cargo-audit = { + enable = true; + entry = "${pkgs.cargo-audit}/bin/cargo-audit audit"; + files = "^Cargo\\.(toml|lock)$"; + pass_filenames = false; + }; }; }; diff --git a/src/cli/args.rs b/src/cli/args.rs index 11fda90..b0da540 100644 --- a/src/cli/args.rs +++ b/src/cli/args.rs @@ -51,9 +51,9 @@ pub enum Commands { /// Display extracted timesheets Timesheet { - /// Display time as decimal hours (X.XXh) instead of the default HH:MM format + /// Display time as minutes (HH:MM) instead of decimal hours (H.Hh) #[arg(short, long)] - decimal: bool, + minutes: bool, /// Show all timecards grouped by day instead of the summary report #[arg(short, long)] diff --git a/src/cli/commands/timesheet.rs b/src/cli/commands/timesheet.rs index 67ab956..2cea3ae 100644 --- a/src/cli/commands/timesheet.rs +++ b/src/cli/commands/timesheet.rs @@ -42,39 +42,28 @@ fn load_all_shards(base_folder: &Path) -> Result, StreamdErr Ok(shards) } -enum DisplayMode { - Minutes, - Decimal, -} - /// Format minutes with sign for display. -fn format_diff(minutes: i64, mode: &DisplayMode) -> String { +fn format_diff(minutes: i64, use_minutes: bool) -> String { let sign = if minutes >= 0 { "+" } else { "-" }; - match mode { - DisplayMode::Minutes => { - let h = minutes.unsigned_abs() / 60; - let m = minutes.unsigned_abs() % 60; - format!("{}{}:{:02}", sign, h, m) - } - DisplayMode::Decimal => { - let hours = minutes.unsigned_abs() as f64 / 60.0; - format!("{}{:.2}h", sign, hours) - } + if use_minutes { + let h = minutes.unsigned_abs() / 60; + let m = minutes.unsigned_abs() % 60; + format!("{}{}:{:02}", sign, h, m) + } else { + let hours = minutes.unsigned_abs() as f64 / 60.0; + format!("{}{:.1}h", sign, hours) } } /// Format minutes for display without sign. -fn format_hours(minutes: i64, mode: &DisplayMode) -> String { - match mode { - DisplayMode::Minutes => { - let h = minutes.unsigned_abs() / 60; - let m = minutes.unsigned_abs() % 60; - format!("{}:{:02}", h, m) - } - DisplayMode::Decimal => { - let hours = minutes.unsigned_abs() as f64 / 60.0; - format!("{:.2}h", hours) - } +fn format_hours(minutes: i64, use_minutes: bool) -> String { + if use_minutes { + let h = minutes.unsigned_abs() / 60; + let m = minutes.unsigned_abs() % 60; + format!("{}:{:02}", h, m) + } else { + let hours = minutes.unsigned_abs() as f64 / 60.0; + format!("{:.1}h", hours) } } @@ -101,8 +90,8 @@ fn print_header() { } /// Print a month report. -fn print_month(month: &MonthReport, mode: &DisplayMode) { - let diff_str = format_diff(month.diff(), mode); +fn print_month(month: &MonthReport, use_minutes: bool) { + let diff_str = format_diff(month.diff(), use_minutes); let month_title = format!("{} {}", month.month_name(), month.year); // Month header with diff @@ -123,9 +112,9 @@ fn print_month(month: &MonthReport, mode: &DisplayMode) { for day in &month.days { let date_str = day.date.format("%Y-%m-%d").to_string(); let weekday = weekday_abbrev(day.date); - let expected = format_hours(day.expected_minutes, mode); - let actual = format_hours(day.actual_minutes, mode); - let diff = format_diff(day.diff(), mode); + let expected = format_hours(day.expected_minutes, use_minutes); + let actual = format_hours(day.actual_minutes, use_minutes); + let diff = format_diff(day.diff(), use_minutes); let type_str = match day.day_type { DayType::Regular => String::new(), @@ -158,26 +147,26 @@ fn print_month(month: &MonthReport, mode: &DisplayMode) { println!(" {}", light_line); println!( " Monthly: {:>7} {:>7} {:>6}", - format_hours(month.total_expected(), mode), - format_hours(month.total_actual(), mode), - format_diff(month.diff(), mode) + format_hours(month.total_expected(), use_minutes), + format_hours(month.total_actual(), use_minutes), + format_diff(month.diff(), use_minutes) ); println!(); } /// Print the cumulative balance. -fn print_cumulative_balance(balance: i64, mode: &DisplayMode) { +fn print_cumulative_balance(balance: i64, use_minutes: bool) { let light_line = "\u{2500}".repeat(SEPARATOR_WIDTH); println!("{}", light_line); println!( " CUMULATIVE BALANCE: {}", - format_diff(balance, mode) + format_diff(balance, use_minutes) ); println!("{}", light_line); } /// Print warnings section. -fn print_warnings(report: &TimesheetReport, mode: &DisplayMode) { +fn print_warnings(report: &TimesheetReport, use_minutes: bool) { if !report.has_warnings() { return; } @@ -242,7 +231,7 @@ fn print_warnings(report: &TimesheetReport, mode: &DisplayMode) { println!( " - {}: {} worked (no period configured)", w.date.format("%Y-%m-%d"), - format_hours(*minutes_worked, mode) + format_hours(*minutes_worked, use_minutes) ); } } @@ -308,12 +297,7 @@ fn print_debug(report: &TimesheetReport, timesheets: &[Timesheet]) { } } -pub fn run(decimal: bool, debug: bool) -> Result<(), StreamdError> { - let mode = if decimal { - DisplayMode::Decimal - } else { - DisplayMode::Minutes - }; +pub fn run(use_minutes: bool, debug: bool) -> Result<(), StreamdError> { let settings = Settings::load()?; let base_folder = Path::new(&settings.base_folder); @@ -355,11 +339,11 @@ pub fn run(decimal: bool, debug: bool) -> Result<(), StreamdError> { print_header(); for month in &report.months { - print_month(month, &mode); + print_month(month, use_minutes); } - print_cumulative_balance(report.cumulative_balance, &mode); - print_warnings(&report, &mode); + print_cumulative_balance(report.cumulative_balance, use_minutes); + print_warnings(&report, use_minutes); } Ok(()) @@ -371,34 +355,33 @@ mod tests { #[test] fn test_format_hours_decimal() { - assert_eq!(format_hours(480, &DisplayMode::Decimal), "8.00h"); - assert_eq!(format_hours(510, &DisplayMode::Decimal), "8.50h"); - assert_eq!(format_hours(507, &DisplayMode::Decimal), "8.45h"); - assert_eq!(format_hours(0, &DisplayMode::Decimal), "0.00h"); + assert_eq!(format_hours(480, false), "8.0h"); + assert_eq!(format_hours(510, false), "8.5h"); + assert_eq!(format_hours(0, false), "0.0h"); } #[test] fn test_format_hours_minutes() { - assert_eq!(format_hours(480, &DisplayMode::Minutes), "8:00"); - assert_eq!(format_hours(510, &DisplayMode::Minutes), "8:30"); - assert_eq!(format_hours(0, &DisplayMode::Minutes), "0:00"); - assert_eq!(format_hours(75, &DisplayMode::Minutes), "1:15"); - assert_eq!(format_hours(77, &DisplayMode::Minutes), "1:17"); - assert_eq!(format_hours(200, &DisplayMode::Minutes), "3:20"); + assert_eq!(format_hours(480, true), "8:00"); + assert_eq!(format_hours(510, true), "8:30"); + assert_eq!(format_hours(0, true), "0:00"); + assert_eq!(format_hours(75, true), "1:15"); + assert_eq!(format_hours(77, true), "1:17"); + assert_eq!(format_hours(200, true), "3:20"); } #[test] fn test_format_diff_decimal() { - assert_eq!(format_diff(30, &DisplayMode::Decimal), "+0.50h"); - assert_eq!(format_diff(-90, &DisplayMode::Decimal), "-1.50h"); - assert_eq!(format_diff(0, &DisplayMode::Decimal), "+0.00h"); + assert_eq!(format_diff(30, false), "+0.5h"); + assert_eq!(format_diff(-90, false), "-1.5h"); + assert_eq!(format_diff(0, false), "+0.0h"); } #[test] fn test_format_diff_minutes() { - assert_eq!(format_diff(30, &DisplayMode::Minutes), "+0:30"); - assert_eq!(format_diff(-90, &DisplayMode::Minutes), "-1:30"); - assert_eq!(format_diff(0, &DisplayMode::Minutes), "+0:00"); - assert_eq!(format_diff(75, &DisplayMode::Minutes), "+1:15"); + assert_eq!(format_diff(30, true), "+0:30"); + assert_eq!(format_diff(-90, true), "-1:30"); + assert_eq!(format_diff(0, true), "+0:00"); + assert_eq!(format_diff(75, true), "+1:15"); } } diff --git a/src/main.rs b/src/main.rs index 4d311a5..354b8dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,8 +15,8 @@ fn main() -> miette::Result<()> { Some(TodoAction::Done { number }) => streamd::cli::commands::todo::run_done(number)?, }, Some(Commands::Edit { number }) => streamd::cli::commands::edit::run(number)?, - Some(Commands::Timesheet { decimal, debug }) => { - streamd::cli::commands::timesheet::run(decimal, debug)? + Some(Commands::Timesheet { minutes, debug }) => { + streamd::cli::commands::timesheet::run(minutes, debug)? } Some(Commands::Completions { shell }) => { streamd::cli::commands::completions::run(shell);