mirror of
https://github.com/junegunn/fzf.git
synced 2025-08-14 11:45:48 -07:00
Fix incompatibility of adaptive height and 'start:reload'
This command would cause a deadlock and make fzf crash: fzf --bind 'start:reload:ls' --height ~100% Because, 1. 'start' event is handled by Terminal 2. When 'reload' is bound to 'start', fzf avoids starting the initial reader 3. Terminal waits for the initial input to find the right height when adaptive height is used 4. Because the initial reader is not started, Terminal never gets the initial list 5. No chance to trigger 'start:reload', hence deadlock This commit fixes the above problem by extracting the reload command bound to 'start' event and starting the initial reader with that command instead of letting Terminal start it. This commit also makes the environment variables available to $FZF_DEFAULT_COMMAND. FZF_DEFAULT_COMMAND='echo $FZF_QUERY' fzf --query foo Fix #3944
This commit is contained in:
40
src/core.go
40
src/core.go
@@ -146,8 +146,23 @@ func Run(opts *Options) (int, error) {
|
||||
// Process executor
|
||||
executor := util.NewExecutor(opts.WithShell)
|
||||
|
||||
// Terminal I/O
|
||||
var terminal *Terminal
|
||||
var err error
|
||||
var initialEnv []string
|
||||
initialReload := opts.extractReloadOnStart()
|
||||
if opts.Filter == nil {
|
||||
terminal, err = NewTerminal(opts, eventBox, executor)
|
||||
if err != nil {
|
||||
return ExitError, err
|
||||
}
|
||||
initialEnv = terminal.environ()
|
||||
var temps []string
|
||||
initialReload, temps = terminal.replacePlaceholderInInitialCommand(initialReload)
|
||||
defer removeFiles(temps)
|
||||
}
|
||||
|
||||
// Reader
|
||||
reloadOnStart := opts.reloadOnStart()
|
||||
streamingFilter := opts.Filter != nil && !sort && !opts.Tac && !opts.Sync
|
||||
var reader *Reader
|
||||
if !streamingFilter {
|
||||
@@ -155,12 +170,7 @@ func Run(opts *Options) (int, error) {
|
||||
return chunkList.Push(data)
|
||||
}, eventBox, executor, opts.ReadZero, opts.Filter == nil)
|
||||
|
||||
if reloadOnStart {
|
||||
// reload or reload-sync action is bound to 'start' event, no need to start the reader
|
||||
eventBox.Set(EvtReadNone, nil)
|
||||
} else {
|
||||
go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
|
||||
}
|
||||
go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, initialReload, initialEnv)
|
||||
}
|
||||
|
||||
// Matcher
|
||||
@@ -212,7 +222,7 @@ func Run(opts *Options) (int, error) {
|
||||
}
|
||||
return false
|
||||
}, eventBox, executor, opts.ReadZero, false)
|
||||
reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
|
||||
reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, initialReload, initialEnv)
|
||||
} else {
|
||||
eventBox.Unwatch(EvtReadNew)
|
||||
eventBox.WaitFor(EvtReadFin)
|
||||
@@ -234,8 +244,7 @@ func Run(opts *Options) (int, error) {
|
||||
}
|
||||
|
||||
// Synchronous search
|
||||
sync := opts.Sync && !reloadOnStart
|
||||
if sync {
|
||||
if opts.Sync {
|
||||
eventBox.Unwatch(EvtReadNew)
|
||||
eventBox.WaitFor(EvtReadFin)
|
||||
}
|
||||
@@ -244,18 +253,14 @@ func Run(opts *Options) (int, error) {
|
||||
go matcher.Loop()
|
||||
defer matcher.Stop()
|
||||
|
||||
// Terminal I/O
|
||||
terminal, err := NewTerminal(opts, eventBox, executor)
|
||||
if err != nil {
|
||||
return ExitError, err
|
||||
}
|
||||
// Handling adaptive height
|
||||
maxFit := 0 // Maximum number of items that can fit on screen
|
||||
padHeight := 0
|
||||
heightUnknown := opts.Height.auto
|
||||
if heightUnknown {
|
||||
maxFit, padHeight = terminal.MaxFitAndPad()
|
||||
}
|
||||
deferred := opts.Select1 || opts.Exit0 || sync
|
||||
deferred := opts.Select1 || opts.Exit0 || opts.Sync
|
||||
go terminal.Loop()
|
||||
if !deferred && !heightUnknown {
|
||||
// Start right away
|
||||
@@ -322,9 +327,6 @@ func Run(opts *Options) (int, error) {
|
||||
err = quitSignal.err
|
||||
stop = true
|
||||
return
|
||||
case EvtReadNone:
|
||||
reading = false
|
||||
terminal.UpdateCount(0, false, nil)
|
||||
case EvtReadNew, EvtReadFin:
|
||||
if evt == EvtReadFin && nextCommand != nil {
|
||||
restart(*nextCommand, nextEnviron)
|
||||
|
Reference in New Issue
Block a user