summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-26 23:03:57 +0300
committerPaul Buetow <paul@buetow.org>2025-06-26 23:03:57 +0300
commite26089b6fb7030e3ba8be314c37603453520d2d4 (patch)
tree47daa60aef8ad5f878a0e7eb62879bf67f98cb98
parent5580124aa9700fdd575d783ab525dceb395634b9 (diff)
feat: Add raw and rawm status options
This commit introduces two new options for the Status: Stopped Elapsed Time: 0s command: - 0: Displays the elapsed time in seconds. - 0: Displays the elapsed time in minutes. Unit tests have been added for both new functionalities, and the has been updated to reflect these changes. The status test has also been refactored to be more robust and less prone to flakiness by directly manipulating the timer state instead of relying on .
-rw-r--r--README.md2
-rw-r--r--cmd/timr/main.go14
-rw-r--r--internal/timer/operations.go28
-rw-r--r--internal/timer/operations_test.go70
4 files changed, 113 insertions, 1 deletions
diff --git a/README.md b/README.md
index 825fa2f..ff38bfd 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,8 @@ sudo mv timr /usr/local/bin/
* `timr start`: Starts the timer. If the timer was previously stopped, it will resume from where it left off.
* `timr stop` or `timr pause`: Stops or pauses the timer. The elapsed time will be saved.
* `timr status`: Shows the current status of the timer (running or stopped) and the total elapsed time.
+* `timr status raw`: Shows the current elapsed time in seconds, in a raw format.
+* `timr status rawm`: Shows the current elapsed time in minutes, in a raw format.
* `timr reset`: Resets the timer. This will set the elapsed time to zero.
* `timr live`: Shows a live, full-screen timer with keyboard controls (q: quit, s: start/stop, r: reset).
diff --git a/cmd/timr/main.go b/cmd/timr/main.go
index 0625070..442e48c 100644
--- a/cmd/timr/main.go
+++ b/cmd/timr/main.go
@@ -24,7 +24,19 @@ func main() {
case "stop", "pause":
output, err = timer.StopTimer()
case "status":
- output, err = timer.GetStatus()
+ if len(os.Args) > 2 {
+ switch os.Args[2] {
+ case "raw":
+ output, err = timer.GetRawStatus()
+ case "rawm":
+ output, err = timer.GetRawMinutesStatus()
+ default:
+ printUsage()
+ os.Exit(1)
+ }
+ } else {
+ output, err = timer.GetStatus()
+ }
case "reset":
output, err = timer.ResetTimer()
case "prompt":
diff --git a/internal/timer/operations.go b/internal/timer/operations.go
index 2b50e9e..6bb825d 100644
--- a/internal/timer/operations.go
+++ b/internal/timer/operations.go
@@ -74,6 +74,34 @@ func ResetTimer() (string, error) {
return "Timer reset.", nil
}
+func GetRawStatus() (string, error) {
+ state, err := LoadState()
+ if err != nil {
+ return "", fmt.Errorf("error loading state: %w", err)
+ }
+
+ elapsed := state.ElapsedTime
+ if state.Running {
+ elapsed += time.Since(state.StartTime)
+ }
+
+ return fmt.Sprintf("%d", int(elapsed.Seconds())), nil
+}
+
+func GetRawMinutesStatus() (string, error) {
+ state, err := LoadState()
+ if err != nil {
+ return "", fmt.Errorf("error loading state: %w", err)
+ }
+
+ elapsed := state.ElapsedTime
+ if state.Running {
+ elapsed += time.Since(state.StartTime)
+ }
+
+ return fmt.Sprintf("%d", int(elapsed.Minutes())), nil
+}
+
func GetPromptStatus() (string, error) {
state, err := LoadState()
if err != nil {
diff --git a/internal/timer/operations_test.go b/internal/timer/operations_test.go
index 39029b0..dc06941 100644
--- a/internal/timer/operations_test.go
+++ b/internal/timer/operations_test.go
@@ -108,6 +108,76 @@ func TestGetStatus(t *testing.T) {
}
}
+func TestGetRawStatus(t *testing.T) {
+ setup(t)
+
+ // Raw status when stopped
+ msg, err := GetRawStatus()
+ if err != nil {
+ t.Fatalf("GetRawStatus() error = %v", err)
+ }
+ want := "0"
+ if msg != want {
+ t.Errorf("GetRawStatus() msg = %q, want %q", msg, want)
+ }
+
+ // Raw status when running
+ state, err := LoadState()
+ if err != nil {
+ t.Fatalf("LoadState() error = %v", err)
+ }
+ state.Running = true
+ state.StartTime = time.Now().Add(-2 * time.Second) // Set start time 2 seconds ago
+ state.ElapsedTime = 0 // Reset elapsed time for this specific test
+ if err := state.Save(); err != nil {
+ t.Fatalf("Save() error = %v", err)
+ }
+
+ msg, err = GetRawStatus()
+ if err != nil {
+ t.Fatalf("GetRawStatus() error = %v", err)
+ }
+ want = "2"
+ if msg != want {
+ t.Errorf("GetRawStatus() msg = %q, want %q", msg, want)
+ }
+}
+
+func TestGetRawMinutesStatus(t *testing.T) {
+ setup(t)
+
+ // Raw minutes status when stopped
+ msg, err := GetRawMinutesStatus()
+ if err != nil {
+ t.Fatalf("GetRawMinutesStatus() error = %v", err)
+ }
+ want := "0"
+ if msg != want {
+ t.Errorf("GetRawMinutesStatus() msg = %q, want %q", msg, want)
+ }
+
+ // Raw minutes status when running (simulating 2 minutes)
+ state, err := LoadState()
+ if err != nil {
+ t.Fatalf("LoadState() error = %v", err)
+ }
+ state.Running = true
+ state.StartTime = time.Now().Add(-2 * time.Minute) // Set start time 2 minutes ago
+ state.ElapsedTime = 0 // Reset elapsed time for this specific test
+ if err := state.Save(); err != nil {
+ t.Fatalf("Save() error = %v", err)
+ }
+
+ msg, err = GetRawMinutesStatus()
+ if err != nil {
+ t.Fatalf("GetRawMinutesStatus() error = %v", err)
+ }
+ want = "2"
+ if msg != want {
+ t.Errorf("GetRawMinutesStatus() msg = %q, want %q", msg, want)
+ }
+}
+
func TestResetTimer(t *testing.T) {
setup(t)