Working on v2
This commit is contained in:
578
old/timer_ops.go
Normal file
578
old/timer_ops.go
Normal file
@@ -0,0 +1,578 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
||||
)
|
||||
|
||||
func (a *AppState) opStatus(args []string) int {
|
||||
if len(*a.TimerList.GetActiveTimers()) == 0 {
|
||||
fmt.Println("No timers running")
|
||||
return 0
|
||||
}
|
||||
var currDur time.Duration
|
||||
for _, v := range *a.TimerList {
|
||||
if v.ActiveToday() {
|
||||
currDur += v.Duration()
|
||||
}
|
||||
}
|
||||
d := currDur.Round(GetRoundToDuration())
|
||||
fmt.Printf("%s ( %.2f hrs )\n", time.Now().Format(time.Stamp), DurationToDecimal(d))
|
||||
for _, v := range *a.TimerList.GetActiveTimers() {
|
||||
fmt.Println(timerToFriendlyString(v))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Just output the time given the filters
|
||||
*/
|
||||
func (a *AppState) opShowTime(args []string) int {
|
||||
list := a.getFilteredTimerList(args)
|
||||
var isActive bool
|
||||
var total time.Duration
|
||||
for _, v := range *list {
|
||||
dur := v.FinishDate.Sub(v.StartDate)
|
||||
if v.FinishDate.IsZero() {
|
||||
dur = time.Now().Sub(v.StartDate)
|
||||
isActive = true
|
||||
}
|
||||
total += dur
|
||||
}
|
||||
total = total.Round(GetRoundToDuration())
|
||||
if isActive {
|
||||
fmt.Printf("%.2f+\n", DurationToDecimal(total))
|
||||
} else {
|
||||
fmt.Printf("%.2f\n", DurationToDecimal(total))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* List timers for a given time span
|
||||
* By default, only list Today
|
||||
*/
|
||||
func (a *AppState) opListTimers(args []string) int {
|
||||
var includeArchive bool
|
||||
var err error
|
||||
start := time.Time{}
|
||||
end := time.Now()
|
||||
var contextFilters []string
|
||||
var projectFilters []string
|
||||
|
||||
var allFilters []func(timertxt.Timer) bool
|
||||
|
||||
if len(args) > 0 {
|
||||
contextFilters, args = getContextsFromSlice(args)
|
||||
projectFilters, args = getProjectsFromSlice(args)
|
||||
}
|
||||
if len(args) > 0 {
|
||||
if args[0] == "--a" {
|
||||
includeArchive = true
|
||||
args = args[1:]
|
||||
}
|
||||
}
|
||||
if len(args) > 0 {
|
||||
if start, err = parseFuzzyTime(args[0]); err != nil {
|
||||
y, m, d := time.Now().Date()
|
||||
start = time.Date(y, m, d, 0, 0, 0, 0, time.Now().Location())
|
||||
} else {
|
||||
args = args[1:]
|
||||
}
|
||||
if len(args) > 0 {
|
||||
if end, err = parseFuzzyTime(args[0]); err != nil {
|
||||
y, m, d := time.Now().Date()
|
||||
end = time.Date(y, m, d, 23, 59, 59, 0, time.Now().Location())
|
||||
} else {
|
||||
args = args[1:]
|
||||
}
|
||||
}
|
||||
}
|
||||
if includeArchive {
|
||||
if err = a.LoadDoneList(); err != nil {
|
||||
fmt.Println("Error loading done.txt entries")
|
||||
fmt.Println(err.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
list := a.TimerList.GetTimersInRange(start, end)
|
||||
if includeArchive {
|
||||
*list = append(*list, (*a.DoneList.GetTimersInRange(start, end))...)
|
||||
}
|
||||
if len(contextFilters) > 0 {
|
||||
allFilters = append(allFilters, func(t timertxt.Timer) bool {
|
||||
for _, v := range contextFilters {
|
||||
v = strings.TrimPrefix(v, "@")
|
||||
if !t.HasContext(v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
if len(projectFilters) > 0 {
|
||||
allFilters = append(allFilters, func(t timertxt.Timer) bool {
|
||||
for _, v := range projectFilters {
|
||||
v = strings.TrimPrefix(v, "+")
|
||||
if !t.HasProject(v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
doFilters := func(t *timertxt.Timer) bool {
|
||||
for _, v := range allFilters {
|
||||
if !v(*t) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// If we made it all the way down here, it matches
|
||||
return true
|
||||
}
|
||||
list = list.Filter(doFilters)
|
||||
|
||||
dayTotals := make(map[string]time.Duration)
|
||||
for _, v := range *list {
|
||||
dur := v.FinishDate.Sub(v.StartDate)
|
||||
if v.FinishDate.IsZero() {
|
||||
dur = time.Now().Sub(v.StartDate)
|
||||
}
|
||||
dayTotals[v.StartDate.Format("2006/01/02")] += dur
|
||||
}
|
||||
var oldDayStr, dayStr string
|
||||
for _, v := range *list {
|
||||
oldDayStr = dayStr
|
||||
dayStr = v.StartDate.Format("2006/01/02")
|
||||
if dayStr != oldDayStr {
|
||||
wrkDur := dayTotals[dayStr].Round(GetRoundToDuration())
|
||||
fmtStr := dayStr + " ( %.2f )\n"
|
||||
fmt.Printf(fmtStr, DurationToDecimal(wrkDur))
|
||||
}
|
||||
|
||||
fmt.Println(" " + timerToFriendlyString(v))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opStartTimer(args []string) int {
|
||||
var contexts, projects, strTags []string
|
||||
t := timertxt.NewTimer()
|
||||
if len(args) > 0 {
|
||||
if start, err := parseFuzzyTime(args[0]); err == nil {
|
||||
t.StartDate = start
|
||||
args = args[1:]
|
||||
}
|
||||
}
|
||||
contexts, args = getContextsFromSlice(args)
|
||||
projects, args = getProjectsFromSlice(args)
|
||||
strTags, args = getAdditionalTagsFromSlice(args)
|
||||
for _, v := range contexts {
|
||||
t.Contexts = append(t.Contexts, strings.TrimPrefix(v, "@"))
|
||||
}
|
||||
for _, v := range projects {
|
||||
t.Projects = append(t.Projects, strings.TrimPrefix(v, "+"))
|
||||
}
|
||||
for _, v := range strTags {
|
||||
tgPts := strings.Split(v, ":")
|
||||
t.AdditionalTags[tgPts[0]] = tgPts[1]
|
||||
}
|
||||
|
||||
a.TimerList.AddTimer(t)
|
||||
if err := a.WriteList(); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return 1
|
||||
}
|
||||
fmt.Println("Started: ", TimerToString(t))
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opToggleTimer(args []string) int {
|
||||
wrk, err := a.getMostRecentTimer()
|
||||
if err != nil {
|
||||
fmt.Print("{\"icon\":\"time\",\"state\":\"Critical\", \"text\": \"Error loading timer entry\"}")
|
||||
return 0
|
||||
}
|
||||
var startArgs []string
|
||||
if wrk.Finished {
|
||||
// Start a new timer with the same data
|
||||
for _, v := range wrk.Contexts {
|
||||
startArgs = append(startArgs, "@"+v)
|
||||
}
|
||||
for _, v := range wrk.Projects {
|
||||
startArgs = append(startArgs, "+"+v)
|
||||
}
|
||||
for k, v := range wrk.AdditionalTags {
|
||||
startArgs = append(startArgs, k+":"+v)
|
||||
}
|
||||
a.opStartTimer(startArgs)
|
||||
} else {
|
||||
// Stop the active timer
|
||||
a.opStopTimer([]string{})
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opStopTimer(args []string) int {
|
||||
var err error
|
||||
var wrk time.Time
|
||||
end := time.Now()
|
||||
id := -1
|
||||
|
||||
if len(args) > 0 {
|
||||
if wrk, err = parseFuzzyTime(args[0]); err != nil {
|
||||
id, err = strconv.Atoi(args[0])
|
||||
} else {
|
||||
end = wrk
|
||||
args = args[1:]
|
||||
}
|
||||
}
|
||||
fmt.Println("Stopping at : " + end.Format(time.RFC3339))
|
||||
var timerIds []int
|
||||
if id == -1 {
|
||||
for _, v := range *a.TimerList.GetActiveTimers() {
|
||||
timerIds = append(timerIds, v.Id)
|
||||
}
|
||||
} else {
|
||||
timerIds = append(timerIds, id)
|
||||
}
|
||||
for _, v := range timerIds {
|
||||
var stopped *timertxt.Timer
|
||||
if stopped, err = a.TimerList.GetTimer(v); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
if err = a.SetTimerFinished(v, end); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
fmt.Println("Stopped Timer:", timerToFriendlyString(stopped))
|
||||
}
|
||||
if err = a.WriteList(); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opSwitchTimer(args []string) int {
|
||||
var timerIds []int
|
||||
var err error
|
||||
end := time.Now()
|
||||
// Stop all running timers and start a new one with the given args
|
||||
for _, v := range *a.TimerList.GetActiveTimers() {
|
||||
timerIds = append(timerIds, v.Id)
|
||||
}
|
||||
fmt.Print("Stopping ", timerIds, "\n")
|
||||
for _, v := range timerIds {
|
||||
var stopped *timertxt.Timer
|
||||
if stopped, err = a.TimerList.GetTimer(v); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
if err = a.SetTimerFinished(v, end); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
continue
|
||||
}
|
||||
fmt.Println("Stopped Timer:", timerToFriendlyString(stopped))
|
||||
}
|
||||
return a.opStartTimer(args)
|
||||
}
|
||||
|
||||
func (a *AppState) opArchiveTimer(args []string) int {
|
||||
if len(args) > 0 {
|
||||
for _, v := range args {
|
||||
var id int
|
||||
var timer *timertxt.Timer
|
||||
var err error
|
||||
if strings.HasPrefix(v, "@") {
|
||||
// We're archiving by context
|
||||
v = strings.TrimPrefix(v, "@")
|
||||
fmt.Println("Archiving by context:", v)
|
||||
timers := a.TimerList.GetTimersWithContext(v)
|
||||
fmt.Println("Found timers: ", len(*timers))
|
||||
for _, tmr := range *timers {
|
||||
if tmr.Finished {
|
||||
if err = a.archiveTimer(tmr.Id); err != nil {
|
||||
fmt.Printf("Error archiving timer %d\n", tmr.Id)
|
||||
continue
|
||||
}
|
||||
fmt.Println(a.getDoneTimerString(*tmr))
|
||||
} else {
|
||||
fmt.Println("Refusing to archive running timer:", tmr.Id)
|
||||
}
|
||||
}
|
||||
} else if strings.HasPrefix(v, "+") {
|
||||
// We're archiving by projcet
|
||||
v = strings.TrimPrefix(v, "+")
|
||||
fmt.Println("Archiving by project:", v)
|
||||
timers := a.TimerList.GetTimersWithProject(v)
|
||||
fmt.Println("Found timers: ", len(*timers))
|
||||
for _, tmr := range *timers {
|
||||
if tmr.Finished {
|
||||
if err = a.archiveTimer(tmr.Id); err != nil {
|
||||
fmt.Printf("Error archiving timer %d\n", tmr.Id)
|
||||
continue
|
||||
}
|
||||
fmt.Println(a.getDoneTimerString(*tmr))
|
||||
} else {
|
||||
fmt.Println("Refusing to archive running timer:", tmr.Id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// I guess we're archiving by timer id
|
||||
if id, err = strconv.Atoi(v); err != nil {
|
||||
fmt.Printf("Invalid id given: %s\n", v)
|
||||
return 1
|
||||
}
|
||||
if timer, err = a.TimerList.GetTimer(id); err != nil {
|
||||
fmt.Printf("Error getting timer %d\n", id)
|
||||
return 1
|
||||
}
|
||||
if timer.Finished {
|
||||
if err = a.archiveTimer(id); err != nil {
|
||||
fmt.Printf("Error archiving timer %d\n", id)
|
||||
return 1
|
||||
}
|
||||
fmt.Println(a.getDoneTimerString(*timer))
|
||||
} else {
|
||||
fmt.Println("Refusing to archive running timer:", timer.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, v := range *a.TimerList {
|
||||
if v.Finished {
|
||||
if err := a.archiveTimer(v.Id); err != nil {
|
||||
fmt.Printf("Error archiving task %d\n", v.Id)
|
||||
return 1
|
||||
}
|
||||
fmt.Println(a.getDoneTimerString(*v))
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opRemoveTimer(args []string) int {
|
||||
if len(args) == 0 {
|
||||
fmt.Println("No timer id given")
|
||||
return 1
|
||||
}
|
||||
id, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
fmt.Println("Invalid timer id given: " + args[0])
|
||||
}
|
||||
t, err := a.TimerList.GetTimer(id)
|
||||
if err != nil {
|
||||
fmt.Println("Error getting timer with id: " + args[0])
|
||||
return 1
|
||||
}
|
||||
if err = a.TimerList.RemoveTimerById(id); err != nil {
|
||||
fmt.Println("Error Removing Timer: " + err.Error())
|
||||
return 1
|
||||
}
|
||||
fmt.Println("Timer removed")
|
||||
fmt.Println(TimerToString(t))
|
||||
if err := a.WriteList(); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opModifyTimer(args []string) int {
|
||||
var timer *timertxt.Timer
|
||||
var contexts, projects []string
|
||||
id, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
// We didn't have a timer id, so try to modify the first active timer
|
||||
if len(*a.TimerList.GetActiveTimers()) > 0 {
|
||||
timer = (*a.TimerList.GetActiveTimers())[0]
|
||||
} else {
|
||||
// And we don't have any active timers
|
||||
fmt.Println("No active timers, 'id' must be provided.")
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
args = args[1:]
|
||||
if timer, err = a.TimerList.GetTimer(id); err != nil {
|
||||
fmt.Printf("Error getting timer %d\n", id)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
var start, end time.Time
|
||||
|
||||
for _, v := range args {
|
||||
pts := strings.Split(v, "=")
|
||||
switch pts[0] {
|
||||
case "beginning", "start":
|
||||
if start, err = parseFuzzyTime(pts[1]); err != nil {
|
||||
fmt.Println("Error parsing start time.")
|
||||
return 1
|
||||
}
|
||||
case "stop", "finish", "end":
|
||||
if end, err = parseFuzzyTime(pts[1]); err != nil {
|
||||
fmt.Println("Error parsing end time.")
|
||||
return 1
|
||||
}
|
||||
case "project", "projects":
|
||||
projects = strings.Split(pts[1], ",")
|
||||
case "context", "contexts":
|
||||
contexts = strings.Split(pts[1], ",")
|
||||
}
|
||||
}
|
||||
if len(contexts) > 0 {
|
||||
for k := range contexts {
|
||||
contexts[k] = strings.TrimPrefix(contexts[k], "@")
|
||||
}
|
||||
timer.Contexts = contexts
|
||||
}
|
||||
if len(projects) > 0 {
|
||||
for k := range projects {
|
||||
projects[k] = strings.TrimPrefix(projects[k], "+")
|
||||
}
|
||||
timer.Projects = projects
|
||||
}
|
||||
if !start.IsZero() {
|
||||
timer.StartDate = start
|
||||
}
|
||||
if !end.IsZero() {
|
||||
timer.FinishDate = end
|
||||
timer.Finished = true
|
||||
}
|
||||
fmt.Println("Modified Timer:")
|
||||
fmt.Println(timerToFriendlyString(timer))
|
||||
|
||||
if err := a.WriteList(); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opFuzzyParse(args []string) int {
|
||||
if len(args) > 0 {
|
||||
if start, err := parseFuzzyTime(args[0]); err == nil {
|
||||
fmt.Println(start.Format(time.RFC3339))
|
||||
} else {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opConfig(args []string) int {
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Config Keys:")
|
||||
for _, v := range a.config.GetKeyList() {
|
||||
fmt.Println(" " + v)
|
||||
}
|
||||
fmt.Println(" timerpath")
|
||||
} else {
|
||||
if args[0] == "timerpath" {
|
||||
fmt.Println(a.directory + a.fileTimer)
|
||||
} else {
|
||||
fmt.Println(a.config.Get(args[0]))
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opPrintUsage(args []string) int {
|
||||
for _, v := range a.ValidOperations {
|
||||
for _, vv := range v {
|
||||
fmt.Println(" " + vv)
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opI3Status(args []string) int {
|
||||
state := "Idle"
|
||||
wrk, err := a.getMostRecentTimer()
|
||||
if err != nil {
|
||||
fmt.Print("{\"icon\":\"time\",\"state\":\"Critical\", \"text\": \"Error loading timer entry\"}")
|
||||
return 0
|
||||
}
|
||||
var text string
|
||||
if wrk.FinishDate.IsZero() {
|
||||
wrkDur := wrk.Duration().Round(time.Minute * 15)
|
||||
hrs := int(wrkDur.Hours())
|
||||
mins := int(wrkDur.Minutes()) - hrs*60
|
||||
if hrs > 0 {
|
||||
text = fmt.Sprintf("%dh%dm", hrs, mins)
|
||||
} else {
|
||||
text = fmt.Sprintf("%dm", mins)
|
||||
}
|
||||
if !wrk.Finished {
|
||||
// If the current time is before 7AM, after 5PM, or a weekend, use a Warning state
|
||||
cTime := time.Now()
|
||||
if cTime.Weekday() == time.Sunday || cTime.Weekday() == time.Saturday || cTime.Hour() < 7 || cTime.Hour() > 17 {
|
||||
state = "Warning"
|
||||
} else {
|
||||
state = "Good"
|
||||
}
|
||||
}
|
||||
for _, ctx := range wrk.Contexts {
|
||||
text = fmt.Sprintf("%s @%s", text, ctx)
|
||||
}
|
||||
for _, prj := range wrk.Projects {
|
||||
text = fmt.Sprintf("%s +%s", text, prj)
|
||||
}
|
||||
} else {
|
||||
text = "("
|
||||
for _, ctx := range wrk.Contexts {
|
||||
text = fmt.Sprintf("%s@%s ", text, ctx)
|
||||
}
|
||||
for _, prj := range wrk.Projects {
|
||||
text = fmt.Sprintf("%s+%s ", text, prj)
|
||||
}
|
||||
if text[len(text)-1] == ' ' {
|
||||
text = text[:len(text)-1]
|
||||
}
|
||||
text = text + ")"
|
||||
getListTotal := func(list *timertxt.TimerList) string {
|
||||
var isActive bool
|
||||
var total time.Duration
|
||||
for _, v := range *list {
|
||||
dur := v.FinishDate.Sub(v.StartDate)
|
||||
if v.FinishDate.IsZero() {
|
||||
dur = time.Now().Sub(v.StartDate)
|
||||
isActive = true
|
||||
}
|
||||
total += dur
|
||||
}
|
||||
total = total.Round(GetRoundToDuration())
|
||||
if isActive {
|
||||
return fmt.Sprintf("%.2f+", DurationToDecimal(total))
|
||||
} else {
|
||||
return fmt.Sprintf("%.2f", DurationToDecimal(total))
|
||||
}
|
||||
}
|
||||
dayList := a.getFilteredTimerList([]string{"--a", BeginningOfDay().Format("2006-01-02"), "@bcw"})
|
||||
text = text + " d:" + getListTotal(dayList)
|
||||
weekList := a.getFilteredTimerList([]string{"--a", BeginningOfWeek().Format("2006-01-02"), "@bcw"})
|
||||
text = text + " w:" + getListTotal(weekList)
|
||||
monthList := a.getFilteredTimerList([]string{"--a", BeginningOfMonth().Format("2006-01-02"), "@bcw"})
|
||||
text = text + " m:" + getListTotal(monthList)
|
||||
}
|
||||
fmt.Printf("{\"icon\":\"time\",\"state\":\"%s\", \"text\": \"%s\"}", state, text)
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *AppState) opEditor(args []string) int {
|
||||
editor := os.Getenv("EDITOR")
|
||||
if editor == "" {
|
||||
fmt.Println("No $EDITOR set")
|
||||
return 1
|
||||
}
|
||||
fmt.Println(editor, a.directory+a.fileTimer)
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user