Skip to content

Commit 1d76168

Browse files
authored
Add --tty-default=/dev/tty and --no-tty-default option (#4352)
Fix #4242. Use --no-tty-default, if you want fzf to perform a TTY look-up instead of defaulting to /dev/tty.
1 parent e491770 commit 1d76168

9 files changed

Lines changed: 53 additions & 27 deletions

File tree

man/man1/fzf.1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ e.g. \fB# Avoid rendering both fzf instances at the same time
228228
(sleep 1; seq 1000000; sleep 1) |
229229
fzf \-\-sync \-\-query 5 \-\-listen \-\-bind start:up,load:up,result:up,focus:change\-header:Ready\fR
230230
.RE
231+
.TP
232+
.B "\-\-no\-tty\-default"
233+
Make fzf search for the current TTY device via standard error instead of using
234+
\fB/dev/tty\fR. This option was added to avoid the problem when trying to open
235+
emacsclient from within fzf. Alternativly, you can change the default TTY
236+
device by setting \fB--tty-default=DEVICE_NAME\fR.
237+
231238
.SS GLOBAL STYLE
232239
.TP
233240
.BI "\-\-style=" "PRESET"

src/options.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ type Options struct {
631631
MEMProfile string
632632
BlockProfile string
633633
MutexProfile string
634+
TtyDefault string
634635
}
635636

636637
func filterNonEmpty(input []string) []string {
@@ -730,6 +731,7 @@ func defaultOptions() *Options {
730731
WalkerOpts: walkerOpts{file: true, hidden: true, follow: true},
731732
WalkerRoot: []string{"."},
732733
WalkerSkip: []string{".git", "node_modules"},
734+
TtyDefault: tui.DefaultTtyDevice,
733735
Help: false,
734736
Version: false}
735737
}
@@ -2336,6 +2338,12 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
23362338
}
23372339
case "--no-tmux":
23382340
opts.Tmux = nil
2341+
case "--tty-default":
2342+
if opts.TtyDefault, err = nextString("tty device name required"); err != nil {
2343+
return err
2344+
}
2345+
case "--no-tty-default":
2346+
opts.TtyDefault = ""
23392347
case "--force-tty-in":
23402348
// NOTE: We need this because `system('fzf --tmux < /dev/tty')` doesn't
23412349
// work on Neovim. Same as '-' option of fzf-tmux.

src/proxy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func runProxy(commandPrefix string, cmdBuilder func(temp string, needBash bool)
145145
env = elems[1:]
146146
}
147147
executor := util.NewExecutor(opts.WithShell)
148-
ttyin, err := tui.TtyIn()
148+
ttyin, err := tui.TtyIn(opts.TtyDefault)
149149
if err != nil {
150150
return ExitError, err
151151
}

src/terminal.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ type Terminal struct {
381381
slab *util.Slab
382382
theme *tui.ColorTheme
383383
tui tui.Renderer
384+
ttyDefault string
384385
ttyin *os.File
385386
executing *util.AtomicBool
386387
termSize tui.TermSize
@@ -809,15 +810,15 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
809810
// when you run fzf multiple times in your Go program. Closing it is known to
810811
// cause problems with 'become' action and invalid terminal state after exit.
811812
if ttyin == nil {
812-
if ttyin, err = tui.TtyIn(); err != nil {
813+
if ttyin, err = tui.TtyIn(opts.TtyDefault); err != nil {
813814
return nil, err
814815
}
815816
}
816817
if fullscreen {
817818
if tui.HasFullscreenRenderer() {
818819
renderer = tui.NewFullscreenRenderer(opts.Theme, opts.Black, opts.Mouse)
819820
} else {
820-
renderer, err = tui.NewLightRenderer(ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit,
821+
renderer, err = tui.NewLightRenderer(opts.TtyDefault, ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit,
821822
true, func(h int) int { return h })
822823
}
823824
} else {
@@ -833,7 +834,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
833834
effectiveMinHeight += borderLines(opts.BorderShape)
834835
return util.Min(termHeight, util.Max(evaluateHeight(opts, termHeight), effectiveMinHeight))
835836
}
836-
renderer, err = tui.NewLightRenderer(ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit, false, maxHeightFunc)
837+
renderer, err = tui.NewLightRenderer(opts.TtyDefault, ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit, false, maxHeightFunc)
837838
}
838839
if err != nil {
839840
return nil, err
@@ -967,6 +968,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
967968
keyChan: make(chan tui.Event),
968969
eventChan: make(chan tui.Event, 6), // start | (load + result + zero|one) | (focus) | (resize)
969970
tui: renderer,
971+
ttyDefault: opts.TtyDefault,
970972
ttyin: ttyin,
971973
initFunc: func() error { return renderer.Init() },
972974
executing: util.NewAtomicBool(false),
@@ -4042,7 +4044,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
40424044
t.executing.Set(true)
40434045
if !background {
40444046
// Open a separate handle for tty input
4045-
if in, _ := tui.TtyIn(); in != nil {
4047+
if in, _ := tui.TtyIn(t.ttyDefault); in != nil {
40464048
cmd.Stdin = in
40474049
if in != os.Stdin {
40484050
defer in.Close()
@@ -4051,15 +4053,15 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
40514053

40524054
cmd.Stdout = os.Stdout
40534055
if !util.IsTty(os.Stdout) {
4054-
if out, _ := tui.TtyOut(); out != nil {
4056+
if out, _ := tui.TtyOut(t.ttyDefault); out != nil {
40554057
cmd.Stdout = out
40564058
defer out.Close()
40574059
}
40584060
}
40594061

40604062
cmd.Stderr = os.Stderr
40614063
if !util.IsTty(os.Stderr) {
4062-
if out, _ := tui.TtyOut(); out != nil {
4064+
if out, _ := tui.TtyOut(t.ttyDefault); out != nil {
40634065
cmd.Stderr = out
40644066
defer out.Close()
40654067
}

src/tui/light.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const (
2828
maxInputBuffer = 1024 * 1024
2929
)
3030

31-
const consoleDevice string = "/dev/tty"
31+
const DefaultTtyDevice string = "/dev/tty"
3232

3333
var offsetRegexp = regexp.MustCompile("(.*?)\x00?\x1b\\[([0-9]+);([0-9]+)R")
3434
var offsetRegexpBegin = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R")
@@ -146,8 +146,8 @@ type LightWindow struct {
146146
wrapSignWidth int
147147
}
148148

149-
func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) {
150-
out, err := openTtyOut()
149+
func NewLightRenderer(ttyDefault string, ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) {
150+
out, err := openTtyOut(ttyDefault)
151151
if err != nil {
152152
out = os.Stderr
153153
}
@@ -271,7 +271,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) ([]byte,
271271
c, ok := r.getch(nonblock)
272272
if !nonblock && !ok {
273273
r.Close()
274-
return nil, errors.New("failed to read " + consoleDevice)
274+
return nil, errors.New("failed to read " + DefaultTtyDevice)
275275
}
276276

277277
retries := 0

src/tui/light_unix.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,35 @@ func (r *LightRenderer) closePlatform() {
4242
r.ttyout.Close()
4343
}
4444

45-
func openTty(mode int) (*os.File, error) {
46-
in, err := os.OpenFile(consoleDevice, mode, 0)
47-
if err != nil {
45+
func openTty(ttyDefault string, mode int) (*os.File, error) {
46+
var in *os.File
47+
var err error
48+
if len(ttyDefault) > 0 {
49+
in, err = os.OpenFile(ttyDefault, mode, 0)
50+
}
51+
if in == nil || err != nil || ttyDefault != DefaultTtyDevice && !util.IsTty(in) {
4852
tty := ttyname()
4953
if len(tty) > 0 {
5054
if in, err := os.OpenFile(tty, mode, 0); err == nil {
5155
return in, nil
5256
}
5357
}
54-
return nil, errors.New("failed to open " + consoleDevice)
58+
if ttyDefault != DefaultTtyDevice {
59+
if in, err = os.OpenFile(DefaultTtyDevice, mode, 0); err == nil {
60+
return in, nil
61+
}
62+
}
63+
return nil, errors.New("failed to open " + DefaultTtyDevice)
5564
}
5665
return in, nil
5766
}
5867

59-
func openTtyIn() (*os.File, error) {
60-
return openTty(syscall.O_RDONLY)
68+
func openTtyIn(ttyDefault string) (*os.File, error) {
69+
return openTty(ttyDefault, syscall.O_RDONLY)
6170
}
6271

63-
func openTtyOut() (*os.File, error) {
64-
return openTty(syscall.O_WRONLY)
72+
func openTtyOut(ttyDefault string) (*os.File, error) {
73+
return openTty(ttyDefault, syscall.O_WRONLY)
6574
}
6675

6776
func (r *LightRenderer) setupTerminal() {

src/tui/light_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ func (r *LightRenderer) closePlatform() {
7676
windows.SetConsoleMode(windows.Handle(r.inHandle), r.origStateInput)
7777
}
7878

79-
func openTtyIn() (*os.File, error) {
79+
func openTtyIn(ttyDefault string) (*os.File, error) {
8080
// not used
8181
return nil, nil
8282
}
8383

84-
func openTtyOut() (*os.File, error) {
84+
func openTtyOut(ttyDefault string) (*os.File, error) {
8585
return os.Stderr, nil
8686
}
8787

src/tui/ttyname_unix.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ func ttyname() string {
4444
}
4545

4646
// TtyIn returns terminal device to read user input
47-
func TtyIn() (*os.File, error) {
48-
return openTtyIn()
47+
func TtyIn(ttyDefault string) (*os.File, error) {
48+
return openTtyIn(ttyDefault)
4949
}
5050

5151
// TtyIn returns terminal device to write to
52-
func TtyOut() (*os.File, error) {
53-
return openTtyOut()
52+
func TtyOut(ttyDefault string) (*os.File, error) {
53+
return openTtyOut(ttyDefault)
5454
}

src/tui/ttyname_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ func ttyname() string {
1111
}
1212

1313
// TtyIn on Windows returns os.Stdin
14-
func TtyIn() (*os.File, error) {
14+
func TtyIn(ttyDefault string) (*os.File, error) {
1515
return os.Stdin, nil
1616
}
1717

1818
// TtyOut on Windows returns nil
19-
func TtyOut() (*os.File, error) {
19+
func TtyOut(ttyDefault string) (*os.File, error) {
2020
return nil, nil
2121
}

0 commit comments

Comments
 (0)