summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-09-28 23:28:17 +0300
committerPaul Buetow <paul@buetow.org>2025-09-28 23:28:17 +0300
commit7bc3e0d8dea4989325203987405ce31d0257fd19 (patch)
tree51d9d9241397f22606009e32c22eeb4dcb97b8ec
parent5d0532428300d048dbc47acfa08f77b8dc9c32bb (diff)
add continue
-rw-r--r--cmd/timr/main.go57
-rw-r--r--internal/timer/operations.go2
-rw-r--r--internal/timer/operations_test.go17
-rw-r--r--internal/timer/timer.go12
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 {