Start on supporting auto-suggestions when checking out a branch

switch to other fuzzy package with no dependencies
This commit is contained in:
Jesse Duffield
2020-11-28 13:14:48 +11:00
parent 90ade3225f
commit da3b0bf7c8
42 changed files with 919 additions and 105 deletions

View File

@@ -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 {