mirror of
https://github.com/junegunn/fzf.git
synced 2025-05-19 12:50:22 -07:00
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.
This commit is contained in:
parent
e491770f1c
commit
1d761684c5
@ -228,6 +228,13 @@ e.g. \fB# Avoid rendering both fzf instances at the same time
|
|||||||
(sleep 1; seq 1000000; sleep 1) |
|
(sleep 1; seq 1000000; sleep 1) |
|
||||||
fzf \-\-sync \-\-query 5 \-\-listen \-\-bind start:up,load:up,result:up,focus:change\-header:Ready\fR
|
fzf \-\-sync \-\-query 5 \-\-listen \-\-bind start:up,load:up,result:up,focus:change\-header:Ready\fR
|
||||||
.RE
|
.RE
|
||||||
|
.TP
|
||||||
|
.B "\-\-no\-tty\-default"
|
||||||
|
Make fzf search for the current TTY device via standard error instead of using
|
||||||
|
\fB/dev/tty\fR. This option was added to avoid the problem when trying to open
|
||||||
|
emacsclient from within fzf. Alternativly, you can change the default TTY
|
||||||
|
device by setting \fB--tty-default=DEVICE_NAME\fR.
|
||||||
|
|
||||||
.SS GLOBAL STYLE
|
.SS GLOBAL STYLE
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-style=" "PRESET"
|
.BI "\-\-style=" "PRESET"
|
||||||
|
@ -631,6 +631,7 @@ type Options struct {
|
|||||||
MEMProfile string
|
MEMProfile string
|
||||||
BlockProfile string
|
BlockProfile string
|
||||||
MutexProfile string
|
MutexProfile string
|
||||||
|
TtyDefault string
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterNonEmpty(input []string) []string {
|
func filterNonEmpty(input []string) []string {
|
||||||
@ -730,6 +731,7 @@ func defaultOptions() *Options {
|
|||||||
WalkerOpts: walkerOpts{file: true, hidden: true, follow: true},
|
WalkerOpts: walkerOpts{file: true, hidden: true, follow: true},
|
||||||
WalkerRoot: []string{"."},
|
WalkerRoot: []string{"."},
|
||||||
WalkerSkip: []string{".git", "node_modules"},
|
WalkerSkip: []string{".git", "node_modules"},
|
||||||
|
TtyDefault: tui.DefaultTtyDevice,
|
||||||
Help: false,
|
Help: false,
|
||||||
Version: false}
|
Version: false}
|
||||||
}
|
}
|
||||||
@ -2336,6 +2338,12 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
}
|
}
|
||||||
case "--no-tmux":
|
case "--no-tmux":
|
||||||
opts.Tmux = nil
|
opts.Tmux = nil
|
||||||
|
case "--tty-default":
|
||||||
|
if opts.TtyDefault, err = nextString("tty device name required"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "--no-tty-default":
|
||||||
|
opts.TtyDefault = ""
|
||||||
case "--force-tty-in":
|
case "--force-tty-in":
|
||||||
// NOTE: We need this because `system('fzf --tmux < /dev/tty')` doesn't
|
// NOTE: We need this because `system('fzf --tmux < /dev/tty')` doesn't
|
||||||
// work on Neovim. Same as '-' option of fzf-tmux.
|
// work on Neovim. Same as '-' option of fzf-tmux.
|
||||||
|
@ -145,7 +145,7 @@ func runProxy(commandPrefix string, cmdBuilder func(temp string, needBash bool)
|
|||||||
env = elems[1:]
|
env = elems[1:]
|
||||||
}
|
}
|
||||||
executor := util.NewExecutor(opts.WithShell)
|
executor := util.NewExecutor(opts.WithShell)
|
||||||
ttyin, err := tui.TtyIn()
|
ttyin, err := tui.TtyIn(opts.TtyDefault)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ExitError, err
|
return ExitError, err
|
||||||
}
|
}
|
||||||
|
@ -381,6 +381,7 @@ type Terminal struct {
|
|||||||
slab *util.Slab
|
slab *util.Slab
|
||||||
theme *tui.ColorTheme
|
theme *tui.ColorTheme
|
||||||
tui tui.Renderer
|
tui tui.Renderer
|
||||||
|
ttyDefault string
|
||||||
ttyin *os.File
|
ttyin *os.File
|
||||||
executing *util.AtomicBool
|
executing *util.AtomicBool
|
||||||
termSize tui.TermSize
|
termSize tui.TermSize
|
||||||
@ -809,7 +810,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
// when you run fzf multiple times in your Go program. Closing it is known to
|
// when you run fzf multiple times in your Go program. Closing it is known to
|
||||||
// cause problems with 'become' action and invalid terminal state after exit.
|
// cause problems with 'become' action and invalid terminal state after exit.
|
||||||
if ttyin == nil {
|
if ttyin == nil {
|
||||||
if ttyin, err = tui.TtyIn(); err != nil {
|
if ttyin, err = tui.TtyIn(opts.TtyDefault); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,7 +818,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
if tui.HasFullscreenRenderer() {
|
if tui.HasFullscreenRenderer() {
|
||||||
renderer = tui.NewFullscreenRenderer(opts.Theme, opts.Black, opts.Mouse)
|
renderer = tui.NewFullscreenRenderer(opts.Theme, opts.Black, opts.Mouse)
|
||||||
} else {
|
} else {
|
||||||
renderer, err = tui.NewLightRenderer(ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit,
|
renderer, err = tui.NewLightRenderer(opts.TtyDefault, ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit,
|
||||||
true, func(h int) int { return h })
|
true, func(h int) int { return h })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -833,7 +834,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
effectiveMinHeight += borderLines(opts.BorderShape)
|
effectiveMinHeight += borderLines(opts.BorderShape)
|
||||||
return util.Min(termHeight, util.Max(evaluateHeight(opts, termHeight), effectiveMinHeight))
|
return util.Min(termHeight, util.Max(evaluateHeight(opts, termHeight), effectiveMinHeight))
|
||||||
}
|
}
|
||||||
renderer, err = tui.NewLightRenderer(ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit, false, maxHeightFunc)
|
renderer, err = tui.NewLightRenderer(opts.TtyDefault, ttyin, opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit, false, maxHeightFunc)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -967,6 +968,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
keyChan: make(chan tui.Event),
|
keyChan: make(chan tui.Event),
|
||||||
eventChan: make(chan tui.Event, 6), // start | (load + result + zero|one) | (focus) | (resize)
|
eventChan: make(chan tui.Event, 6), // start | (load + result + zero|one) | (focus) | (resize)
|
||||||
tui: renderer,
|
tui: renderer,
|
||||||
|
ttyDefault: opts.TtyDefault,
|
||||||
ttyin: ttyin,
|
ttyin: ttyin,
|
||||||
initFunc: func() error { return renderer.Init() },
|
initFunc: func() error { return renderer.Init() },
|
||||||
executing: util.NewAtomicBool(false),
|
executing: util.NewAtomicBool(false),
|
||||||
@ -4042,7 +4044,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
t.executing.Set(true)
|
t.executing.Set(true)
|
||||||
if !background {
|
if !background {
|
||||||
// Open a separate handle for tty input
|
// Open a separate handle for tty input
|
||||||
if in, _ := tui.TtyIn(); in != nil {
|
if in, _ := tui.TtyIn(t.ttyDefault); in != nil {
|
||||||
cmd.Stdin = in
|
cmd.Stdin = in
|
||||||
if in != os.Stdin {
|
if in != os.Stdin {
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
@ -4051,7 +4053,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
|
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
if !util.IsTty(os.Stdout) {
|
if !util.IsTty(os.Stdout) {
|
||||||
if out, _ := tui.TtyOut(); out != nil {
|
if out, _ := tui.TtyOut(t.ttyDefault); out != nil {
|
||||||
cmd.Stdout = out
|
cmd.Stdout = out
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
}
|
}
|
||||||
@ -4059,7 +4061,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
|
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if !util.IsTty(os.Stderr) {
|
if !util.IsTty(os.Stderr) {
|
||||||
if out, _ := tui.TtyOut(); out != nil {
|
if out, _ := tui.TtyOut(t.ttyDefault); out != nil {
|
||||||
cmd.Stderr = out
|
cmd.Stderr = out
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ const (
|
|||||||
maxInputBuffer = 1024 * 1024
|
maxInputBuffer = 1024 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
const consoleDevice string = "/dev/tty"
|
const DefaultTtyDevice string = "/dev/tty"
|
||||||
|
|
||||||
var offsetRegexp = regexp.MustCompile("(.*?)\x00?\x1b\\[([0-9]+);([0-9]+)R")
|
var offsetRegexp = regexp.MustCompile("(.*?)\x00?\x1b\\[([0-9]+);([0-9]+)R")
|
||||||
var offsetRegexpBegin = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R")
|
var offsetRegexpBegin = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R")
|
||||||
@ -146,8 +146,8 @@ type LightWindow struct {
|
|||||||
wrapSignWidth int
|
wrapSignWidth int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) {
|
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) {
|
||||||
out, err := openTtyOut()
|
out, err := openTtyOut(ttyDefault)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out = os.Stderr
|
out = os.Stderr
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) ([]byte,
|
|||||||
c, ok := r.getch(nonblock)
|
c, ok := r.getch(nonblock)
|
||||||
if !nonblock && !ok {
|
if !nonblock && !ok {
|
||||||
r.Close()
|
r.Close()
|
||||||
return nil, errors.New("failed to read " + consoleDevice)
|
return nil, errors.New("failed to read " + DefaultTtyDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
retries := 0
|
retries := 0
|
||||||
|
@ -42,26 +42,35 @@ func (r *LightRenderer) closePlatform() {
|
|||||||
r.ttyout.Close()
|
r.ttyout.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func openTty(mode int) (*os.File, error) {
|
func openTty(ttyDefault string, mode int) (*os.File, error) {
|
||||||
in, err := os.OpenFile(consoleDevice, mode, 0)
|
var in *os.File
|
||||||
if err != nil {
|
var err error
|
||||||
|
if len(ttyDefault) > 0 {
|
||||||
|
in, err = os.OpenFile(ttyDefault, mode, 0)
|
||||||
|
}
|
||||||
|
if in == nil || err != nil || ttyDefault != DefaultTtyDevice && !util.IsTty(in) {
|
||||||
tty := ttyname()
|
tty := ttyname()
|
||||||
if len(tty) > 0 {
|
if len(tty) > 0 {
|
||||||
if in, err := os.OpenFile(tty, mode, 0); err == nil {
|
if in, err := os.OpenFile(tty, mode, 0); err == nil {
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("failed to open " + consoleDevice)
|
if ttyDefault != DefaultTtyDevice {
|
||||||
|
if in, err = os.OpenFile(DefaultTtyDevice, mode, 0); err == nil {
|
||||||
|
return in, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errors.New("failed to open " + DefaultTtyDevice)
|
||||||
}
|
}
|
||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func openTtyIn() (*os.File, error) {
|
func openTtyIn(ttyDefault string) (*os.File, error) {
|
||||||
return openTty(syscall.O_RDONLY)
|
return openTty(ttyDefault, syscall.O_RDONLY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openTtyOut() (*os.File, error) {
|
func openTtyOut(ttyDefault string) (*os.File, error) {
|
||||||
return openTty(syscall.O_WRONLY)
|
return openTty(ttyDefault, syscall.O_WRONLY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) setupTerminal() {
|
func (r *LightRenderer) setupTerminal() {
|
||||||
|
@ -76,12 +76,12 @@ func (r *LightRenderer) closePlatform() {
|
|||||||
windows.SetConsoleMode(windows.Handle(r.inHandle), r.origStateInput)
|
windows.SetConsoleMode(windows.Handle(r.inHandle), r.origStateInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openTtyIn() (*os.File, error) {
|
func openTtyIn(ttyDefault string) (*os.File, error) {
|
||||||
// not used
|
// not used
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func openTtyOut() (*os.File, error) {
|
func openTtyOut(ttyDefault string) (*os.File, error) {
|
||||||
return os.Stderr, nil
|
return os.Stderr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,11 +44,11 @@ func ttyname() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TtyIn returns terminal device to read user input
|
// TtyIn returns terminal device to read user input
|
||||||
func TtyIn() (*os.File, error) {
|
func TtyIn(ttyDefault string) (*os.File, error) {
|
||||||
return openTtyIn()
|
return openTtyIn(ttyDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TtyIn returns terminal device to write to
|
// TtyIn returns terminal device to write to
|
||||||
func TtyOut() (*os.File, error) {
|
func TtyOut(ttyDefault string) (*os.File, error) {
|
||||||
return openTtyOut()
|
return openTtyOut(ttyDefault)
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@ func ttyname() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TtyIn on Windows returns os.Stdin
|
// TtyIn on Windows returns os.Stdin
|
||||||
func TtyIn() (*os.File, error) {
|
func TtyIn(ttyDefault string) (*os.File, error) {
|
||||||
return os.Stdin, nil
|
return os.Stdin, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TtyOut on Windows returns nil
|
// TtyOut on Windows returns nil
|
||||||
func TtyOut() (*os.File, error) {
|
func TtyOut(ttyDefault string) (*os.File, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user