diff --git a/src/terminal.go b/src/terminal.go index 7f9a51d9..e2bdc8bb 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -6366,12 +6366,18 @@ func (t *Terminal) Loop() error { needBarrier = false } - // These variables are defined outside the loop to be accessible from closures + // These variables are defined outside the loop to be accessible from closures. + // In particular, async bg-transform callbacks run in a later iteration than + // the one that scheduled them, but still need to mutate state that the + // loop-end reload/event dispatch reads. events := []util.EventType{} changed := false var newNth *[]Range var newWithNth *withNthSpec var newHeaderLines *int + var newCommand *commandSpec + var reloadSync bool + var denylist []int32 req := func(evts ...util.EventType) { for _, event := range evts { events = append(events, event) @@ -6383,16 +6389,16 @@ func (t *Terminal) Loop() error { // The main event loop for loopIndex := int64(0); looping; loopIndex++ { - var newCommand *commandSpec - var reloadSync bool events = []util.EventType{} changed = false newNth = nil newWithNth = nil newHeaderLines = nil + newCommand = nil + reloadSync = false + denylist = nil beof := false queryChanged := false - denylist := []int32{} // Special handling of --sync. Activate the interface on the second tick. if loopIndex == 1 && t.deferActivation() { diff --git a/test/test_core.rb b/test/test_core.rb index 56a3f555..16f6ade4 100644 --- a/test/test_core.rb +++ b/test/test_core.rb @@ -2153,6 +2153,24 @@ class TestCore < TestInteractive tmux.until { |lines| assert lines.any_include?('a b c') || lines.any_include?('d e f') } end + # Regression: actions emitted by bg-transform must affect the iteration that + # processes the async result, not the (no-longer-active) iteration that + # scheduled the transform. Covers reload (newCommand) and exclude (denylist). + def test_bg_transform_action_output + tmux.send_keys %(seq 5 | #{FZF} --bind 'a:bg-transform(echo reload:seq 10 20),b:bg-transform(echo exclude)'), :Enter + tmux.until { |lines| assert_equal 5, lines.item_count } + tmux.send_keys :a + tmux.until do |lines| + assert_equal 11, lines.match_count + assert_includes lines, '> 10' + end + tmux.send_keys :b + tmux.until do |lines| + assert_equal 10, lines.match_count + assert_includes lines, '> 11' + end + end + def test_change_with_nth_search input = [ 'alpha bravo charlie',