stopwatch/main.go
tijl e7a16c663a
All checks were successful
build / build (push) Successful in 10s
updates
2024-09-27 17:56:15 +02:00

168 lines
3.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os"
"os/signal"
"os/user"
"path/filepath"
"syscall"
"time"
)
type Stopwatches map[string]time.Time
var configPath string
func main() {
args := os.Args[1:]
if len(args) == 0 {
// Quick stop watch
stopwatchUI(time.Now())
} else if len(args) == 1 && (args[0] == "help" || args[0] == "-h" || args[0] == "--help") {
printHelp()
} else if len(args) == 1 {
namedStopwatch(args[0])
} else if len(args) == 2 && (args[0] == "clear" || args[0] == "-c" || args[0] == "--clear") {
clearStopwatch(args[1])
} else if len(args) == 2 && (args[0] == "timer" || args[0] == "-t" || args[0] == "--timer") {
d, err := time.ParseDuration(args[1])
if err != nil {
fmt.Println("Error parsing duration:", err)
}
timerUI(time.Now().Add(d))
}
}
func namedStopwatch(name string) {
stopwatches, err := loadStopwatches()
if err != nil {
fmt.Println("Error loading stopwatches:", err)
return
}
startTime, exists := stopwatches[name]
if !exists {
stopwatches[name] = time.Now()
saveStopwatches(stopwatches)
} else {
stopwatchUI(startTime)
}
}
func clearStopwatch(name string) {
stopwatches, err := loadStopwatches()
if err != nil {
fmt.Println("Error loading stopwatches:", err)
return
}
if _, exists := stopwatches[name]; exists {
delete(stopwatches, name)
err := saveStopwatches(stopwatches)
if err != nil {
fmt.Println("Error saving stopwatches:", err)
return
}
} else {
fmt.Printf("Stopwatch '%s' does not exist.\n", name)
}
}
func init() {
usr, err := user.Current()
if err != nil {
fmt.Println("Error getting user home directory:", err)
os.Exit(1)
}
configDir := filepath.Join(usr.HomeDir, ".config")
configPath = filepath.Join(configDir, ".stopwatches")
if _, err := os.Stat(configDir); os.IsNotExist(err) {
os.MkdirAll(configDir, 0755)
}
}
func loadStopwatches() (Stopwatches, error) {
stopwatches := Stopwatches{}
if _, err := os.Stat(configPath); err == nil {
data, err := os.ReadFile(configPath)
if err != nil {
return stopwatches, err
}
err = json.Unmarshal(data, &stopwatches)
if err != nil {
return stopwatches, err
}
}
return stopwatches, nil
}
func saveStopwatches(stopwatches Stopwatches) error {
data, err := json.MarshalIndent(stopwatches, "", " ")
if err != nil {
return err
}
return os.WriteFile(configPath, data, 0644)
}
func stopwatchUI(startTime time.Time) {
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-stop
os.Exit(0)
}()
for {
elapsed := time.Since(startTime)
fmt.Printf("\r%02dd %02dh %02dm %02ds %03dms",
elapsed/(24*time.Hour),
(elapsed%(24*time.Hour))/time.Hour,
(elapsed%time.Hour)/time.Minute,
(elapsed%time.Minute)/time.Second,
(elapsed%time.Second)/time.Millisecond)
time.Sleep(10 * time.Millisecond)
}
}
func timerUI(startTime time.Time) {
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-stop
fmt.Printf("\n")
os.Exit(0)
}()
for {
elapsed := time.Until(startTime)
if elapsed.Milliseconds() == 0 {
fmt.Printf("\n")
break
}
fmt.Printf("\r%02dd %02dh %02dm %02ds %03dms",
elapsed/(24*time.Hour),
(elapsed%(24*time.Hour))/time.Hour,
(elapsed%time.Hour)/time.Minute,
(elapsed%time.Minute)/time.Second,
(elapsed%time.Second)/time.Millisecond)
time.Sleep(1 * time.Millisecond)
}
}
func printHelp() {
fmt.Println("Usage:")
fmt.Println(" stopwatch - Start a quick stopwatch")
fmt.Println(" stopwatch [name] - Start or view a named stopwatch")
fmt.Println(" stopwatch -t [time] - Start a quick timer")
fmt.Println(" stopwatch -c [name] - Remove a named stopwatch")
fmt.Println(" stopwatch -h - View help menu")
}