From 0b70dfbf46400a5bad36f8b4c87f1122a322c417 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 28 Mar 2024 09:13:52 +0100 Subject: [PATCH] Fix crash when filtering the keybindings menu It would crash when some keybindings are set to null, and the filter string is such that only those keybindings remain visible. The reason for the crash is that when inserting non-model items (menu section headers in this case) you specify a column to align them to. This works on the assumption that the number of columns is always the same. It can cope with the case that columns are removed because they are empty for all items; but it can't cope with the case that the getDisplayStrings function returns a lower number of columns. And this is what happened here: MenuViewModel.GetDisplayStrings would omit the keybinding column when none of the entries have a keybinding. This logic is unnecessary, the generic list rendering mechanism takes care of this, so removing this logic fixes the crash. We do have to make sure though that the column is really empty when there's no keybinding, so change the logic to use FgCyan only when there's a keybinding. --- pkg/gui/context/menu_context.go | 11 +++---- .../filter_menu_with_no_keybindings.go | 32 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 3 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 pkg/integration/tests/filter_and_search/filter_menu_with_no_keybindings.go diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go index 9db09b74f..6d87d2bb7 100644 --- a/pkg/gui/context/menu_context.go +++ b/pkg/gui/context/menu_context.go @@ -74,9 +74,6 @@ func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem, columnAlignment // TODO: move into presentation package func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string { menuItems := self.FilteredListViewModel.GetItems() - showKeys := lo.SomeBy(menuItems, func(item *types.MenuItem) bool { - return item.Key != nil - }) return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string { displayStrings := item.LabelColumns @@ -84,12 +81,12 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string { displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0]) } - if !showKeys { - return displayStrings + keyLabel := "" + if item.Key != nil { + keyLabel = style.FgCyan.Sprint(keybindings.LabelFromKey(item.Key)) } - keyLabel := keybindings.LabelFromKey(item.Key) - displayStrings = utils.Prepend(displayStrings, style.FgCyan.Sprint(keyLabel)) + displayStrings = utils.Prepend(displayStrings, keyLabel) return displayStrings }) } diff --git a/pkg/integration/tests/filter_and_search/filter_menu_with_no_keybindings.go b/pkg/integration/tests/filter_and_search/filter_menu_with_no_keybindings.go new file mode 100644 index 000000000..40aa8a3d1 --- /dev/null +++ b/pkg/integration/tests/filter_and_search/filter_menu_with_no_keybindings.go @@ -0,0 +1,32 @@ +package filter_and_search + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var FilterMenuWithNoKeybindings = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Filtering the keybindings menu so that only entries without keybinding are left", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) { + config.UserConfig.Keybinding.Universal.ToggleWhitespaceInDiffView = "" + }, + SetupRepo: func(shell *Shell) { + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Files(). + IsFocused(). + Press(keys.Universal.OptionMenu) + + t.ExpectPopup().Menu(). + Title(Equals("Keybindings")). + Filter("whitespace"). + Lines( + // menu has filtered down to the one item that matches the + // filter, and it doesn't have a keybinding + Equals("--- Global ---"), + Equals("Toggle whitespace").IsSelected(), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 1dbfe95fb..a7257fe91 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -146,6 +146,7 @@ var tests = []*components.IntegrationTest{ filter_and_search.FilterFuzzy, filter_and_search.FilterMenu, filter_and_search.FilterMenuCancelFilterWithEscape, + filter_and_search.FilterMenuWithNoKeybindings, filter_and_search.FilterRemoteBranches, filter_and_search.FilterRemotes, filter_and_search.FilterSearchHistory,