From 0a71b5f8371596eed5107e965cc1c2ceda1040c1 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 9 Nov 2024 16:38:14 +1100 Subject: [PATCH] WIP --- pkg/gui/context.go | 2 + pkg/gui/context/confirmation_context.go | 1 + .../controllers/confirmation_controller.go | 54 +++++++++++++++---- .../helpers/confirmation_helper.go | 33 +++++++++--- pkg/gui/popup/popup_handler.go | 1 + .../custom_commands/handler_creator.go | 21 ++++++++ pkg/gui/types/common.go | 3 ++ pkg/i18n/english.go | 2 + 8 files changed, 101 insertions(+), 16 deletions(-) diff --git a/pkg/gui/context.go b/pkg/gui/context.go index 36f4e9dda..29fdc606a 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -70,6 +70,8 @@ func (self *ContextMgr) Push(c types.Context, opts ...types.OnFocusOpts) { return } + gui.resetHelpersAndControllers() + contextsToDeactivate, contextToActivate := self.pushToContextStack(c) for _, contextToDeactivate := range contextsToDeactivate { diff --git a/pkg/gui/context/confirmation_context.go b/pkg/gui/context/confirmation_context.go index 69c498e49..3e4865c83 100644 --- a/pkg/gui/context/confirmation_context.go +++ b/pkg/gui/context/confirmation_context.go @@ -14,6 +14,7 @@ type ConfirmationContext struct { type ConfirmationContextState struct { OnConfirm func() error OnClose func() error + Multiline bool } var _ types.Context = (*ConfirmationContext)(nil) diff --git a/pkg/gui/controllers/confirmation_controller.go b/pkg/gui/controllers/confirmation_controller.go index 6bfff6b98..62b5cfb2b 100644 --- a/pkg/gui/controllers/confirmation_controller.go +++ b/pkg/gui/controllers/confirmation_controller.go @@ -24,20 +24,54 @@ func NewConfirmationController( } func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { - bindings := []*types.Binding{ - { - Key: opts.GetKey(opts.Config.Universal.Confirm), - Handler: func() error { return self.context().State.OnConfirm() }, - Description: self.c.Tr.Confirm, - DisplayOnScreen: true, - }, - { + bindings := []*types.Binding{} + + if self.context().State.Multiline { + bindings = append(bindings, + &types.Binding{ + // Hard coding because this is always the button that adds a newline. + Key: opts.GetKey(""), + Handler: func() error { + self.c.Log.Warn("In handler") + self.c.Views().Confirmation.TextArea.TypeString("\n") + self.c.Views().Confirmation.RenderTextArea() + return nil + }, + Description: self.c.Tr.Confirm, + DisplayOnScreen: false, + }, + &types.Binding{ + Key: opts.GetKey(opts.Config.Universal.ConfirmInEditor), + Handler: func() error { + self.c.Log.Warn("In handler") + return self.context().State.OnConfirm() + }, + Description: self.c.Tr.Confirm, + DisplayOnScreen: true, + }, + ) + } else { + bindings = append(bindings, + &types.Binding{ + Key: opts.GetKey(opts.Config.Universal.Confirm), + Handler: func() error { + self.c.Log.Warn("In single-line confirm handler") + return self.context().State.OnConfirm() + }, + Description: self.c.Tr.Confirm, + DisplayOnScreen: true, + }, + ) + } + + bindings = append(bindings, + &types.Binding{ Key: opts.GetKey(opts.Config.Universal.Return), Handler: func() error { return self.context().State.OnClose() }, Description: self.c.Tr.CloseCancel, DisplayOnScreen: true, }, - { + &types.Binding{ Key: opts.GetKey(opts.Config.Universal.TogglePanel), Handler: func() error { if len(self.c.Contexts().Suggestions.State.Suggestions) > 0 { @@ -54,7 +88,7 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [ return nil }, }, - } + ) return bindings } diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 89a150fca..6490de2fa 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -8,6 +8,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/theme" + "github.com/jesseduffield/lazygit/pkg/utils" "github.com/mattn/go-runewidth" ) @@ -156,12 +157,14 @@ func (self *ConfirmationHelper) getPopupPanelWidth() int { func (self *ConfirmationHelper) prepareConfirmationPanel( opts types.ConfirmOpts, ) { - self.c.Views().Confirmation.Title = opts.Title + self.c.Contexts().Confirmation.State.Multiline = opts.Multiline + confirmationView := self.c.Views().Confirmation + confirmationView.Title = opts.Title // for now we do not support wrapping in our editor - self.c.Views().Confirmation.Wrap = !opts.Editable - self.c.Views().Confirmation.FgColor = theme.GocuiDefaultTextColor - self.c.Views().Confirmation.Mask = runeForMask(opts.Mask) - self.c.Views().Confirmation.SetOrigin(0, 0) + confirmationView.Wrap = !opts.Editable + confirmationView.FgColor = theme.GocuiDefaultTextColor + confirmationView.Mask = runeForMask(opts.Mask) + confirmationView.SetOrigin(0, 0) suggestionsContext := self.c.Contexts().Suggestions suggestionsContext.State.FindSuggestions = opts.FindSuggestionsFunc @@ -206,6 +209,7 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ self.prepareConfirmationPanel( types.ConfirmOpts{ Title: opts.Title, + Multiline: opts.Multiline, Prompt: opts.Prompt, FindSuggestionsFunc: opts.FindSuggestionsFunc, Editable: opts.Editable, @@ -213,6 +217,14 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ }) confirmationView := self.c.Views().Confirmation confirmationView.Editable = opts.Editable + if opts.Multiline { + confirmationView.Subtitle = utils.ResolvePlaceholderString( + self.c.Tr.PressToSubmit, + map[string]string{"Key": self.c.UserConfig().Keybinding.Universal.ConfirmInEditor}, + ) + } else { + confirmationView.Subtitle = "" + } if opts.Editable { textArea := confirmationView.TextArea @@ -363,7 +375,16 @@ func (self *ConfirmationHelper) resizeConfirmationPanel(parentPopupContext types prompt = self.c.Views().Confirmation.TextArea.GetContent() wrap = false } - panelHeight := getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight + + multiline := self.c.Contexts().Confirmation.State.Multiline + inputHeight := getMessageHeight(wrap, prompt, panelWidth) + + minMultilineHeight := 5 + if multiline && inputHeight < minMultilineHeight { + inputHeight = minMultilineHeight + } + + panelHeight := inputHeight + suggestionsViewHeight x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext) confirmationViewBottom := y1 - suggestionsViewHeight _, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0) diff --git a/pkg/gui/popup/popup_handler.go b/pkg/gui/popup/popup_handler.go index 8ea50de2b..0418576f6 100644 --- a/pkg/gui/popup/popup_handler.go +++ b/pkg/gui/popup/popup_handler.go @@ -107,6 +107,7 @@ func (self *PopupHandler) Confirm(opts types.ConfirmOpts) { func (self *PopupHandler) Prompt(opts types.PromptOpts) { self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{ Title: opts.Title, + Multiline: opts.Multiline, Prompt: opts.InitialContent, Editable: true, HandleConfirmPrompt: opts.HandleConfirm, diff --git a/pkg/gui/services/custom_commands/handler_creator.go b/pkg/gui/services/custom_commands/handler_creator.go index 95de40a2e..60958f611 100644 --- a/pkg/gui/services/custom_commands/handler_creator.go +++ b/pkg/gui/services/custom_commands/handler_creator.go @@ -79,6 +79,14 @@ func (self *HandlerCreator) call(customCommand config.CustomCommand) func() erro } return self.inputPrompt(resolvedPrompt, wrappedF) } + case "textbox": + f = func() error { + resolvedPrompt, err := self.resolver.resolvePrompt(&prompt, resolveTemplate) + if err != nil { + return err + } + return self.textboxPrompt(resolvedPrompt, wrappedF) + } case "menu": f = func() error { resolvedPrompt, err := self.resolver.resolvePrompt(&prompt, resolveTemplate) @@ -130,6 +138,19 @@ func (self *HandlerCreator) inputPrompt(prompt *config.CustomCommandPrompt, wrap return nil } +func (self *HandlerCreator) textboxPrompt(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error { + self.c.Prompt(types.PromptOpts{ + Title: prompt.Title, + InitialContent: prompt.InitialValue, + Multiline: true, + HandleConfirm: func(str string) error { + return wrappedF(str) + }, + }) + + return nil +} + func (self *HandlerCreator) generateFindSuggestionsFunc(prompt *config.CustomCommandPrompt) (func(string) []*types.Suggestion, error) { if prompt.Suggestions.Preset != "" && prompt.Suggestions.Command != "" { return nil, fmt.Errorf( diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 9213cfc24..d7e4838e3 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -153,6 +153,7 @@ type CreatePopupPanelOpts struct { HasLoader bool Editable bool Title string + Multiline bool Prompt string HandleConfirm func() error HandleConfirmPrompt func(string) error @@ -166,6 +167,7 @@ type CreatePopupPanelOpts struct { type ConfirmOpts struct { Title string + Multiline bool Prompt string HandleConfirm func() error HandleClose func() error @@ -176,6 +178,7 @@ type ConfirmOpts struct { type PromptOpts struct { Title string + Multiline bool InitialContent string FindSuggestionsFunc func(string) []*Suggestion HandleConfirm func(string) error diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index fa28130a9..8be996c50 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -555,6 +555,7 @@ type TranslationSet struct { MustStashWarning string MustStashTitle string ConfirmationTitle string + PressToSubmit string PrevPage string NextPage string GotoTop string @@ -1545,6 +1546,7 @@ func EnglishTranslationSet() *TranslationSet { MustStashWarning: "Pulling a patch out into the index requires stashing and unstashing your changes. If something goes wrong, you'll be able to access your files from the stash. Continue?", MustStashTitle: "Must stash", ConfirmationTitle: "Confirmation panel", + PressToSubmit: "Press {{.Key}} to submit", PrevPage: "Previous page", NextPage: "Next page", GotoTop: "Scroll to top",