From 1be1a5cbfd3a7455562228b0b4c00459f893d97c Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 11 Nov 2026 12:14:44 +0100 Subject: [PATCH] Add a test for pasting while input is blocked While a long-running operation blocks input, lazygit buffers key events and replays them when the operation ends. Paste events aren't buffered, so they take effect right away. If the user pastes text during the block, the paste has ended by the time its keys are replayed, and lazygit treats them as typed keys. In a list panel, every character of the text then runs the command bound to it. Without the block, lazygit ignores keys pasted into a list panel. Co-Authored-By: Claude Opus 5.5 --- pkg/gocui/block_events_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pkg/gocui/block_events_test.go b/pkg/gocui/block_events_test.go index adde75829..a2643f96b 100644 --- a/pkg/gocui/block_events_test.go +++ b/pkg/gocui/block_events_test.go @@ -18,6 +18,9 @@ func TestEventWithheldWhileBlocking(t *testing.T) { {"mouse move", GocuiEvent{Type: eventMouseMove}, true}, {"resize", GocuiEvent{Type: eventResize}, false}, {"focus", GocuiEvent{Type: eventFocus}, false}, + /* EXPECTED: + {"paste", GocuiEvent{Type: eventPaste}, true}, + ACTUAL: */ {"paste", GocuiEvent{Type: eventPaste}, false}, {"error", GocuiEvent{Type: eventError}, false}, } @@ -111,6 +114,32 @@ func TestBlockingEvents_KeysArrivingBeforeTheReplayGoBehindIt(t *testing.T) { assert.Equal(t, []int{1, 0}, *fired, "the keys should arrive in the order they were pressed") } +func TestBlockingEvents_PastedKeysReplayedAsPasted(t *testing.T) { + g := newTestGui(t) + keyEvent, fired := setupKeyRecorder(t, g) + pasteStart := GocuiEvent{Type: eventPaste, Start: true} + pasteEnd := GocuiEvent{Type: eventPaste, Start: false} + + // Pasting into a view that isn't editable doesn't run its keybindings. + assert.NoError(t, g.handleEvent(&pasteStart)) + assert.NoError(t, g.handleEvent(&keyEvent)) + assert.NoError(t, g.handleEvent(&pasteEnd)) + assert.Empty(t, *fired) + + // The same must hold for a paste that arrives while input is blocked. + g.BeginBlockingEvents() + assert.NoError(t, g.handleEvent(&pasteStart)) + assert.NoError(t, g.handleEvent(&keyEvent)) + assert.NoError(t, g.handleEvent(&pasteEnd)) + g.EndBlockingEvents() + runQueuedWork(t, g) + /* EXPECTED: + assert.Empty(t, *fired) + ACTUAL: */ + assert.Len(t, *fired, 1) + assert.False(t, g.IsPasting) +} + func TestBlockingEvents_NestsWithCounter(t *testing.T) { g := newTestGui(t) keyEvent, fired := setupKeyRecorder(t, g)