From fee5794c83040c228856bcb05a3ea56d11b304da Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 14:38:27 +0200 Subject: [PATCH 1/8] Remove outdated comment Maybe I'm misunderstanding what the comment was supposed to mean, but we do show all paths if nothing has been typed. --- pkg/gui/controllers/helpers/suggestions_helper.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/gui/controllers/helpers/suggestions_helper.go b/pkg/gui/controllers/helpers/suggestions_helper.go index 912e6cf59..c68a40a7c 100644 --- a/pkg/gui/controllers/helpers/suggestions_helper.go +++ b/pkg/gui/controllers/helpers/suggestions_helper.go @@ -89,8 +89,6 @@ func (self *SuggestionsHelper) GetBranchNameSuggestionsFunc() func(string) []*ty // self.c.Model().FilesTrie. On the main thread we'll be doing a fuzzy search via // self.c.Model().FilesTrie. So if we've looked for a file previously, we'll start with // the old trie and eventually it'll be swapped out for the new one. -// Notably, unlike other suggestion functions we're not showing all the options -// if nothing has been typed because there'll be too much to display efficiently func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*types.Suggestion { _ = self.c.WithWaitingStatus(self.c.Tr.LoadingFileSuggestions, func(gocui.Task) error { trie := patricia.NewTrie() From 4a6041f3ce4c2c2ed87294802e714c8272434082 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 14:39:16 +0200 Subject: [PATCH 2/8] Exclude "." from file path suggestions It looks funny and doesn't have any value. --- pkg/gui/controllers/helpers/suggestions_helper.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/gui/controllers/helpers/suggestions_helper.go b/pkg/gui/controllers/helpers/suggestions_helper.go index c68a40a7c..38ef45430 100644 --- a/pkg/gui/controllers/helpers/suggestions_helper.go +++ b/pkg/gui/controllers/helpers/suggestions_helper.go @@ -103,7 +103,9 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type if err != nil { return err } - trie.Insert(patricia.Prefix(path), path) + if path != "." { + trie.Insert(patricia.Prefix(path), path) + } return nil }) From 2e5cf46716417e8a723dd9beb795ebc21cd39e6d Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 15:06:30 +0200 Subject: [PATCH 3/8] Make conditions easier to understand This doesn't change behavior, just makes the code a little bit easier to understand: the outermost condition is "do we show a popup and is the mouse event for some other view than the focused one". Only if that's true do we need to define the isCommitMessageView function, and check whether both views belong to the commit message editor. --- pkg/gui/keybindings.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 4b41ebe1d..029cb4598 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -504,15 +504,16 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error { func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error { baseHandler := binding.Handler newHandler := func(opts gocui.ViewMouseBindingOpts) error { - // we ignore click events on views that aren't popup panels, when a popup panel is focused. - // Unless both the current view and the clicked-on view are either commit message or commit - // description, because we want to allow switching between those two views by clicking. - isCommitMessageView := func(viewName string) bool { - return viewName == "commitMessage" || viewName == "commitDescription" - } - if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName && - (!isCommitMessageView(gui.currentViewName()) || !isCommitMessageView(binding.ViewName)) { - return nil + if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName { + // we ignore click events on views that aren't popup panels, when a popup panel is focused. + // Unless both the current view and the clicked-on view are either commit message or commit + // description, because we want to allow switching between those two views by clicking. + isCommitMessageView := func(viewName string) bool { + return viewName == "commitMessage" || viewName == "commitDescription" + } + if !isCommitMessageView(gui.currentViewName()) || !isCommitMessageView(binding.ViewName) { + return nil + } } return baseHandler(opts) From f6c20f2745b0e93bc3a991533368c363d8bb05bf Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 17:46:43 +0200 Subject: [PATCH 4/8] Cleanup: use FocusedView property for mouse bindings This way the click is only handled if a given view has the focus, and we don't have to check this manually in the handler. --- .../controllers/commit_description_controller.go | 14 +++++--------- pkg/gui/controllers/commit_message_controller.go | 13 +++++-------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/pkg/gui/controllers/commit_description_controller.go b/pkg/gui/controllers/commit_description_controller.go index 1247de076..24653c767 100644 --- a/pkg/gui/controllers/commit_description_controller.go +++ b/pkg/gui/controllers/commit_description_controller.go @@ -2,7 +2,6 @@ package controllers import ( "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" @@ -58,9 +57,10 @@ func (self *CommitDescriptionController) Context() types.Context { func (self *CommitDescriptionController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { return []*gocui.ViewMouseBinding{ { - ViewName: self.Context().GetViewName(), - Key: gocui.MouseLeft, - Handler: self.onClick, + ViewName: self.Context().GetViewName(), + FocusedView: self.c.Contexts().CommitMessage.GetViewName(), + Key: gocui.MouseLeft, + Handler: self.onClick, }, } } @@ -137,10 +137,6 @@ func (self *CommitDescriptionController) openCommitMenu() error { } func (self *CommitDescriptionController) onClick(opts gocui.ViewMouseBindingOpts) error { - // Activate the description panel when the commit message panel is currently active - if self.c.Context().Current().GetKey() == context.COMMIT_MESSAGE_CONTEXT_KEY { - self.c.Context().Replace(self.c.Contexts().CommitDescription) - } - + self.c.Context().Replace(self.c.Contexts().CommitDescription) return nil } diff --git a/pkg/gui/controllers/commit_message_controller.go b/pkg/gui/controllers/commit_message_controller.go index 6f96cdd21..e9ff1bc67 100644 --- a/pkg/gui/controllers/commit_message_controller.go +++ b/pkg/gui/controllers/commit_message_controller.go @@ -62,9 +62,10 @@ func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts) func (self *CommitMessageController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { return []*gocui.ViewMouseBinding{ { - ViewName: self.Context().GetViewName(), - Key: gocui.MouseLeft, - Handler: self.onClick, + ViewName: self.Context().GetViewName(), + FocusedView: self.c.Contexts().CommitDescription.GetViewName(), + Key: gocui.MouseLeft, + Handler: self.onClick, }, } } @@ -194,10 +195,6 @@ func (self *CommitMessageController) openCommitMenu() error { } func (self *CommitMessageController) onClick(opts gocui.ViewMouseBindingOpts) error { - // Activate the commit message panel when the commit description panel is currently active - if self.c.Context().Current().GetKey() == context.COMMIT_DESCRIPTION_CONTEXT_KEY { - self.c.Context().Replace(self.c.Contexts().CommitMessage) - } - + self.c.Context().Replace(self.c.Contexts().CommitMessage) return nil } From 8ad2637715447954b7c60ac66ddfdaad1630d86a Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 15:11:21 +0200 Subject: [PATCH 5/8] Allow scrolling background views with the mouse wheel when a popup is showing I see little reason to suppress this; the check was really only for click events, not wheel events. --- pkg/gui/keybindings.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 029cb4598..2149be119 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -504,7 +504,8 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error { func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error { baseHandler := binding.Handler newHandler := func(opts gocui.ViewMouseBindingOpts) error { - if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName { + if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName && + !gocui.IsMouseScrollKey(opts.Key) { // we ignore click events on views that aren't popup panels, when a popup panel is focused. // Unless both the current view and the clicked-on view are either commit message or commit // description, because we want to allow switching between those two views by clicking. From 21dd901bd9827d60b0941b1781cc3c1b30496c56 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 18:06:41 +0200 Subject: [PATCH 6/8] Extract helper function --- .../controllers/confirmation_controller.go | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pkg/gui/controllers/confirmation_controller.go b/pkg/gui/controllers/confirmation_controller.go index 6bfff6b98..f121bb0f1 100644 --- a/pkg/gui/controllers/confirmation_controller.go +++ b/pkg/gui/controllers/confirmation_controller.go @@ -41,15 +41,7 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [ Key: opts.GetKey(opts.Config.Universal.TogglePanel), Handler: func() error { if len(self.c.Contexts().Suggestions.State.Suggestions) > 0 { - subtitle := "" - if self.c.State().GetRepoState().GetCurrentPopupOpts().HandleDeleteSuggestion != nil { - // We assume that whenever things are deletable, they - // are also editable, so we show both keybindings - subtitle = fmt.Sprintf(self.c.Tr.SuggestionsSubtitle, - self.c.UserConfig().Keybinding.Universal.Remove, self.c.UserConfig().Keybinding.Universal.Edit) - } - self.c.Views().Suggestions.Subtitle = subtitle - self.c.Context().Replace(self.c.Contexts().Suggestions) + self.switchToSuggestions() } return nil }, @@ -72,3 +64,15 @@ func (self *ConfirmationController) Context() types.Context { func (self *ConfirmationController) context() *context.ConfirmationContext { return self.c.Contexts().Confirmation } + +func (self *ConfirmationController) switchToSuggestions() { + subtitle := "" + if self.c.State().GetRepoState().GetCurrentPopupOpts().HandleDeleteSuggestion != nil { + // We assume that whenever things are deletable, they + // are also editable, so we show both keybindings + subtitle = fmt.Sprintf(self.c.Tr.SuggestionsSubtitle, + self.c.UserConfig().Keybinding.Universal.Remove, self.c.UserConfig().Keybinding.Universal.Edit) + } + self.c.Views().Suggestions.Subtitle = subtitle + self.c.Context().Replace(self.c.Contexts().Suggestions) +} From 3ff4552960ea6b2e61d08b09711482787e1ff591 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 18:03:41 +0200 Subject: [PATCH 7/8] Allow switching between confirmation and suggestions by clicking This is very similar to what we are doing to allow switching between commit subject and description in the commit message editor. --- pkg/gui/controllers/confirmation_controller.go | 17 +++++++++++++++++ pkg/gui/controllers/suggestions_controller.go | 14 ++++++++++++++ pkg/gui/keybindings.go | 10 ++++++---- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/pkg/gui/controllers/confirmation_controller.go b/pkg/gui/controllers/confirmation_controller.go index f121bb0f1..97754655f 100644 --- a/pkg/gui/controllers/confirmation_controller.go +++ b/pkg/gui/controllers/confirmation_controller.go @@ -3,6 +3,7 @@ package controllers import ( "fmt" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -51,6 +52,22 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [ return bindings } +func (self *ConfirmationController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { + return []*gocui.ViewMouseBinding{ + { + ViewName: self.c.Contexts().Suggestions.GetViewName(), + FocusedView: self.c.Contexts().Confirmation.GetViewName(), + Key: gocui.MouseLeft, + Handler: func(gocui.ViewMouseBindingOpts) error { + self.switchToSuggestions() + // Let it fall through to the ListController's click handler so that + // the clicked line gets selected: + return gocui.ErrKeybindingNotHandled + }, + }, + } +} + func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) { return func(types.OnFocusLostOpts) { self.c.Helpers().Confirmation.DeactivateConfirmationPrompt() diff --git a/pkg/gui/controllers/suggestions_controller.go b/pkg/gui/controllers/suggestions_controller.go index 4737bdec8..d97e56289 100644 --- a/pkg/gui/controllers/suggestions_controller.go +++ b/pkg/gui/controllers/suggestions_controller.go @@ -1,6 +1,7 @@ package controllers import ( + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -69,6 +70,19 @@ func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) [] return bindings } +func (self *SuggestionsController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { + return []*gocui.ViewMouseBinding{ + { + ViewName: self.c.Contexts().Confirmation.GetViewName(), + FocusedView: self.c.Contexts().Suggestions.GetViewName(), + Key: gocui.MouseLeft, + Handler: func(gocui.ViewMouseBindingOpts) error { + return self.switchToConfirmation() + }, + }, + } +} + func (self *SuggestionsController) switchToConfirmation() error { self.c.Views().Suggestions.Subtitle = "" self.c.Views().Suggestions.Highlight = false diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 2149be119..98850cf2d 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -508,11 +508,13 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error { !gocui.IsMouseScrollKey(opts.Key) { // we ignore click events on views that aren't popup panels, when a popup panel is focused. // Unless both the current view and the clicked-on view are either commit message or commit - // description, because we want to allow switching between those two views by clicking. - isCommitMessageView := func(viewName string) bool { - return viewName == "commitMessage" || viewName == "commitDescription" + // description, or a confirmation and the suggestions view, because we want to allow switching + // between those two views by clicking. + isCommitMessageOrSuggestionsView := func(viewName string) bool { + return viewName == "commitMessage" || viewName == "commitDescription" || + viewName == "confirmation" || viewName == "suggestions" } - if !isCommitMessageView(gui.currentViewName()) || !isCommitMessageView(binding.ViewName) { + if !isCommitMessageOrSuggestionsView(gui.currentViewName()) || !isCommitMessageOrSuggestionsView(binding.ViewName) { return nil } } From 9baf7870597126149be3ffe1c205b84b39364977 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 10 Jul 2025 18:50:03 +0200 Subject: [PATCH 8/8] Allow double-clicking suggestions --- pkg/gui/context/suggestions_context.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/gui/context/suggestions_context.go b/pkg/gui/context/suggestions_context.go index 45364b3b5..97d28ffc7 100644 --- a/pkg/gui/context/suggestions_context.go +++ b/pkg/gui/context/suggestions_context.go @@ -88,3 +88,7 @@ func (self *SuggestionsContext) RefreshSuggestions() { func (self *SuggestionsContext) RangeSelectEnabled() bool { return false } + +func (self *SuggestionsContext) GetOnClick() func() error { + return self.State.OnConfirm +}