Skip to content

Commit b02a1fb

Browse files
committed
Port the bash setup function to Go
1 parent a573689 commit b02a1fb

File tree

1 file changed

+91
-2
lines changed
  • tools/tui/shell_integration

1 file changed

+91
-2
lines changed

tools/tui/shell_integration/api.go

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,97 @@ func fish_setup_func(shell_integration_dir string, argv []string, env map[string
142142
return argv, env, nil
143143
}
144144

145-
func bash_setup_func(shell_integration_dir string, argv []string, env map[string]string) (final_argv []string, final_env map[string]string, err error) {
146-
return
145+
func bash_setup_func(shell_integration_dir string, argv []string, env map[string]string) ([]string, map[string]string, error) {
146+
inject := utils.NewSetWithItems(`1`)
147+
var posix_env, rcfile string
148+
remove_args := utils.NewSet[int](8)
149+
expecting_multi_chars_opt := true
150+
var expecting_option_arg, interactive_opt, expecting_file_arg, file_arg_set bool
151+
152+
for i := 1; i < len(argv); i++ {
153+
arg := argv[i]
154+
if expecting_file_arg {
155+
file_arg_set = true
156+
break
157+
}
158+
if expecting_option_arg {
159+
expecting_option_arg = false
160+
continue
161+
}
162+
if arg == `-` || arg == `--` {
163+
if !expecting_file_arg {
164+
expecting_file_arg = true
165+
}
166+
continue
167+
} else if len(arg) > 1 && arg[1] != '-' && (arg[0] == '-' || strings.HasPrefix(arg, `+O`)) {
168+
expecting_multi_chars_opt = false
169+
options := strings.TrimLeft(arg, `-+`)
170+
// shopt option
171+
if a, b, found := strings.Cut(options, `O`); found {
172+
if b == "" {
173+
expecting_option_arg = true
174+
}
175+
options = a
176+
}
177+
// command string
178+
if strings.ContainsRune(options, 'c') {
179+
// non-interactive shell
180+
// also skip `bash -ic` interactive mode with command string
181+
return argv, env, nil
182+
}
183+
// read from stdin and follow with args
184+
if strings.ContainsRune(options, 's') {
185+
break
186+
}
187+
// interactive option
188+
if strings.ContainsRune(options, 'i') {
189+
interactive_opt = true
190+
}
191+
} else if strings.HasPrefix(arg, `--`) && expecting_multi_chars_opt {
192+
if arg == `--posix` {
193+
inject.Add(`posix`)
194+
posix_env = env[`ENV`]
195+
remove_args.Add(i)
196+
} else if arg == `--norc` {
197+
inject.Add(`no-rc`)
198+
remove_args.Add(i)
199+
} else if arg == `--noprofile` {
200+
inject.Add(`no-profile`)
201+
remove_args.Add(i)
202+
} else if (arg == `--rcfile` || arg == `--init-file`) && i+1 < len(argv) {
203+
expecting_option_arg = true
204+
rcfile = argv[i+1]
205+
remove_args.AddItems(i, i+1)
206+
}
207+
} else {
208+
file_arg_set = true
209+
break
210+
}
211+
}
212+
if file_arg_set && !interactive_opt {
213+
// non-interactive shell
214+
return argv, env, nil
215+
}
216+
env[`ENV`] = filepath.Join(shell_integration_dir, `kitty.bash`)
217+
env[`KITTY_BASH_INJECT`] = strings.Join(inject.AsSlice(), " ")
218+
if posix_env != "" {
219+
env[`KITTY_BASH_POSIX_ENV`] = posix_env
220+
}
221+
if rcfile != "" {
222+
env[`KITTY_BASH_RCFILE`] = rcfile
223+
}
224+
sorted := remove_args.AsSlice()
225+
slices.Sort(sorted)
226+
for _, i := range utils.Reverse(sorted) {
227+
slices.Delete(argv, i, i+1)
228+
}
229+
if env[`HISTFILE`] == "" && !inject.Has(`posix`) {
230+
// In POSIX mode the default history file is ~/.sh_history instead of ~/.bash_history
231+
env[`HISTFILE`] = utils.Expanduser(`~/.bash_history`)
232+
env[`KITTY_BASH_UNEXPORT_HISTFILE`] = `1`
233+
}
234+
argv = slices.Insert(argv, 1, `--posix`)
235+
return argv, env, nil
147236
}
148237

149238
func setup_func_for_shell(shell_name string) integration_setup_func {

0 commit comments

Comments
 (0)