mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-11-12 15:53:33 -04:00
Let a menu's filter receive pasted text in one piece
The filter takes a single line of text. Drop the newlines at the start and end of the pasted text, and replace the remaining newlines and tabs with spaces. A pasted newline therefore no longer runs the selected menu item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f6ceabdebe
commit
e68f195e33
@@ -1,6 +1,8 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
)
|
||||
|
||||
@@ -76,6 +78,34 @@ func (gui *Gui) menuFilterEditor(v *gocui.View, key gocui.Key) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (gui *Gui) pasteIntoMenuFilter(text string) {
|
||||
v := gui.Views.MenuFilter
|
||||
if typePastedTextIntoSingleLineView(v, text) {
|
||||
gui.onMenuFilterContentChanged(v.TextArea.GetContent())
|
||||
}
|
||||
}
|
||||
|
||||
// typePastedTextIntoSingleLineView returns false if nothing is left of the text
|
||||
// to type.
|
||||
func typePastedTextIntoSingleLineView(v *gocui.View, text string) bool {
|
||||
text = pastedTextAsSingleLine(text)
|
||||
if text == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
v.TextArea.TypeString(text)
|
||||
v.RenderTextArea()
|
||||
return true
|
||||
}
|
||||
|
||||
// Views that take a single line of text get pasted text without the newlines at
|
||||
// its start and end, which are often part of a copied line, and with spaces in
|
||||
// place of the newlines and tabs inside it.
|
||||
func pastedTextAsSingleLine(text string) string {
|
||||
text = strings.Trim(text, "\n")
|
||||
return strings.NewReplacer("\n", " ", "\t", " ").Replace(text)
|
||||
}
|
||||
|
||||
func (gui *Gui) onMenuFilterContentChanged(content string) {
|
||||
menuContext := gui.State.Contexts.Menu
|
||||
menuContext.SetFilterStarted(true)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPastedTextAsSingleLine(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
text string
|
||||
expected string
|
||||
}{
|
||||
{"single line", "foo bar", "foo bar"},
|
||||
{"newlines at start and end", "\n\nfoo\n", "foo"},
|
||||
{"newlines inside", "foo\nbar\n\nbaz", "foo bar baz"},
|
||||
{"tabs", "\tfoo\tbar", " foo bar"},
|
||||
{"only newlines", "\n\n", ""},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
assert.Equal(t, s.expected, pastedTextAsSingleLine(s.text))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -150,6 +150,10 @@ func (gui *Gui) createAllViews() error {
|
||||
gui.Views.MenuFilter.Frame = false
|
||||
gui.Views.MenuFilter.Editable = true
|
||||
gui.Views.MenuFilter.Editor = gocui.EditorFunc(gui.menuFilterEditor)
|
||||
gui.Views.MenuFilter.OnPaste = func(text string) error {
|
||||
gui.pasteIntoMenuFilter(text)
|
||||
return nil
|
||||
}
|
||||
// The filter row belongs to the menu: it shares the menu's focus, and keys
|
||||
// that the input field doesn't take are the menu's to handle.
|
||||
gui.Views.MenuFilterFrame.ParentView = gui.Views.Menu
|
||||
|
||||
@@ -27,10 +27,7 @@ var PasteIntoKeybindingsMenu = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
|
||||
t.Views().Files().
|
||||
Lines(
|
||||
/* EXPECTED:
|
||||
Contains(`??`).Contains(`myfile`),
|
||||
ACTUAL: */
|
||||
Contains(`A `).Contains(`myfile`),
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package filter_and_search
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var PasteIntoMenuFilter = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Paste text into the filter of a menu that filters as you type",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFile("myfile", "myfile")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.OptionMenu)
|
||||
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Keybindings")).
|
||||
Paste("\nIgnore\n").
|
||||
Lines(
|
||||
Contains(`─── Local`),
|
||||
Contains(`Ignore`).IsSelected(),
|
||||
)
|
||||
|
||||
t.Views().MenuFilter().
|
||||
Content(Equals("Ignore"))
|
||||
},
|
||||
})
|
||||
@@ -338,6 +338,7 @@ var tests = []*components.IntegrationTest{
|
||||
filter_and_search.NestedFilterTransient,
|
||||
filter_and_search.NewSearch,
|
||||
filter_and_search.PasteIntoKeybindingsMenu,
|
||||
filter_and_search.PasteIntoMenuFilter,
|
||||
filter_and_search.RerenderTheSearchedMainView,
|
||||
filter_and_search.SearchALongDiff,
|
||||
filter_and_search.SearchStatusAfterARerender,
|
||||
|
||||
Reference in New Issue
Block a user