186 lines
3.8 KiB
Go
186 lines
3.8 KiB
Go
|
package gotime
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type GoTime struct {
|
||
|
Dir string
|
||
|
timers []Timer
|
||
|
files []string
|
||
|
timeFormat string
|
||
|
Tags []string
|
||
|
}
|
||
|
|
||
|
// Create creates a new instance of GoTime
|
||
|
// with the given data directory
|
||
|
func Create(dir string) *GoTime {
|
||
|
g := &GoTime{Dir: dir}
|
||
|
g.timeFormat = "20060102T150405Z"
|
||
|
|
||
|
g.files = g.getTimerFiles()
|
||
|
for _, f := range g.files {
|
||
|
g.addTimersFromFile(f)
|
||
|
}
|
||
|
g.ResetIds()
|
||
|
return g
|
||
|
}
|
||
|
|
||
|
func (g *GoTime) ResetIds() {
|
||
|
// Now set IDs
|
||
|
id := 1
|
||
|
for i := len(g.timers) - 1; i >= 0; i-- {
|
||
|
g.timers[i].SetId(id)
|
||
|
id++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// IsOn returns true if a timer is currently running
|
||
|
func (g *GoTime) IsOn() bool {
|
||
|
t := g.Status()
|
||
|
if t.End.IsZero() {
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// Status returns the most recent timer
|
||
|
func (g *GoTime) Status() *Timer {
|
||
|
if len(g.timers) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return &g.timers[len(g.timers)-1]
|
||
|
}
|
||
|
|
||
|
// IsRunning returns if the Status() is running
|
||
|
func (g *GoTime) IsRunning() bool {
|
||
|
return g.Status().IsRunning()
|
||
|
}
|
||
|
|
||
|
func (g *GoTime) GetAllTimers() []Timer {
|
||
|
return g.timers
|
||
|
}
|
||
|
|
||
|
// getTimerFiles Returns a string slice of all of the data file names
|
||
|
func (g *GoTime) getTimerFiles() []string {
|
||
|
var ret []string
|
||
|
// Timer files are all files in g.dir/data except undo.data
|
||
|
files, _ := ioutil.ReadDir(g.Dir + "/data/")
|
||
|
for _, f := range files {
|
||
|
if f.Name() != "undo.data" {
|
||
|
ret = append(ret, f.Name())
|
||
|
}
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
// addTimersFromFile Adds all timer lines from g.Dir/data/f and adds a timer for it
|
||
|
func (g *GoTime) addTimersFromFile(f string) error {
|
||
|
content, err := ioutil.ReadFile(g.Dir + "/data/" + f)
|
||
|
if err != nil {
|
||
|
fmt.Println(err)
|
||
|
return err
|
||
|
}
|
||
|
cntString := strings.TrimSpace(string(content))
|
||
|
|
||
|
lines := strings.Split(cntString, "\n")
|
||
|
for i := range lines {
|
||
|
if err = g.AddTimerFromString(lines[i]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// AddTimerFromString takes a string in the format of the lines from the data file
|
||
|
// and builds a timer from it.
|
||
|
func (g *GoTime) AddTimerFromString(st string) error {
|
||
|
var err error
|
||
|
t := new(Timer)
|
||
|
flds := strings.Fields(st)
|
||
|
if len(flds) > 1 && flds[0] == "inc" {
|
||
|
// Start Time
|
||
|
if len(flds) >= 2 {
|
||
|
if t.Beg, err = time.Parse(g.timeFormat, flds[1]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
// End Time
|
||
|
if len(flds) >= 4 && flds[2] == "-" {
|
||
|
if t.End, err = time.Parse(g.timeFormat, flds[3]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
var inTags bool
|
||
|
for i := range flds {
|
||
|
if flds[i] == "#" {
|
||
|
inTags = true
|
||
|
continue
|
||
|
}
|
||
|
if inTags {
|
||
|
tg := strings.Trim(flds[i], "\"")
|
||
|
t.Tags = append(t.Tags, tg)
|
||
|
g.AddTag(tg)
|
||
|
}
|
||
|
}
|
||
|
if !t.Beg.IsZero() {
|
||
|
g.timers = append(g.timers, *t)
|
||
|
}
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// AddTag adds a tag to list of all used tags
|
||
|
func (g *GoTime) AddTag(tg string) {
|
||
|
if !g.HasTag(tg) {
|
||
|
g.Tags = append(g.Tags, tg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// HasTag returns if this tag is in our list
|
||
|
func (g *GoTime) HasTag(tg string) bool {
|
||
|
for i := range g.Tags {
|
||
|
if g.Tags[i] == tg {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// Start starts a new timer. If one is already active, it stops it first
|
||
|
func (g *GoTime) StartTimer() *Timer {
|
||
|
if g.IsRunning() {
|
||
|
g.StopTimer()
|
||
|
}
|
||
|
t := new(Timer)
|
||
|
t.Beg = time.Now()
|
||
|
g.timers = append(g.timers, *t)
|
||
|
// TODO: Add a line to the YYYY-MM.data file
|
||
|
// TODO: Update the Undo File
|
||
|
g.ResetIds()
|
||
|
|
||
|
return g.Status()
|
||
|
}
|
||
|
|
||
|
// Stop stops the currently active timer
|
||
|
func (g *GoTime) StopTimer() *Timer {
|
||
|
if g.IsRunning() {
|
||
|
g.Status().Stop()
|
||
|
}
|
||
|
// TODO: Add a stop time to the last line in the YYYY-MM.data file
|
||
|
// TODO: Update the Undo File
|
||
|
return g.Status()
|
||
|
}
|
||
|
|
||
|
// AddTag adds a new tag to the most recent timer
|
||
|
func (g *GoTime) AddTagToCurrentTimer(tg string) *Timer {
|
||
|
g.Status().AddTag(tg)
|
||
|
// TODO: Add the tag to the last line in the YYYY-MM.data file
|
||
|
// TODO: Update the Undo File
|
||
|
|
||
|
return g.Status()
|
||
|
}
|