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 {
|
func (self *SuggestionsContext) RangeSelectEnabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *SuggestionsContext) GetOnClick() func() error {
|
||||||
|
return self.State.OnConfirm
|
||||||
|
}
|
||||||
|
@ -2,7 +2,6 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
@ -59,6 +58,7 @@ func (self *CommitDescriptionController) GetMouseKeybindings(opts types.Keybindi
|
|||||||
return []*gocui.ViewMouseBinding{
|
return []*gocui.ViewMouseBinding{
|
||||||
{
|
{
|
||||||
ViewName: self.Context().GetViewName(),
|
ViewName: self.Context().GetViewName(),
|
||||||
|
FocusedView: self.c.Contexts().CommitMessage.GetViewName(),
|
||||||
Key: gocui.MouseLeft,
|
Key: gocui.MouseLeft,
|
||||||
Handler: self.onClick,
|
Handler: self.onClick,
|
||||||
},
|
},
|
||||||
@ -137,10 +137,6 @@ func (self *CommitDescriptionController) openCommitMenu() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitDescriptionController) onClick(opts gocui.ViewMouseBindingOpts) 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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ func (self *CommitMessageController) GetMouseKeybindings(opts types.KeybindingsO
|
|||||||
return []*gocui.ViewMouseBinding{
|
return []*gocui.ViewMouseBinding{
|
||||||
{
|
{
|
||||||
ViewName: self.Context().GetViewName(),
|
ViewName: self.Context().GetViewName(),
|
||||||
|
FocusedView: self.c.Contexts().CommitDescription.GetViewName(),
|
||||||
Key: gocui.MouseLeft,
|
Key: gocui.MouseLeft,
|
||||||
Handler: self.onClick,
|
Handler: self.onClick,
|
||||||
},
|
},
|
||||||
@ -194,10 +195,6 @@ func (self *CommitMessageController) openCommitMenu() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitMessageController) onClick(opts gocui.ViewMouseBindingOpts) 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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"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),
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
||||||
Handler: func() error {
|
Handler: func() error {
|
||||||
if len(self.c.Contexts().Suggestions.State.Suggestions) > 0 {
|
if len(self.c.Contexts().Suggestions.State.Suggestions) > 0 {
|
||||||
subtitle := ""
|
self.switchToSuggestions()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -59,6 +52,22 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [
|
|||||||
return bindings
|
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) {
|
func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) {
|
||||||
return func(types.OnFocusLostOpts) {
|
return func(types.OnFocusLostOpts) {
|
||||||
self.c.Helpers().Confirmation.DeactivateConfirmationPrompt()
|
self.c.Helpers().Confirmation.DeactivateConfirmationPrompt()
|
||||||
@ -72,3 +81,15 @@ func (self *ConfirmationController) Context() types.Context {
|
|||||||
func (self *ConfirmationController) context() *context.ConfirmationContext {
|
func (self *ConfirmationController) context() *context.ConfirmationContext {
|
||||||
return self.c.Contexts().Confirmation
|
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. 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
|
// 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.
|
// 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 {
|
func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*types.Suggestion {
|
||||||
_ = self.c.WithWaitingStatus(self.c.Tr.LoadingFileSuggestions, func(gocui.Task) error {
|
_ = self.c.WithWaitingStatus(self.c.Tr.LoadingFileSuggestions, func(gocui.Task) error {
|
||||||
trie := patricia.NewTrie()
|
trie := patricia.NewTrie()
|
||||||
@ -105,7 +103,9 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if path != "." {
|
||||||
trie.Insert(patricia.Prefix(path), path)
|
trie.Insert(patricia.Prefix(path), path)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
@ -69,6 +70,19 @@ func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []
|
|||||||
return bindings
|
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 {
|
func (self *SuggestionsController) switchToConfirmation() error {
|
||||||
self.c.Views().Suggestions.Subtitle = ""
|
self.c.Views().Suggestions.Subtitle = ""
|
||||||
self.c.Views().Suggestions.Highlight = false
|
self.c.Views().Suggestions.Highlight = false
|
||||||
|
@ -504,16 +504,20 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error {
|
|||||||
func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
|
func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
|
||||||
baseHandler := binding.Handler
|
baseHandler := binding.Handler
|
||||||
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
|
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
|
||||||
|
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.
|
// 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
|
// 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.
|
// description, or a confirmation and the suggestions view, because we want to allow switching
|
||||||
isCommitMessageView := func(viewName string) bool {
|
// between those two views by clicking.
|
||||||
return viewName == "commitMessage" || viewName == "commitDescription"
|
isCommitMessageOrSuggestionsView := func(viewName string) bool {
|
||||||
|
return viewName == "commitMessage" || viewName == "commitDescription" ||
|
||||||
|
viewName == "confirmation" || viewName == "suggestions"
|
||||||
}
|
}
|
||||||
if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName &&
|
if !isCommitMessageOrSuggestionsView(gui.currentViewName()) || !isCommitMessageOrSuggestionsView(binding.ViewName) {
|
||||||
(!isCommitMessageView(gui.currentViewName()) || !isCommitMessageView(binding.ViewName)) {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return baseHandler(opts)
|
return baseHandler(opts)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user