From 8193c327fe3cbf1bcc91c07da9a2b8183dc75163 Mon Sep 17 00:00:00 2001 From: Broderick Westrope Date: Fri, 15 Nov 2024 12:15:23 +1100 Subject: [PATCH] feat: use XDG for config --- README.md | 4 ++-- cmd/tetrigo/main.go | 30 +++++++++++++++++++++--------- cmd/tetrigo/subcommands.go | 8 ++++---- internal/config/config.go | 4 ++-- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index cb83202..21c6024 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ To see more options for starting the game you can run: More complex configuration can be done using a TOML file. If no config file is found sensible defaults will be used. -By default, Tetrigo will look for the file `config.toml` in the working directory. You can specify a different file using the `--config` flag. +By default, Tetrigo will look for the file `./tetrigo/config.toml` within the devices XDG config (or equivalent) directory. The [adrg/xdg](https://github.com/adrg/xdg) defines values `XDG_CONFIG_HOME` for various operating systems (eg. on macOS it is `~/Library/Application Support` directory exists it will be stored there, otherwise in `~/Library/Preferences`). You can specify a different file using the `--config` flag. ```bash ./tetrigo --config=/path/to/config.toml @@ -120,7 +120,7 @@ An example configuration file is provided in [`example.config.toml`](./example.c ## Data -The game data is stored in a SQLite database. By default, the database is stored in `./tetrigo/tetrigo.db` within the devices XDG data (or equivalent) directory. The [adrg/xdg](https://github.com/adrg/xdg) defines values `XDG_DATA_DIRS` for various operating systems (eg. on macOS if the `/Library/Application Support` directory exists it will be stored there, otherwise in `~/.local/share`). You can specify a different file path using the `--db` flag. +The game data is stored in a SQLite database. By default, the database is stored in `./tetrigo/tetrigo.db` within the devices XDG data (or equivalent) directory. The [adrg/xdg](https://github.com/adrg/xdg) defines `XDG_DATA_HOME` for various operating systems (eg. on macOS if the `~/Library/Application Support` directory exists it will be stored there, otherwise in `/Library/Application Support`). You can specify a different file path using the `--db` flag. ```bash ./tetrigo --db=/path/to/data.db diff --git a/cmd/tetrigo/main.go b/cmd/tetrigo/main.go index 5a954f6..643674c 100644 --- a/cmd/tetrigo/main.go +++ b/cmd/tetrigo/main.go @@ -1,8 +1,6 @@ package main import ( - "log" - "github.com/adrg/xdg" "github.com/alecthomas/kong" ) @@ -16,7 +14,7 @@ type CLI struct { } type GlobalVars struct { - Config string `help:"Path to config file" default:"config.toml" type:"path"` + Config string `help:"Path to config file. Empty value will use XDG data directory." default:""` DB string `help:"Path to database file. Empty value will use XDG data directory." default:""` } @@ -28,15 +26,29 @@ func main() { kong.UsageOnError(), ) - if cli.GlobalVars.DB == "" { - var err error - cli.GlobalVars.DB, err = xdg.DataFile("./tetrigo/tetrigo.db") - if err != nil { - log.Fatal(err) - } + if err := handleDefaultGlobals(&cli.GlobalVars); err != nil { + ctx.FatalIfErrorf(err) } // Call the Run() method of the selected parsed command. err := ctx.Run(&cli.GlobalVars) ctx.FatalIfErrorf(err) } + +func handleDefaultGlobals(g *GlobalVars) error { + if g.Config == "" { + var err error + g.Config, err = xdg.ConfigFile("./tetrigo/config.toml") + if err != nil { + return err + } + } + if g.DB == "" { + var err error + g.DB, err = xdg.DataFile("./tetrigo/tetrigo.db") + if err != nil { + return err + } + } + return nil +} diff --git a/cmd/tetrigo/subcommands.go b/cmd/tetrigo/subcommands.go index 1e5778c..8f80d4c 100644 --- a/cmd/tetrigo/subcommands.go +++ b/cmd/tetrigo/subcommands.go @@ -49,23 +49,23 @@ func (c *LeaderboardCmd) Run(globals *GlobalVars) error { func launchStarter(globals *GlobalVars, starterMode tui.Mode, switchIn tui.SwitchModeInput) error { db, err := data.NewDB(globals.DB) if err != nil { - return fmt.Errorf("error opening database: %w", err) + return fmt.Errorf("opening database: %w", err) } cfg, err := config.GetConfig(globals.Config) if err != nil { - return fmt.Errorf("error getting config: %w", err) + return fmt.Errorf("getting config: %w", err) } model, err := starter.NewModel( starter.NewInput(starterMode, switchIn, db, cfg), ) if err != nil { - return fmt.Errorf("error creating starter model: %w", err) + return fmt.Errorf("creating starter model: %w", err) } if _, err = tea.NewProgram(model, tea.WithAltScreen()).Run(); err != nil { - return fmt.Errorf("error running tea program: %w", err) + return fmt.Errorf("running tea program: %w", err) } return nil diff --git a/internal/config/config.go b/internal/config/config.go index b90907f..0ff4927 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -48,12 +48,12 @@ func GetConfig(path string) (*Config, error) { if errors.Is(err, os.ErrNotExist) { return &c, nil } - return nil, err + return nil, fmt.Errorf("decoding toml file: %w", err) } err = c.validate() if err != nil { - return nil, fmt.Errorf("invalid config: %w", err) + return nil, fmt.Errorf("validating config: %w", err) } return &c, nil