Skip to content

Commit 228d442

Browse files
authored
Improve mouse handling of suggestions panel (#4726)
- **PR Description** In prompts with a suggestions panel (e.g. the "Execute shell command" window, or the "Filter by path" panel), you can now - scroll the list of suggestions with the mouse wheel even when the focus is in the edit field - click in the suggestions list or in the edit field to switch focus between them - double-click a suggestion to trigger it
2 parents 43b379f + 9baf787 commit 228d442

File tree

7 files changed

+73
-37
lines changed

7 files changed

+73
-37
lines changed

pkg/gui/context/suggestions_context.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,7 @@ func (self *SuggestionsContext) RefreshSuggestions() {
8888
func (self *SuggestionsContext) RangeSelectEnabled() bool {
8989
return false
9090
}
91+
92+
func (self *SuggestionsContext) GetOnClick() func() error {
93+
return self.State.OnConfirm
94+
}

pkg/gui/controllers/commit_description_controller.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package controllers
22

33
import (
44
"github.com/jesseduffield/gocui"
5-
"github.com/jesseduffield/lazygit/pkg/gui/context"
65
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
76
"github.com/jesseduffield/lazygit/pkg/gui/types"
87
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -58,9 +57,10 @@ func (self *CommitDescriptionController) Context() types.Context {
5857
func (self *CommitDescriptionController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
5958
return []*gocui.ViewMouseBinding{
6059
{
61-
ViewName: self.Context().GetViewName(),
62-
Key: gocui.MouseLeft,
63-
Handler: self.onClick,
60+
ViewName: self.Context().GetViewName(),
61+
FocusedView: self.c.Contexts().CommitMessage.GetViewName(),
62+
Key: gocui.MouseLeft,
63+
Handler: self.onClick,
6464
},
6565
}
6666
}
@@ -137,10 +137,6 @@ func (self *CommitDescriptionController) openCommitMenu() error {
137137
}
138138

139139
func (self *CommitDescriptionController) onClick(opts gocui.ViewMouseBindingOpts) error {
140-
// Activate the description panel when the commit message panel is currently active
141-
if self.c.Context().Current().GetKey() == context.COMMIT_MESSAGE_CONTEXT_KEY {
142-
self.c.Context().Replace(self.c.Contexts().CommitDescription)
143-
}
144-
140+
self.c.Context().Replace(self.c.Contexts().CommitDescription)
145141
return nil
146142
}

pkg/gui/controllers/commit_message_controller.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts)
6262
func (self *CommitMessageController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
6363
return []*gocui.ViewMouseBinding{
6464
{
65-
ViewName: self.Context().GetViewName(),
66-
Key: gocui.MouseLeft,
67-
Handler: self.onClick,
65+
ViewName: self.Context().GetViewName(),
66+
FocusedView: self.c.Contexts().CommitDescription.GetViewName(),
67+
Key: gocui.MouseLeft,
68+
Handler: self.onClick,
6869
},
6970
}
7071
}
@@ -194,10 +195,6 @@ func (self *CommitMessageController) openCommitMenu() error {
194195
}
195196

196197
func (self *CommitMessageController) onClick(opts gocui.ViewMouseBindingOpts) error {
197-
// Activate the commit message panel when the commit description panel is currently active
198-
if self.c.Context().Current().GetKey() == context.COMMIT_DESCRIPTION_CONTEXT_KEY {
199-
self.c.Context().Replace(self.c.Contexts().CommitMessage)
200-
}
201-
198+
self.c.Context().Replace(self.c.Contexts().CommitMessage)
202199
return nil
203200
}

pkg/gui/controllers/confirmation_controller.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controllers
33
import (
44
"fmt"
55

6+
"github.com/jesseduffield/gocui"
67
"github.com/jesseduffield/lazygit/pkg/gui/context"
78
"github.com/jesseduffield/lazygit/pkg/gui/types"
89
)
@@ -41,15 +42,7 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [
4142
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
4243
Handler: func() error {
4344
if len(self.c.Contexts().Suggestions.State.Suggestions) > 0 {
44-
subtitle := ""
45-
if self.c.State().GetRepoState().GetCurrentPopupOpts().HandleDeleteSuggestion != nil {
46-
// We assume that whenever things are deletable, they
47-
// are also editable, so we show both keybindings
48-
subtitle = fmt.Sprintf(self.c.Tr.SuggestionsSubtitle,
49-
self.c.UserConfig().Keybinding.Universal.Remove, self.c.UserConfig().Keybinding.Universal.Edit)
50-
}
51-
self.c.Views().Suggestions.Subtitle = subtitle
52-
self.c.Context().Replace(self.c.Contexts().Suggestions)
45+
self.switchToSuggestions()
5346
}
5447
return nil
5548
},
@@ -59,6 +52,22 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [
5952
return bindings
6053
}
6154

55+
func (self *ConfirmationController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
56+
return []*gocui.ViewMouseBinding{
57+
{
58+
ViewName: self.c.Contexts().Suggestions.GetViewName(),
59+
FocusedView: self.c.Contexts().Confirmation.GetViewName(),
60+
Key: gocui.MouseLeft,
61+
Handler: func(gocui.ViewMouseBindingOpts) error {
62+
self.switchToSuggestions()
63+
// Let it fall through to the ListController's click handler so that
64+
// the clicked line gets selected:
65+
return gocui.ErrKeybindingNotHandled
66+
},
67+
},
68+
}
69+
}
70+
6271
func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) {
6372
return func(types.OnFocusLostOpts) {
6473
self.c.Helpers().Confirmation.DeactivateConfirmationPrompt()
@@ -72,3 +81,15 @@ func (self *ConfirmationController) Context() types.Context {
7281
func (self *ConfirmationController) context() *context.ConfirmationContext {
7382
return self.c.Contexts().Confirmation
7483
}
84+
85+
func (self *ConfirmationController) switchToSuggestions() {
86+
subtitle := ""
87+
if self.c.State().GetRepoState().GetCurrentPopupOpts().HandleDeleteSuggestion != nil {
88+
// We assume that whenever things are deletable, they
89+
// are also editable, so we show both keybindings
90+
subtitle = fmt.Sprintf(self.c.Tr.SuggestionsSubtitle,
91+
self.c.UserConfig().Keybinding.Universal.Remove, self.c.UserConfig().Keybinding.Universal.Edit)
92+
}
93+
self.c.Views().Suggestions.Subtitle = subtitle
94+
self.c.Context().Replace(self.c.Contexts().Suggestions)
95+
}

pkg/gui/controllers/helpers/suggestions_helper.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ func (self *SuggestionsHelper) GetBranchNameSuggestionsFunc() func(string) []*ty
8989
// self.c.Model().FilesTrie. On the main thread we'll be doing a fuzzy search via
9090
// self.c.Model().FilesTrie. So if we've looked for a file previously, we'll start with
9191
// the old trie and eventually it'll be swapped out for the new one.
92-
// Notably, unlike other suggestion functions we're not showing all the options
93-
// if nothing has been typed because there'll be too much to display efficiently
9492
func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*types.Suggestion {
9593
_ = self.c.WithWaitingStatus(self.c.Tr.LoadingFileSuggestions, func(gocui.Task) error {
9694
trie := patricia.NewTrie()
@@ -105,7 +103,9 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type
105103
if err != nil {
106104
return err
107105
}
108-
trie.Insert(patricia.Prefix(path), path)
106+
if path != "." {
107+
trie.Insert(patricia.Prefix(path), path)
108+
}
109109
return nil
110110
})
111111

pkg/gui/controllers/suggestions_controller.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package controllers
22

33
import (
4+
"github.com/jesseduffield/gocui"
45
"github.com/jesseduffield/lazygit/pkg/gui/context"
56
"github.com/jesseduffield/lazygit/pkg/gui/types"
67
)
@@ -69,6 +70,19 @@ func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []
6970
return bindings
7071
}
7172

73+
func (self *SuggestionsController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
74+
return []*gocui.ViewMouseBinding{
75+
{
76+
ViewName: self.c.Contexts().Confirmation.GetViewName(),
77+
FocusedView: self.c.Contexts().Suggestions.GetViewName(),
78+
Key: gocui.MouseLeft,
79+
Handler: func(gocui.ViewMouseBindingOpts) error {
80+
return self.switchToConfirmation()
81+
},
82+
},
83+
}
84+
}
85+
7286
func (self *SuggestionsController) switchToConfirmation() error {
7387
self.c.Views().Suggestions.Subtitle = ""
7488
self.c.Views().Suggestions.Highlight = false

pkg/gui/keybindings.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -504,15 +504,19 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error {
504504
func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
505505
baseHandler := binding.Handler
506506
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
507-
// we ignore click events on views that aren't popup panels, when a popup panel is focused.
508-
// Unless both the current view and the clicked-on view are either commit message or commit
509-
// description, because we want to allow switching between those two views by clicking.
510-
isCommitMessageView := func(viewName string) bool {
511-
return viewName == "commitMessage" || viewName == "commitDescription"
512-
}
513507
if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName &&
514-
(!isCommitMessageView(gui.currentViewName()) || !isCommitMessageView(binding.ViewName)) {
515-
return nil
508+
!gocui.IsMouseScrollKey(opts.Key) {
509+
// we ignore click events on views that aren't popup panels, when a popup panel is focused.
510+
// Unless both the current view and the clicked-on view are either commit message or commit
511+
// description, or a confirmation and the suggestions view, because we want to allow switching
512+
// between those two views by clicking.
513+
isCommitMessageOrSuggestionsView := func(viewName string) bool {
514+
return viewName == "commitMessage" || viewName == "commitDescription" ||
515+
viewName == "confirmation" || viewName == "suggestions"
516+
}
517+
if !isCommitMessageOrSuggestionsView(gui.currentViewName()) || !isCommitMessageOrSuggestionsView(binding.ViewName) {
518+
return nil
519+
}
516520
}
517521

518522
return baseHandler(opts)

0 commit comments

Comments
 (0)