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:
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user