2020-09-08 18:35:47 +02:00
|
|
|
package pomo
|
2019-07-05 00:13:04 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2021-10-14 01:36:25 +02:00
|
|
|
"fmt"
|
2019-07-05 00:13:04 +02:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
|
2022-05-28 12:12:43 +02:00
|
|
|
"github.com/adrg/xdg"
|
2019-07-05 00:13:04 +02:00
|
|
|
"github.com/fatih/color"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
defaultDateTimeFmt = "2006-01-02 15:04"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Config represents user preferences
|
|
|
|
type Config struct {
|
|
|
|
Colors *ColorMap `json:"colors"`
|
|
|
|
DateTimeFmt string `json:"dateTimeFmt"`
|
2019-07-05 00:57:41 +02:00
|
|
|
BasePath string `json:"basePath"`
|
2019-07-05 00:13:04 +02:00
|
|
|
DBPath string `json:"dbPath"`
|
2019-07-05 00:57:41 +02:00
|
|
|
SocketPath string `json:"socketPath"`
|
|
|
|
IconPath string `json:"iconPath"`
|
2022-05-31 08:20:58 +02:00
|
|
|
OnEvent []string `json:"onEvent"`
|
2021-07-29 19:01:25 +02:00
|
|
|
// Publish pushes updates to the configured
|
|
|
|
// SocketPath rather than listening for requests
|
|
|
|
Publish bool `json:"publish"`
|
|
|
|
// PublishJson pushes socket updates as a JSON
|
|
|
|
// encoded status message instead of string formatted
|
|
|
|
PublishJson bool `json:"publishJson"`
|
2021-10-14 01:26:42 +02:00
|
|
|
// If Publish is true, provide a socket path to publish to
|
|
|
|
PublishSocketPath string `json:"publishSocketPath"`
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type ColorMap struct {
|
|
|
|
colors map[string]*color.Color
|
|
|
|
tags map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ColorMap) Get(name string) *color.Color {
|
|
|
|
if color, ok := c.colors[name]; ok {
|
|
|
|
return color
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ColorMap) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(c.tags)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ColorMap) UnmarshalJSON(raw []byte) error {
|
|
|
|
lookup := map[string]*color.Color{
|
|
|
|
"black": color.New(color.FgBlack),
|
|
|
|
"hiblack": color.New(color.FgHiBlack),
|
|
|
|
"blue": color.New(color.FgBlue),
|
|
|
|
"hiblue": color.New(color.FgHiBlue),
|
|
|
|
"cyan": color.New(color.FgCyan),
|
|
|
|
"hicyan": color.New(color.FgHiCyan),
|
|
|
|
"green": color.New(color.FgGreen),
|
|
|
|
"higreen": color.New(color.FgHiGreen),
|
|
|
|
"magenta": color.New(color.FgMagenta),
|
|
|
|
"himagenta": color.New(color.FgHiMagenta),
|
|
|
|
"red": color.New(color.FgRed),
|
|
|
|
"hired": color.New(color.FgHiRed),
|
|
|
|
"white": color.New(color.FgWhite),
|
|
|
|
"hiwrite": color.New(color.FgHiWhite),
|
|
|
|
"yellow": color.New(color.FgYellow),
|
|
|
|
"hiyellow": color.New(color.FgHiYellow),
|
|
|
|
}
|
|
|
|
cm := &ColorMap{
|
|
|
|
colors: map[string]*color.Color{},
|
|
|
|
tags: map[string]string{},
|
|
|
|
}
|
|
|
|
err := json.Unmarshal(raw, &cm.tags)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for tag, colorName := range cm.tags {
|
|
|
|
if color, ok := lookup[colorName]; ok {
|
|
|
|
cm.colors[tag] = color
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*c = *cm
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-07-05 00:57:41 +02:00
|
|
|
func LoadConfig(configPath string, config *Config) error {
|
2019-07-05 00:13:04 +02:00
|
|
|
raw, err := ioutil.ReadFile(configPath)
|
|
|
|
if err != nil {
|
2019-07-05 00:57:41 +02:00
|
|
|
os.MkdirAll(path.Dir(configPath), 0755)
|
2019-07-05 00:13:04 +02:00
|
|
|
// Create an empty config file
|
|
|
|
// if it does not already exist.
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
raw, _ := json.Marshal(map[string]string{})
|
|
|
|
err := ioutil.WriteFile(configPath, raw, 0644)
|
|
|
|
if err != nil {
|
2019-07-05 00:57:41 +02:00
|
|
|
return err
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
return LoadConfig(configPath, config)
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
return err
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|
|
|
|
err = json.Unmarshal(raw, config)
|
|
|
|
if err != nil {
|
2019-07-05 00:57:41 +02:00
|
|
|
return err
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|
|
|
|
if config.DateTimeFmt == "" {
|
|
|
|
config.DateTimeFmt = defaultDateTimeFmt
|
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
if config.BasePath == "" {
|
|
|
|
config.BasePath = path.Dir(configPath)
|
2022-05-28 12:12:43 +02:00
|
|
|
err := os.MkdirAll(config.BasePath, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
}
|
2019-07-05 00:13:04 +02:00
|
|
|
if config.DBPath == "" {
|
2022-05-28 12:12:43 +02:00
|
|
|
config.DBPath = path.Join(xdg.DataHome, "pomo", "pomo.db")
|
|
|
|
err := os.MkdirAll(path.Dir(config.DBPath), os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
if config.SocketPath == "" {
|
2022-05-28 12:12:43 +02:00
|
|
|
config.SocketPath = path.Join(xdg.RuntimeDir, "pomo.sock")
|
|
|
|
err := os.MkdirAll(path.Dir(config.SocketPath), os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
}
|
|
|
|
if config.IconPath == "" {
|
2022-05-28 12:12:43 +02:00
|
|
|
config.IconPath = path.Join(xdg.DataHome, "pomo", "icon.png")
|
|
|
|
err := os.MkdirAll(path.Dir(config.IconPath), os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-07-05 00:57:41 +02:00
|
|
|
}
|
2021-10-14 01:36:25 +02:00
|
|
|
if config.Publish && (config.PublishSocketPath == "" || config.PublishSocketPath == config.SocketPath) {
|
|
|
|
return fmt.Errorf("'publish' option now requires 'publishSocketPath' which must not be the same as 'socketPath'")
|
|
|
|
}
|
|
|
|
|
2019-07-05 00:57:41 +02:00
|
|
|
return nil
|
2019-07-05 00:13:04 +02:00
|
|
|
}
|