summaryrefslogtreecommitdiff
path: root/src/tmux.go
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2024-05-20 17:06:44 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2024-05-20 18:24:14 +0900
commit573df524fed1c493ce7d8ea893f06ab90f2ca18a (patch)
tree0bd1185bf827de5860aaf6a4944c2fd1c8ed69ef /src/tmux.go
parentaee417c46a2f6d2aa87ea3fcc799fdc7bc830dfe (diff)
downloadfzf-573df524fed1c493ce7d8ea893f06ab90f2ca18a.tar.gz
Use winpty to launch fzf in Git bash (mintty)
Close #3806 Known limitation: * --height cannot be used
Diffstat (limited to 'src/tmux.go')
-rw-r--r--src/tmux.go131
1 files changed, 9 insertions, 122 deletions
diff --git a/src/tmux.go b/src/tmux.go
index 5cc970fa..3be95661 100644
--- a/src/tmux.go
+++ b/src/tmux.go
@@ -1,81 +1,24 @@
package fzf
import (
- "bufio"
- "errors"
- "fmt"
- "io"
"os"
"os/exec"
- "path/filepath"
- "strings"
- "time"
"github.com/junegunn/fzf/src/tui"
- "github.com/junegunn/fzf/src/util"
)
-func escapeSingleQuote(str string) string {
- return "'" + strings.ReplaceAll(str, "'", "'\\''") + "'"
-}
-
func runTmux(args []string, opts *Options) (int, error) {
- ns := time.Now().UnixNano()
-
- output := filepath.Join(os.TempDir(), fmt.Sprintf("fzf-tmux-output-%d", ns))
- if err := mkfifo(output, 0666); err != nil {
- return ExitError, err
- }
- defer os.Remove(output)
-
- // Find fzf executable
- fzf := "fzf"
- if found, err := os.Executable(); err == nil {
- fzf = found
- }
-
// Prepare arguments
- args = append([]string{"--bind=ctrl-z:ignore"}, args...)
+ fzf := args[0]
+ args = append([]string{"--bind=ctrl-z:ignore"}, args[1:]...)
if opts.BorderShape == tui.BorderUndefined {
args = append(args, "--border")
}
- args = append(args, "--no-height")
- args = append(args, "--no-tmux")
- argStr := ""
+ argStr := escapeSingleQuote(fzf)
for _, arg := range args {
- // %q formatting escapes $'foo\nbar' to "foo\nbar"
argStr += " " + escapeSingleQuote(arg)
}
- argStr += ` --tmux-script "$0"`
-
- // Build command
- var command string
- if opts.Input == nil && util.IsTty() {
- command = fmt.Sprintf(`%q%s > %q`, fzf, argStr, output)
- } else {
- input := filepath.Join(os.TempDir(), fmt.Sprintf("fzf-tmux-input-%d", ns))
- if err := mkfifo(input, 0644); err != nil {
- return ExitError, err
- }
- defer os.Remove(input)
-
- go func() {
- inputFile, err := os.OpenFile(input, os.O_WRONLY, 0)
- if err != nil {
- return
- }
- if opts.Input == nil {
- io.Copy(inputFile, os.Stdin)
- } else {
- for item := range opts.Input {
- fmt.Fprint(inputFile, item+opts.PrintSep)
- }
- }
- inputFile.Close()
- }()
-
- command = fmt.Sprintf(`%q%s < %q > %q`, fzf, argStr, input, output)
- }
+ argStr += ` --no-tmux --no-height`
// Get current directory
dir, err := os.Getwd()
@@ -106,65 +49,9 @@ func runTmux(args []string, opts *Options) (int, error) {
tmuxArgs = append(tmuxArgs, "-w"+opts.Tmux.width.String())
tmuxArgs = append(tmuxArgs, "-h"+opts.Tmux.height.String())
- // To ensure that the options are processed by a POSIX-compliant shell,
- // we need to write the command to a temporary file and execute it with sh.
- exports := os.Environ()
- for idx, pairStr := range exports {
- pair := strings.SplitN(pairStr, "=", 2)
- exports[idx] = fmt.Sprintf("export %s=%s", pair[0], escapeSingleQuote(pair[1]))
- }
- temp := writeTemporaryFile(append(exports, command), "\n")
- defer os.Remove(temp)
- tmuxArgs = append(tmuxArgs, "sh", temp)
-
- // Take the output
- go func() {
- outputFile, err := os.OpenFile(output, os.O_RDONLY, 0)
- if err != nil {
- return
- }
- if opts.Output == nil {
- io.Copy(os.Stdout, outputFile)
- } else {
- reader := bufio.NewReader(outputFile)
- sep := opts.PrintSep[0]
- for {
- item, err := reader.ReadString(sep)
- if err != nil {
- break
- }
- opts.Output <- item
- }
- }
-
- outputFile.Close()
- }()
-
- cmd := exec.Command("tmux", tmuxArgs...)
- if err := cmd.Run(); err != nil {
- if exitError, ok := err.(*exec.ExitError); ok {
- code := exitError.ExitCode()
- if code == ExitBecome {
- data, err := os.ReadFile(temp)
- if err != nil {
- return ExitError, err
- }
- elems := strings.Split(string(data), "\x00")
- if len(elems) < 1 {
- return ExitError, errors.New("invalid become command")
- }
- command := elems[0]
- env := []string{}
- if len(elems) > 1 {
- env = elems[1:]
- }
- os.Remove(temp)
- executor := util.NewExecutor(opts.WithShell)
- executor.Become(tui.TtyIn(), env, command)
- }
- return code, err
- }
- }
-
- return ExitOk, nil
+ return runProxy(argStr, func(temp string) *exec.Cmd {
+ sh, _ := sh()
+ tmuxArgs = append(tmuxArgs, sh, temp)
+ return exec.Command("tmux", tmuxArgs...)
+ }, opts, true)
}