Skip to content

Commit ca5b666

Browse files
committed
feat: improve terminal multiplexer integration
* replace hooks system with terminal interface supporting * add automatic terminal detection based on environment variables * implement terminal-specific editor opening strategies (zellij edit, tmux respawn-pane, direct exec)
1 parent 0372dc9 commit ca5b666

4 files changed

Lines changed: 98 additions & 70 deletions

File tree

internal/app/app.go

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,18 @@ package app
22

33
import (
44
"fmt"
5-
"os"
6-
"os/exec"
7-
"syscall"
85

96
"github.com/samber/mo"
107

118
"dev/internal/filesystem"
12-
"dev/internal/hooks"
139
"dev/internal/projects"
10+
"dev/internal/terminal"
1411
"dev/internal/tui"
1512
)
1613

1714
type Config struct {
18-
Icons tui.Icons
19-
Hooks []hooks.Hook
15+
Icons tui.Icons
16+
Terminal terminal.Terminal
2017
}
2118

2219
func Run(args []string, cfg Config, fs filesystem.FileSystem) mo.Result[string] {
@@ -40,34 +37,7 @@ func Run(args []string, cfg Config, fs filesystem.FileSystem) mo.Result[string]
4037
return mo.Err[string](err)
4138
}
4239

43-
hooks.RunAll(cfg.Hooks, tuiResult.Name)
40+
cfg.Terminal.RenameTab(tuiResult.Name)
4441

45-
return openEditor(tuiResult.Path)
46-
}
47-
48-
func openEditor(path string) mo.Result[string] {
49-
editor, err := getEditorFromEnv().Get()
50-
if err != nil {
51-
return mo.Err[string](err)
52-
}
53-
54-
editorPath, err := exec.LookPath(editor)
55-
if err != nil {
56-
return mo.Err[string](err)
57-
}
58-
if err := syscall.Exec(editorPath, []string{editor, path}, os.Environ()); err != nil {
59-
return mo.Err[string](err)
60-
}
61-
62-
return mo.Ok(editorPath)
63-
}
64-
65-
func getEditorFromEnv() mo.Result[string] {
66-
if editor := os.Getenv("VISUAL"); editor != "" {
67-
return mo.Ok(editor)
68-
}
69-
if editor := os.Getenv("EDITOR"); editor != "" {
70-
return mo.Ok(editor)
71-
}
72-
return mo.Err[string](fmt.Errorf("$VISUAL or $EDITOR is not set"))
42+
return cfg.Terminal.OpenEditor(tuiResult.Path)
7343
}

internal/hooks/hooks.go

Lines changed: 0 additions & 33 deletions
This file was deleted.

internal/terminal/terminal.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package terminal
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
8+
"github.com/samber/mo"
9+
)
10+
11+
type Terminal interface {
12+
OpenEditor(path string) mo.Result[string]
13+
RenameTab(name string) error
14+
}
15+
16+
func Detect() Terminal {
17+
if os.Getenv("ZELLIJ") != "" {
18+
return &Zellij{}
19+
}
20+
if os.Getenv("TMUX") != "" {
21+
return &Tmux{}
22+
}
23+
return &Default{}
24+
}
25+
26+
type Zellij struct{}
27+
28+
func (z *Zellij) OpenEditor(path string) mo.Result[string] {
29+
return run("zellij", "", "edit", "--cwd", path, "-i", ".")
30+
}
31+
32+
func (z *Zellij) RenameTab(name string) error {
33+
return exec.Command("zellij", "action", "rename-tab", name).Run()
34+
}
35+
36+
type Tmux struct{}
37+
38+
func (t *Tmux) OpenEditor(path string) mo.Result[string] {
39+
editor, err := getEditorFromEnv().Get()
40+
if err != nil {
41+
return mo.Err[string](err)
42+
}
43+
return run("tmux", "", "respawn-pane", "-k", "-c", path, editor, ".")
44+
}
45+
46+
func (t *Tmux) RenameTab(name string) error {
47+
return exec.Command("tmux", "rename-window", name).Run()
48+
}
49+
50+
type Default struct{}
51+
52+
func (d *Default) OpenEditor(path string) mo.Result[string] {
53+
editor, err := getEditorFromEnv().Get()
54+
if err != nil {
55+
return mo.Err[string](err)
56+
}
57+
return run(editor, path, ".")
58+
}
59+
60+
func (d *Default) RenameTab(name string) error {
61+
return nil
62+
}
63+
64+
func run(name string, dir string, args ...string) mo.Result[string] {
65+
path, err := exec.LookPath(name)
66+
if err != nil {
67+
return mo.Err[string](err)
68+
}
69+
70+
cmd := exec.Command(path, args...)
71+
cmd.Dir = dir
72+
cmd.Stdin = os.Stdin
73+
cmd.Stdout = os.Stdout
74+
cmd.Stderr = os.Stderr
75+
76+
if err := cmd.Run(); err != nil {
77+
return mo.Err[string](err)
78+
}
79+
80+
return mo.Ok(path)
81+
}
82+
83+
func getEditorFromEnv() mo.Result[string] {
84+
if editor := os.Getenv("VISUAL"); editor != "" {
85+
return mo.Ok(editor)
86+
}
87+
if editor := os.Getenv("EDITOR"); editor != "" {
88+
return mo.Ok(editor)
89+
}
90+
return mo.Err[string](fmt.Errorf("$VISUAL or $EDITOR is not set"))
91+
}

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
"dev/internal/app"
99
"dev/internal/filesystem"
10-
"dev/internal/hooks"
10+
"dev/internal/terminal"
1111
"dev/internal/tui"
1212
)
1313

@@ -37,7 +37,7 @@ func main() {
3737
Icons: tui.Icons{
3838
Dir: "",
3939
},
40-
Hooks: hooks.Default,
40+
Terminal: terminal.Detect(),
4141
}
4242
fs := &filesystem.RealFileSystem{}
4343

0 commit comments

Comments
 (0)