diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2024-05-23 20:08:20 +0900 |
|---|---|---|
| committer | Junegunn Choi <junegunn.c@gmail.com> | 2024-05-23 21:11:12 +0900 |
| commit | 3dee8778d073199e0fe1e186e54f7eabc2fdef43 (patch) | |
| tree | 1c39e76cf456b176cee9c4763ddbd8447e4ce406 /src/tui | |
| parent | d4216b0dcc13567479d81cc5ad2adedb1443ea8b (diff) | |
| download | fzf-3dee8778d073199e0fe1e186e54f7eabc2fdef43.tar.gz | |
execute: Open separate handles to /dev/tty (in, out, err)
# This will no longer cause 'Vim: Warning: Output is not to a terminal'
fzf --bind 'enter:execute:vim {}' > /tmp/foo
Diffstat (limited to 'src/tui')
| -rw-r--r-- | src/tui/light.go | 8 | ||||
| -rw-r--r-- | src/tui/light_unix.go | 38 | ||||
| -rw-r--r-- | src/tui/tcell_test.go | 3 | ||||
| -rw-r--r-- | src/tui/ttyname_unix.go | 25 | ||||
| -rw-r--r-- | src/tui/ttyname_windows.go | 13 |
5 files changed, 36 insertions, 51 deletions
diff --git a/src/tui/light.go b/src/tui/light.go index 1181d167..f202899a 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -127,11 +127,7 @@ type LightWindow struct { bg Color } -func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) { - in, err := openTtyIn() - if err != nil { - return nil, err - } +func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) { out, err := openTtyOut() if err != nil { out = os.Stderr @@ -142,7 +138,7 @@ func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop in forceBlack: forceBlack, mouse: mouse, clearOnExit: clearOnExit, - ttyin: in, + ttyin: ttyin, ttyout: out, yoffset: 0, tabstop: tabstop, diff --git a/src/tui/light_unix.go b/src/tui/light_unix.go index 8d5a279b..06099d2f 100644 --- a/src/tui/light_unix.go +++ b/src/tui/light_unix.go @@ -7,7 +7,6 @@ import ( "os" "os/exec" "strings" - "sync" "syscall" "github.com/junegunn/fzf/src/util" @@ -15,13 +14,6 @@ import ( "golang.org/x/term" ) -var ( - tty string - ttyin *os.File - ttyout *os.File - mutex sync.Mutex -) - func IsLightRendererSupported() bool { return true } @@ -53,15 +45,13 @@ func (r *LightRenderer) initPlatform() error { } func (r *LightRenderer) closePlatform() { - // NOOP + r.ttyout.Close() } func openTty(mode int) (*os.File, error) { in, err := os.OpenFile(consoleDevice, mode, 0) if err != nil { - if len(tty) == 0 { - tty = ttyname() - } + tty := ttyname() if len(tty) > 0 { if in, err := os.OpenFile(tty, mode, 0); err == nil { return in, nil @@ -73,31 +63,11 @@ func openTty(mode int) (*os.File, error) { } func openTtyIn() (*os.File, error) { - mutex.Lock() - defer mutex.Unlock() - - if ttyin != nil { - return ttyin, nil - } - in, err := openTty(syscall.O_RDONLY) - if err == nil { - ttyin = in - } - return in, err + return openTty(syscall.O_RDONLY) } func openTtyOut() (*os.File, error) { - mutex.Lock() - defer mutex.Unlock() - - if ttyout != nil { - return ttyout, nil - } - out, err := openTty(syscall.O_WRONLY) - if err == nil { - ttyout = out - } - return out, err + return openTty(syscall.O_WRONLY) } func (r *LightRenderer) setupTerminal() { diff --git a/src/tui/tcell_test.go b/src/tui/tcell_test.go index 54b9c9b3..217ad048 100644 --- a/src/tui/tcell_test.go +++ b/src/tui/tcell_test.go @@ -3,6 +3,7 @@ package tui import ( + "os" "testing" "github.com/gdamore/tcell/v2" @@ -20,7 +21,7 @@ func assert(t *testing.T, context string, got interface{}, want interface{}) boo // Test the handling of the tcell keyboard events. func TestGetCharEventKey(t *testing.T) { - if util.ToTty() { + if util.IsTty(os.Stdout) { // This test is skipped when output goes to terminal, because it causes // some glitches: // - output lines may not start at the beginning of a row which makes diff --git a/src/tui/ttyname_unix.go b/src/tui/ttyname_unix.go index 384115fb..d0350a0b 100644 --- a/src/tui/ttyname_unix.go +++ b/src/tui/ttyname_unix.go @@ -4,12 +4,19 @@ package tui import ( "os" + "sync/atomic" "syscall" ) var devPrefixes = [...]string{"/dev/pts/", "/dev/"} +var tty atomic.Value + func ttyname() string { + if cached := tty.Load(); cached != nil { + return cached.(string) + } + var stderr syscall.Stat_t if syscall.Fstat(2, &stderr) != nil { return "" @@ -27,17 +34,21 @@ func ttyname() string { continue } if stat, ok := info.Sys().(*syscall.Stat_t); ok && stat.Rdev == stderr.Rdev { - return prefix + file.Name() + value := prefix + file.Name() + tty.Store(value) + return value } } } return "" } -// TtyIn returns terminal device to be used as STDIN, falls back to os.Stdin -func TtyIn() *os.File { - if in, err := openTtyIn(); err == nil { - return in - } - return os.Stdin +// TtyIn returns terminal device to read user input +func TtyIn() (*os.File, error) { + return openTtyIn() +} + +// TtyIn returns terminal device to write to +func TtyOut() (*os.File, error) { + return openTtyOut() } diff --git a/src/tui/ttyname_windows.go b/src/tui/ttyname_windows.go index 39b84f70..0313c608 100644 --- a/src/tui/ttyname_windows.go +++ b/src/tui/ttyname_windows.go @@ -2,13 +2,20 @@ package tui -import "os" +import ( + "os" +) func ttyname() string { return "" } // TtyIn on Windows returns os.Stdin -func TtyIn() *os.File { - return os.Stdin +func TtyIn() (*os.File, error) { + return os.Stdin, nil +} + +// TtyIn on Windows returns nil +func TtyOut() (*os.File, error) { + return nil, nil } |
