134 lines
2.8 KiB
Go
134 lines
2.8 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])
|
|
}
|
|
}
|
|
|
|
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 printHelp() {
|
|
fmt.Println("Usage:")
|
|
fmt.Println(" stopwatch - Start a quick stopwatch")
|
|
fmt.Println(" stopwatch [name] - Start or view a named stopwatch")
|
|
fmt.Println(" stopwatch clear [name] - Remove a named stopwatch")
|
|
}
|