Repository: jesseduffield/lazygit (language: go)

Issue:
Duplicate entries in the footer
**Describe the bug**
The footer has duplicated entries, see screenshot below.
This bug happens in all the panels

**To Reproduce**
Steps to reproduce the behavior:

1. Open lazygit
2. See duplicate entries

**Expected behavior**
No duplicate entries

**Screenshots**
<img width="1678" alt="Screenshot 2024-05-29 at 15 36 14" src="https://github.com/jesseduffield/lazygit/assets/60045235/537978b8-2035-48a5-9f3d-644c0f9270a9">

**Version info:**
lazygit version
```
commit=3675570a391b1a49ddd198b4c7e71e17701d4404, build date=2024-03-23T09:09:11Z, build source=binaryRelease, version=0.41.0, os=darwin, arch=arm64, git version=2.39.3 (Apple Git-146)
```
git version
```
git version 2.39.3 (Apple Git-146)
```


Discussion / hints:
Interesting, can't reproduce, and I have no idea why this should happen on your system but not on mine.

I'm not even sure what I could ask you to get more information about this.

@jesseduffield Any ideas?
can't reproduce on my end either, and also don't know why it would happen on only some people's computers.
If I have time this weekend I can give a look at the source code and try to find the reason, having the machine with the error.
Can you guide me on which files to check for these entries?
The function that renders the keybindings is here: https://github.com/jesseduffield/lazygit/blob/7492521829114b935c91a4eab856a554160122bd/pkg/gui/options_map.go#L35

The `bindingsToDisplay :=` a few lines down is where it filters down the list to find the ones to display, but that's probably not the issue. It looks like for you the whole list of keybindings is duplicated for some reason, so we need to find out why that happens.
I have just noticed this issue as well.
It's happening while using the panel "[1] - Status" and switching to recent repos.
Open lazygit with repo A, switch to repo B, switch back to repo A, options items are doubled.

`commit=, build date=, build source=homebrew, version=0.42.0, os=darwin, arch=arm64, git version=2.45.2`

Please let me know if you need more info.

Fix patch:
diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go
index beaa61446b3..dfcced021b3 100644
--- a/pkg/gui/context/base_context.go
+++ b/pkg/gui/context/base_context.go
@@ -133,6 +133,11 @@ func (self *BaseContext) AddMouseKeybindingsFn(fn types.MouseKeybindingsFn) {
 	self.mouseKeybindingsFns = append(self.mouseKeybindingsFns, fn)
 }
 
+func (self *BaseContext) ClearAllBindingsFn() {
+	self.keybindingsFns = []types.KeybindingsFn{}
+	self.mouseKeybindingsFns = []types.MouseKeybindingsFn{}
+}
+
 func (self *BaseContext) AddOnClickFn(fn func() error) {
 	if fn != nil {
 		self.onClickFn = fn
diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go
index 1dbf9b7d7d8..d6ac5a26870 100644
--- a/pkg/gui/controllers.go
+++ b/pkg/gui/controllers.go
@@ -20,6 +20,10 @@ func (gui *Gui) Helpers() *helpers.Helpers {
 // in the keybinding menu: the earlier that the controller is attached to a context,
 // the lower in the list the keybindings will appear.
 func (gui *Gui) resetHelpersAndControllers() {
+	for _, context := range gui.Contexts().Flatten() {
+		context.ClearAllBindingsFn()
+	}
+
 	helperCommon := gui.c
 	recordDirectoryHelper := helpers.NewRecordDirectoryHelper(helperCommon)
 	reposHelper := helpers.NewRecentReposHelper(helperCommon, recordDirectoryHelper, gui.onNewRepo)
diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go
index 691d5694d4b..003035fc205 100644
--- a/pkg/gui/types/context.go
+++ b/pkg/gui/types/context.go
@@ -74,6 +74,7 @@ type IBaseContext interface {
 
 	AddKeybindingsFn(KeybindingsFn)
 	AddMouseKeybindingsFn(MouseKeybindingsFn)
+	ClearAllBindingsFn()
 
 	// This is a bit of a hack at the moment: we currently only set an onclick function so that
 	// our list controller can come along and wrap it in a list-specific click handler.
diff --git a/pkg/integration/components/shell.go b/pkg/integration/components/shell.go
index a8caff77d5f..01a9caf3a80 100644
--- a/pkg/integration/components/shell.go
+++ b/pkg/integration/components/shell.go
@@ -360,6 +360,12 @@ func (self *Shell) Clone(repoName string) *Shell {
 	return self
 }
 
+func (self *Shell) CloneNonBare(repoName string) *Shell {
+	self.RunCommand([]string{"git", "clone", ".", "../" + repoName})
+
+	return self
+}
+
 func (self *Shell) SetBranchUpstream(branch string, upstream string) *Shell {
 	self.RunCommand([]string{"git", "branch", "--set-upstream-to=" + upstream, branch})
 


Test patch:
diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go
index 5fbbfb4e2d3..cc7fc6ca185 100644
--- a/pkg/integration/tests/test_list.go
+++ b/pkg/integration/tests/test_list.go
@@ -315,6 +315,7 @@ var tests = []*components.IntegrationTest{
 	ui.Accordion,
 	ui.DoublePopup,
 	ui.EmptyMenu,
+	ui.KeybindingSuggestionsWhenSwitchingRepos,
 	ui.ModeSpecificKeybindingSuggestions,
 	ui.OpenLinkFailure,
 	ui.RangeSelect,
diff --git a/pkg/integration/tests/ui/keybinding_suggestions_when_switching_repos.go b/pkg/integration/tests/ui/keybinding_suggestions_when_switching_repos.go
new file mode 100644
index 00000000000..62cb16b60d9
--- /dev/null
+++ b/pkg/integration/tests/ui/keybinding_suggestions_when_switching_repos.go
@@ -0,0 +1,42 @@
+package ui
+
+import (
+	"path/filepath"
+
+	"github.com/jesseduffield/lazygit/pkg/config"
+	. "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var KeybindingSuggestionsWhenSwitchingRepos = NewIntegrationTest(NewIntegrationTestArgs{
+	Description:  "Show correct keybinding suggestions after switching between repos",
+	ExtraCmdArgs: []string{},
+	Skip:         false,
+	SetupConfig: func(config *config.AppConfig) {
+		otherRepo, _ := filepath.Abs("../other")
+		config.AppState.RecentRepos = []string{otherRepo}
+	},
+	SetupRepo: func(shell *Shell) {
+		shell.CloneNonBare("other")
+	},
+	Run: func(t *TestDriver, keys config.KeybindingConfig) {
+		switchToRepo := func(repo string) {
+			t.GlobalPress(keys.Universal.OpenRecentRepos)
+			t.ExpectPopup().Menu().Title(Equals("Recent repositories")).
+				Lines(
+					Contains(repo).IsSelected(),
+					Contains("Cancel"),
+				).Confirm()
+			t.Views().Status().Content(Contains(repo + " → master"))
+		}
+
+		t.Views().Files().Focus()
+		t.Views().Options().Content(
+			Equals("Commit: c | Stash: s | Reset: D | Keybindings: ? | Cancel: <esc>"))
+
+		switchToRepo("other")
+		switchToRepo("repo")
+
+		t.Views().Options().Content(
+			Equals("Commit: c | Stash: s | Reset: D | Keybindings: ? | Cancel: <esc>"))
+	},
+})