This commit is contained in:
Brian Buller 2023-01-12 06:52:15 -06:00
commit a4f1603df5
10 changed files with 162 additions and 185 deletions

View File

@ -33,13 +33,13 @@ func (p *Program) GetTimerFilePath() string {
func (p *Program) LoadTimerList() error { func (p *Program) LoadTimerList() error {
var err error var err error
var tl timertxt.TimerList var tl *timertxt.TimerList
tl, err = timertxt.LoadFromFilename(p.timerPath) tl, err = timertxt.LoadFromFilename(p.timerPath)
if err != nil { if err != nil {
return err return err
} }
tl.Sort(timertxt.SORT_UNFINISHED_START) tl.Sort(timertxt.SORT_UNFINISHED_START)
p.TimerList = &tl p.TimerList = tl
return nil return nil
} }
@ -53,12 +53,12 @@ func (p *Program) GetDoneFilePath() string {
func (p *Program) LoadDoneList() error { func (p *Program) LoadDoneList() error {
var err error var err error
var tl timertxt.TimerList var tl *timertxt.TimerList
tl, err = timertxt.LoadFromFilename(p.donePath) tl, err = timertxt.LoadFromFilename(p.donePath)
if err != nil { if err != nil {
return err return err
} }
p.DoneList = &tl p.DoneList = tl
return nil return nil
} }
@ -110,14 +110,14 @@ func (p *Program) GetFilteredTimerList(args []string) *timertxt.TimerList {
} }
} }
list := p.TimerList.GetTimersInRange(start, end) list := p.TimerList.GetTimersInRange(start, end)
if includeArchive { if includeArchive {
if err = p.LoadDoneList(); err != nil { if err = p.LoadDoneList(); err != nil {
fmt.Println("Error loading done.txt entries") fmt.Println("Error loading done.txt entries")
fmt.Println(err.Error()) fmt.Println(err.Error())
return nil return nil
} }
*list = append(*list, (*p.DoneList.GetTimersInRange(start, end))...) doneList := p.DoneList.GetTimersInRange(start, end)
list.Combine(doneList)
} }
if len(contextFilters) > 0 { if len(contextFilters) > 0 {
allFilters = append(allFilters, func(t timertxt.Timer) bool { allFilters = append(allFilters, func(t timertxt.Timer) bool {

View File

@ -91,7 +91,7 @@ func opI3Status(cmd *cobra.Command, args []string) error {
getListTotal := func(list *timertxt.TimerList) string { getListTotal := func(list *timertxt.TimerList) string {
var isActive bool var isActive bool
var total time.Duration var total time.Duration
for _, v := range *list { for _, v := range list.GetTimerSlice() {
dur := v.FinishDate.Sub(v.StartDate) dur := v.FinishDate.Sub(v.StartDate)
if v.FinishDate.IsZero() { if v.FinishDate.IsZero() {
dur = time.Now().Sub(v.StartDate) dur = time.Now().Sub(v.StartDate)

View File

@ -76,7 +76,7 @@ func opListTimers(cmd *cobra.Command, args []string) error {
list = list.Filter(filter) list = list.Filter(filter)
dayTotals := make(map[string]time.Duration) dayTotals := make(map[string]time.Duration)
for _, v := range *list { for _, v := range list.GetTimerSlice() {
dur := v.FinishDate.Sub(v.StartDate) dur := v.FinishDate.Sub(v.StartDate)
if v.FinishDate.IsZero() { if v.FinishDate.IsZero() {
dur = time.Now().Sub(v.StartDate) dur = time.Now().Sub(v.StartDate)
@ -84,7 +84,7 @@ func opListTimers(cmd *cobra.Command, args []string) error {
dayTotals[v.StartDate.Format("2006/01/02")] += dur dayTotals[v.StartDate.Format("2006/01/02")] += dur
} }
var oldDayStr, dayStr string var oldDayStr, dayStr string
for _, v := range *list { for _, v := range list.GetTimerSlice() {
oldDayStr = dayStr oldDayStr = dayStr
dayStr = v.StartDate.Format("2006/01/02") dayStr = v.StartDate.Format("2006/01/02")
if dayStr != oldDayStr { if dayStr != oldDayStr {

View File

@ -42,8 +42,9 @@ func opMod(cmd *cobra.Command, args []string) error {
id, err := strconv.Atoi(args[0]) id, err := strconv.Atoi(args[0])
if err != nil { if err != nil {
// We didn't have a timer id, so try to modify the first active timer // We didn't have a timer id, so try to modify the first active timer
if len(*p.TimerList.GetActiveTimers()) > 0 { active := p.TimerList.GetActiveTimers().GetTimerSlice()
timer = (*p.TimerList.GetActiveTimers())[0] if len(active) > 0 {
timer = active[0]
} else { } else {
// And we don't have any active timers // And we don't have any active timers
return fmt.Errorf("No active timers, 'id' must be provided: %w", err) return fmt.Errorf("No active timers, 'id' must be provided: %w", err)

View File

@ -34,12 +34,13 @@ func opStatus(cmd *cobra.Command, args []string) error {
if err := p.LoadTimerList(); err != nil { if err := p.LoadTimerList(); err != nil {
return fmt.Errorf("Error loading timer list: %w", err) return fmt.Errorf("Error loading timer list: %w", err)
} }
if len(*p.TimerList.GetActiveTimers()) == 0 { active := p.TimerList.GetActiveTimers().GetTimerSlice()
if len(active) == 0 {
fmt.Println("No timers running") fmt.Println("No timers running")
return nil return nil
} }
var currDur time.Duration var currDur time.Duration
for _, v := range *p.TimerList { for _, v := range active {
if v.ActiveToday() { if v.ActiveToday() {
currDur += v.Duration() currDur += v.Duration()
} }
@ -47,7 +48,7 @@ func opStatus(cmd *cobra.Command, args []string) error {
d := util.Round(currDur) d := util.Round(currDur)
fmt.Printf("%s ( %.2f hrs )\n", time.Now().Format(time.Stamp), util.DurationToDecimal(d)) fmt.Printf("%s ( %.2f hrs )\n", time.Now().Format(time.Stamp), util.DurationToDecimal(d))
for _, v := range *p.TimerList.GetActiveTimers() { for _, v := range active {
fmt.Println(util.TimerToFriendlyString(v)) fmt.Println(util.TimerToFriendlyString(v))
} }
return nil return nil

View File

@ -51,7 +51,7 @@ func opStop(cmd *cobra.Command, args []string) error {
fmt.Println("Stopping at : " + end.Format(time.RFC3339)) fmt.Println("Stopping at : " + end.Format(time.RFC3339))
var timerIds []int var timerIds []int
if id == -1 { if id == -1 {
for _, v := range *p.TimerList.GetActiveTimers() { for _, v := range p.TimerList.GetActiveTimers().GetTimerSlice() {
timerIds = append(timerIds, v.Id) timerIds = append(timerIds, v.Id)
} }
} else { } else {

View File

@ -38,7 +38,7 @@ func opSwitch(cmd *cobra.Command, args []string) error {
var timerIds []int var timerIds []int
end := time.Now() end := time.Now()
// Stop all running timers and start a new one with the given args // Stop all running timers and start a new one with the given args
for _, v := range *p.TimerList.GetActiveTimers() { for _, v := range p.TimerList.GetActiveTimers().GetTimerSlice() {
timerIds = append(timerIds, v.Id) timerIds = append(timerIds, v.Id)
} }
fmt.Print("Stopping ", timerIds, "\n") fmt.Print("Stopping ", timerIds, "\n")

View File

@ -37,7 +37,7 @@ func opShowTimers(cmd *cobra.Command, args []string) error {
list := p.GetFilteredTimerList(args) list := p.GetFilteredTimerList(args)
var isActive bool var isActive bool
var total time.Duration var total time.Duration
for _, v := range *list { for _, v := range list.GetTimerSlice() {
dur := v.FinishDate.Sub(v.StartDate) dur := v.FinishDate.Sub(v.StartDate)
if v.FinishDate.IsZero() { if v.FinishDate.IsZero() {
dur = time.Now().Sub(v.StartDate) dur = time.Now().Sub(v.StartDate)

View File

@ -1,168 +0,0 @@
package ui
import (
"fmt"
"strings"
"time"
"git.bullercodeworks.com/brian/gime/util"
"git.bullercodeworks.com/brian/go-timertxt"
"git.bullercodeworks.com/brian/wandle"
"git.bullercodeworks.com/brian/widdles"
"github.com/nsf/termbox-go"
)
type listTimersScreen struct {
ui *Ui
initialized bool
menu *widdles.TopMenu
scrollbar *widdles.Scrollbar
cursor int
timerList *timertxt.TimerList
doneList *timertxt.TimerList
timerFilterList *timertxt.TimerList
doneFilterList *timertxt.TimerList
filter string
msg string
err error
}
type ListTimersMsg ScreenMsg
func NewListTimersScreen(u *Ui) *listTimersScreen {
w, h := termbox.Size()
s := listTimersScreen{
ui: u,
menu: widdles.NewTopMenu(0, 0, 0),
scrollbar: widdles.NewScrollbar(w-2, 2, 1, h-2),
}
return &s
}
func (s *listTimersScreen) Init() wandle.Cmd {
if s.initialized {
return nil
}
s.initialized = true
// Set up the top menu
fileMenu := s.menu.NewSubMenu("File")
settingsOption := widdles.NewMenuItem("Settings")
settingsOption.SetCommand(s.ui.GotoScreen(SettingsId))
fileMenu.AddOption(settingsOption)
quitOption := widdles.NewMenuItem("Quit")
quitOption.Hotkey = termbox.KeyCtrlC
quitOption.SetCommand(func() wandle.Msg { return wandle.Quit() })
fileMenu.AddOption(quitOption)
s.menu.Measure()
// Timer Lists
s.timerList, s.doneList = s.ui.program.TimerList, s.ui.program.DoneList
s.timerFilterList, s.doneFilterList = s.timerList, s.doneList
s.timerFilterList.Sort(timertxt.SORT_START_DATE_DESC)
s.doneFilterList.Sort(timertxt.SORT_START_DATE_DESC)
return nil
}
func (s *listTimersScreen) Update(msg wandle.Msg) wandle.Cmd {
switch msg := msg.(type) {
case ScreenMsg:
case termbox.Event:
return s.handleTermboxEvent(msg)
}
return nil
}
func (s *listTimersScreen) View(style wandle.Style) {
_, h := termbox.Size()
if s.menu.IsActive() {
s.menu.View(style)
}
y := 2
wandle.Print(1, y, style.Bold(true), "Active Timers")
y++
for idx, tmr := range s.timerFilterList.GetTimerSlice() {
if y > h-2 {
break
}
st := style
if s.cursor == idx {
st = st.Invert()
}
wandle.Print(1, y, st, "[ ]")
s.ViewTimer(5, y, st, tmr)
y++
}
y++
wandle.Print(1, y, style.Bold(true), "Done Timers")
y++
for idx, tmr := range s.doneFilterList.GetTimerSlice() {
if y > h-2 {
break
}
st := style
if s.cursor == s.timerFilterList.Size()+idx {
st = st.Invert()
}
wandle.Print(1, y, st, "[ ]")
s.ViewTimer(5, y, st, tmr)
y++
}
s.scrollbar.View(style)
}
func (s *listTimersScreen) ViewTimer(x, y int, style wandle.Style, tmr *timertxt.Timer) {
var tags []string
for _, k := range util.SortedTagKeyList(tmr.AdditionalTags) {
tags = append(tags, fmt.Sprintf("%s:%s", k, tmr.AdditionalTags[k]))
}
wandle.Print(x, y, style, fmt.Sprintf("%s %s %s %s %s", tmr.StartDate.Format(time.Stamp), tmr.Duration(), tmr.Contexts, tmr.Projects, strings.Join(tags, "; ")))
}
func (s *listTimersScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
if (msg.Type == termbox.EventKey && msg.Key == termbox.KeyEsc) || s.menu.IsActive() {
return s.menu.Update(msg)
}
switch msg.Type {
case termbox.EventKey:
top := s.timerFilterList.Size() + s.doneFilterList.Size() - 2
if msg.Key == termbox.KeyEnter {
/*
if s.cursor >= 0 && s.cursor < s.timerFilterList.Size()+s.doneFilterList.Size() {
} else {
}
*/
} else if msg.Key == termbox.KeyArrowUp || msg.Ch == 'k' {
if s.cursor > 0 {
s.cursor--
} else {
s.cursor = 0
}
return nil
} else if msg.Key == termbox.KeyArrowDown || msg.Ch == 'j' {
if s.cursor < top {
s.cursor++
} else {
s.cursor = top
}
return nil
} else if msg.Ch == 'G' {
s.cursor = top
}
}
return nil
}
func (s *listTimersScreen) gotoSettingsScreen() wandle.Msg {
return ScreenMsg{
source: ListTimersId,
command: CmdGotoSettings,
}
}

143
ui/widdle_manageparts.go Normal file
View File

@ -0,0 +1,143 @@
package ui
import (
"fmt"
"git.bullercodeworks.com/brian/wandle"
"git.bullercodeworks.com/brian/widdles"
"github.com/nsf/termbox-go"
)
/*
* PartManager is for adding/editing/removing groups of strings
*/
type PartManager struct {
active bool
visible bool
x, y, w, h int
label string
typeString string
options []string
selOptions map[int]bool
input *widdles.ToggleField
cursor int
}
var _ widdles.Widdle = (*PartManager)(nil)
func NewPartManager(label string, x, y, w, h int) *PartManager {
return &PartManager{
label: label,
selOptions: make(map[int]bool),
input: widdles.NewToggleField("Value:", "", x+1, y+2, w-2, 1),
}
}
func (w *PartManager) Init() wandle.Cmd { return nil }
func (w *PartManager) Update(msg wandle.Msg) wandle.Cmd {
if w.active {
if msg, ok := msg.(termbox.Event); ok {
return w.handleTermboxEvent(msg)
}
}
return nil
}
func (w *PartManager) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
if w.cursor == 0 {
if opt := w.input.Update(msg); opt != nil {
return opt
} else {
//return w.handleKeyPress(msg)
}
}
return w.handleKeyPress(msg)
}
func (w *PartManager) handleKeyPress(msg termbox.Event) wandle.Cmd {
if msg.Key == termbox.KeyEsc {
return func() wandle.Msg {
w.Hide()
return nil
}
} else if msg.Ch == 'j' || msg.Key == termbox.KeyArrowDown {
if w.cursor < len(w.options) {
w.cursor = w.cursor + 1
}
} else if msg.Ch == 'k' || msg.Key == termbox.KeyArrowUp {
if w.cursor > 0 {
w.cursor = w.cursor - 1
}
}
if w.IsActive() {
return func() wandle.Msg { return nil }
}
return nil
}
func (w *PartManager) View(style wandle.Style) {
if w.visible {
wandle.TitledBorderFilled(w.label, w.x, w.y, w.x+w.w, w.y+w.h, style, wandle.BRD_SIMPLE)
st := style
if w.cursor == 0 {
st = st.Invert()
}
w.input.View(st)
y := w.input.GetY() + 1
wandle.Print(w.x+1, y, style, fmt.Sprintf("Add %s:", w.typeString))
y++
for i := range w.options {
st := style
if w.cursor-1 == i {
st = st.Invert()
}
wandle.Print(w.x+3, y, st, w.options[i])
y++
}
}
}
func (w *PartManager) IsActive() bool { return w.active }
func (w *PartManager) SetActive(b bool) { w.active = b }
func (w *PartManager) Focusable() bool { return true }
func (w *PartManager) SetX(x int) {
w.x = x
w.Measure()
}
func (w *PartManager) GetX() int { return w.x }
func (w *PartManager) SetY(y int) {
w.y = y
w.Measure()
}
func (w *PartManager) GetY() int { return w.y }
func (w *PartManager) SetHeight(h int) {
w.h = h
w.Measure()
}
func (w *PartManager) GetHeight() int { return w.h }
func (w *PartManager) SetWidth(v int) {
w.w = v
w.Measure()
}
func (w *PartManager) GetWidth() int { return w.w }
func (w *PartManager) Measure() {
w.input.SetX(w.x + 1)
w.input.SetY(w.y + 1)
w.input.SetWidth(w.w - 2)
w.input.SetHeight(1)
}
func (w *PartManager) SetLabel(lbl string) { w.label = lbl }
func (w *PartManager) SetType(tp string) { w.typeString = tp }
func (w *PartManager) SetValue(val string) { w.input.SetValue(val) }
func (w *PartManager) GetValue() string { return w.input.GetValue() }
func (w *PartManager) SetOptions(opts []string) { w.options = opts }
func (w *PartManager) SetVisible(is bool) { w.visible = is }
func (w *PartManager) IsVisible() bool { return w.visible }
func (w *PartManager) Show() {
w.SetVisible(true)
w.SetActive(true)
}
func (w *PartManager) Hide() {
w.SetVisible(false)
w.SetActive(false)
}