mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-08-06 22:33:07 +02:00
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
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
)
|
||||
@ -41,15 +42,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
|
||||
},
|
||||
@ -59,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()
|
||||
@ -72,3 +81,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)
|
||||
}
|
||||
|
@ -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()
|
||||
@ -105,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
|
||||
})
|
||||
|
||||
|
@ -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
|
||||
|
@ -504,15 +504,19 @@ 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
|
||||
!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, 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 !isCommitMessageOrSuggestionsView(gui.currentViewName()) || !isCommitMessageOrSuggestionsView(binding.ViewName) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return baseHandler(opts)
|
||||
|
Reference in New Issue
Block a user