From 3720902431cb0ac458eadd3c07b129ed3fda5d8b Mon Sep 17 00:00:00 2001 From: jk <47693+sectore@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:51:39 +0200 Subject: [PATCH 1/2] feat(cli): add `--tabata` argument Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 1 + README.md | 3 ++- src/app.rs | 24 +++++++++++++++--------- src/args.rs | 6 ++++++ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 430c50c..01fcc05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- (cli) Add `--tabata` argument [#208](https://github.com/sectore/timr-tui/pull/208) - (pomodoro) auto-detect `Tabata` [#207](https://github.com/sectore/timr-tui/pull/207) - (pomodoro) introduce `max rounds` to limit sessions [#205](https://github.com/sectore/timr-tui/pull/205), [#206](https://github.com/sectore/timr-tui/pull/206) - (notification) detailed pomodoro status in system notification [#204](https://github.com/sectore/timr-tui/pull/204) diff --git a/README.md b/README.md index 0851323..65955fb 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,9 @@ Options: -c, --countdown Countdown time to start from. Formats: 'Yy Dd hh:mm:ss', 'Dd hh:mm:ss', 'Yy mm:ss', 'Dd mm:ss', 'Yy ss', 'Dd ss', 'hh:mm:ss', 'mm:ss', 'ss'. Examples: '1y 5d 10:30:00', '2d 4:00', '1d 10', '5:03'. -w, --work Work time to count down from. Formats: 'ss', 'mm:ss', 'hh:mm:ss' -p, --pause Pause duration. Single value (every round): '5:00'. Variable: 'regular,special[,every_n_rounds]' - special pause every N rounds, default every 4. Examples: '5:00,25:00' or '5:00,30:00,5'. Duration formats: 'ss', 'mm:ss', 'hh:mm:ss'. - --auto-switch Enable auto-switch between `work` and `pause` screens. --max-rounds Maximum number of pomodoro rounds. 0 = unlimited. + --tabata Tabata regimen: work 20s, pause 10s, 8 rounds, auto-switch enabled. + --auto-switch Enable auto-switch between `work` and `pause` screens. -e, --event Event date time and title (optional). Format: 'YYYY-MM-DD HH:MM:SS' or 'time=YYYY-MM-DD HH:MM:SS[,title=...]'. Examples: '2025-10-10 14:30:00' or 'time=2025-10-10 14:30:00,title=My Event'. -d, --decis Show deciseconds. -m, --mode Mode to start with. [possible values: countdown, timer, pomodoro, event, localtime] diff --git a/src/app.rs b/src/app.rs index f084ed9..b07709c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,7 +1,7 @@ use crate::{ args::Args, common::{AppEditMode, AppTime, AppTimeFormat, ClockTypeId, Content, Style, Toggle}, - constants::TICK_VALUE_MS, + constants::{TABATA_MAX_ROUNDS, TABATA_PAUSE, TABATA_WORK, TICK_VALUE_MS}, event::Event, events::{self, TuiEventHandler}, storage::AppStorage, @@ -105,8 +105,15 @@ impl From for App { fn from(args: FromAppArgs) -> Self { let FromAppArgs { args, stg, app_tx } = args; - let is_pause_from_args = args.pause.is_some(); - let pause_duration = args.pause.unwrap_or(stg.pause_duration); + let work_from_args = args.tabata.then_some(TABATA_WORK).or(args.work); + let pause_from_args = args + .tabata + .then_some(PauseDuration::Fixed(TABATA_PAUSE)) + .or(args.pause); + let effective_max_rounds = args.tabata.then_some(TABATA_MAX_ROUNDS).or(args.max_rounds); + + let is_pause_from_args = pause_from_args.is_some(); + let pause_duration = pause_from_args.unwrap_or(stg.pause_duration); let current_value_pause = if is_pause_from_args { pause_duration.for_round(stg.pomodoro_count) } else { @@ -125,7 +132,7 @@ impl From for App { Some(mode) => mode, // check other args (especially durations) None => { - if args.work.is_some() || is_pause_from_args { + if work_from_args.is_some() || is_pause_from_args { Content::Pomodoro } else if args.countdown.is_some() { Content::Countdown @@ -141,15 +148,14 @@ impl From for App { style: args.style.unwrap_or(stg.style), pomodoro_mode: stg.pomodoro_mode, pomodoro_round: stg.pomodoro_count, - pomodoro_auto_switch: args.auto_switch || stg.pomodoro_auto_switch, - pomodoro_max_rounds: args - .max_rounds + pomodoro_auto_switch: args.auto_switch || args.tabata || stg.pomodoro_auto_switch, + pomodoro_max_rounds: effective_max_rounds // 0 -> resets `max_rounds` .and_then(|n| (n > 0).then_some(n)) .or(stg.pomodoro_max_rounds), - initial_value_work: args.work.unwrap_or(stg.inital_value_work), + initial_value_work: work_from_args.unwrap_or(stg.inital_value_work), // invalidate `current_value_work` if an initial value is set via args - current_value_work: args.work.unwrap_or(stg.current_value_work), + current_value_work: work_from_args.unwrap_or(stg.current_value_work), pause_duration, current_value_pause, initial_value_countdown: args.countdown.unwrap_or(stg.inital_value_countdown), diff --git a/src/args.rs b/src/args.rs index ba03cd7..021b1bb 100644 --- a/src/args.rs +++ b/src/args.rs @@ -33,6 +33,12 @@ pub struct Args { #[arg(long, help = "Maximum number of pomodoro rounds. 0 = unlimited.")] pub max_rounds: Option, + #[arg( + long, + help = "Tabata regimen: work 20s, pause 10s, 8 rounds, auto-switch enabled." + )] + pub tabata: bool, + #[arg(long, help = "Enable auto-switch between `work` and `pause` screens.")] pub auto_switch: bool, From 220547b49e80d03008cb91afb165b79724ed3b25 Mon Sep 17 00:00:00 2001 From: jk <47693+sectore@users.noreply.github.com> Date: Wed, 17 Jun 2026 15:33:38 +0200 Subject: [PATCH 2/2] keep wording consistent --- src/app.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app.rs b/src/app.rs index b07709c..3e98cb0 100644 --- a/src/app.rs +++ b/src/app.rs @@ -110,7 +110,7 @@ impl From for App { .tabata .then_some(PauseDuration::Fixed(TABATA_PAUSE)) .or(args.pause); - let effective_max_rounds = args.tabata.then_some(TABATA_MAX_ROUNDS).or(args.max_rounds); + let max_rounds_from_args = args.tabata.then_some(TABATA_MAX_ROUNDS).or(args.max_rounds); let is_pause_from_args = pause_from_args.is_some(); let pause_duration = pause_from_args.unwrap_or(stg.pause_duration); @@ -149,7 +149,7 @@ impl From for App { pomodoro_mode: stg.pomodoro_mode, pomodoro_round: stg.pomodoro_count, pomodoro_auto_switch: args.auto_switch || args.tabata || stg.pomodoro_auto_switch, - pomodoro_max_rounds: effective_max_rounds + pomodoro_max_rounds: max_rounds_from_args // 0 -> resets `max_rounds` .and_then(|n| (n > 0).then_some(n)) .or(stg.pomodoro_max_rounds),