You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.7 KiB
Go

package pomo
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"github.com/adrg/xdg"
"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"`
BasePath string `json:"basePath"`
DBPath string `json:"dbPath"`
SocketPath string `json:"socketPath"`
IconPath string `json:"iconPath"`
OnEvent []string `json:"onEvent"`
// 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"`
// If Publish is true, provide a socket path to publish to
PublishSocketPath string `json:"publishSocketPath"`
}
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
}
func LoadConfig(configPath string, config *Config) error {
raw, err := ioutil.ReadFile(configPath)
if err != nil {
os.MkdirAll(path.Dir(configPath), 0755)
// 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 {
return err
}
return LoadConfig(configPath, config)
}
return err
}
err = json.Unmarshal(raw, config)
if err != nil {
return err
}
if config.DateTimeFmt == "" {
config.DateTimeFmt = defaultDateTimeFmt
}
if config.BasePath == "" {
config.BasePath = path.Dir(configPath)
err := os.MkdirAll(config.BasePath, os.ModePerm)
if err != nil {
return err
}
}
if config.DBPath == "" {
config.DBPath = path.Join(xdg.DataHome, "pomo", "pomo.db")
err := os.MkdirAll(path.Dir(config.DBPath), os.ModePerm)
if err != nil {
return err
}
}
if config.SocketPath == "" {
config.SocketPath = path.Join(xdg.RuntimeDir, "pomo.sock")
err := os.MkdirAll(path.Dir(config.SocketPath), os.ModePerm)
if err != nil {
return err
}
}
if config.IconPath == "" {
config.IconPath = path.Join(xdg.DataHome, "pomo", "icon.png")
err := os.MkdirAll(path.Dir(config.IconPath), os.ModePerm)
if err != nil {
return err
}
}
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'")
}
return nil
}