When no active timer show summary on i3status
This commit is contained in:
parent
6ea133d20d
commit
2b357839e9
17
helpers.go
17
helpers.go
@ -283,3 +283,20 @@ func diff(a, b time.Time) (year, month, day, hour, min, sec int) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BeginningOfDay() time.Time {
|
||||||
|
now := time.Now()
|
||||||
|
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BeginningOfWeek() time.Time {
|
||||||
|
now := time.Now()
|
||||||
|
t := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||||
|
weekday := int(t.Weekday())
|
||||||
|
return t.AddDate(0, 0, -weekday)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BeginningOfMonth() time.Time {
|
||||||
|
now := time.Now()
|
||||||
|
return time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||||
|
}
|
||||||
|
107
model.go
107
model.go
@ -1,26 +1,113 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// If we have an active timer in timer.txt, return the most recent one
|
||||||
|
// Otherwise, check if we have a more recent completed timer in done.txt
|
||||||
|
// Return the most recent done from timer.txt or dont.txt
|
||||||
func (a *AppState) getMostRecentTimer() (*timertxt.Timer, error) {
|
func (a *AppState) getMostRecentTimer() (*timertxt.Timer, error) {
|
||||||
wrk, err := a.TimerList.GetMostRecentTimer()
|
work, wErr := a.TimerList.GetMostRecentTimer()
|
||||||
if err != nil {
|
if wErr != nil && work.FinishDate.IsZero() {
|
||||||
// Couldn't find a timer in the 'timer.txt'... Check the 'done' file
|
return work, nil
|
||||||
if err = a.LoadDoneList(); err != nil {
|
}
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
wrk, err = a.DoneList.GetMostRecentTimer()
|
if err := a.LoadDoneList(); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
|
done, dErr := a.DoneList.GetMostRecentTimer()
|
||||||
|
if dErr != nil {
|
||||||
|
return nil, dErr
|
||||||
|
}
|
||||||
|
if !done.FinishDate.IsZero() && done.FinishDate.After(work.FinishDate) {
|
||||||
|
return done, nil
|
||||||
|
}
|
||||||
|
return work, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) getFilteredTimerList(args []string) *timertxt.TimerList {
|
||||||
|
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:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wrk, nil
|
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:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list := a.TimerList.GetTimersInRange(start, end)
|
||||||
|
|
||||||
|
if includeArchive {
|
||||||
|
if err = a.LoadDoneList(); err != nil {
|
||||||
|
fmt.Println("Error loading done.txt entries")
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
*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
|
||||||
|
}
|
||||||
|
return list.Filter(doFilters)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppState) SetTimerFinished(id int, end time.Time) error {
|
func (a *AppState) SetTimerFinished(id int, end time.Time) error {
|
||||||
|
149
timer_ops.go
149
timer_ops.go
@ -17,33 +17,67 @@ func (a *AppState) opI3Status(args []string) int {
|
|||||||
fmt.Print("{\"icon\":\"time\",\"state\":\"Critical\", \"text\": \"Error loading timer entry\"}")
|
fmt.Print("{\"icon\":\"time\",\"state\":\"Critical\", \"text\": \"Error loading timer entry\"}")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get Weekly/Daily totals
|
|
||||||
var text string
|
var text string
|
||||||
if wrk.Finished {
|
if !wrk.Finished {
|
||||||
wrkDur := wrk.Duration().Round(time.Minute * 15)
|
wrkDur := wrk.Duration().Round(time.Minute * 15)
|
||||||
hrs := int(wrkDur.Hours())
|
hrs := int(wrkDur.Hours())
|
||||||
mins := int(wrkDur.Minutes()) - hrs*60
|
mins := int(wrkDur.Minutes()) - hrs*60
|
||||||
if hrs > 0 {
|
if hrs > 0 {
|
||||||
text = fmt.Sprintf("%dh%dm", hrs, mins)
|
text = fmt.Sprintf("%dh%dm", hrs, mins)
|
||||||
} else {
|
} else {
|
||||||
text = fmt.Sprintf("%d", mins)
|
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 {
|
} else {
|
||||||
text = fmt.Sprint(wrk.Duration().Round(time.Minute))
|
text = "("
|
||||||
// If the current time is before 7AM, after 5PM, or a weekend, use a Warning state
|
for _, ctx := range wrk.Contexts {
|
||||||
cTime := time.Now()
|
text = fmt.Sprintf("%s@%s ", text, ctx)
|
||||||
if cTime.Weekday() == time.Sunday || cTime.Weekday() == time.Saturday || cTime.Hour() < 7 || cTime.Hour() > 17 {
|
|
||||||
state = "Warning"
|
|
||||||
} else {
|
|
||||||
state = "Good"
|
|
||||||
}
|
}
|
||||||
}
|
for _, prj := range wrk.Projects {
|
||||||
for _, ctx := range wrk.Contexts {
|
text = fmt.Sprintf("%s+%s ", text, prj)
|
||||||
text = fmt.Sprintf("%s @%s", text, ctx)
|
}
|
||||||
}
|
if text[len(text)-1] == ' ' {
|
||||||
for _, prj := range wrk.Projects {
|
text = text[:len(text)-1]
|
||||||
text = fmt.Sprintf("%s +%s", text, prj)
|
}
|
||||||
|
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)
|
fmt.Printf("{\"icon\":\"time\",\"state\":\"%s\", \"text\": \"%s\"}", state, text)
|
||||||
return 0
|
return 0
|
||||||
@ -82,86 +116,7 @@ func (a *AppState) opStatus(args []string) int {
|
|||||||
* Just output the time given the filters
|
* Just output the time given the filters
|
||||||
*/
|
*/
|
||||||
func (a *AppState) opShowTime(args []string) int {
|
func (a *AppState) opShowTime(args []string) int {
|
||||||
var includeArchive bool
|
list := a.getFilteredTimerList(args)
|
||||||
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)
|
|
||||||
|
|
||||||
var isActive bool
|
var isActive bool
|
||||||
var total time.Duration
|
var total time.Duration
|
||||||
for _, v := range *list {
|
for _, v := range *list {
|
||||||
|
Loading…
Reference in New Issue
Block a user