diff --git a/config.go b/config.go new file mode 100644 index 0000000..777e82e --- /dev/null +++ b/config.go @@ -0,0 +1,102 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "os" + "path" + + "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"` + DBPath string `json:"dbPath"` +} + +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 NewConfig(configPath string) (*Config, error) { + raw, err := ioutil.ReadFile(configPath) + if err != nil { + // 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 nil, err + } + return NewConfig(configPath) + } + return nil, err + } + config := &Config{} + err = json.Unmarshal(raw, config) + if err != nil { + return nil, err + } + if config.DateTimeFmt == "" { + config.DateTimeFmt = defaultDateTimeFmt + } + if config.DBPath == "" { + config.DBPath = path.Dir(configPath) + "/pomo.db" + } + return config, nil +} diff --git a/main.go b/main.go index bbe75b1..e4c1f47 100644 --- a/main.go +++ b/main.go @@ -207,6 +207,17 @@ func _status(path *string) func(*cli.Cmd) { } } +func config(path *string) func(*cli.Cmd) { + return func(cmd *cli.Cmd) { + cmd.Spec = "[OPTIONS]" + cmd.Action = func() { + config, err := NewConfig(*path + "/config.json") + maybe(err) + maybe(json.NewEncoder(os.Stdout).Encode(config)) + } + } +} + func main() { app := cli.App("pomo", "Pomodoro CLI") app.LongDesc = "Pomo helps you track what you did, how long it took you to do it, and how much effort you expect it to take." @@ -217,6 +228,7 @@ func main() { app.Version("v version", Version) app.Command("start s", "start a new task", start(path)) app.Command("init", "initialize the sqlite database", initialize(path)) + app.Command("config cf", "display the current configuration", config(path)) app.Command("create c", "create a new task without starting", create(path)) app.Command("begin b", "begin requested pomodoro", begin(path)) app.Command("list l", "list historical tasks", list(path)) diff --git a/types.go b/types.go index ea36f1b..d248aed 100644 --- a/types.go +++ b/types.go @@ -1,18 +1,11 @@ package main import ( - "encoding/json" - "fmt" "io/ioutil" "os" "time" "github.com/0xAX/notificator" - "github.com/fatih/color" -) - -const ( - defaultDateTimeFmt = "2006-01-02 15:04" ) type State int @@ -59,77 +52,6 @@ func (w *Wheel) String() string { return "" } -// Config represents user preferences -type Config struct { - Colors map[string]*color.Color - DateTimeFmt string -} - -var colorMap = 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), -} - -func (c *Config) UnmarshalJSON(raw []byte) error { - config := &struct { - Colors map[string]string `json:"colors"` - DateTimeFmt string `json:"datetimefmt"` - }{} - err := json.Unmarshal(raw, config) - if err != nil { - return err - } - for key, name := range config.Colors { - if color, ok := colorMap[name]; ok { - c.Colors[key] = color - } else { - return fmt.Errorf("bad color choice: %s", name) - } - } - if config.DateTimeFmt != "" { - c.DateTimeFmt = config.DateTimeFmt - } else { - c.DateTimeFmt = defaultDateTimeFmt - } - return nil -} - -func NewConfig(path string) (*Config, error) { - raw, err := ioutil.ReadFile(path) - if err != nil { - // Create an empty config file - // if it does not already exist. - if os.IsNotExist(err) { - raw, _ := json.Marshal(map[string]*color.Color{}) - ioutil.WriteFile(path, raw, 0644) - return NewConfig(path) - } - return nil, err - } - config := &Config{ - Colors: map[string]*color.Color{}, - } - err = json.Unmarshal(raw, config) - if err != nil { - return nil, err - } - return config, json.Unmarshal(raw, config) -} - // Task describes some activity type Task struct { ID int `json:"id"` diff --git a/util.go b/util.go index b65288a..d49501c 100644 --- a/util.go +++ b/util.go @@ -62,7 +62,7 @@ func summerizeTasks(config *Config, tasks []*Task) { fmt.Printf(" ") } // user specified color mapping exists - if color, ok := config.Colors[tag]; ok { + if color := config.Colors.Get(tag); color != nil { color.Printf("%s", tag) } else { // no color mapping