Skip to content

Commit a573689

Browse files
committed
Port the zsh setup function to Go
1 parent 3a76ccf commit a573689

File tree

1 file changed

+56
-0
lines changed
  • tools/tui/shell_integration

1 file changed

+56
-0
lines changed

tools/tui/shell_integration/api.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"kitty/tools/utils"
1010
"os"
11+
"os/exec"
1112
"path/filepath"
1213
"strings"
1314

@@ -68,7 +69,62 @@ func EnsureShellIntegrationFilesFor(shell_name string) (shell_integration_dir st
6869
return filepath.Join(base, "shell-integration"), nil
6970
}
7071

72+
func is_new_zsh_install(env map[string]string, zdotdir string) bool {
73+
// if ZDOTDIR is empty, zsh will read user rc files from /
74+
// if there aren't any, it'll run zsh-newuser-install
75+
// the latter will bail if there are rc files in $HOME
76+
if zdotdir == "" {
77+
if zdotdir = env[`HOME`]; zdotdir == "" {
78+
if q, err := os.UserHomeDir(); err == nil {
79+
zdotdir = q
80+
} else {
81+
return true
82+
}
83+
}
84+
}
85+
for _, q := range []string{`.zshrc`, `.zshenv`, `.zprofile`, `.zlogin`} {
86+
if _, e := os.Stat(filepath.Join(zdotdir, q)); e == nil {
87+
return false
88+
}
89+
}
90+
return true
91+
}
92+
93+
func get_zsh_zdotdir_from_global_zshenv(argv []string, env map[string]string) string {
94+
c := exec.Command(utils.FindExe(argv[0]), `--norcs`, `--interactive`, `-c`, `echo -n $ZDOTDIR`)
95+
for k, v := range env {
96+
c.Env = append(c.Env, k+"="+v)
97+
}
98+
if raw, err := c.Output(); err == nil {
99+
return utils.UnsafeBytesToString(raw)
100+
}
101+
return ""
102+
}
103+
71104
func zsh_setup_func(shell_integration_dir string, argv []string, env map[string]string) (final_argv []string, final_env map[string]string, err error) {
105+
zdotdir := env[`ZDOTDIR`]
106+
final_argv, final_env = argv, env
107+
if is_new_zsh_install(env, zdotdir) {
108+
if zdotdir == "" {
109+
// Try to get ZDOTDIR from /etc/zshenv, when all startup files are not present
110+
zdotdir = get_zsh_zdotdir_from_global_zshenv(argv, env)
111+
if zdotdir == "" || is_new_zsh_install(env, zdotdir) {
112+
return final_argv, final_env, nil
113+
}
114+
} else {
115+
// dont prevent zsh-newuser-install from running
116+
// zsh-newuser-install never runs as root but we assume that it does
117+
return final_argv, final_env, nil
118+
}
119+
}
120+
if zdotdir != "" {
121+
env[`KITTY_ORIG_ZDOTDIR`] = zdotdir
122+
} else {
123+
// KITTY_ORIG_ZDOTDIR can be set at this point if, for example, the global
124+
// zshenv overrides ZDOTDIR; we try to limit the damage in this case
125+
delete(final_env, `KITTY_ORIG_ZDOTDIR`)
126+
}
127+
final_env[`ZDOTDIR`] = shell_integration_dir
72128
return
73129
}
74130

0 commit comments

Comments
 (0)