summaryrefslogtreecommitdiff
path: root/internal/editor
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-02 11:41:44 +0300
committerPaul Buetow <paul@buetow.org>2026-05-02 11:41:55 +0300
commit266bedf71fe8a54b86af038889522a68bae562a8 (patch)
tree6ca2b100e63ea5b4e746e71b2b79b626ba70c597 /internal/editor
parentd9184a5bfdc39d40232cb0d66a350daffcd7a326 (diff)
Drop hexai edit; document hexai config only.
The CLI now opens the config file only via hexai config (and --config). README, usage, and configuration docs describe the subcommand. Version 0.38.4. Co-authored-by: Cursor <cursoragent@cursor.com>
Diffstat (limited to 'internal/editor')
-rw-r--r--internal/editor/editor.go20
-rw-r--r--internal/editor/editor_test.go42
2 files changed, 62 insertions, 0 deletions
diff --git a/internal/editor/editor.go b/internal/editor/editor.go
index a1af1be..722e336 100644
--- a/internal/editor/editor.go
+++ b/internal/editor/editor.go
@@ -68,3 +68,23 @@ func OpenTempAndEdit(initial []byte) (string, error) {
}
return strings.TrimSpace(string(b)), nil
}
+
+// OpenFile ensures the parent directory exists, then opens path in the editor
+// from Resolve() (HEXAI_EDITOR or EDITOR).
+func OpenFile(path string) error {
+ ed, err := Resolve()
+ if err != nil {
+ return err
+ }
+ path = filepath.Clean(strings.TrimSpace(path))
+ if path == "" || path == "." {
+ return errors.New("config path is empty")
+ }
+ dir := filepath.Dir(path)
+ if dir != "" && dir != "." {
+ if mkErr := os.MkdirAll(dir, 0o700); mkErr != nil {
+ return mkErr
+ }
+ }
+ return RunEditor(ed, path)
+}
diff --git a/internal/editor/editor_test.go b/internal/editor/editor_test.go
index 260fb85..403d165 100644
--- a/internal/editor/editor_test.go
+++ b/internal/editor/editor_test.go
@@ -182,3 +182,45 @@ func TestOpenTempAndEdit_TempFileCleanup(t *testing.T) {
t.Fatalf("temp file was not cleaned up: %s", capturedPath)
}
}
+
+func TestOpenFile_CreatesParentAndInvokesEditor(t *testing.T) {
+ old := RunEditor
+ t.Cleanup(func() { RunEditor = old })
+ t.Setenv("HEXAI_EDITOR", "dummy")
+ target := filepath.Join(t.TempDir(), "nested", "config.toml")
+ var gotEditor, gotPath string
+ RunEditor = func(editorCmd, path string) error {
+ gotEditor = editorCmd
+ gotPath = path
+ return nil
+ }
+ if err := OpenFile(target); err != nil {
+ t.Fatalf("OpenFile: %v", err)
+ }
+ if gotEditor != "dummy" {
+ t.Fatalf("editor = %q", gotEditor)
+ }
+ if gotPath != target {
+ t.Fatalf("path = %q, want %q", gotPath, target)
+ }
+ if _, err := os.Stat(filepath.Dir(target)); err != nil {
+ t.Fatalf("parent dir: %v", err)
+ }
+}
+
+func TestOpenFile_NoEditor(t *testing.T) {
+ t.Setenv("HEXAI_EDITOR", "")
+ t.Setenv("EDITOR", "")
+ err := OpenFile(filepath.Join(t.TempDir(), "x.toml"))
+ if err == nil {
+ t.Fatal("expected error when no editor is set")
+ }
+}
+
+func TestOpenFile_EmptyPath(t *testing.T) {
+ t.Setenv("HEXAI_EDITOR", "true")
+ err := OpenFile(" ")
+ if err == nil {
+ t.Fatal("expected error for empty path")
+ }
+}