m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-19 00:53:42 -05:00

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
This commit is contained in:
Junegunn Choi
2024-05-23 20:08:20 +09:00
parent d4216b0dcc
commit 3dee8778d0
9 changed files with 80 additions and 66 deletions

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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
}