Initial Commit
This commit is contained in:
parent
7305e4e54c
commit
cf80d56e20
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
# ---> Go
|
# ---> Go
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
|
gime
|
||||||
*.exe
|
*.exe
|
||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
|
189
app_state.go
Normal file
189
app_state.go
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
||||||
|
"github.com/br0xen/user-config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppState struct {
|
||||||
|
Name string
|
||||||
|
Version int
|
||||||
|
config *userConfig.Config
|
||||||
|
directory string
|
||||||
|
fileTimer string
|
||||||
|
fileDone string
|
||||||
|
fileReport string
|
||||||
|
ValidOperations map[string][]string
|
||||||
|
OpFuncs map[string]func([]string) int
|
||||||
|
|
||||||
|
TimerList *timertxt.TimerList
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApp() *AppState {
|
||||||
|
app := &AppState{Name: AppName, Version: AppVersion}
|
||||||
|
app.initialize()
|
||||||
|
app.doVersionCheck()
|
||||||
|
if err := app.LoadTimerList(); err != nil {
|
||||||
|
if len(os.Args) > 1 && os.Args[1] != "--reinit" {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) run(parms []string) int {
|
||||||
|
if len(parms) == 0 || parms[0] == "ui" {
|
||||||
|
// UI Mode
|
||||||
|
//return uiLoop()
|
||||||
|
}
|
||||||
|
if fn, ok := a.OpFuncs[parms[0]]; ok {
|
||||||
|
return fn(parms[1:])
|
||||||
|
}
|
||||||
|
fmt.Println("Unknown Command")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) getTimerFile() string {
|
||||||
|
return a.directory + a.fileTimer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) getDoneFile() string {
|
||||||
|
return a.directory + a.fileDone
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) getReportFile() string {
|
||||||
|
return a.directory + a.fileReport
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) addOperation(name string, desc []string, fn func([]string) int) {
|
||||||
|
a.ValidOperations[name] = desc
|
||||||
|
a.OpFuncs[name] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) doVersionCheck() {
|
||||||
|
confVer, _ := a.config.GetInt("version")
|
||||||
|
for confVer < a.Version {
|
||||||
|
confVer = a.migrate(confVer, a.Version)
|
||||||
|
}
|
||||||
|
a.config.SetInt("version", confVer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) migrate(from, to int) int {
|
||||||
|
if from == to {
|
||||||
|
return to
|
||||||
|
}
|
||||||
|
switch from {
|
||||||
|
case 0:
|
||||||
|
a.initializeConfig()
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
// If we get all the way down here, we _must_ be done.
|
||||||
|
return to
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) initialize() {
|
||||||
|
var err error
|
||||||
|
a.config, err = userConfig.NewConfig(a.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
a.ValidOperations = make(map[string][]string)
|
||||||
|
a.OpFuncs = make(map[string]func([]string) int)
|
||||||
|
a.addOperation("ls",
|
||||||
|
[]string{
|
||||||
|
"ls - List Timers",
|
||||||
|
},
|
||||||
|
a.opListTimers,
|
||||||
|
)
|
||||||
|
a.addOperation("lsa",
|
||||||
|
[]string{
|
||||||
|
"lsa - The same as 'ls -a'",
|
||||||
|
},
|
||||||
|
func(args []string) int {
|
||||||
|
return a.opListTimers(append([]string{"-a"}, args...))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
a.addOperation("start",
|
||||||
|
[]string{
|
||||||
|
"start [time] [@contexts...] [+projects...] [tag:value...]",
|
||||||
|
" - Start a timer with the given details",
|
||||||
|
" If the first argument looks like a time,",
|
||||||
|
" the timer will be started then (past or future)",
|
||||||
|
},
|
||||||
|
a.opStartTimer,
|
||||||
|
)
|
||||||
|
a.addOperation("stop",
|
||||||
|
[]string{
|
||||||
|
"stop [time] - Stops the current timer",
|
||||||
|
" If the first argument looks like a time,",
|
||||||
|
" the timer will be stopped then (past or future)",
|
||||||
|
},
|
||||||
|
a.opStopTimer,
|
||||||
|
)
|
||||||
|
a.addOperation("status",
|
||||||
|
[]string{
|
||||||
|
"status - Prints the status of all active timers",
|
||||||
|
},
|
||||||
|
a.opStatus,
|
||||||
|
)
|
||||||
|
a.addOperation("fuzzyparse",
|
||||||
|
[]string{
|
||||||
|
"fuzzyparse [date string] - Parses the passed string and print the RFC3339 result (for testing)",
|
||||||
|
},
|
||||||
|
a.opFuzzyParse,
|
||||||
|
)
|
||||||
|
a.addOperation("--reinit",
|
||||||
|
[]string{"--reinit - Reset all Configuration Settings"},
|
||||||
|
func(args []string) int {
|
||||||
|
a.initializeConfig()
|
||||||
|
return 0
|
||||||
|
},
|
||||||
|
)
|
||||||
|
a.addOperation("-h",
|
||||||
|
[]string{"-h - Print this message"},
|
||||||
|
a.opPrintUsage,
|
||||||
|
)
|
||||||
|
a.addOperation("help",
|
||||||
|
[]string{"help - Print this message"},
|
||||||
|
a.opPrintUsage,
|
||||||
|
)
|
||||||
|
a.addOperation("--h",
|
||||||
|
[]string{"--h - Print this message"},
|
||||||
|
a.opPrintUsage,
|
||||||
|
)
|
||||||
|
a.directory = a.config.Get("directory")
|
||||||
|
a.fileTimer = a.config.Get("timerfile")
|
||||||
|
a.fileDone = a.config.Get("donefile")
|
||||||
|
a.fileReport = a.config.Get("reportfile")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) initializeConfig() {
|
||||||
|
fmt.Println("Initializing " + a.Name)
|
||||||
|
for {
|
||||||
|
var add string
|
||||||
|
if a.directory != "" {
|
||||||
|
add = " (" + a.directory + ")"
|
||||||
|
}
|
||||||
|
fmt.Println("Path to timer.txt" + add + ":")
|
||||||
|
var resp string
|
||||||
|
fmt.Scanln(&resp)
|
||||||
|
if resp == "" && a.directory != "" {
|
||||||
|
resp = a.directory
|
||||||
|
}
|
||||||
|
if resp != "" {
|
||||||
|
if !strings.HasSuffix(resp, "/") {
|
||||||
|
resp = resp + "/"
|
||||||
|
}
|
||||||
|
fmt.Println("Setting timer.txt directory to: " + resp)
|
||||||
|
a.config.Set("directory", resp)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.config.Set("timerfile", "timer.txt")
|
||||||
|
a.config.Set("donefile", "done.txt")
|
||||||
|
a.config.Set("reportfile", "report.txt")
|
||||||
|
}
|
234
helpers.go
Normal file
234
helpers.go
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetRoundToDuration() time.Duration {
|
||||||
|
var dur time.Duration
|
||||||
|
var err error
|
||||||
|
if dur, err = time.ParseDuration(app.config.Get("roundto")); err != nil {
|
||||||
|
app.config.Set("roundto", DefRoundTo)
|
||||||
|
dur, _ = time.ParseDuration(DefRoundTo)
|
||||||
|
}
|
||||||
|
return dur
|
||||||
|
}
|
||||||
|
|
||||||
|
func DurationToDecimal(dur time.Duration) float64 {
|
||||||
|
mins := dur.Minutes() - (dur.Hours() * 60)
|
||||||
|
return dur.Hours() + (mins / 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getContextsFromSlice pulls all '@' (contexts) out of the
|
||||||
|
// string slice and return those contexts and the remaining
|
||||||
|
// strings from the slice
|
||||||
|
func getContextsFromSlice(args []string) ([]string, []string) {
|
||||||
|
return splitSlice(args, func(v string) bool {
|
||||||
|
return strings.HasPrefix(v, "@")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// getProjectsFromSlice pulls all '+' (projects) out of the
|
||||||
|
// string slice and return those projects and the remaining
|
||||||
|
// strings from the slice
|
||||||
|
func getProjectsFromSlice(args []string) ([]string, []string) {
|
||||||
|
return splitSlice(args, func(v string) bool {
|
||||||
|
return strings.HasPrefix(v, "+")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitSlice(args []string, predicate func(string) bool) ([]string, []string) {
|
||||||
|
var rem1, rem2 []string
|
||||||
|
for _, v := range args {
|
||||||
|
if predicate(v) {
|
||||||
|
rem1 = append(rem1, v)
|
||||||
|
} else {
|
||||||
|
rem2 = append(rem2, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rem1, rem2
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFuzzyTime(t string) (time.Time, error) {
|
||||||
|
var ret time.Time
|
||||||
|
var err error
|
||||||
|
for i := range fuzzyFormats {
|
||||||
|
ret, err = time.Parse(fuzzyFormats[i], t)
|
||||||
|
if err == nil {
|
||||||
|
// Make sure it's in the local timezone
|
||||||
|
tz := time.Now().Format("Z07:00")
|
||||||
|
t = ret.Format("2006-01-02T15:04:05") + tz
|
||||||
|
if ret, err = time.Parse(time.RFC3339, t); err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
// Check for zero on year/mo/day
|
||||||
|
if ret.Year() == 0 && ret.Month() == time.January && ret.Day() == 1 {
|
||||||
|
ret = ret.AddDate(time.Now().Year(), int(time.Now().Month())-1, time.Now().Day()-1)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return time.Time{}, errors.New("Unable to parse time: " + t)
|
||||||
|
}
|
||||||
|
|
||||||
|
var fuzzyFormats = []string{
|
||||||
|
"1504",
|
||||||
|
"15:04", // Kitchen, 24hr
|
||||||
|
time.Kitchen,
|
||||||
|
time.RFC3339,
|
||||||
|
"2006-01-02T15:04:05", // RFC3339 without timezone
|
||||||
|
"2006-01-02T15:04", // RFC3339 without seconds or timezone
|
||||||
|
time.Stamp,
|
||||||
|
"02 Jan 06 15:04:05", // RFC822 with second
|
||||||
|
time.RFC822,
|
||||||
|
"01/02/2006 15:04", // U.S. Format
|
||||||
|
"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",
|
||||||
|
"20060102T15:04",
|
||||||
|
"20060102T15:04:05",
|
||||||
|
"20060102T1504",
|
||||||
|
"20060102T150405",
|
||||||
|
}
|
||||||
|
|
||||||
|
func timerToFriendlyString(t *timertxt.Timer) string {
|
||||||
|
var start, end, contexts, projects string
|
||||||
|
start = t.StartDate.Format(friendlyFormatForTime(t.StartDate))
|
||||||
|
if t.FinishDate.IsZero() {
|
||||||
|
end = "**:**"
|
||||||
|
} else {
|
||||||
|
end = t.FinishDate.Format(friendlyFormatForTime(t.FinishDate))
|
||||||
|
}
|
||||||
|
for _, v := range t.Contexts {
|
||||||
|
contexts += "@" + v + " "
|
||||||
|
}
|
||||||
|
for _, v := range t.Projects {
|
||||||
|
projects += "+" + v + " "
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("% 2d. %s - %s [ %s] [ %s] %s", t.Id, start, end, contexts, projects, t.Notes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func friendlyFormatForTime(t time.Time) string {
|
||||||
|
nowTime := time.Now()
|
||||||
|
if t.Year() != nowTime.Year() || t.Month() != nowTime.Month() {
|
||||||
|
return "2006-01-02 15:04"
|
||||||
|
} else if t.Day() != nowTime.Day() {
|
||||||
|
return "01/02 15:04"
|
||||||
|
}
|
||||||
|
return "15:04"
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeToFriendlyString returns an easier to read version of the time
|
||||||
|
// giving enough details that the user should be fine inferring the rest
|
||||||
|
func timeToFriendlyString(t time.Time) string {
|
||||||
|
return t.Format(friendlyFormatForTime(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func sinceToString(tm time.Time) string {
|
||||||
|
return diffToString(tm, time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
func diffToString(tm1, tm2 time.Time) string {
|
||||||
|
ret := ""
|
||||||
|
yr, mo, dy, hr, mn, sc := diff(tm1, tm2)
|
||||||
|
higher := false
|
||||||
|
|
||||||
|
if yr > 0 {
|
||||||
|
ret += fmt.Sprintf("%4dy ", yr)
|
||||||
|
higher = true
|
||||||
|
}
|
||||||
|
if mo > 0 || higher {
|
||||||
|
ret += fmt.Sprintf("%2dm ", mo)
|
||||||
|
higher = true
|
||||||
|
}
|
||||||
|
if dy > 0 || higher {
|
||||||
|
ret += fmt.Sprintf("%2dd ", dy)
|
||||||
|
higher = true
|
||||||
|
}
|
||||||
|
if hr > 0 || higher {
|
||||||
|
ret += fmt.Sprintf("%2dh ", hr)
|
||||||
|
higher = true
|
||||||
|
}
|
||||||
|
if mn > 0 || higher {
|
||||||
|
ret += fmt.Sprintf("%2dm ", mn)
|
||||||
|
higher = true
|
||||||
|
}
|
||||||
|
if sc > 0 || higher {
|
||||||
|
ret += fmt.Sprintf("%2ds", sc)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func padRight(st string, l int) string {
|
||||||
|
for len(st) < l {
|
||||||
|
st = st + " "
|
||||||
|
}
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
|
||||||
|
func padLeft(st string, l int) string {
|
||||||
|
for len(st) < l {
|
||||||
|
st = " " + st
|
||||||
|
}
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
|
||||||
|
func diff(a, b time.Time) (year, month, day, hour, min, sec int) {
|
||||||
|
if a.Location() != b.Location() {
|
||||||
|
b = b.In(a.Location())
|
||||||
|
}
|
||||||
|
if a.After(b) {
|
||||||
|
a, b = b, a
|
||||||
|
}
|
||||||
|
y1, M1, d1 := a.Date()
|
||||||
|
y2, M2, d2 := b.Date()
|
||||||
|
|
||||||
|
h1, m1, s1 := a.Clock()
|
||||||
|
h2, m2, s2 := b.Clock()
|
||||||
|
|
||||||
|
year = int(y2 - y1)
|
||||||
|
month = int(M2 - M1)
|
||||||
|
day = int(d2 - d1)
|
||||||
|
hour = int(h2 - h1)
|
||||||
|
min = int(m2 - m1)
|
||||||
|
sec = int(s2 - s1)
|
||||||
|
|
||||||
|
// Normalize negative values
|
||||||
|
if sec < 0 {
|
||||||
|
sec += 60
|
||||||
|
min--
|
||||||
|
}
|
||||||
|
if min < 0 {
|
||||||
|
min += 60
|
||||||
|
hour--
|
||||||
|
}
|
||||||
|
if hour < 0 {
|
||||||
|
hour += 24
|
||||||
|
day--
|
||||||
|
}
|
||||||
|
if day < 0 {
|
||||||
|
// days in month:
|
||||||
|
t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC)
|
||||||
|
day += 32 - t.Day()
|
||||||
|
month--
|
||||||
|
}
|
||||||
|
if month < 0 {
|
||||||
|
month += 12
|
||||||
|
year--
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
25
main.go
Normal file
25
main.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
const (
|
||||||
|
AppName = "gime"
|
||||||
|
AppVersion = 1
|
||||||
|
|
||||||
|
DefRoundTo = "1m0s"
|
||||||
|
)
|
||||||
|
|
||||||
|
var app *AppState
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app = NewApp()
|
||||||
|
|
||||||
|
var parms []string
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
parms = os.Args[1:]
|
||||||
|
} else {
|
||||||
|
// if no parameters were passed, just do a status
|
||||||
|
parms = append(parms, "status")
|
||||||
|
}
|
||||||
|
os.Exit(app.run(parms))
|
||||||
|
}
|
45
model.go
Normal file
45
model.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *AppState) SetTimerFinished(id int, end time.Time) error {
|
||||||
|
var t *timertxt.Timer
|
||||||
|
var err error
|
||||||
|
if t, err = a.TimerList.GetTimer(id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.FinishDate = end
|
||||||
|
t.Finished = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) LoadTimerList() error {
|
||||||
|
var err error
|
||||||
|
var tl timertxt.TimerList
|
||||||
|
tl, err = timertxt.LoadFromFilename(a.getTimerFile())
|
||||||
|
tl.Sort(timertxt.SORT_UNFINISHED_START)
|
||||||
|
a.TimerList = &tl
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) WriteList() error {
|
||||||
|
return a.TimerList.WriteToFilename(a.getTimerFile())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (a *AppState) LoadDoneList() error {
|
||||||
|
var err error
|
||||||
|
var tl timertxt.TimerList
|
||||||
|
tl, err = timertxt.LoadFromFilename(a.getDoneFile())
|
||||||
|
a.DoneList = &tl
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) WriteDoneList() error {
|
||||||
|
return a.DoneList.WriteToFilename(a.getDoneFile())
|
||||||
|
}
|
||||||
|
*/
|
138
task_ops.go
Normal file
138
task_ops.go
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
timertxt "git.bullercodeworks.com/brian/go-timertxt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *AppState) opStatus(args []string) int {
|
||||||
|
fmt.Println("Current Time: " + time.Now().Format(time.Stamp))
|
||||||
|
if len(*a.TimerList.GetActiveTimers()) == 0 {
|
||||||
|
fmt.Println("No timers running")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for _, v := range *a.TimerList.GetActiveTimers() {
|
||||||
|
fmt.Println(timerToFriendlyString(&v))
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppState) opListTimers(args []string) int {
|
||||||
|
// By default only list today
|
||||||
|
// Format:
|
||||||
|
// 2019/02/20 (9.25)
|
||||||
|
// start - end [ contexts ] [ projects ]
|
||||||
|
// ...
|
||||||
|
dayTotals := make(map[string]time.Duration)
|
||||||
|
for _, v := range *a.TimerList {
|
||||||
|
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 *a.TimerList {
|
||||||
|
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 []string
|
||||||
|
t := timertxt.NewTimer()
|
||||||
|
contexts, args = getContextsFromSlice(args)
|
||||||
|
projects, args = getProjectsFromSlice(args)
|
||||||
|
if len(args) > 0 {
|
||||||
|
if start, err := parseFuzzyTime(args[0]); err == nil {
|
||||||
|
t.StartDate = start
|
||||||
|
args = args[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Contexts = contexts
|
||||||
|
t.Projects = projects
|
||||||
|
|
||||||
|
a.TimerList.AddTimer(t)
|
||||||
|
if err := a.WriteList(); err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
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) opState(args []string) int {
|
||||||
|
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) opPrintUsage(args []string) int {
|
||||||
|
for _, v := range a.ValidOperations {
|
||||||
|
for _, vv := range v {
|
||||||
|
fmt.Println(" " + vv)
|
||||||
|
fmt.Println("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user