返回 DeepSeek-Reasonix
terminal_inputrc_unix.go
根目录 / desktop / terminal_inputrc_unix.go
1 //go:build !windows
2
3 package main
4
5 import (
6 "fmt"
7 "os"
8 "path/filepath"
9 "strings"
10 "sync"
11 )
12
13 // Bash's Readline must accept eight-bit terminal input even when the user
14 // deliberately selects LC_ALL=C. Preserve their inputrc via include, then set
15 // only the byte-transport options. Unlike machine commands, raw keystrokes
16 // cannot be encoded as shell literals.
17 func terminalInputEnvironment(spec terminalStartSpec) ([]string, func(), error) {
18 noop := func() {}
19 if filepath.Base(spec.command.path) != "bash" {
20 return spec.env, noop, nil
21 }
22 values := make(map[string]string)
23 for _, item := range spec.env {
24 key, value, _ := strings.Cut(item, "=")
25 values[key] = value
26 }
27 source := values["INPUTRC"]
28 if source == "" {
29 source = filepath.Join(values["HOME"], ".inputrc")
30 if _, err := os.Stat(source); err != nil {
31 source = "/etc/inputrc"
32 }
33 }
34 // Readline expands tilde-prefixed include paths itself, just as it does
35 // for INPUTRC. Resolve ordinary relative paths against the terminal cwd.
36 if !filepath.IsAbs(source) && !strings.HasPrefix(source, "~") {
37 source = filepath.Join(spec.dir, source)
38 }
39 if strings.ContainsAny(source, "\r\n") {
40 return nil, noop, fmt.Errorf("terminal inputrc path contains a line break")
41 }
42 file, err := os.CreateTemp("", "reasonix-terminal-inputrc-*")
43 if err != nil {
44 return nil, noop, err
45 }
46 var once sync.Once
47 cleanup := func() { once.Do(func() { _ = os.Remove(file.Name()) }) }
48 _, err = fmt.Fprintf(file, "$include %s\nset convert-meta off\nset input-meta on\nset output-meta on\n", source)
49 closeErr := file.Close()
50 if err == nil {
51 err = closeErr
52 }
53 if err != nil {
54 cleanup()
55 return nil, noop, err
56 }
57 env := make([]string, 0, len(spec.env)+1)
58 for _, item := range spec.env {
59 if !strings.HasPrefix(item, "INPUTRC=") {
60 env = append(env, item)
61 }
62 }
63 return append(env, "INPUTRC="+file.Name()), cleanup, nil
64 }
65
65 lines GO