diff --git a/config.go b/config.go index 777e82e..ec68006 100644 --- a/config.go +++ b/config.go @@ -17,7 +17,10 @@ const ( 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"` } type ColorMap struct { @@ -72,31 +75,40 @@ func (c *ColorMap) UnmarshalJSON(raw []byte) error { return nil } -func NewConfig(configPath string) (*Config, error) { +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 nil, err + return err } - return NewConfig(configPath) + return LoadConfig(configPath, config) } - return nil, err + return err } - config := &Config{} err = json.Unmarshal(raw, config) if err != nil { - return nil, err + return err } if config.DateTimeFmt == "" { config.DateTimeFmt = defaultDateTimeFmt } - if config.DBPath == "" { - config.DBPath = path.Dir(configPath) + "/pomo.db" + if config.BasePath == "" { + config.BasePath = path.Dir(configPath) } - return config, nil + if config.DBPath == "" { + config.DBPath = path.Join(config.BasePath, "/pomo.db") + } + if config.SocketPath == "" { + config.SocketPath = path.Join(config.BasePath, "/pomo.sock") + } + if config.IconPath == "" { + config.IconPath = path.Join(config.BasePath, "/icon.png") + } + return nil } diff --git a/main.go b/main.go index e4c1f47..a7ebcf9 100644 --- a/main.go +++ b/main.go @@ -11,7 +11,7 @@ import ( cli "github.com/jawher/mow.cli" ) -func start(path *string) func(*cli.Cmd) { +func start(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS] MESSAGE" var ( @@ -23,7 +23,7 @@ func start(path *string) func(*cli.Cmd) { cmd.Action = func() { parsed, err := time.ParseDuration(*duration) maybe(err) - db, err := NewStore(*path) + db, err := NewStore(config.DBPath) maybe(err) defer db.Close() task := &Task{ @@ -40,9 +40,9 @@ func start(path *string) func(*cli.Cmd) { task.ID = id return nil })) - runner, err := NewTaskRunner(task, db, NewXnotifier(*path+"/icon.png")) + runner, err := NewTaskRunner(task, db, NewXnotifier(config.IconPath)) maybe(err) - server, err := NewServer(*path+"/pomo.sock", runner) + server, err := NewServer(config.SocketPath, runner) maybe(err) server.Start() defer server.Stop() @@ -52,7 +52,7 @@ func start(path *string) func(*cli.Cmd) { } } -func create(path *string) func(*cli.Cmd) { +func create(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS] MESSAGE" var ( @@ -64,7 +64,7 @@ func create(path *string) func(*cli.Cmd) { cmd.Action = func() { parsed, err := time.ParseDuration(*duration) maybe(err) - db, err := NewStore(*path) + db, err := NewStore(config.DBPath) maybe(err) defer db.Close() task := &Task{ @@ -85,7 +85,7 @@ func create(path *string) func(*cli.Cmd) { } } -func begin(path *string) func(*cli.Cmd) { +func begin(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS] TASK_ID" var ( @@ -93,7 +93,7 @@ func begin(path *string) func(*cli.Cmd) { ) cmd.Action = func() { - db, err := NewStore(*path) + db, err := NewStore(config.DBPath) maybe(err) defer db.Close() var task *Task @@ -110,9 +110,9 @@ func begin(path *string) func(*cli.Cmd) { task.Pomodoros = []*Pomodoro{} return nil })) - runner, err := NewTaskRunner(task, db, NewXnotifier(*path+"/icon.png")) + runner, err := NewTaskRunner(task, db, NewXnotifier(config.IconPath)) maybe(err) - server, err := NewServer(*path+"/pomo.sock", runner) + server, err := NewServer(config.SocketPath, runner) maybe(err) server.Start() defer server.Stop() @@ -122,11 +122,11 @@ func begin(path *string) func(*cli.Cmd) { } } -func initialize(path *string) func(*cli.Cmd) { +func initialize(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS]" cmd.Action = func() { - db, err := NewStore(*path) + db, err := NewStore(config.DBPath) maybe(err) defer db.Close() maybe(initDB(db)) @@ -134,7 +134,7 @@ func initialize(path *string) func(*cli.Cmd) { } } -func list(path *string) func(*cli.Cmd) { +func list(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS]" var ( @@ -147,7 +147,7 @@ func list(path *string) func(*cli.Cmd) { cmd.Action = func() { duration, err := time.ParseDuration(*duration) maybe(err) - db, err := NewStore(*path) + db, err := NewStore(config.DBPath) maybe(err) defer db.Close() maybe(db.With(func(tx *sql.Tx) error { @@ -166,7 +166,6 @@ func list(path *string) func(*cli.Cmd) { maybe(json.NewEncoder(os.Stdout).Encode(tasks)) return nil } - config, err := NewConfig(*path + "/config.json") maybe(err) summerizeTasks(config, tasks) return nil @@ -175,12 +174,12 @@ func list(path *string) func(*cli.Cmd) { } } -func _delete(path *string) func(*cli.Cmd) { +func _delete(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS] TASK_ID" var taskID = cmd.IntArg("TASK_ID", -1, "task to delete") cmd.Action = func() { - db, err := NewStore(*path) + db, err := NewStore(config.DBPath) maybe(err) defer db.Close() maybe(db.With(func(tx *sql.Tx) error { @@ -190,11 +189,11 @@ func _delete(path *string) func(*cli.Cmd) { } } -func _status(path *string) func(*cli.Cmd) { +func _status(config *Config) func(*cli.Cmd) { return func(cmd *cli.Cmd) { cmd.Spec = "[OPTIONS]" cmd.Action = func() { - client, err := NewClient(*path + "/pomo.sock") + client, err := NewClient(config.SocketPath) if err != nil { outputStatus(Status{}) return @@ -207,12 +206,10 @@ func _status(path *string) func(*cli.Cmd) { } } -func config(path *string) func(*cli.Cmd) { +func _config(config *Config) 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)) } } @@ -223,16 +220,20 @@ func main() { 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." app.Spec = "[OPTIONS]" var ( - path = app.StringOpt("p path", defaultConfigPath(), "path to the pomo config directory") + config = &Config{} + path = app.StringOpt("p path", defaultConfigPath(), "path to the pomo config directory") ) + app.Before = func() { + maybe(LoadConfig(*path, config)) + } 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)) - app.Command("delete d", "delete a stored task", _delete(path)) - app.Command("status st", "output the current status", _status(path)) + app.Command("start s", "start a new task", start(config)) + app.Command("init", "initialize the sqlite database", initialize(config)) + app.Command("config cf", "display the current configuration", _config(config)) + app.Command("create c", "create a new task without starting", create(config)) + app.Command("begin b", "begin requested pomodoro", begin(config)) + app.Command("list l", "list historical tasks", list(config)) + app.Command("delete d", "delete a stored task", _delete(config)) + app.Command("status st", "output the current status", _status(config)) app.Run(os.Args) } diff --git a/runner_test.go b/runner_test.go index 8c35da7..ca1b6f3 100644 --- a/runner_test.go +++ b/runner_test.go @@ -3,13 +3,14 @@ package main import ( "fmt" "io/ioutil" + "path" "testing" "time" ) func TestTaskRunner(t *testing.T) { - path, _ := ioutil.TempDir("/tmp", "") - store, err := NewStore(path) + baseDir, _ := ioutil.TempDir("/tmp", "") + store, err := NewStore(path.Join(baseDir, "pomo.db")) if err != nil { t.Error(err) } diff --git a/store.go b/store.go index 0152fbe..f3bf795 100644 --- a/store.go +++ b/store.go @@ -2,7 +2,6 @@ package main import ( "database/sql" - "os" "strings" "time" @@ -19,8 +18,7 @@ type Store struct { } func NewStore(path string) (*Store, error) { - os.Mkdir(path, 0755) - db, err := sql.Open("sqlite3", path+"/pomo.db") + db, err := sql.Open("sqlite3", path) if err != nil { return nil, err } diff --git a/util.go b/util.go index d49501c..5ecb373 100644 --- a/util.go +++ b/util.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/user" + "path" "time" "github.com/fatih/color" @@ -19,7 +20,7 @@ func maybe(err error) { func defaultConfigPath() string { u, err := user.Current() maybe(err) - return u.HomeDir + "/.pomo" + return path.Join(u.HomeDir, "/.pomo/config.json") } func summerizeTasks(config *Config, tasks []*Task) {