// License: GPLv3 Copyright: 2023, Kovid Goyal, package tui import ( "errors" "fmt" "os" "os/exec" "path/filepath" "strconv" "strings" "time" "github.com/shirou/gopsutil/v3/process" "golang.org/x/sys/unix" "kitty/tools/utils" ) var _ = fmt.Print var TmuxExe = (&utils.Once[string]{Run: func() string { return utils.FindExe("tmux") }}).Get func tmux_socket_address() (socket string) { socket = os.Getenv("TMUX") if socket == "" { return "" } addr, pid_str, found := strings.Cut(socket, ",") if !found { return "" } if unix.Access(addr, unix.R_OK|unix.W_OK) != nil { return "" } pid_str, _, _ = strings.Cut(pid_str, ",") pid, err := strconv.ParseInt(pid_str, 10, 32) if err != nil { return "" } p, err := process.NewProcess(int32(pid)) if err != nil { return "" } cmd, err := p.CmdlineSlice() if err != nil { return "" } if len(cmd) > 0 && strings.ToLower(filepath.Base(cmd[0])) != "tmux" { return "" } return socket } var TmuxSocketAddress = (&utils.Once[string]{Run: tmux_socket_address}).Get func tmux_command(args ...string) (c *exec.Cmd, stderr *strings.Builder) { c = exec.Command(TmuxExe(), args...) stderr = &strings.Builder{} c.Stderr = stderr return c, stderr } func tmux_allow_passthrough() error { c, stderr := tmux_command("show", "-Ap", "allow-passthrough") allowed, not_allowed := errors.New("allowed"), errors.New("not allowed") get_result := make(chan error) go func() { output, err := c.Output() if err != nil { get_result <- fmt.Errorf("Running %#v failed with error: %w. STDERR: %s", c.Args, err, stderr.String()) } else { q := strings.TrimSpace(utils.UnsafeBytesToString(output)) if strings.HasSuffix(q, " on") || strings.HasSuffix(q, " all") { get_result <- allowed } else { get_result <- not_allowed } } }() select { case r := <-get_result: if r == allowed { return nil } if r != not_allowed { return r } c, stderr = tmux_command("set", "-p", "allow-passthrough", "on") err := c.Run() if err != nil { err = fmt.Errorf("Running %#v failed with error: %w. STDERR: %s", c.Args, err, stderr.String()) } return err case <-time.After(2 * time.Second): return fmt.Errorf("Tmux command timed out. This often happens when the version of tmux on your PATH is older than the version of the running tmux server") } } var TmuxAllowPassthrough = (&utils.Once[error]{Run: tmux_allow_passthrough}).Get