summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--pkg/gui/branches_panel.go7
-rw-r--r--pkg/gui/commit_files_panel.go6
-rw-r--r--pkg/gui/commit_message_panel.go40
-rw-r--r--pkg/gui/confirmation_panel.go104
-rw-r--r--pkg/gui/context.go32
-rw-r--r--pkg/gui/credentials_panel.go2
-rw-r--r--pkg/gui/editors.go93
-rw-r--r--pkg/gui/files_panel.go6
-rw-r--r--pkg/gui/gui.go8
-rw-r--r--pkg/gui/layout.go4
-rw-r--r--pkg/gui/list_context.go20
-rw-r--r--pkg/gui/menu_panel.go2
-rw-r--r--pkg/gui/merge_panel.go6
-rw-r--r--pkg/gui/patch_building_panel.go2
-rw-r--r--pkg/gui/patch_options_panel.go2
-rw-r--r--pkg/gui/presentation/suggestions.go15
-rw-r--r--pkg/gui/quitting.go2
-rw-r--r--pkg/gui/rebase_options_panel.go2
-rw-r--r--pkg/gui/remote_branches_panel.go2
-rw-r--r--pkg/gui/remotes_panel.go2
-rw-r--r--pkg/gui/reset_menu_panel.go2
-rw-r--r--pkg/gui/searching.go2
-rw-r--r--pkg/gui/side_window.go6
-rw-r--r--pkg/gui/staging_panel.go6
-rw-r--r--pkg/gui/status_panel.go2
-rw-r--r--pkg/gui/sub_commits_panel.go2
-rw-r--r--pkg/gui/suggestions_panel.go22
-rw-r--r--pkg/gui/tags_panel.go2
-rw-r--r--pkg/gui/view_helpers.go7
-rw-r--r--pkg/utils/fuzzy_search.go28
-rw-r--r--pkg/utils/fuzzy_search_test.go53
-rw-r--r--vendor/github.com/sahilm/fuzzy/.gitignore2
-rw-r--r--vendor/github.com/sahilm/fuzzy/CONTRIBUTING.md1
-rw-r--r--vendor/github.com/sahilm/fuzzy/Gopkg.lock20
-rw-r--r--vendor/github.com/sahilm/fuzzy/Gopkg.toml4
-rw-r--r--vendor/github.com/sahilm/fuzzy/LICENSE21
-rw-r--r--vendor/github.com/sahilm/fuzzy/Makefile57
-rw-r--r--vendor/github.com/sahilm/fuzzy/README.md184
-rw-r--r--vendor/github.com/sahilm/fuzzy/fuzzy.go235
-rw-r--r--vendor/modules.txt5
42 files changed, 919 insertions, 105 deletions
diff --git a/go.mod b/go.mod
index 633bcb6ed..23babf27e 100644
--- a/go.mod
+++ b/go.mod
@@ -23,11 +23,13 @@ require (
github.com/jesseduffield/yaml v2.1.0+incompatible
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
+ github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/mattn/go-runewidth v0.0.9
github.com/mgutz/str v1.2.0
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
+ github.com/sahilm/fuzzy v0.1.0
github.com/sirupsen/logrus v1.4.2
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
github.com/stretchr/testify v1.4.0
diff --git a/go.sum b/go.sum
index 63d20d766..01eb8e3fa 100644
--- a/go.sum
+++ b/go.sum
@@ -86,6 +86,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -114,6 +116,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
+github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index 48e322025..523ecd0c2 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -212,7 +212,6 @@ func (gui *Gui) handleCheckoutByName(g *gocui.Gui, v *gocui.View) error {
onRefNotFound: func(ref string) error {
return gui.ask(askOpts{
-
title: gui.Tr.BranchNotFoundTitle,
prompt: fmt.Sprintf("%s %s%s", gui.Tr.BranchNotFoundPrompt, ref, "?"),
handleConfirm: func() error {
@@ -278,7 +277,6 @@ func (gui *Gui) deleteNamedBranch(selectedBranch *models.Branch, force bool) err
)
return gui.ask(askOpts{
-
title: title,
prompt: message,
handleConfirm: func() error {
@@ -315,7 +313,6 @@ func (gui *Gui) mergeBranchIntoCheckedOutBranch(branchName string) error {
)
return gui.ask(askOpts{
-
title: gui.Tr.MergingTitle,
prompt: prompt,
handleConfirm: func() error {
@@ -357,7 +354,6 @@ func (gui *Gui) handleRebaseOntoBranch(selectedBranchName string) error {
)
return gui.ask(askOpts{
-
title: gui.Tr.RebasingTitle,
prompt: prompt,
handleConfirm: func() error {
@@ -454,7 +450,6 @@ func (gui *Gui) handleRenameBranch(g *gocui.Gui, v *gocui.View) error {
}
return gui.ask(askOpts{
-
title: gui.Tr.LcRenameBranch,
prompt: gui.Tr.RenameBranchWarning,
handleConfirm: promptForNewName,
@@ -500,7 +495,7 @@ func (gui *Gui) handleNewBranchOffCurrentItem() error {
}
if context.GetKey() != gui.Contexts.Branches.Context.GetKey() {
- if err := gui.switchContext(gui.Contexts.Branches.Context); err != nil {
+ if err := gui.pushContext(gui.Contexts.Branches.Context); err != nil {
return err
}
}
diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go
index c560e667b..98a8d98a9 100644
--- a/pkg/gui/commit_files_panel.go
+++ b/pkg/gui/commit_files_panel.go
@@ -176,7 +176,7 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
}
}
- if err := gui.switchContext(gui.Contexts.PatchBuilding.Context); err != nil {
+ if err := gui.pushContext(gui.Contexts.PatchBuilding.Context); err != nil {
return err
}
return gui.handleRefreshPatchBuildingPanel(selectedLineIdx)
@@ -192,7 +192,7 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
return enterTheFile(selectedLineIdx)
},
handleClose: func() error {
- return gui.switchContext(gui.Contexts.CommitFiles.Context)
+ return gui.pushContext(gui.Contexts.CommitFiles.Context)
},
})
}
@@ -215,5 +215,5 @@ func (gui *Gui) switchToCommitFilesContext(refName string, canRebase bool, conte
return err
}
- return gui.switchContext(gui.Contexts.CommitFiles.Context)
+ return gui.pushContext(gui.Contexts.CommitFiles.Context)
}
diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go
index 333882467..1cdd51770 100644
--- a/pkg/gui/commit_message_panel.go
+++ b/pkg/gui/commit_message_panel.go
@@ -79,43 +79,3 @@ func (gui *Gui) RenderCommitLength() {
v := gui.getCommitMessageView()
v.Subtitle = gui.getBufferLength(v)
}
-
-// we've just copy+pasted the editor from gocui to here so that we can also re-
-// render the commit message length on each keypress
-func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
- newlineKey, ok := gui.getKey(gui.Config.GetUserConfig().Keybinding.Universal.AppendNewline).(gocui.Key)
- if !ok {
- newlineKey = gocui.KeyTab
- }
-
- switch {
- case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
- v.EditDelete(true)
- case key == gocui.KeyDelete:
- v.EditDelete(false)
- case key == gocui.KeyArrowDown:
- v.MoveCursor(0, 1, false)
- case key == gocui.KeyArrowUp:
- v.MoveCursor(0, -1, false)
- case key == gocui.KeyArrowLeft:
- v.MoveCursor(-1, 0, false)
- case key == gocui.KeyArrowRight:
- v.MoveCursor(1, 0, false)
- case key == newlineKey:
- v.EditNewLine()
- case key == gocui.KeySpace:
- v.EditWrite(' ')
- case key == gocui.KeyInsert:
- v.Overwrite = !v.Overwrite
- case key == gocui.KeyCtrlU:
- v.EditDeleteToStartOfLine()
- case key == gocui.KeyCtrlA:
- v.EditGotoToStartOfLine()
- case key == gocui.KeyCtrlE:
- v.EditGotoToEndOfLine()
- default:
- v.EditWrite(ch)
- }
-
- gui.RenderCommitLength()
-}
diff --git a/pkg/gui/confirmation_panel.go b/pkg/gui/confirmation_panel.go
index fbea691ad..dfea11c05 100644
--- a/pkg/gui/confirmation_panel.go
+++ b/pkg/gui/confirmation_panel.go
@@ -27,14 +27,17 @@ type createPopupPanelOpts struct {
// when handlersManageFocus is true, do not return from the confirmation context automatically. It's expected that the handlers will manage focus, whether that means switching to another context, or manually returning the context.
handlersManageFocus bool
+
+ showSuggestionsPanel bool
}
type askOpts struct {
- title string
- prompt string
- handleConfirm func() error
- handleClose func() error
- handlersManageFocus bool
+ title string
+ prompt string
+ handleConfirm func() error
+ handleClose func() error
+ handlersManageFocus bool
+ showSuggestionsPanel bool
}
func (gui *Gui) createLoaderPanel(prompt string) error {
@@ -46,20 +49,22 @@ func (gui *Gui) createLoaderPanel(prompt string) error {
func (gui *Gui) ask(opts askOpts) error {
return gui.createPopupPanel(createPopupPanelOpts{
- title: opts.title,
- prompt: opts.prompt,
- handleConfirm: opts.handleConfirm,
- handleClose: opts.handleClose,
- handlersManageFocus: opts.handlersManageFocus,
+ title: opts.title,
+ prompt: opts.prompt,
+ handleConfirm: opts.handleConfirm,
+ handleClose: opts.handleClose,
+ handlersManageFocus: opts.handlersManageFocus,
+ showSuggestionsPanel: opts.showSuggestionsPanel,
})
}
func (gui *Gui) prompt(title string, initialContent string, handleConfirm func(string) error) error {
return gui.createPopupPanel(createPopupPanelOpts{
- title: title,
- prompt: initialContent,
- editable: true,
- handleConfirmPrompt: handleConfirm,
+ title: title,
+ prompt: initialContent,
+ editable: true,
+ handleConfirmPrompt: handleConfirm,
+ showSuggestionsPanel: true,
})
}
@@ -79,10 +84,10 @@ func (gui *Gui) wrappedConfirmationFunction(handlersManageFocus bool, function f
}
}
-func (gui *Gui) wrappedPromptConfirmationFunction(handlersManageFocus bool, function func(string) error) func(*gocui.Gui, *gocui.View) error {
- return func(g *gocui.Gui, v *gocui.View) error {
+func (gui *Gui) wrappedPromptConfirmationFunction(handlersManageFocus bool, function func(string) error, getResponse func() string) func(*gocui.Gui, *gocui.View) error {
+ return gui.wrappedHandler(func() error {
if function != nil {
- if err := function(v.Buffer()); err != nil {
+ if err := function(getResponse()); err != nil {
return gui.surfaceError(err)
}
}
@@ -92,7 +97,7 @@ func (gui *Gui) wrappedPromptConfirmationFunction(handlersManageFocus bool, func
}
return nil
- }
+ })
}
func (gui *Gui) deleteConfirmationView() {
@@ -104,6 +109,15 @@ func (gui *Gui) deleteConfirmationView() {
_ = gui.g.DeleteView("confirmation")
}
+func (gui *Gui) deleteSuggestionsView() {
+ keybindingConfig := gui.Config.GetUserConfig().Keybinding
+ _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.Confirm), gocui.ModNone)
+ _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone)
+ _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone)
+
+ _ = gui.g.DeleteView("suggestions")
+}
+
func (gui *Gui) closeConfirmationPrompt(handlersManageFocus bool) error {
view := gui.getConfirmationView()
if view == nil {
@@ -117,6 +131,9 @@ func (gui *Gui) closeConfirmationPrompt(handlersManageFocus bool) error {
}
gui.deleteConfirmationView()
+
+ _, _ = gui.g.SetViewOnBottom("suggestions")
+
return nil
}
@@ -156,7 +173,7 @@ func (gui *Gui) getConfirmationPanelDimensions(wrap bool, prompt string) (int, i
height/2 + panelHeight/2
}
-func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool) (*gocui.View, error) {
+func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool, showSuggestionsPanel bool) (*gocui.View, error) {
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(true, prompt)
confirmationView, err := gui.g.SetView("confirmation", x0, y0, x1, y1, 0)
if err != nil {
@@ -171,8 +188,23 @@ func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool) (
confirmationView.Wrap = true
confirmationView.FgColor = theme.GocuiDefaultTextColor
}
+
+ if showSuggestionsPanel {
+ suggestionsViewHeight := 11
+ suggestionsView, err := gui.g.SetView("suggestions", x0, y1, x1, y1+suggestionsViewHeight, 0)
+ if err != nil {
+ if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
+ return nil, err
+ }
+ suggestionsView.Wrap = true
+ suggestionsView.FgColor = theme.GocuiDefaultTextColor
+ }
+ gui.setSuggestions([]string{})
+ _, _ = gui.g.SetViewOnTop("suggestions")
+ }
+
gui.g.Update(func(g *gocui.Gui) error {
- return gui.switchContext(gui.Contexts.Confirmation.Context)
+ return gui.pushContext(gui.Contexts.Confirmation.Context)
})
return confirmationView, nil
}
@@ -183,11 +215,12 @@ func (gui *Gui) createPopupPanel(opts createPopupPanelOpts) error {
if view, _ := g.View("confirmation"); view != nil {
gui.deleteConfirmationView()
}
- confirmationView, err := gui.prepareConfirmationPanel(opts.title, opts.prompt, opts.hasLoader)
+ confirmationView, err := gui.prepareConfirmationPanel(opts.title, opts.prompt, opts.hasLoader, opts.showSuggestionsPanel)
if err != nil {
return err
}
confirmationView.Editable = opts.editable
+ confirmationView.Editor = gocui.EditorFunc(gui.editorWithCallback)
if opts.editable {
go utils.Safe(func() {
// TODO: remove this wait (right now if you remove it the EditGotoToEndOfLine method doesn't seem to work)
@@ -200,6 +233,7 @@ func (gui *Gui) createPopupPanel(opts createPopupPanelOpts) error {
}
gui.renderString("confirmation", opts.prompt)
+
return gui.setKeyBindings(opts)
})
return nil
@@ -217,7 +251,7 @@ func (gui *Gui) setKeyBindings(opts createPopupPanelOpts) error {
gui.renderString("options", actions)
var onConfirm func(*gocui.Gui, *gocui.View) error
if opts.handleConfirmPrompt != nil {
- onConfirm = gui.wrappedPromptConfirmationFunction(opts.handlersManageFocus, opts.handleConfirmPrompt)
+ onConfirm = gui.wrappedPromptConfirmationFunction(opts.handlersManageFocus, opts.handleConfirmPrompt, func() string { return gui.getConfirmationView().Buffer() })
} else {
onConfirm = gui.wrappedConfirmationFunction(opts.handlersManageFocus, opts.handleConfirm)
}
@@ -230,7 +264,31 @@ func (gui *Gui) setKeyBindings(opts createPopupPanelOpts) error {
return err
}
- return gui.g.SetKeybinding("confirmation", nil, gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone, gui.wrappedConfirmationFunction(opts.handlersManageFocus, opts.handleClose))
+ if err := gui.g.SetKeybinding("confirmation", nil, gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone, gui.wrappedConfirmationFunction(opts.handlersManageFocus, opts.handleClose)); err != nil {
+ return err
+ }
+
+ if err := gui.g.SetKeybinding("confirmation", nil, gui.getKey(keybindingConfig.Universal.TogglePanel), gocui.ModNone, gui.wrappedHandler(func() error { return gui.replaceContext(gui.Contexts.Suggestions.Context) })); err != nil {
+ return err
+ }
+
+ onSuggestionConfirm := gui.wrappedPromptConfirmationFunction(opts.handlersManageFocus, opts.handleConfirmPrompt, func() string { return gui.getSelectedSuggestion() })
+ if err := gui.g.SetKeybinding("suggestions", nil, gui.getKey(keybindingConfig.Universal.Confirm), gocui.ModNone, onSuggestionConfirm); err != nil {
+ return err
+ }
+ if err := gui.g.SetKeybinding("suggestions", nil, gui.getKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone, onSuggestionConfirm); err != nil {
+ return err
+ }
+
+ if err := gui.g.SetKeybinding("suggestions", nil, gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone, gui.wrappedConfirmationFunction(opts.handlersManageFocus, opts.handleClose)); err != nil {
+ return err
+ }
+
+ if err := gui.g.SetKeybinding("suggestions", nil, gui.getKey(keybindingConfig.Universal.TogglePanel), gocui.ModNone, gui.wrappedHandler(func() error { return gui.replaceContext(gui.Contexts.Confirmation.Context) })); err != nil {
+ return err
+ }
+
+ return nil
}
func (gui *Gui) createErrorPanel(message string) error {
diff --git a/pkg/gui/context.go b/pkg/gui/context.go
index 3784bb1d5..c28fc9efc 100644
--- a/pkg/gui/context.go
+++ b/pkg/gui/context.go
@@ -35,6 +35,7 @@ const (
SEARCH_CONTEXT_KEY = "search"
COMMIT_MESSAGE_CONTEXT_KEY = "commitMessage"
SUBMODULES_CONTEXT_KEY = "submodules"
+ SUGGESTIONS_CONTEXT_KEY = "suggestions"
)
var allContextKeys = []string{
@@ -59,6 +60,7 @@ var allContextKeys = []string{
SEARCH_CONTEXT_KEY,
COMMIT_MESSAGE_CONTEXT_KEY,
SUBMODULES_CONTEXT_KEY,
+ SUGGESTIONS_CONTEXT_KEY,
}
type SimpleContextNode struct {
@@ -91,6 +93,7 @@ type ContextTree struct {
Confirmation SimpleContextNode
CommitMessage SimpleContextNode
Search SimpleContextNode
+ Suggestions SimpleContextNode
}
func (gui *Gui) allContexts() []Context {
@@ -115,6 +118,7 @@ func (gui *Gui) allContexts() []Context {
gui.Contexts.Merging.Context,
gui.Contexts.PatchBuilding.Context,
gui.Contexts.SubCommits.Context,
+ gui.Contexts.Suggestions.Context,
}
}
@@ -303,6 +307,9 @@ func (gui *Gui) contextTree() ContextTree {
Key: CONFIRMATION_CONTEXT_KEY,
},
},
+ Suggestions: SimpleContextNode{
+ Context: gui.suggestionsListContext(),
+ },
CommitMessage: SimpleContextNode{
Context: BasicContext{
OnFocus: gui.handleCommitMessageFocused,
@@ -400,7 +407,24 @@ func (gui *Gui) currentContextKeyIgnoringPopups() string {
return ""
}
-func (gui *Gui) switchContext(c Context) error {
+// use replaceContext when you don't want to return to the original context upon
+// hitting escape: you want to go that context's parent instead.
+func (gui *Gui) replaceContext(c Context) error {
+ gui.g.Update(func(*gocui.Gui) error {
+ if len(gui.State.ContextStack) == 0 {
+ gui.State.ContextStack = []Context{c}
+ } else {
+ // replace the last item with the given item
+ gui.State.ContextStack = append(gui.State.ContextStack[0:len(gui.State.ContextStack)-1], c)
+ }
+
+ return gui.activateContext(c)
+ })
+
+ return nil
+}
+
+func (gui *Gui) pushContext(c Context) error {
gui.g.Update(func(*gocui.Gui) error {
// push onto stack
// if we are switching to a side context, remove all other contexts in the stack
@@ -424,11 +448,11 @@ func (gui *Gui) switchContext(c Context) error {
return nil
}
-// switchContextToView is to be used when you don't know which context you
+// pushContextWithView is to be used when you don't know which context you
// want to switch to: you only know the view that you want to switch to. It will
// look up the context currently active for that view and switch to that context
-func (gui *Gui) switchContextToView(viewName string) error {
- return gui.switchContext(gui.State.ViewContextMap[viewName])
+func (gui *Gui) pushContextWithView(viewName string) error {
+ return gui.pushContext(gui.State.ViewContextMap[viewName])
}
func (gui *Gui) returnFromContext() error {
diff --git a/pkg/gui/credentials_panel.go b/pkg/gui/credentials_panel.go
index 53166aa76..fe97dc9aa 100644
--- a/pkg/gui/credentials_panel.go
+++ b/pkg/gui/credentials_panel.go
@@ -26,7 +26,7 @@ func (gui *Gui) promptUserForCredential(passOrUname string) string {
credentialsView.Mask = '*'
}
- if err := gui.switchContext(gui.Contexts.Credentials.Context); err != nil {
+ if err := gui.pushContext(gui.Contexts.Credentials.Context); err != nil {
return err
}
diff --git a/pkg/gui/editors.go b/pkg/gui/editors.go
new file mode 100644
index 000000000..baffd19a3
--- /dev/null
+++ b/pkg/gui/editors.go
@@ -0,0 +1,93 @@
+package gui
+
+import (
+ "github.com/jesseduffield/gocui"
+ "github.com/jesseduffield/lazygit/pkg/utils"
+)
+
+// we've just copy+pasted the editor from gocui to here so that we can also re-
+// render the commit message length on each keypress
+func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
+ newlineKey, ok := gui.getKey(gui.Config.GetUserConfig().Keybinding.Universal.AppendNewline).(gocui.Key)
+ if !ok {
+ newlineKey = gocui.KeyTab
+ }
+
+ switch {
+ case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
+ v.EditDelete(true)
+ case key == gocui.KeyDelete:
+ v.EditDelete(false)
+ case key == gocui.KeyArrowDown:
+ v.MoveCursor(0, 1, false)
+ case key == gocui.KeyArrowUp:
+ v.MoveCursor(0, -1, false)
+ case key == gocui.KeyArrowLeft:
+ v.MoveCursor(-1, 0, false)
+ case key == gocui.KeyArrowRight:
+ v.MoveCursor(1, 0, false)
+ case key == newlineKey:
+ v.EditNewLine()
+ case key == gocui.KeySpace:
+ v.EditWrite(' ')
+ case key == gocui.KeyInsert:
+ v.Overwrite = !v.Overwrite
+ case key == gocui.KeyCtrlU:
+ v.EditDeleteToStartOfLine()
+ case key == gocui.KeyCtrlA:
+ v.EditGotoToStartOfLine()
+ case key == gocui.KeyCtrlE:
+ v.EditGotoToEndOfLine()
+ default:
+ v.EditWrite(ch)
+ }
+
+ gui.RenderCommitLength()
+}
+
+// we've just copy+pasted the editor from gocui to here so that we can also re-
+// render the commit message length on each keypress
+func (gui *Gui) editorWithCallback(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
+ switch {
+ case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
+ v.EditDelete(true)
+ case key == gocui.KeyDelete:
+ v.EditDelete(false)
+ case key == gocui.KeyArrowDown:
+ v.MoveCursor(0, 1, false)
+ case key == gocui.KeyArrowUp:
+ v.MoveCursor(0, -1, false)
+ case key == gocui.KeyArrowLeft:
+ v.MoveCursor(-1, 0, false)
+ case key == gocui.KeyArrowRight:
+ v.MoveCursor(1, 0, false)
+ case key == gocui.KeySpace:
+ v.EditWrite(' ')
+ case key == gocui.KeyInsert:
+ v.Overwrite = !v.Overwrite
+ case key == gocui.KeyCtrlU:
+ v.EditDeleteToStartOfLine()
+ case key == gocui.KeyCtrlA:
+ v.EditGotoToStartOfLine()
+ case key == gocui.KeyCtrlE:
+ v.EditGotoToEndOfLine()
+ default:
+ v.EditWrite(ch)
+ }
+
+ input := v.Buffer()
+ branchNames := gui.getBranchNames()
+
+ suggestions := utils.FuzzySearch(input, branchNames)
+ gui.setSuggestions(suggestions)
+}
+
+func (gui *Gui) getBranchNames() []string {
+ result := make([]string, len(gui.State.Branches))
+
+ for i, branch := range gui.State.Branches {
+ result[i] = branch.Name
+ }
+
+ return result
+}
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 1d17b7771..665a403cf 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -183,7 +183,7 @@ func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error
if file.HasMergeConflicts {
return gui.createErrorPanel(gui.Tr.FileStagingRequirements)
}
- _ = gui.switchContext(gui.Contexts.Staging.Context)
+ _ = gui.pushContext(gui.Contexts.Staging.Context)
return gui.handleRefreshStagingPanel(forceSecondaryFocused, selectedLineIdx) // TODO: check if this is broken, try moving into context code
}
@@ -341,7 +341,7 @@ func (gui *Gui) handleCommitPress() error {
}
gui.g.Update(func(g *gocui.Gui) error {
- if err := gui.switchContext(gui.Contexts.CommitMessage.Context); err != nil {
+ if err := gui.pushContext(gui.Contexts.CommitMessage.Context); err != nil {
return err
}
@@ -642,7 +642,7 @@ func (gui *Gui) handleSwitchToMerge() error {
return gui.createErrorPanel(gui.Tr.FileNoMergeCons)
}
- return gui.switchContext(gui.Contexts.Merging.Context)
+ return gui.pushContext(gui.Contexts.Merging.Context)
}
func (gui *Gui) openFile(filename string) error {
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index a1dbd909c..a90770ca9 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -220,6 +220,10 @@ type submodulePanelState struct {
listPanelState
}
+type suggestionsPanelState struct {
+ listPanelState
+}
+
type panelStates struct {
Files *filePanelState
Branches *branchPanelState
@@ -235,6 +239,7 @@ type pa