diff --git a/README.md b/README.md index 464b6b6e..ddab11f5 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Matcha has a built-in plugin system with 35+ community plugins. Browse and insta matcha marketplace # browse plugins in the TUI matcha install # install a plugin matcha config # configure an installed plugin +matcha config path # print the config file location ``` Anyone can submit their own plugin — just add an entry to `plugins/registry.json` and open a PR. [Learn more](https://docs.matcha.email/Features/Plugins#submit-your-plugin) diff --git a/cli/config.go b/cli/config.go index 73b602dd..560ceddb 100644 --- a/cli/config.go +++ b/cli/config.go @@ -5,10 +5,22 @@ import ( "os" "os/exec" "path/filepath" + + "github.com/floatpane/matcha/config" ) // RunConfig handles `matcha config [plugin_name]`. func RunConfig(args []string) error { + // `matcha config path` prints the resolved config file location and exits. + if len(args) == 1 && args[0] == "path" { + path, err := config.GetConfigFile() + if err != nil { + return fmt.Errorf("cannot resolve config path: %w", err) + } + fmt.Println(path) + return nil + } + editor := os.Getenv("EDITOR") if editor == "" { editor = "vi" diff --git a/cli/config_test.go b/cli/config_test.go new file mode 100644 index 00000000..fab78fa7 --- /dev/null +++ b/cli/config_test.go @@ -0,0 +1,46 @@ +package cli + +import ( + "io" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/floatpane/matcha/config" +) + +func TestRunConfigPath(t *testing.T) { + tempDir := t.TempDir() + t.Setenv("HOME", tempDir) + + want, err := config.GetConfigFile() + if err != nil { + t.Fatalf("GetConfigFile failed: %v", err) + } + + orig := os.Stdout + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("pipe failed: %v", err) + } + os.Stdout = w + + runErr := RunConfig([]string{"path"}) + + w.Close() + os.Stdout = orig + out, _ := io.ReadAll(r) + + if runErr != nil { + t.Fatalf("RunConfig(path) returned error: %v", runErr) + } + + got := strings.TrimSpace(string(out)) + if got != want { + t.Errorf("RunConfig(path) printed %q, want %q", got, want) + } + if filepath.Base(got) != "config.json" { + t.Errorf("printed path %q does not end in config.json", got) + } +} diff --git a/config/config.go b/config/config.go index ec722ae5..efa8aa67 100644 --- a/config/config.go +++ b/config/config.go @@ -392,6 +392,11 @@ func GetConfigDir() (string, error) { return configDir() } +// GetConfigFile returns the full path to the configuration file (exported). +func GetConfigFile() (string, error) { + return configFile() +} + // configDir returns the path to the configuration directory (internal). func configDir() (string, error) { home, err := os.UserHomeDir() diff --git a/config/config_test.go b/config/config_test.go index 5ce909fc..78fb5c0e 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -725,3 +725,31 @@ func TestResolvePassword(t *testing.T) { } }) } + +// TestGetConfigFile verifies the resolved config file path is built from the +// config directory and ends at config.json. +func TestGetConfigFile(t *testing.T) { + tempDir := t.TempDir() + t.Setenv("HOME", tempDir) + // os.UserHomeDir() reads USERPROFILE on Windows, so set it too or the + // override is ignored and the resolved path points at the real home. + t.Setenv("USERPROFILE", tempDir) + + got, err := GetConfigFile() + if err != nil { + t.Fatalf("GetConfigFile failed: %v", err) + } + + want := filepath.Join(tempDir, ".config", "matcha", "config.json") + if got != want { + t.Errorf("GetConfigFile() = %q, want %q", got, want) + } + + dir, err := GetConfigDir() + if err != nil { + t.Fatalf("GetConfigDir failed: %v", err) + } + if filepath.Dir(got) != dir { + t.Errorf("config file %q is not inside config dir %q", got, dir) + } +} diff --git a/docs/docs/Features/CLI.md b/docs/docs/Features/CLI.md index 387404dc..1c94fb70 100644 --- a/docs/docs/Features/CLI.md +++ b/docs/docs/Features/CLI.md @@ -240,6 +240,14 @@ matcha config ai_rewrite Opens `~/.config/matcha/plugins/ai_rewrite.lua` so you can edit settings like API keys or model names. +**Print the config file location:** + +```bash +matcha config path +``` + +Prints the resolved path to `config.json` and exits without opening an editor. Useful in scripts or when you just need to know where Matcha keeps its configuration. + ## matcha update Check for and install the latest version of Matcha.