diff options
| author | Paul Buetow <paul@buetow.org> | 2025-09-28 23:28:17 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-09-28 23:28:17 +0300 |
| commit | 7bc3e0d8dea4989325203987405ce31d0257fd19 (patch) | |
| tree | 51d9d9241397f22606009e32c22eeb4dcb97b8ec | |
| parent | 5d0532428300d048dbc47acfa08f77b8dc9c32bb (diff) | |
add continue
| -rw-r--r-- | cmd/timr/main.go | 57 | ||||
| -rw-r--r-- | internal/timer/operations.go | 2 | ||||
| -rw-r--r-- | internal/timer/operations_test.go | 17 | ||||
| -rw-r--r-- | internal/timer/timer.go | 12 |
4 files changed, 59 insertions, 29 deletions
diff --git a/cmd/timr/main.go b/cmd/timr/main.go index cbc6481..4bd6025 100644 --- a/cmd/timr/main.go +++ b/cmd/timr/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "strconv" "strings" "github.com/charmbracelet/bubbletea" @@ -11,29 +12,52 @@ import ( ) func main() { - if len(os.Args) < 2 { - printUsage() + output, err := runCommand(os.Args) + if err != nil { + fmt.Println("Error:", err) os.Exit(1) } + fmt.Println(output) +} + +func runCommand(args []string) (string, error) { + if len(args) < 2 { + printUsage() + return "", fmt.Errorf("no command specified") + } var err error var output string - switch os.Args[1] { + switch args[1] { case "start": output, err = timer.StartTimer() + case "continue": + rawStatus, err := timer.GetRawStatus() + if err != nil { + return "", err + } + status, err := strconv.ParseFloat(rawStatus, 64) + if err != nil { + return "", err + } + if status > 0 { + output, err = timer.StartTimer() + } else { + output = "Timer is at 0, cannot continue." + } case "stop", "pause": output, err = timer.StopTimer() case "status": - if len(os.Args) > 2 { - switch os.Args[2] { + if len(args) > 2 { + switch args[2] { case "raw": output, err = timer.GetRawStatus() case "rawm": output, err = timer.GetRawMinutesStatus() default: printUsage() - os.Exit(1) + return "", fmt.Errorf("unknown status command: %s", args[2]) } } else { output, err = timer.GetStatus() @@ -43,33 +67,30 @@ func main() { case "prompt": output, err = timer.GetPromptStatus() case "track": - if len(os.Args) < 3 { - fmt.Println("Error: track command requires a description") + if len(args) < 3 { printUsage() - os.Exit(1) + return "", fmt.Errorf("track command requires a description") } // Join all arguments after "track" as the description - description := strings.Join(os.Args[2:], " ") + description := strings.Join(args[2:], " ") output, err = timer.TrackTime(description) case "live": p := tea.NewProgram(live.NewModel()) if err := p.Start(); err != nil { - fmt.Println("Error running program:", err) - os.Exit(1) + return "", err } - return + return "", nil default: printUsage() - os.Exit(1) + return "", fmt.Errorf("unknown command: %s", args[1]) } if err != nil { - fmt.Println("Error:", err) - os.Exit(1) + return "", err } - fmt.Println(output) + return output, nil } func printUsage() { - fmt.Println("Usage: timr <start|stop|pause|status|reset|live|prompt|track <description>>") + fmt.Println("Usage: timr <start|continue|stop|pause|status|reset|live|prompt|track <description>>") } diff --git a/internal/timer/operations.go b/internal/timer/operations.go index 8a5a1f4..97be22d 100644 --- a/internal/timer/operations.go +++ b/internal/timer/operations.go @@ -86,7 +86,7 @@ func GetRawStatus() (string, error) { elapsed += time.Since(state.StartTime) } - return fmt.Sprintf("%d", int(elapsed.Seconds())), nil + return fmt.Sprintf("%f", elapsed.Seconds()), nil } func GetRawMinutesStatus() (string, error) { diff --git a/internal/timer/operations_test.go b/internal/timer/operations_test.go index 68eb4af..0cb86fc 100644 --- a/internal/timer/operations_test.go +++ b/internal/timer/operations_test.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "strconv" "testing" "time" ) @@ -12,9 +13,9 @@ import ( func setup(t *testing.T) { t.Helper() tempDir := t.TempDir() - stateFilePathOverride = filepath.Join(tempDir, ".timr_state") + StateFilePathOverride = filepath.Join(tempDir, ".timr_state") t.Cleanup(func() { - stateFilePathOverride = "" + StateFilePathOverride = "" }) } @@ -118,7 +119,7 @@ func TestGetRawStatus(t *testing.T) { if err != nil { t.Fatalf("GetRawStatus() error = %v", err) } - want := "0" + want := "0.000000" if msg != want { t.Errorf("GetRawStatus() msg = %q, want %q", msg, want) } @@ -139,9 +140,13 @@ func TestGetRawStatus(t *testing.T) { if err != nil { t.Fatalf("GetRawStatus() error = %v", err) } - want = "2" - if msg != want { - t.Errorf("GetRawStatus() msg = %q, want %q", msg, want) + // we can't know the exact float, so we check if it's close to 2 + val, err := strconv.ParseFloat(msg, 64) + if err != nil { + t.Fatalf("could not parse float: %v", err) + } + if val < 1.9 || val > 2.1 { + t.Errorf("GetRawStatus() msg = %q, want around 2.0", msg) } } diff --git a/internal/timer/timer.go b/internal/timer/timer.go index 3f2e3f5..e8585d5 100644 --- a/internal/timer/timer.go +++ b/internal/timer/timer.go @@ -11,8 +11,12 @@ const ( stateFile = ".timr_state" ) -// stateFilePathOverride is used by tests to override the state file path. -var stateFilePathOverride string +// StateFilePathOverride is used by tests to override the state file path. +var StateFilePathOverride string + +func SetStateFilePathOverride(path string) { + StateFilePathOverride = path +} type State struct { StartTime time.Time @@ -21,8 +25,8 @@ type State struct { } func GetStateFile() (string, error) { - if stateFilePathOverride != "" { - return stateFilePathOverride, nil + if StateFilePathOverride != "" { + return StateFilePathOverride, nil } configDir, err := os.UserConfigDir() if err != nil { |
