Render UI directly to /dev/tty

See https://github.com/junegunn/fzf/discussions/3792

This allows us to separately capture the standard error from fzf and its
child processes, and there's less chance of user errors of redirecting
the error stream and hiding fzf.
pull/3794/head
Junegunn Choi 3 weeks ago
parent 6432f00f0d
commit d274d093af
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -73,7 +73,7 @@ func (r *LightRenderer) csi(code string) string {
func (r *LightRenderer) flush() {
if r.queued.Len() > 0 {
fmt.Fprint(os.Stderr, "\x1b[?7l\x1b[?25l"+r.queued.String()+"\x1b[?25h\x1b[?7h")
fmt.Fprint(r.ttyout, "\x1b[?7l\x1b[?25l"+r.queued.String()+"\x1b[?25h\x1b[?7h")
r.queued.Reset()
}
}
@ -88,6 +88,7 @@ type LightRenderer struct {
prevDownTime time.Time
clicks [][2]int
ttyin *os.File
ttyout *os.File
buffer []byte
origState *term.State
width int
@ -131,6 +132,10 @@ func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop in
if err != nil {
return nil, err
}
out, err := openTtyOut()
if err != nil {
out = os.Stderr
}
r := LightRenderer{
closed: util.NewAtomicBool(false),
theme: theme,
@ -138,6 +143,7 @@ func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop in
mouse: mouse,
clearOnExit: clearOnExit,
ttyin: in,
ttyout: out,
yoffset: 0,
tabstop: tabstop,
fullscreen: fullscreen,

@ -14,6 +14,8 @@ import (
"golang.org/x/term"
)
var tty string
func IsLightRendererSupported() bool {
return true
}
@ -48,12 +50,14 @@ func (r *LightRenderer) closePlatform() {
// NOOP
}
func openTtyIn() (*os.File, error) {
in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0)
func openTty(mode int) (*os.File, error) {
in, err := os.OpenFile(consoleDevice, mode, 0)
if err != nil {
tty := ttyname()
if len(tty) == 0 {
tty = ttyname()
}
if len(tty) > 0 {
if in, err := os.OpenFile(tty, syscall.O_RDONLY, 0); err == nil {
if in, err := os.OpenFile(tty, mode, 0); err == nil {
return in, nil
}
}
@ -62,6 +66,14 @@ func openTtyIn() (*os.File, error) {
return in, nil
}
func openTtyIn() (*os.File, error) {
return openTty(syscall.O_RDONLY)
}
func openTtyOut() (*os.File, error) {
return openTty(syscall.O_WRONLY)
}
func (r *LightRenderer) setupTerminal() {
term.MakeRaw(r.fd())
}

@ -96,6 +96,11 @@ func openTtyIn() (*os.File, error) {
return nil, nil
}
func openTtyOut() (*os.File, error) {
// not used
return nil, nil
}
func (r *LightRenderer) setupTerminal() error {
if err := windows.SetConsoleMode(windows.Handle(r.outHandle), consoleFlagsOutput); err != nil {
return err

Loading…
Cancel
Save