diff --git a/cmd/gime/main.go b/cmd/gime/main.go index 524ecad..aa670be 100644 --- a/cmd/gime/main.go +++ b/cmd/gime/main.go @@ -47,6 +47,18 @@ func main() { os.Exit(ret) } +func loadActiveTimeEntries() { + timeEntries = gdb.LoadTimeEntryCollection(gime.TypeCurrent) +} + +func loadActiveAndRecentTimeEntries() { + timeEntries = gdb.LoadTimeEntryCollection(gime.TypeNoArchive) +} + +func getMostRecentTimeEntry() (*gime.TimeEntry, error) { + return gdb.GetLatestTimeEntry() +} + func cmdDoArchive(args []string) int { fmt.Println("Not implemented yet.") return 1 @@ -59,7 +71,7 @@ func cmdDoConfig(args []string) int { } for _, opt := range args { - if strings.Index(opt, "=") == -1 { + if !strings.Contains(opt, "=") { // Single word triggers switch opt { case "reset": @@ -72,6 +84,8 @@ func cmdDoConfig(args []string) int { for _, v := range cfg.GetKeyList() { fmt.Println(" " + v + ": " + cfg.Get(v)) } + case "dbpath": + fmt.Println(cfg.Get("dbdir") + cfg.Get("dbname")) } } else { // Key=Value options @@ -123,21 +137,50 @@ func cmdPrintHelp(args []string) int { return 0 } -func loadActiveTimeEntries() { - timeEntries = gdb.LoadTimeEntryCollection(gime.TypeCurrent) -} - -func loadActiveAndRecentTimeEntries() { - timeEntries = gdb.LoadTimeEntryCollection(gime.TypeNoArchive) -} - func cmdPrintList(args []string) int { loadActiveAndRecentTimeEntries() // By default, list all entries ending today or still running filter := func(t *gime.TimeEntry) bool { return t.EndsToday() || t.IsRunning() } - fmt.Println(TimerCollectionToString(filterTimerCollection(timeEntries, filter))) + /* + for _, opt := range args { + // Do our best to figure out what timers the user wants to list + var err error + var beg, end time.Time + if strings.Contains(opt, "-") { + pts := strings.Split(opt, "-") + if len(pts[0]) > 0 { + // This should be the starting date + if beg, err = parseFuzzyTime(pts[0]); err != nil { + fmt.Println("Start date:", err.Error()) + return 1 + } + } + if len(pts[1]) > 0 { + // This should be the ending date + if end, err = parseFuzzyTime(pts[1]); err != nil { + fmt.Println("End date:", err.Error()) + return 1 + } + } + if end.IsZero() { + end = time.Now() + } + } else if strings.HasPrefix(opt, "week") { + + } else if strings.HasPrefix(opt, "biweek") { + + } + fmt.Println(beg, " - ", end) + } + return 0 + */ + + fmt.Println(time.Now().Format("2006/01/02")) + str := TimerCollectionToString(filterTimerCollection(timeEntries, filter)) + str = " " + strings.Replace(str, "\n", "\n ", -1) + fmt.Println(str) return 0 } @@ -171,11 +214,30 @@ func cmdPrintStatus(args []string) int { return 0 } +func cmdDoFuzzyParse(args []string) int { + if len(args) == 0 { + return 1 + } + var t time.Time + var err error + if t, err = parseFuzzyTime(args[0]); err != nil { + fmt.Println(err.Error()) + return 1 + } + fmt.Println(t.Format(time.RFC3339)) + return 0 +} + func initialize() { var err error validOperations = make(map[string][]string) opFuncs = make(map[string]func([]string) int) + opFuncs["cont"] = cmdContinueTimer + validOperations["cont"] = []string{ + "cont [time] - Continue the last stopped timer", + } + opFuncs["config"] = cmdDoConfig validOperations["config"] = []string{ "config [command] - Perform configuration", @@ -256,7 +318,13 @@ func initialize() { opFuncs["archive"] = cmdDoArchive validOperations["archive"] = []string{ - "archive - Archive all entries older than the archive date", + "archive - Archive all entries older than the archive date", + } + + opFuncs["fuzzyparse"] = cmdDoFuzzyParse + validOperations["fuzzyparse"] = []string{ + "fuzzyparse - Parse the next argument as a date/time and print", + " the RFC3339 result. (Basically for testing)", } // Load the Config @@ -296,6 +364,14 @@ func initialize() { "01/02/2006 15:04:05", // U.S. Format with seconds "01/02/06 15:04", // U.S. Format, short year "01/02/06 15:04:05", // U.S. Format, short year, with seconds + "2006-01-02", + "2006-01-02 15:04", + "2006-01-02 15:04:05", + "20060102", + "20060102 15:04", + "20060102 15:04:05", + "20060102 1504", + "20060102 150405", } } diff --git a/cmd/gime/timer_operations.go b/cmd/gime/timer_operations.go index fbfdcd4..60b119c 100644 --- a/cmd/gime/timer_operations.go +++ b/cmd/gime/timer_operations.go @@ -8,6 +8,22 @@ import ( "git.bullercodeworks.com/brian/gime" ) +func cmdContinueTimer(args []string) int { + // Get the last running timer and start a new one with the same tags + te, err := getMostRecentTimeEntry() + if err != nil { + fmt.Println(err.Error()) + return 1 + } + tagColl := te.GetTags() + var tags []string + for i := 0; i < tagColl.Length(); i++ { + tags = append(tags, tagColl.Get(i)) + } + args = append(args, tags...) + return cmdStartTimer(args) +} + // switchTimer performs a stop on any currently running timers // and starts a new timer with the given arguments func cmdSwitchTimer(args []string) int { @@ -75,34 +91,27 @@ func cmdStopTimer(args []string) int { tm := time.Now() actTimers := gdb.LoadTimeEntryCollection(gime.TypeCurrent) var tmr *gime.TimeEntry - stopAll := len(args) > 0 && args[0] == "all" - - if !stopAll { - if actTimers.Length() != 1 && (len(args) < 1 || args[0][0] != '@') { - fmt.Println("Couldn't determine which timer(s) to stop") - return 1 + stopId := "@0" // By default, stop the first timer + for i := range args { + if args[i] == "all" || args[i][0] == '@' { + stopId = args[i] + continue } - if actTimers.Length() == 1 { - // only one timer running - tmr = actTimers.Get(0) - } else { - // We've got a timer id to delete - timerId, err := strconv.Atoi(args[0][1:]) - if err != nil { - fmt.Println("Error parsing timer id: " + err.Error()) - return 1 - } - tmr, _, err = findTimerById(timerId) - if err != nil { - fmt.Println(err.Error()) - return 1 - } + tmpTm, err := parseFuzzyTime(args[i]) + if err == nil { + // We found a time + tm = tmpTm + continue } } - - if len(args) > 1 { - // Check if the next argument looks like a date/time - tm, err = parseFuzzyTime(args[1]) + if stopId != "all" { + // Find the timer that we're stopping + timerId, err := strconv.Atoi(stopId[1:]) + if err != nil { + fmt.Println("Error parsing timer id:", err.Error()) + return 1 + } + tmr, _, err = findTimerById(timerId) if err != nil { fmt.Println(err.Error()) return 1 @@ -118,7 +127,7 @@ func cmdStopTimer(args []string) int { fmt.Println("Stopped:", InferTimerDetailString(tmr)) return 0 } - if stopAll { + if stopId == "all" { var ret int for i := 0; i < actTimers.Length(); i++ { ret += stopTimer(actTimers.Get(i), tm) @@ -128,6 +137,7 @@ func cmdStopTimer(args []string) int { } return 0 } + // Just stop the one timer return stopTimer(tmr, tm) } diff --git a/model_timeentry.go b/model_timeentry.go index f31a97b..e521e2e 100644 --- a/model_timeentry.go +++ b/model_timeentry.go @@ -2,12 +2,34 @@ package gime import ( "errors" + "sort" "strconv" "time" "github.com/br0xen/boltease" ) +// GetLastTimeEntry pulls the time entry with the most recent stop time +func (gdb *GimeDB) GetLatestTimeEntry() (*TimeEntry, error) { + var ret *TimeEntry + var err error + tc := gdb.LoadTimeEntryCollection(TypeRecent) + for i := 0; i < tc.Length(); i++ { + te := tc.Get(i) + if ret == nil { + ret = te + } else { + if te.GetEnd().After(ret.GetEnd()) { + ret = te + } + } + } + if ret == nil { + err = errors.New("Could not find latest time entry") + } + return ret, err +} + // FindTimeEntryByUUID searches all entries // for the time entry with the given uuid, return the TimeEntry, the type, and/or and error // Types are searched TypeCurrent -> TypeRecent -> TypeArchive @@ -142,6 +164,9 @@ func (gdb *GimeDB) dbGetAllTimeEntries(tp int) []TimeEntry { if sttimes, err = useDb.GetBucketList([]string{TypeToString(tp)}); err != nil { return ret } + sort.Slice(sttimes, func(i, j int) bool { + return sttimes[j] < sttimes[i] + }) for _, v := range sttimes { if te, _ := gdb.dbGetTimeEntry(tp, v); te != nil { ret = append(ret, *te)