|
8 | 8 | "fmt" |
9 | 9 | "kitty/tools/utils" |
10 | 10 | "os" |
| 11 | + "os/exec" |
11 | 12 | "path/filepath" |
12 | 13 | "strings" |
13 | 14 |
|
@@ -68,7 +69,62 @@ func EnsureShellIntegrationFilesFor(shell_name string) (shell_integration_dir st |
68 | 69 | return filepath.Join(base, "shell-integration"), nil |
69 | 70 | } |
70 | 71 |
|
| 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 | + |
71 | 104 | 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 |
72 | 128 | return |
73 | 129 | } |
74 | 130 |
|
|
0 commit comments