summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2024-07-27 10:38:08 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2024-07-27 11:30:25 +0900
commit587df594b884c3649b14c8f19dfbcee78e74a0a9 (patch)
tree23c9575ef902e8e8a5adaacad0473a87eede247d
parentb896e0d3140e4a80725fe5a54a9703e4a46e8b65 (diff)
downloadfzf-587df594b884c3649b14c8f19dfbcee78e74a0a9.tar.gz
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
-rw-r--r--CHANGELOG.md8
-rw-r--r--src/constants.go1
-rw-r--r--src/core.go40
-rw-r--r--src/options.go15
-rw-r--r--src/reader.go6
-rw-r--r--src/terminal.go4
6 files changed, 45 insertions, 29 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86fad6d2..1706dde7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,14 @@
CHANGELOG
=========
+0.54.3
+------
+- Fixed incompatibility of adaptive height and 'start:reload'
+- Environment variables are now available to `$FZF_DEFAULT_COMMAND`
+ ```sh
+ FZF_DEFAULT_COMMAND='echo $FZF_QUERY' fzf --query foo
+ ```
+
0.54.2
------
- Fixed incorrect syntax highlighting of truncated multi-line entries
diff --git a/src/constants.go b/src/constants.go
index 29874b29..980e1583 100644
--- a/src/constants.go
+++ b/src/constants.go
@@ -58,7 +58,6 @@ const (
const (
EvtReadNew util.EventType = iota
EvtReadFin
- EvtReadNone
EvtSearchNew
EvtSearchProgress
EvtSearchFin
diff --git a/src/core.go b/src/core.go
index caada27c..2d1443df 100644
--- a/src/core.go
+++ b/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)
diff --git a/src/options.go b/src/options.go
index d32daf10..1593d6f8 100644
--- a/src/options.go
+++ b/src/options.go
@@ -2964,17 +2964,18 @@ func ParseOptions(useDefaults bool, args []string) (*Options, error) {
return opts, nil
}
-func (opts *Options) reloadOnStart() bool {
- // Not compatible with --filter
- if opts.Filter != nil {
- return false
- }
+func (opts *Options) extractReloadOnStart() string {
+ cmd := ""
if actions, prs := opts.Keymap[tui.Start.AsEvent()]; prs {
+ filtered := []*action{}
for _, action := range actions {
if action.t == actReload || action.t == actReloadSync {
- return true
+ cmd = action.a
+ } else {
+ filtered = append(filtered, action)
}
}
+ opts.Keymap[tui.Start.AsEvent()] = filtered
}
- return false
+ return cmd
}
diff --git a/src/reader.go b/src/reader.go
index a4049c4e..ccaf8c62 100644
--- a/src/reader.go
+++ b/src/reader.go
@@ -111,18 +111,20 @@ func (r *Reader) readChannel(inputChan chan string) bool {
}
// ReadSource reads data from the default command or from standard input
-func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts, ignores []string) {
+func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts, ignores []string, initCmd string, initEnv []string) {
r.startEventPoller()
var success bool
if inputChan != nil {
success = r.readChannel(inputChan)
+ } else if len(initCmd) > 0 {
+ success = r.readFromCommand(initCmd, initEnv)
} else if util.IsTty(os.Stdin) {
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
if len(cmd) == 0 {
success = r.readFiles(root, opts, ignores)
} else {
// We can't export FZF_* environment variables to the default command
- success = r.readFromCommand(cmd, nil)
+ success = r.readFromCommand(cmd, initEnv)
}
} else {
success = r.readFromStdin()
diff --git a/src/terminal.go b/src/terminal.go
index f43bb8e9..09a08985 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -2946,6 +2946,10 @@ type replacePlaceholderParams struct {
executor *util.Executor
}
+func (t *Terminal) replacePlaceholderInInitialCommand(template string) (string, []string) {
+ return t.replacePlaceholder(template, false, string(t.input), []*Item{nil, nil})
+}
+
func (t *Terminal) replacePlaceholder(template string, forcePlus bool, input string, list []*Item) (string, []string) {
return replacePlaceholder(replacePlaceholderParams{
template: template,