Do not start the initial reader if 'reload*' is bound to 'start'

This commit is contained in:
Junegunn Choi 2024-06-24 17:05:53 +09:00
parent 1525768094
commit 5b52833785
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
5 changed files with 51 additions and 7 deletions

View File

@ -32,6 +32,15 @@ CHANGELOG
fzf --listen --sync --bind 'focus:transform-header:curl -s localhost:$FZF_PORT?limit=0 | jq .'
```
- Added `offset-middle` action to place the current item is in the middle of the screen
- fzf will not start the initial reader when `reload` or `reload-sync` is bound to `start` event. `fzf < /dev/null` or `: | fzf` are no longer required and extraneous `load` event will not fire due to the empty list.
```sh
# Now this will work as expected. Previously, this would print an invalid header line.
# `fzf < /dev/null` or `: | fzf` would fix the problem, but then an extraneous
# `load` event would fire and the header would be prematurely updated.
fzf --header 'Loading ...' --header-lines 1 \
--bind 'start:reload:sleep 1; ps -ef' \
--bind 'load:change-header:Loaded!'
```
- Fixed mouse support on Windows
- Fixed crash when using `--tiebreak=end` with very long items
- zsh 5.0 compatibility (thanks to @LangLangBart)

View File

@ -58,6 +58,7 @@ const (
const (
EvtReadNew util.EventType = iota
EvtReadFin
EvtReadNone
EvtSearchNew
EvtSearchProgress
EvtSearchFin

View File

@ -147,14 +147,21 @@ func Run(opts *Options) (int, error) {
executor := util.NewExecutor(opts.WithShell)
// Reader
reloadOnStart := opts.reloadOnStart()
streamingFilter := opts.Filter != nil && !sort && !opts.Tac && !opts.Sync
var reader *Reader
if !streamingFilter {
reader = NewReader(func(data []byte) bool {
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)
}
}
// Matcher
forward := true
@ -227,7 +234,8 @@ func Run(opts *Options) (int, error) {
}
// Synchronous search
if opts.Sync {
sync := opts.Sync && !reloadOnStart
if sync {
eventBox.Unwatch(EvtReadNew)
eventBox.WaitFor(EvtReadFin)
}
@ -247,7 +255,7 @@ func Run(opts *Options) (int, error) {
if heightUnknown {
maxFit, padHeight = terminal.MaxFitAndPad()
}
deferred := opts.Select1 || opts.Exit0 || opts.Sync
deferred := opts.Select1 || opts.Exit0 || sync
go terminal.Loop()
if !deferred && !heightUnknown {
// Start right away
@ -314,6 +322,9 @@ 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)

View File

@ -2945,3 +2945,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
}
if actions, prs := opts.Keymap[tui.Start.AsEvent()]; prs {
for _, action := range actions {
if action.t == actReload || action.t == actReloadSync {
return true
}
}
}
return false
}

View File

@ -26,12 +26,12 @@ BASE = File.expand_path('..', __dir__)
Dir.chdir(BASE)
FZF = "FZF_DEFAULT_OPTS=\"--no-scrollbar --pointer \\> --marker \\>\" FZF_DEFAULT_COMMAND= #{BASE}/bin/fzf"
def wait
def wait(timeout = DEFAULT_TIMEOUT)
since = Time.now
begin
yield or raise Minitest::Assertion, 'Assertion failure'
rescue Minitest::Assertion
raise if Time.now - since > DEFAULT_TIMEOUT
raise if Time.now - since > timeout
sleep(0.05)
retry
@ -103,10 +103,10 @@ class Tmux
go(%W[capture-pane -p -J -t #{win}]).map(&:rstrip).reverse.drop_while(&:empty?).reverse
end
def until(refresh = false)
def until(refresh = false, timeout: DEFAULT_TIMEOUT)
lines = nil
begin
wait do
wait(timeout) do
lines = capture
class << lines
def counts
@ -3356,6 +3356,14 @@ class TestGoFZF < TestBase
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_start_on_reload
tmux.send_keys %[echo foo | #{FZF} --header Loading --header-lines 1 --bind 'start:reload:sleep 2; echo bar' --bind 'load:change-header:Loaded'], :Enter
tmux.until(timeout: 1) { |lines| assert_includes lines[-3], 'Loading' }
tmux.until(timeout: 1) { |lines| refute_includes lines[-4], 'foo' }
tmux.until { |lines| assert_includes lines[-3], 'Loaded' }
tmux.until { |lines| assert_includes lines[-4], 'bar' }
end
end
module TestShell