I believe that all functionality is implemented

This commit is contained in:
Brian Buller 2022-01-21 08:40:44 -06:00
parent 54c91f0d3c
commit 45d13e7052
12 changed files with 333 additions and 72 deletions

View File

@ -1,6 +1,18 @@
# This how we want to name the binary output
BINARY=gime
# These are the values we want to pass for VERSION and BUILD
# git tag 1.0.1
# git commit -am "One more change after the tags"
VERSION=`git describe --tags`
BUILD=`date +%FT%T%z`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS=-ldflags "-w -s -X cmd.Version=${VERSION} -X cmd.Build=${BUILD}"
# Builds the project
gime: gime:
go build -o build/gime *.go go build ${LDFLAGS} -o build/${BINARY}
clean: clean:
rm build/* rm build/*

View File

@ -7,6 +7,7 @@ package cmd
import ( import (
"fmt" "fmt"
"sort" "sort"
"strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -15,8 +16,11 @@ import (
// configCmd represents the config command // configCmd represents the config command
var configCmd = &cobra.Command{ var configCmd = &cobra.Command{
Use: "config", Use: "config",
Short: "Print all configuration values", Short: "Show or update configuration values",
RunE: opConfig, Long: `To set values just list them in key=value format.
For example:
gime config copytags=true roundto=30m`,
RunE: opConfig,
} }
func init() { func init() {
@ -24,9 +28,36 @@ func init() {
} }
func opConfig(cmd *cobra.Command, args []string) error { func opConfig(cmd *cobra.Command, args []string) error {
updConfig := make(map[string]string)
if len(args) > 0 {
// We're setting arguments
for _, a := range args {
pts := strings.Split(a, "=")
if len(pts) == 2 {
updConfig[pts[0]] = pts[1]
} else {
return fmt.Errorf("Unable to parse config values.")
}
}
}
var settings []string var settings []string
for k, v := range viper.AllSettings() { for k, v := range viper.AllSettings() {
settings = append(settings, fmt.Sprintf("%s: %s", k, v)) switch v.(type) {
case bool:
if nv, ok := updConfig[k]; ok {
v = nv == "true"
viper.Set(k, v)
viper.WriteConfig()
}
settings = append(settings, fmt.Sprintf("%s: %t", k, v))
default:
if nv, ok := updConfig[k]; ok {
v = nv
viper.Set(k, v)
viper.WriteConfig()
}
settings = append(settings, fmt.Sprintf("%s: %s", k, v))
}
} }
sort.Strings(settings) sort.Strings(settings)
fmt.Println("Configuration File:", viper.ConfigFileUsed()) fmt.Println("Configuration File:", viper.ConfigFileUsed())

View File

@ -17,14 +17,8 @@ import (
// i3statusCmd represents the i3status command // i3statusCmd represents the i3status command
var i3statusCmd = &cobra.Command{ var i3statusCmd = &cobra.Command{
Use: "i3status", Use: "i3status",
Short: "", Short: "Output your timer.txt status in json for the i3 status bar",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opI3Status,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opI3Status,
} }
func init() { func init() {

View File

@ -6,21 +6,21 @@ package cmd
import ( import (
"fmt" "fmt"
"strconv"
"strings"
"time"
"git.bullercodeworks.com/brian/gime/cli"
"git.bullercodeworks.com/brian/gime/util"
"git.bullercodeworks.com/brian/go-timertxt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// modCmd represents the mod command // modCmd represents the mod command
var modCmd = &cobra.Command{ var modCmd = &cobra.Command{
Use: "mod", Use: "mod",
Short: "A brief description of your command", Short: "Modify a timer",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opMod,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opMod,
} }
func init() { func init() {
@ -28,6 +28,75 @@ func init() {
} }
func opMod(cmd *cobra.Command, args []string) error { func opMod(cmd *cobra.Command, args []string) error {
fmt.Println("mod called") var err error
p := cli.Program{}
err = p.Initialize()
if err != nil {
return err
}
if err = p.LoadTimerList(); err != nil {
return err
}
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(*p.TimerList.GetActiveTimers()) > 0 {
timer = (*p.TimerList.GetActiveTimers())[0]
} else {
// And we don't have any active timers
return fmt.Errorf("No active timers, 'id' must be provided: %w", err)
}
} else {
args = args[1:]
if timer, err = p.TimerList.GetTimer(id); err != nil {
return fmt.Errorf("Error getting timer %d: %w", id, err)
}
}
var start, end time.Time
for _, v := range args {
pts := strings.Split(v, "=")
switch pts[0] {
case "beginning", "start":
if start, err = util.ParseFuzzyTime(pts[1]); err != nil {
return fmt.Errorf("Error parsing start time: %w", err)
}
case "stop", "finish", "end":
if end, err = util.ParseFuzzyTime(pts[1]); err != nil {
return fmt.Errorf("Error parsing end time: %w", err)
}
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(util.TimerToFriendlyString(timer))
if err := p.WriteTimerList(); err != nil {
return fmt.Errorf("Error writing timer list: %w", err)
}
return nil return nil
} }

View File

@ -6,21 +6,18 @@ package cmd
import ( import (
"fmt" "fmt"
"strconv"
"git.bullercodeworks.com/brian/gime/cli"
"git.bullercodeworks.com/brian/gime/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// rmCmd represents the rm command // rmCmd represents the rm command
var rmCmd = &cobra.Command{ var rmCmd = &cobra.Command{
Use: "rm", Use: "rm",
Short: "A brief description of your command", Short: "Remove a timer",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opRemove,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opRemove,
} }
func init() { func init() {
@ -28,6 +25,33 @@ func init() {
} }
func opRemove(cmd *cobra.Command, args []string) error { func opRemove(cmd *cobra.Command, args []string) error {
fmt.Println("remove called") var err error
p := cli.Program{}
err = p.Initialize()
if err != nil {
return err
}
if err = p.LoadTimerList(); err != nil {
return err
}
if len(args) == 0 {
return fmt.Errorf("No timer id given")
}
id, err := strconv.Atoi(args[0])
if err != nil {
return fmt.Errorf("Invalid timer id given %s: %w", args[0], err)
}
t, err := p.TimerList.GetTimer(id)
if err != nil {
return fmt.Errorf("Error getting timer with id %s: %w", args[0], err)
}
if err = p.TimerList.RemoveTimerById(id); err != nil {
return fmt.Errorf("Error Removing Timer: %w", err)
}
fmt.Println("Timer removed")
fmt.Println(util.TimerToString(t))
if err := p.WriteTimerList(); err != nil {
return fmt.Errorf("Error writing timer list: %w", err)
}
return nil return nil
} }

View File

@ -15,14 +15,16 @@ import (
) )
var ( var (
Version = "2.0" Version string
Build string
configFile string configFile string
// rootCmd represents the base command when called without any subcommands // rootCmd represents the base command when called without any subcommands
rootCmd = &cobra.Command{ rootCmd = &cobra.Command{
Use: "gime", Use: "gime",
Short: "Timer.txt Client", Short: "Timer.txt Client",
Long: "Gime is a timer.txt client to make all aspects of timekeeping simpler.", Long: fmt.Sprintf("Gime is a timer.txt client to make all aspects of timekeeping simpler.\nVersion: %s\nBuild Date: %s\n", Version, Build),
RunE: opStatus, RunE: opStatus,
} }
) )
@ -46,6 +48,7 @@ func initConfig() {
viper.SetDefault("timerfile", "timer.txt") viper.SetDefault("timerfile", "timer.txt")
viper.SetDefault("donefile", "done.txt") viper.SetDefault("donefile", "done.txt")
viper.SetDefault("reportfile", "report.txt") viper.SetDefault("reportfile", "report.txt")
viper.SetDefault("copytags", false)
var firstDir string // In case we need to make directories var firstDir string // In case we need to make directories
if configFile != "" { if configFile != "" {
viper.SetConfigFile(configFile) viper.SetConfigFile(configFile)

View File

@ -6,21 +6,19 @@ package cmd
import ( import (
"fmt" "fmt"
"strings"
"git.bullercodeworks.com/brian/gime/cli"
"git.bullercodeworks.com/brian/gime/util"
"git.bullercodeworks.com/brian/go-timertxt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// startCmd represents the start command // startCmd represents the start command
var startCmd = &cobra.Command{ var startCmd = &cobra.Command{
Use: "start", Use: "start",
Short: "A brief description of your command", Short: "Start a timer",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opStart,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opStart,
} }
func init() { func init() {
@ -28,6 +26,41 @@ func init() {
} }
func opStart(cmd *cobra.Command, args []string) error { func opStart(cmd *cobra.Command, args []string) error {
fmt.Println("start called") var err error
p := cli.Program{}
err = p.Initialize()
if err != nil {
return err
}
if err = p.LoadTimerList(); err != nil {
return err
}
var contexts, projects, strTags []string
t := timertxt.NewTimer()
if len(args) > 0 {
if start, err := util.ParseFuzzyTime(args[0]); err == nil {
t.StartDate = start
args = args[1:]
}
}
contexts, args = util.GetContextsFromSlice(args)
projects, args = util.GetProjectsFromSlice(args)
strTags, args = util.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]
}
p.TimerList.AddTimer(t)
if err := p.WriteTimerList(); err != nil {
return fmt.Errorf("Error writing timer list: %w", err)
}
fmt.Println("Started: ", util.TimerToString(t))
return nil return nil
} }

View File

@ -32,7 +32,7 @@ func opStatus(cmd *cobra.Command, args []string) error {
return err return err
} }
if err := p.LoadTimerList(); err != nil { if err := p.LoadTimerList(); err != nil {
return err return fmt.Errorf("Error loading timer list: %w", err)
} }
if len(*p.TimerList.GetActiveTimers()) == 0 { if len(*p.TimerList.GetActiveTimers()) == 0 {
fmt.Println("No timers running") fmt.Println("No timers running")

View File

@ -6,21 +6,20 @@ package cmd
import ( import (
"fmt" "fmt"
"strconv"
"time"
"git.bullercodeworks.com/brian/gime/cli"
"git.bullercodeworks.com/brian/gime/util"
"git.bullercodeworks.com/brian/go-timertxt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// stopCmd represents the stop command // stopCmd represents the stop command
var stopCmd = &cobra.Command{ var stopCmd = &cobra.Command{
Use: "stop", Use: "stop",
Short: "A brief description of your command", Short: "Stop a timer",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opStop,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opStop,
} }
func init() { func init() {
@ -28,6 +27,47 @@ func init() {
} }
func opStop(cmd *cobra.Command, args []string) error { func opStop(cmd *cobra.Command, args []string) error {
fmt.Println("stop called") var err error
p := cli.Program{}
err = p.Initialize()
if err != nil {
return err
}
if err = p.LoadTimerList(); err != nil {
return err
}
var wrk time.Time
end := time.Now()
id := -1
if len(args) > 0 {
if wrk, err = util.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 *p.TimerList.GetActiveTimers() {
timerIds = append(timerIds, v.Id)
}
} else {
timerIds = append(timerIds, id)
}
for _, v := range timerIds {
var stopped *timertxt.Timer
if stopped, err = p.TimerList.GetTimer(v); err != nil {
fmt.Println(err.Error())
}
stopped.FinishDate = end
stopped.Finished = true
fmt.Println("Stopped Timer:", util.TimerToFriendlyString(stopped))
}
if err = p.WriteTimerList(); err != nil {
return fmt.Errorf("Error writing timer list: %w", err)
}
return nil return nil
} }

View File

@ -6,21 +6,19 @@ package cmd
import ( import (
"fmt" "fmt"
"time"
"git.bullercodeworks.com/brian/gime/cli"
"git.bullercodeworks.com/brian/gime/util"
"git.bullercodeworks.com/brian/go-timertxt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// switchCmd represents the switch command // switchCmd represents the switch command
var switchCmd = &cobra.Command{ var switchCmd = &cobra.Command{
Use: "switch", Use: "switch",
Short: "A brief description of your command", Short: "Stop the current timer and start a new one copying the last one's parameters",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opSwitch,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opSwitch,
} }
func init() { func init() {
@ -28,6 +26,31 @@ func init() {
} }
func opSwitch(cmd *cobra.Command, args []string) error { func opSwitch(cmd *cobra.Command, args []string) error {
fmt.Println("switch called") var err error
return nil p := cli.Program{}
err = p.Initialize()
if err != nil {
return err
}
if err = p.LoadTimerList(); err != nil {
return err
}
var timerIds []int
end := time.Now()
// Stop all running timers and start a new one with the given args
for _, v := range *p.TimerList.GetActiveTimers() {
timerIds = append(timerIds, v.Id)
}
fmt.Print("Stopping ", timerIds, "\n")
for _, v := range timerIds {
var stopped *timertxt.Timer
if stopped, err = p.TimerList.GetTimer(v); err != nil {
fmt.Println(err.Error())
continue
}
stopped.FinishDate = end
stopped.Finished = true
fmt.Println("Stopped Timer:", util.TimerToFriendlyString(stopped))
}
return opStart(cmd, args)
} }

View File

@ -7,20 +7,16 @@ package cmd
import ( import (
"fmt" "fmt"
"git.bullercodeworks.com/brian/gime/cli"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// toggleCmd represents the toggle command // toggleCmd represents the toggle command
var toggleCmd = &cobra.Command{ var toggleCmd = &cobra.Command{
Use: "toggle", Use: "toggle",
Short: "A brief description of your command", Short: "Toggle the most recent timer on and off",
Long: `A longer description that spans multiple lines and likely contains examples RunE: opToggle,
and usage of using your command. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
RunE: opToggle,
} }
func init() { func init() {
@ -28,6 +24,37 @@ func init() {
} }
func opToggle(cmd *cobra.Command, args []string) error { func opToggle(cmd *cobra.Command, args []string) error {
fmt.Println("toggle called") var err error
return nil p := cli.Program{}
err = p.Initialize()
if err != nil {
return err
}
if err = p.LoadTimerList(); err != nil {
return err
}
wrk, err := p.GetMostRecentTimer()
if err != nil {
fmt.Print("{\"icon\":\"time\",\"state\":\"Critical\", \"text\": \"Error loading timer entry\"}")
return nil
}
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)
}
if viper.GetBool("copytags") {
for k, v := range wrk.AdditionalTags {
startArgs = append(startArgs, k+":"+v)
}
}
return opStart(cmd, startArgs)
} else {
// Stop the active timer
return opStop(cmd, []string{})
}
} }

View File

@ -1,11 +1,16 @@
/* /*
Copyright © 2022 NAME HERE <EMAIL ADDRESS> Copyright © 2022 Brian Buller <brian@bullercodeworks.com>
*/ */
package main package main
import "git.bullercodeworks.com/brian/gime/cmd" import "git.bullercodeworks.com/brian/gime/cmd"
var (
VERSION string
BUILD string
)
func main() { func main() {
cmd.Execute() cmd.Execute()
} }