Skip to content

Commit

Permalink
Added support for editing config files with $EDITOR (#30)
Browse files Browse the repository at this point in the history
* Added support for configuring files with editor
* Added tests
  • Loading branch information
baalimago authored Feb 7, 2025
1 parent 5a3a39a commit ab0819d
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
11 changes: 7 additions & 4 deletions internal/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
conf
del
newaction
confWithEditor
)

var ErrUserExit = errors.New("user exit")
Expand All @@ -38,6 +39,8 @@ func (a action) String() string {
return "[d]el"
case newaction:
return "create [n]ew"
case confWithEditor:
return "configure with [e]ditor"
default:
return "unset"
}
Expand Down Expand Up @@ -75,23 +78,23 @@ func Run() error {
return fmt.Errorf("failed to get configs files: %w", err)
}
configs = t
action, err := queryForAction([]action{conf, del})
qAct, err := queryForAction([]action{conf, del, confWithEditor})
if err != nil {
return fmt.Errorf("failed to find action: %w", err)
}
a = action
a = qAct
case "2":
profilesDir := filepath.Join(claiDir, "profiles")
t, err := getConfigs(filepath.Join(profilesDir, "*.json"), []string{})
if err != nil {
return fmt.Errorf("failed to get configs files: %w", err)
}
configs = t
action, err := queryForAction([]action{conf, del, newaction})
qAct, err := queryForAction([]action{conf, del, newaction, confWithEditor})
if err != nil {
return fmt.Errorf("failed to find action: %w", err)
}
a = action
a = qAct
if a == newaction {
c, err := createProFile(profilesDir)
if err != nil {
Expand Down
30 changes: 30 additions & 0 deletions internal/setup/setup_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io"
"os"
"os/exec"
"regexp"
"slices"
"strconv"
Expand Down Expand Up @@ -40,6 +41,10 @@ func queryForAction(options []action) (action, error) {
if slices.Contains(options, newaction) {
ret = newaction
}
case "e", "configureWithEditor":
if slices.Contains(options, confWithEditor) {
ret = confWithEditor
}
case "q", "quit":
return unset, ErrUserExit
}
Expand Down Expand Up @@ -76,6 +81,8 @@ func configure(cfgs []config, a action) error {
switch a {
case conf:
return reconfigure(cfgs[index])
case confWithEditor:
return reconfigureWithEditor(cfgs[index])
case del:
return remove(cfgs[index])
default:
Expand All @@ -95,6 +102,29 @@ func reconfigure(cfg config) error {
return interractiveReconfigure(cfg, b)
}

// reconfigureWithEditor. As in the $EDITOR environment variable
func reconfigureWithEditor(cfg config) error {
editor := os.Getenv("EDITOR")
if editor == "" {
return fmt.Errorf("environment variable EDITOR is not set")
}
cmd := exec.Command(editor, cfg.filePath)

cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to edit file %s: %v", cfg.filePath, err)
}
newConfig, err := os.ReadFile(cfg.filePath)
if err != nil {
return fmt.Errorf("editor exited OK, failed to read config file '%v' after, error: %v", cfg.filePath, err)
}
ancli.Okf("new config:\n%v", string(newConfig))
return nil
}

func remove(cfg config) error {
fmt.Printf("Are you sure you want to delete: '%v'?\n[y/n]: ", cfg.filePath)
var input string
Expand Down
49 changes: 49 additions & 0 deletions internal/setup/setup_actions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package setup

import (
"os"
"path/filepath"
"reflect"
"testing"
)
Expand Down Expand Up @@ -88,3 +89,51 @@ func TestGetToolsValue(t *testing.T) {
t.Errorf("getToolsValue() returned %d tools, want 3", len(result))
}
}

func TestReconfigureWithEditor(t *testing.T) {
tests := []struct {
name string
editor string
content string
wantErr bool
}{
{
name: "No editor set",
editor: "",
content: "",
wantErr: true,
},
{
name: "Valid editor",
editor: "echo",
content: "{\"test\": \"value\"}",
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Setup temporary file
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "config.json")
if err := os.WriteFile(tmpFile, []byte(tt.content), 0o644); err != nil {
t.Fatal(err)
}

// Set environment
oldEditor := os.Getenv("EDITOR")
defer os.Setenv("EDITOR", oldEditor)
os.Setenv("EDITOR", tt.editor)

cfg := config{
name: "test",
filePath: tmpFile,
}

err := reconfigureWithEditor(cfg)
if (err != nil) != tt.wantErr {
t.Errorf("reconfigureWithEditor() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

0 comments on commit ab0819d

Please sign in to comment.