diff --git a/pkg/gui/basic_context.go b/pkg/gui/basic_context.go index 1043cca89..e9a3ca933 100644 --- a/pkg/gui/basic_context.go +++ b/pkg/gui/basic_context.go @@ -1,71 +1,48 @@ package gui import ( + "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) -type BasicContext struct { +type SimpleContext struct { OnFocus func(opts ...types.OnFocusOpts) error OnFocusLost func() error OnRender func() error // this is for pushing some content to the main view - OnRenderToMain func(opts ...types.OnFocusOpts) error - Kind types.ContextKind - Key types.ContextKey - ViewName string - WindowName string - OnGetOptionsMap func() map[string]string + OnRenderToMain func(opts ...types.OnFocusOpts) error - ParentContext types.Context - // we can't know on the calling end whether a Context is actually a nil value without reflection, so we're storing this flag here to tell us. There has got to be a better way around this - hasParent bool + *context.BaseContext } -var _ types.Context = &BasicContext{} +type NewSimpleContextOpts struct { + OnFocus func(opts ...types.OnFocusOpts) error + OnFocusLost func() error + OnRender func() error + // this is for pushing some content to the main view + OnRenderToMain func(opts ...types.OnFocusOpts) error +} -func (self *BasicContext) GetOptionsMap() map[string]string { - if self.OnGetOptionsMap != nil { - return self.OnGetOptionsMap() +func NewSimpleContext(baseContext *context.BaseContext, opts NewSimpleContextOpts) *SimpleContext { + return &SimpleContext{ + OnFocus: opts.OnFocus, + OnFocusLost: opts.OnFocusLost, + OnRender: opts.OnRender, + OnRenderToMain: opts.OnRenderToMain, + BaseContext: baseContext, } - return nil } -func (self *BasicContext) SetParentContext(context types.Context) { - self.ParentContext = context - self.hasParent = true -} +var _ types.Context = &SimpleContext{} -func (self *BasicContext) GetParentContext() (types.Context, bool) { - return self.ParentContext, self.hasParent -} - -func (self *BasicContext) SetWindowName(windowName string) { - self.WindowName = windowName -} - -func (self *BasicContext) GetWindowName() string { - windowName := self.WindowName - - if windowName != "" { - return windowName - } - - // TODO: actually set this for everything so we don't default to the view name - return self.ViewName -} - -func (self *BasicContext) HandleRender() error { +func (self *SimpleContext) HandleRender() error { if self.OnRender != nil { return self.OnRender() } return nil } -func (self *BasicContext) GetViewName() string { - return self.ViewName -} - -func (self *BasicContext) HandleFocus(opts ...types.OnFocusOpts) error { +func (self *SimpleContext) HandleFocus(opts ...types.OnFocusOpts) error { if self.OnFocus != nil { if err := self.OnFocus(opts...); err != nil { return err @@ -81,25 +58,17 @@ func (self *BasicContext) HandleFocus(opts ...types.OnFocusOpts) error { return nil } -func (self *BasicContext) HandleFocusLost() error { +func (self *SimpleContext) HandleFocusLost() error { if self.OnFocusLost != nil { return self.OnFocusLost() } return nil } -func (self *BasicContext) HandleRenderToMain() error { +func (self *SimpleContext) HandleRenderToMain() error { if self.OnRenderToMain != nil { return self.OnRenderToMain() } return nil } - -func (self *BasicContext) GetKind() types.ContextKind { - return self.Kind -} - -func (self *BasicContext) GetKey() types.ContextKey { - return self.Key -} diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 18094b297..7b179e2ff 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -8,7 +8,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/controllers" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -145,7 +144,7 @@ func (gui *Gui) handleForceCheckout() error { message := gui.c.Tr.SureForceCheckout title := gui.c.Tr.ForceCheckoutBranch - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: title, Prompt: message, HandleConfirm: func() error { @@ -159,14 +158,14 @@ func (gui *Gui) handleForceCheckout() error { } func (gui *Gui) handleCheckoutByName() error { - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: gui.c.Tr.BranchName + ":", FindSuggestionsFunc: gui.suggestionsHelper.GetRefsSuggestionsFunc(), HandleConfirm: func(response string) error { gui.c.LogAction("Checkout branch") return gui.refHelper.CheckoutRef(response, types.CheckoutRefOptions{ OnRefNotFound: func(ref string) error { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.BranchNotFoundTitle, Prompt: fmt.Sprintf("%s %s%s", gui.c.Tr.BranchNotFoundPrompt, ref, "?"), HandleConfirm: func() error { @@ -232,7 +231,7 @@ func (gui *Gui) deleteNamedBranch(selectedBranch *models.Branch, force bool) err }, ) - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: title, Prompt: message, HandleConfirm: func() error { @@ -265,7 +264,7 @@ func (gui *Gui) mergeBranchIntoCheckedOutBranch(branchName string) error { }, ) - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.MergingTitle, Prompt: prompt, HandleConfirm: func() error { @@ -299,7 +298,7 @@ func (gui *Gui) handleRebaseOntoBranch(selectedBranchName string) error { }, ) - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.RebasingTitle, Prompt: prompt, HandleConfirm: func() error { @@ -368,7 +367,7 @@ func (gui *Gui) handleRenameBranch() error { } promptForNewName := func() error { - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: gui.c.Tr.NewBranchNamePrompt + " " + branch.Name + ":", InitialContent: branch.Name, HandleConfirm: func(newBranchName string) error { @@ -402,7 +401,7 @@ func (gui *Gui) handleRenameBranch() error { return promptForNewName() } - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.LcRenameBranch, Prompt: gui.c.Tr.RenameBranchWarning, HandleConfirm: promptForNewName, @@ -430,7 +429,7 @@ func (gui *Gui) handleNewBranchOffCurrentItem() error { prefilledName = strings.SplitAfterN(item.ID(), "/", 2)[1] } - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: message, InitialContent: prefilledName, HandleConfirm: func(response string) error { diff --git a/pkg/gui/cherry_picking.go b/pkg/gui/cherry_picking.go index 28554edce..be6fe379d 100644 --- a/pkg/gui/cherry_picking.go +++ b/pkg/gui/cherry_picking.go @@ -2,7 +2,6 @@ package gui import ( "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -135,7 +134,7 @@ func (gui *Gui) handleCopyCommitRange() error { // HandlePasteCommits begins a cherry-pick rebase with the commits the user has copied func (gui *Gui) HandlePasteCommits() error { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.CherryPick, Prompt: gui.c.Tr.SureCherryPick, HandleConfirm: func() error { diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index abae8196f..ef2c94bef 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -5,7 +5,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/patch" "github.com/jesseduffield/lazygit/pkg/gui/controllers" "github.com/jesseduffield/lazygit/pkg/gui/filetree" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -81,7 +80,7 @@ func (gui *Gui) handleDiscardOldFileChange() error { fileName := gui.getSelectedCommitFileName() - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.DiscardFileChangesTitle, Prompt: gui.c.Tr.DiscardFileChangesPrompt, HandleConfirm: func() error { @@ -181,7 +180,7 @@ func (gui *Gui) handleToggleFileForPatch() error { } if gui.git.Patch.PatchManager.Active() && gui.git.Patch.PatchManager.To != gui.State.CommitFileTreeViewModel.GetParent() { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.DiscardPatch, Prompt: gui.c.Tr.DiscardPatchConfirm, HandleConfirm: func() error { @@ -229,7 +228,7 @@ func (gui *Gui) enterCommitFile(opts types.OnFocusOpts) error { } if gui.git.Patch.PatchManager.Active() && gui.git.Patch.PatchManager.To != gui.State.CommitFileTreeViewModel.GetParent() { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.DiscardPatch, Prompt: gui.c.Tr.DiscardPatchConfirm, HandleConfirm: func() error { diff --git a/pkg/gui/confirmation_panel.go b/pkg/gui/confirmation_panel.go index 1d865348f..51c71b30b 100644 --- a/pkg/gui/confirmation_panel.go +++ b/pkg/gui/confirmation_panel.go @@ -191,12 +191,6 @@ func (gui *Gui) setKeyBindings(opts popup.CreatePopupPanelOpts) error { onConfirm = gui.wrappedConfirmationFunction(opts.HandlersManageFocus, opts.HandleConfirm) } - type confirmationKeybinding struct { - viewName string - key interface{} - handler func() error - } - keybindingConfig := gui.c.UserConfig.Keybinding onSuggestionConfirm := gui.wrappedPromptConfirmationFunction( opts.HandlersManageFocus, @@ -204,26 +198,30 @@ func (gui *Gui) setKeyBindings(opts popup.CreatePopupPanelOpts) error { gui.getSelectedSuggestionValue, ) - confirmationKeybindings := []confirmationKeybinding{ + bindings := []*types.Binding{ { - viewName: "confirmation", - key: gui.getKey(keybindingConfig.Universal.Confirm), - handler: onConfirm, + ViewName: "confirmation", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.Confirm), + Handler: onConfirm, }, { - viewName: "confirmation", - key: gui.getKey(keybindingConfig.Universal.ConfirmAlt1), - handler: onConfirm, + ViewName: "confirmation", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.ConfirmAlt1), + Handler: onConfirm, }, { - viewName: "confirmation", - key: gui.getKey(keybindingConfig.Universal.Return), - handler: gui.wrappedConfirmationFunction(opts.HandlersManageFocus, opts.HandleClose), + ViewName: "confirmation", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.Return), + Handler: gui.wrappedConfirmationFunction(opts.HandlersManageFocus, opts.HandleClose), }, { - viewName: "confirmation", - key: gui.getKey(keybindingConfig.Universal.TogglePanel), - handler: func() error { + ViewName: "confirmation", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.TogglePanel), + Handler: func() error { if len(gui.State.Suggestions) > 0 { return gui.replaceContext(gui.State.Contexts.Suggestions) } @@ -231,29 +229,33 @@ func (gui *Gui) setKeyBindings(opts popup.CreatePopupPanelOpts) error { }, }, { - viewName: "suggestions", - key: gui.getKey(keybindingConfig.Universal.Confirm), - handler: onSuggestionConfirm, + ViewName: "suggestions", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.Confirm), + Handler: onSuggestionConfirm, }, { - viewName: "suggestions", - key: gui.getKey(keybindingConfig.Universal.ConfirmAlt1), - handler: onSuggestionConfirm, + ViewName: "suggestions", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.ConfirmAlt1), + Handler: onSuggestionConfirm, }, { - viewName: "suggestions", - key: gui.getKey(keybindingConfig.Universal.Return), - handler: gui.wrappedConfirmationFunction(opts.HandlersManageFocus, opts.HandleClose), + ViewName: "suggestions", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.Return), + Handler: gui.wrappedConfirmationFunction(opts.HandlersManageFocus, opts.HandleClose), }, { - viewName: "suggestions", - key: gui.getKey(keybindingConfig.Universal.TogglePanel), - handler: func() error { return gui.replaceContext(gui.State.Contexts.Confirmation) }, + ViewName: "suggestions", + Contexts: []string{string(CONFIRMATION_CONTEXT_KEY)}, + Key: gui.getKey(keybindingConfig.Universal.TogglePanel), + Handler: func() error { return gui.replaceContext(gui.State.Contexts.Confirmation) }, }, } - for _, binding := range confirmationKeybindings { - if err := gui.g.SetKeybinding(binding.viewName, nil, binding.key, gocui.ModNone, gui.wrappedHandler(binding.handler)); err != nil { + for _, binding := range bindings { + if err := gui.SetKeybinding(binding); err != nil { return err } } @@ -271,12 +273,6 @@ func (gui *Gui) clearConfirmationViewKeyBindings() { _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone) } -func (gui *Gui) wrappedHandler(f func() error) func(g *gocui.Gui, v *gocui.View) error { - return func(g *gocui.Gui, v *gocui.View) error { - return f() - } -} - func (gui *Gui) refreshSuggestions() { gui.suggestionsAsyncHandler.Do(func() func() { suggestions := gui.findSuggestions(gui.c.GetPromptInput()) diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go new file mode 100644 index 000000000..e95b298a4 --- /dev/null +++ b/pkg/gui/context/base_context.go @@ -0,0 +1,67 @@ +package context + +import "github.com/jesseduffield/lazygit/pkg/gui/types" + +type BaseContext struct { + Kind types.ContextKind + Key types.ContextKey + ViewName string + WindowName string + OnGetOptionsMap func() map[string]string + + *ParentContextMgr +} + +func (self *BaseContext) GetOptionsMap() map[string]string { + if self.OnGetOptionsMap != nil { + return self.OnGetOptionsMap() + } + return nil +} + +func (self *BaseContext) SetWindowName(windowName string) { + self.WindowName = windowName +} + +func (self *BaseContext) GetWindowName() string { + windowName := self.WindowName + + if windowName != "" { + return windowName + } + + // TODO: actually set this for everything so we don't default to the view name + return self.ViewName +} + +func (self *BaseContext) GetViewName() string { + return self.ViewName +} + +func (self *BaseContext) GetKind() types.ContextKind { + return self.Kind +} + +func (self *BaseContext) GetKey() types.ContextKey { + return self.Key +} + +type NewBaseContextOpts struct { + Kind types.ContextKind + Key types.ContextKey + ViewName string + WindowName string + + OnGetOptionsMap func() map[string]string +} + +func NewBaseContext(opts NewBaseContextOpts) *BaseContext { + return &BaseContext{ + Kind: opts.Kind, + Key: opts.Key, + ViewName: opts.ViewName, + WindowName: opts.WindowName, + OnGetOptionsMap: opts.OnGetOptionsMap, + ParentContextMgr: &ParentContextMgr{}, + } +} diff --git a/pkg/gui/context/context.go b/pkg/gui/context/context.go index 67de237ed..30030990f 100644 --- a/pkg/gui/context/context.go +++ b/pkg/gui/context/context.go @@ -10,7 +10,7 @@ type ContextTree struct { Branches types.IListContext Remotes types.IListContext RemoteBranches types.IListContext - Tags types.IListContext + Tags *TagsContext BranchCommits types.IListContext CommitFiles types.IListContext ReflogCommits types.IListContext diff --git a/pkg/gui/context/list_context_trait.go b/pkg/gui/context/list_context_trait.go new file mode 100644 index 000000000..776056fad --- /dev/null +++ b/pkg/gui/context/list_context_trait.go @@ -0,0 +1,231 @@ +package context + +import ( + "fmt" + + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/config" + "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/jesseduffield/lazygit/pkg/utils" +) + +type Thing interface { + // the boolean here tells us whether the item is nil. This is needed because you can't work it out on the calling end once the pointer is wrapped in an interface (unless you want to use reflection) + GetSelectedItem() (types.ListItem, bool) +} + +type ListContextTrait struct { + base types.IBaseContext + thing Thing + listTrait *ListTrait + viewTrait *ViewTrait + + takeFocus func() error + + GetDisplayStrings func(startIdx int, length int) [][]string + OnFocus func(...types.OnFocusOpts) error + OnRenderToMain func(...types.OnFocusOpts) error + OnFocusLost func() error + + // if this is true, we'll call GetDisplayStrings for just the visible part of the + // view and re-render that. This is useful when you need to render different + // content based on the selection (e.g. for showing the selected commit) + RenderSelection bool + + c *types.ControllerCommon +} + +func (self *ListContextTrait) GetPanelState() types.IListPanelState { + return self.listTrait +} + +func (self *ListContextTrait) FocusLine() { + // we need a way of knowing whether we've rendered to the view yet. + self.viewTrait.FocusPoint(self.listTrait.GetSelectedLineIdx()) + if self.RenderSelection { + min, max := self.viewTrait.ViewPortYBounds() + displayStrings := self.GetDisplayStrings(min, max) + content := utils.RenderDisplayStrings(displayStrings) + self.viewTrait.SetViewPortContent(content) + } + self.viewTrait.SetFooter(formatListFooter(self.listTrait.GetSelectedLineIdx(), self.listTrait.GetItemsLength())) +} + +func formatListFooter(selectedLineIdx int, length int) string { + return fmt.Sprintf("%d of %d", selectedLineIdx+1, length) +} + +func (self *ListContextTrait) GetSelectedItemId() string { + item, ok := self.thing.GetSelectedItem() + + if !ok { + return "" + } + + return item.ID() +} + +// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view +func (self *ListContextTrait) HandleRender() error { + if self.GetDisplayStrings != nil { + self.listTrait.RefreshSelectedIdx() + content := utils.RenderDisplayStrings(self.GetDisplayStrings(0, self.listTrait.GetItemsLength())) + self.viewTrait.SetContent(content) + self.c.Render() + } + + return nil +} + +func (self *ListContextTrait) HandleFocusLost() error { + if self.OnFocusLost != nil { + return self.OnFocusLost() + } + + self.viewTrait.SetOriginX(0) + + return nil +} + +func (self *ListContextTrait) HandleFocus(opts ...types.OnFocusOpts) error { + self.FocusLine() + + if self.OnFocus != nil { + if err := self.OnFocus(opts...); err != nil { + return err + } + } + + if self.OnRenderToMain != nil { + if err := self.OnRenderToMain(opts...); err != nil { + return err + } + } + + return nil +} + +func (self *ListContextTrait) HandlePrevLine() error { + return self.handleLineChange(-1) +} + +func (self *ListContextTrait) HandleNextLine() error { + return self.handleLineChange(1) +} + +func (self *ListContextTrait) HandleScrollLeft() error { + return self.scroll(self.viewTrait.ScrollLeft) +} + +func (self *ListContextTrait) HandleScrollRight() error { + return self.scroll(self.viewTrait.ScrollRight) +} + +func (self *ListContextTrait) scroll(scrollFunc func()) error { + scrollFunc() + + return self.HandleFocus() +} + +func (self *ListContextTrait) handleLineChange(change int) error { + before := self.listTrait.GetSelectedLineIdx() + self.listTrait.MoveSelectedLine(change) + after := self.listTrait.GetSelectedLineIdx() + + if before != after { + return self.HandleFocus() + } + + return nil +} + +func (self *ListContextTrait) HandlePrevPage() error { + return self.handleLineChange(-self.viewTrait.PageDelta()) +} + +func (self *ListContextTrait) HandleNextPage() error { + return self.handleLineChange(self.viewTrait.PageDelta()) +} + +func (self *ListContextTrait) HandleGotoTop() error { + return self.handleLineChange(-self.listTrait.GetItemsLength()) +} + +func (self *ListContextTrait) HandleGotoBottom() error { + return self.handleLineChange(self.listTrait.GetItemsLength()) +} + +func (self *ListContextTrait) HandleClick(onClick func() error) error { + prevSelectedLineIdx := self.listTrait.GetSelectedLineIdx() + // because we're handling a click, we need to determine the new line idx based + // on the view itself. + newSelectedLineIdx := self.viewTrait.SelectedLineIdx() + + currentContextKey := self.c.CurrentContext().GetKey() + alreadyFocused := currentContextKey == self.base.GetKey() + + // we need to focus the view + if !alreadyFocused { + + if err := self.takeFocus(); err != nil { + return err + } + } + + if newSelectedLineIdx > self.listTrait.GetItemsLength()-1 { + return nil + } + + self.listTrait.SetSelectedLineIdx(newSelectedLineIdx) + + if prevSelectedLineIdx == newSelectedLineIdx && alreadyFocused && onClick != nil { + return onClick() + } + return self.HandleFocus() +} + +func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error { + self.listTrait.SetSelectedLineIdx(selectedLineIdx) + return self.HandleFocus() +} + +func (self *ListContextTrait) HandleRenderToMain() error { + if self.OnRenderToMain != nil { + return self.OnRenderToMain() + } + + return nil +} + +func (self *ListContextTrait) Keybindings( + getKey func(key string) interface{}, + config config.KeybindingConfig, + guards types.KeybindingGuards, +) []*types.Binding { + return []*types.Binding{ + {Tag: "navigation", Key: getKey(config.Universal.PrevItemAlt), Modifier: gocui.ModNone, Handler: self.HandlePrevLine}, + {Tag: "navigation", Key: getKey(config.Universal.PrevItem), Modifier: gocui.ModNone, Handler: self.HandlePrevLine}, + {Tag: "navigation", Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, Handler: self.HandlePrevLine}, + {Tag: "navigation", Key: getKey(config.Universal.NextItemAlt), Modifier: gocui.ModNone, Handler: self.HandleNextLine}, + {Tag: "navigation", Key: getKey(config.Universal.NextItem), Modifier: gocui.ModNone, Handler: self.HandleNextLine}, + {Tag: "navigation", Key: getKey(config.Universal.PrevPage), Modifier: gocui.ModNone, Handler: self.HandlePrevPage, Description: self.c.Tr.LcPrevPage}, + {Tag: "navigation", Key: getKey(config.Universal.NextPage), Modifier: gocui.ModNone, Handler: self.HandleNextPage, Description: self.c.Tr.LcNextPage}, + {Tag: "navigation", Key: getKey(config.Universal.GotoTop), Modifier: gocui.ModNone, Handler: self.HandleGotoTop, Description: self.c.Tr.LcGotoTop}, + {Key: gocui.MouseLeft, Modifier: gocui.ModNone, Handler: func() error { return self.HandleClick(nil) }}, + {Tag: "navigation", Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, Handler: self.HandleNextLine}, + {Tag: "navigation", Key: getKey(config.Universal.ScrollLeft), Modifier: gocui.ModNone, Handler: self.HandleScrollLeft}, + {Tag: "navigation", Key: getKey(config.Universal.ScrollRight), Modifier: gocui.ModNone, Handler: self.HandleScrollRight}, + { + Key: getKey(config.Universal.StartSearch), + Handler: func() error { self.c.OpenSearch(); return nil }, + Description: self.c.Tr.LcStartSearch, + Tag: "navigation", + }, + { + Key: getKey(config.Universal.GotoBottom), + Description: self.c.Tr.LcGotoBottom, + Handler: self.HandleGotoBottom, + Tag: "navigation", + }, + } +} diff --git a/pkg/gui/context/list_trait.go b/pkg/gui/context/list_trait.go new file mode 100644 index 000000000..27b0b5345 --- /dev/null +++ b/pkg/gui/context/list_trait.go @@ -0,0 +1,32 @@ +package context + +import "github.com/jesseduffield/lazygit/pkg/gui/types" + +type HasLength interface { + GetItemsLength() int +} + +type ListTrait struct { + selectedIdx int + HasLength +} + +var _ types.IListPanelState = (*ListTrait)(nil) + +func (self *ListTrait) GetSelectedLineIdx() int { + return self.selectedIdx +} + +func (self *ListTrait) SetSelectedLineIdx(value int) { + self.selectedIdx = clamp(value, 0, self.GetItemsLength()-1) +} + +// moves the cursor up or down by the given amount +func (self *ListTrait) MoveSelectedLine(value int) { + self.SetSelectedLineIdx(self.selectedIdx + value) +} + +// to be called when the model might have shrunk so that our selection is not not out of bounds +func (self *ListTrait) RefreshSelectedIdx() { + self.SetSelectedLineIdx(self.selectedIdx) +} diff --git a/pkg/gui/context/parent_context_mgr.go b/pkg/gui/context/parent_context_mgr.go new file mode 100644 index 000000000..50747a3a0 --- /dev/null +++ b/pkg/gui/context/parent_context_mgr.go @@ -0,0 +1,20 @@ +package context + +import "github.com/jesseduffield/lazygit/pkg/gui/types" + +type ParentContextMgr struct { + ParentContext types.Context + // we can't know on the calling end whether a Context is actually a nil value without reflection, so we're storing this flag here to tell us. There has got to be a better way around this + hasParent bool +} + +var _ types.ParentContexter = (*ParentContextMgr)(nil) + +func (self *ParentContextMgr) SetParentContext(context types.Context) { + self.ParentContext = context + self.hasParent = true +} + +func (self *ParentContextMgr) GetParentContext() (types.Context, bool) { + return self.ParentContext, self.hasParent +} diff --git a/pkg/gui/context/tags_context.go b/pkg/gui/context/tags_context.go new file mode 100644 index 000000000..f5e7f6cb8 --- /dev/null +++ b/pkg/gui/context/tags_context.go @@ -0,0 +1,107 @@ +package context + +import ( + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type TagsContext struct { + *TagsContextAux + *BaseContext + *ListContextTrait +} + +var _ types.IListContext = (*TagsContext)(nil) + +func NewTagsContext( + getModel func() []*models.Tag, + getView func() *gocui.View, + getDisplayStrings func(startIdx int, length int) [][]string, + + onFocus func(...types.OnFocusOpts) error, + onRenderToMain func(...types.OnFocusOpts) error, + onFocusLost func() error, + + c *types.ControllerCommon, +) *TagsContext { + baseContext := NewBaseContext(NewBaseContextOpts{ + ViewName: "branches", + WindowName: "branches", + Key: TAGS_CONTEXT_KEY, + Kind: types.SIDE_CONTEXT, + }) + + self := &TagsContext{} + takeFocus := func() error { return c.PushContext(self) } + + aux := NewTagsContextAux(getModel) + viewTrait := NewViewTrait(getView) + listContextTrait := &ListContextTrait{ + base: baseContext, + thing: aux, + listTrait: aux.list, + viewTrait: viewTrait, + + GetDisplayStrings: getDisplayStrings, + OnFocus: onFocus, + OnRenderToMain: onRenderToMain, + OnFocusLost: onFocusLost, + takeFocus: takeFocus, + + // TODO: handle this in a trait + RenderSelection: false, + + c: c, + } + + self.BaseContext = baseContext + self.ListContextTrait = listContextTrait + self.TagsContextAux = aux + + return self +} + +type TagsContextAux struct { + list *ListTrait + getModel func() []*models.Tag +} + +func (self *TagsContextAux) GetItemsLength() int { + return len(self.getModel()) +} + +func (self *TagsContextAux) GetSelectedTag() *models.Tag { + if self.GetItemsLength() == 0 { + return nil + } + + return self.getModel()[self.list.GetSelectedLineIdx()] +} + +func (self *TagsContextAux) GetSelectedItem() (types.ListItem, bool) { + tag := self.GetSelectedTag() + return tag, tag != nil +} + +func NewTagsContextAux(getModel func() []*models.Tag) *TagsContextAux { + self := &TagsContextAux{ + getModel: getModel, + } + + self.list = &ListTrait{ + selectedIdx: 0, + HasLength: self, + } + + return self +} + +func clamp(x int, min int, max int) int { + if x < min { + return min + } else if x > max { + return max + } + return x +} diff --git a/pkg/gui/context/view_trait.go b/pkg/gui/context/view_trait.go new file mode 100644 index 000000000..4c02a4990 --- /dev/null +++ b/pkg/gui/context/view_trait.go @@ -0,0 +1,80 @@ +package context + +import ( + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/utils" +) + +const HORIZONTAL_SCROLL_FACTOR = 3 + +type ViewTrait struct { + getView func() *gocui.View +} + +func NewViewTrait(getView func() *gocui.View) *ViewTrait { + return &ViewTrait{getView: getView} +} + +func (self *ViewTrait) FocusPoint(yIdx int) { + view := self.getView() + view.FocusPoint(view.OriginX(), yIdx) +} + +func (self *ViewTrait) SetViewPortContent(content string) { + view := self.getView() + + _, y := view.Origin() + view.OverwriteLines(y, content) +} + +func (self *ViewTrait) SetContent(content string) { + self.getView().SetContent(content) +} + +func (self *ViewTrait) SetFooter(value string) { + self.getView().Footer = value +} + +func (self *ViewTrait) SetOriginX(value int) { + self.getView().SetOriginX(value) +} + +// tells us the bounds of line indexes shown in the view currently +func (self *ViewTrait) ViewPortYBounds() (int, int) { + view := self.getView() + + _, min := view.Origin() + max := view.InnerHeight() + 1 + return min, max +} + +func (self *ViewTrait) ScrollLeft() { + view := self.getView() + + newOriginX := utils.Max(view.OriginX()-view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR, 0) + _ = view.SetOriginX(newOriginX) +} + +func (self *ViewTrait) ScrollRight() { + view := self.getView() + + _ = view.SetOriginX(view.OriginX() + view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR) +} + +// this returns the amount we'll scroll if we want to scroll by a page. +func (self *ViewTrait) PageDelta() int { + view := self.getView() + + _, height := view.Size() + + delta := height - 1 + if delta == 0 { + return 1 + } + + return delta +} + +func (self *ViewTrait) SelectedLineIdx() int { + return self.getView().SelectedLineIdx() +} diff --git a/pkg/gui/context_config.go b/pkg/gui/context_config.go index b27514381..d2903f705 100644 --- a/pkg/gui/context_config.go +++ b/pkg/gui/context_config.go @@ -86,12 +86,17 @@ func (gui *Gui) allContexts() []types.Context { func (gui *Gui) contextTree() context.ContextTree { return context.ContextTree{ - Status: &BasicContext{ - OnRenderToMain: OnFocusWrapper(gui.statusRenderToMain), - Kind: types.SIDE_CONTEXT, - ViewName: "status", - Key: STATUS_CONTEXT_KEY, - }, + Status: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.SIDE_CONTEXT, + ViewName: "status", + Key: STATUS_CONTEXT_KEY, + WindowName: "status", + }), + NewSimpleContextOpts{ + OnRenderToMain: OnFocusWrapper(gui.statusRenderToMain), + }, + ), Files: gui.filesListContext(), Submodules: gui.submodulesListContext(), Menu: gui.menuListContext(), @@ -104,86 +109,130 @@ func (gui *Gui) contextTree() context.ContextTree { Branches: gui.branchesListContext(), Tags: gui.tagsListContext(), Stash: gui.stashListContext(), - Normal: &BasicContext{ - OnFocus: func(opts ...types.OnFocusOpts) error { - return nil // TODO: should we do something here? We should allow for scrolling the panel + Suggestions: gui.suggestionsListContext(), + Normal: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + ViewName: "main", + WindowName: "main", + Key: MAIN_NORMAL_CONTEXT_KEY, + }), + NewSimpleContextOpts{ + OnFocus: func(opts ...types.OnFocusOpts) error { + return nil // TODO: should we do something here? We should allow for scrolling the panel + }, }, - Kind: types.MAIN_CONTEXT, - ViewName: "main", - Key: MAIN_NORMAL_CONTEXT_KEY, - }, - Staging: &BasicContext{ - OnFocus: func(opts ...types.OnFocusOpts) error { - forceSecondaryFocused := false - selectedLineIdx := -1 - if len(opts) > 0 && opts[0].ClickedViewName != "" { - if opts[0].ClickedViewName == "main" || opts[0].ClickedViewName == "secondary" { + ), + Staging: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + ViewName: "main", + WindowName: "main", + Key: MAIN_STAGING_CONTEXT_KEY, + }), + NewSimpleContextOpts{ + OnFocus: func(opts ...types.OnFocusOpts) error { + forceSecondaryFocused := false + selectedLineIdx := -1 + if len(opts) > 0 && opts[0].ClickedViewName != "" { + if opts[0].ClickedViewName == "main" || opts[0].ClickedViewName == "secondary" { + selectedLineIdx = opts[0].ClickedViewLineIdx + } + if opts[0].ClickedViewName == "secondary" { + forceSecondaryFocused = true + } + } + return gui.onStagingFocus(forceSecondaryFocused, selectedLineIdx) + }, + }, + ), + PatchBuilding: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + ViewName: "main", + WindowName: "main", + Key: MAIN_PATCH_BUILDING_CONTEXT_KEY, + }), + NewSimpleContextOpts{ + OnFocus: func(opts ...types.OnFocusOpts) error { + selectedLineIdx := -1 + if len(opts) > 0 && (opts[0].ClickedViewName == "main" || opts[0].ClickedViewName == "secondary") { selectedLineIdx = opts[0].ClickedViewLineIdx } - if opts[0].ClickedViewName == "secondary" { - forceSecondaryFocused = true - } - } - return gui.onStagingFocus(forceSecondaryFocused, selectedLineIdx) - }, - Kind: types.MAIN_CONTEXT, - ViewName: "main", - Key: MAIN_STAGING_CONTEXT_KEY, - }, - PatchBuilding: &BasicContext{ - OnFocus: func(opts ...types.OnFocusOpts) error { - selectedLineIdx := -1 - if len(opts) > 0 && (opts[0].ClickedViewName == "main" || opts[0].ClickedViewName == "secondary") { - selectedLineIdx = opts[0].ClickedViewLineIdx - } - return gui.onPatchBuildingFocus(selectedLineIdx) + return gui.onPatchBuildingFocus(selectedLineIdx) + }, }, - Kind: types.MAIN_CONTEXT, - ViewName: "main", - Key: MAIN_PATCH_BUILDING_CONTEXT_KEY, - }, - Merging: &BasicContext{ - OnFocus: OnFocusWrapper(func() error { return gui.renderConflictsWithLock(true) }), - Kind: types.MAIN_CONTEXT, - ViewName: "main", - Key: MAIN_MERGING_CONTEXT_KEY, - OnGetOptionsMap: gui.getMergingOptions, - }, - Credentials: &BasicContext{ - OnFocus: OnFocusWrapper(gui.handleAskFocused), - Kind: types.PERSISTENT_POPUP, - ViewName: "credentials", - Key: CREDENTIALS_CONTEXT_KEY, - }, - Confirmation: &BasicContext{ - OnFocus: OnFocusWrapper(gui.handleAskFocused), - Kind: types.TEMPORARY_POPUP, - ViewName: "confirmation", - Key: CONFIRMATION_CONTEXT_KEY, - }, - Suggestions: gui.suggestionsListContext(), - CommitMessage: &BasicContext{ - OnFocus: OnFocusWrapper(gui.handleCommitMessageFocused), - Kind: types.PERSISTENT_POPUP, - ViewName: "commitMessage", - Key: COMMIT_MESSAGE_CONTEXT_KEY, - }, - Search: &BasicContext{ - Kind: types.PERSISTENT_POPUP, - ViewName: "search", - Key: SEARCH_CONTEXT_KEY, - }, - CommandLog: &BasicContext{ - Kind: types.EXTRAS_CONTEXT, - ViewName: "extras", - Key: COMMAND_LOG_CONTEXT_KEY, - OnGetOptionsMap: gui.getMergingOptions, - OnFocusLost: func() error { - gui.Views.Extras.Autoscroll = true - return nil + ), + Merging: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + ViewName: "main", + WindowName: "main", + Key: MAIN_MERGING_CONTEXT_KEY, + OnGetOptionsMap: gui.getMergingOptions, + }), + NewSimpleContextOpts{ + OnFocus: OnFocusWrapper(func() error { return gui.renderConflictsWithLock(true) }), }, - }, + ), + Credentials: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.PERSISTENT_POPUP, + ViewName: "credentials", + WindowName: "credentials", + Key: CREDENTIALS_CONTEXT_KEY, + }), + NewSimpleContextOpts{ + OnFocus: OnFocusWrapper(gui.handleAskFocused), + }, + ), + Confirmation: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.TEMPORARY_POPUP, + ViewName: "confirmation", + WindowName: "confirmation", + Key: CONFIRMATION_CONTEXT_KEY, + }), + NewSimpleContextOpts{ + OnFocus: OnFocusWrapper(gui.handleAskFocused), + }, + ), + CommitMessage: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.PERSISTENT_POPUP, + ViewName: "commitMessage", + WindowName: "commitMessage", + Key: COMMIT_MESSAGE_CONTEXT_KEY, + }), + NewSimpleContextOpts{ + OnFocus: OnFocusWrapper(gui.handleCommitMessageFocused), + }, + ), + Search: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.PERSISTENT_POPUP, + ViewName: "search", + WindowName: "search", + Key: SEARCH_CONTEXT_KEY, + }), + NewSimpleContextOpts{}, + ), + CommandLog: NewSimpleContext( + context.NewBaseContext(context.NewBaseContextOpts{ + Kind: types.EXTRAS_CONTEXT, + ViewName: "extras", + WindowName: "extras", + Key: COMMAND_LOG_CONTEXT_KEY, + OnGetOptionsMap: gui.getMergingOptions, + }), + NewSimpleContextOpts{ + OnFocusLost: func() error { + gui.Views.Extras.Autoscroll = true + return nil + }, + }, + ), } } diff --git a/pkg/gui/controllers/bisect_controller.go b/pkg/gui/controllers/bisect_controller.go index 06602a445..8bfcba5a9 100644 --- a/pkg/gui/controllers/bisect_controller.go +++ b/pkg/gui/controllers/bisect_controller.go @@ -8,12 +8,11 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) type BisectController struct { - c *ControllerCommon + c *types.ControllerCommon getContext func() types.IListContext git *commands.GitCommand @@ -24,7 +23,7 @@ type BisectController struct { var _ types.IController = &BisectController{} func NewBisectController( - c *ControllerCommon, + c *types.ControllerCommon, getContext func() types.IListContext, git *commands.GitCommand, @@ -80,7 +79,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c // ref, because we'll be reloading our commits in that case. waitToReselect := selectCurrentAfter && !self.git.Bisect.ReachableFromStart(info) - menuItems := []*popup.MenuItem{ + menuItems := []*types.MenuItem{ { DisplayString: fmt.Sprintf(self.c.Tr.Bisect.Mark, commit.ShortSha(), info.NewTerm()), OnPress: func() error { @@ -122,16 +121,16 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c }, } - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.Bisect.BisectMenuTitle, Items: menuItems, }) } func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo, commit *models.Commit) error { - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.Bisect.BisectMenuTitle, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.NewTerm()), OnPress: func() error { @@ -167,7 +166,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo, } func (self *BisectController) Reset() error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.Bisect.ResetTitle, Prompt: self.c.Tr.Bisect.ResetPrompt, HandleConfirm: func() error { @@ -192,7 +191,7 @@ func (self *BisectController) showBisectCompleteMessage(candidateShas []string) return self.c.Error(err) } - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.Bisect.CompleteTitle, Prompt: fmt.Sprintf(prompt, strings.TrimSpace(formattedCommits)), HandleConfirm: func() error { diff --git a/pkg/gui/controllers/controller_common.go b/pkg/gui/controllers/controller_common.go deleted file mode 100644 index 013439945..000000000 --- a/pkg/gui/controllers/controller_common.go +++ /dev/null @@ -1,10 +0,0 @@ -package controllers - -import "github.com/jesseduffield/lazygit/pkg/common" - -// if Go let me do private struct embedding of structs with public fields (which it should) -// I would just do that. But alas. -type ControllerCommon struct { - *common.Common - IGuiCommon -} diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 8f4641147..e2626078d 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -12,7 +12,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/filetree" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -22,7 +21,7 @@ type FilesController struct { // case I would actually prefer a _zero_ letter variable name in the form of // struct embedding, but Go does not allow hiding public fields in an embedded struct // to the client - c *ControllerCommon + c *types.ControllerCommon getContext func() types.IListContext git *commands.GitCommand os *oscommands.OSCommand @@ -48,7 +47,7 @@ type FilesController struct { var _ types.IController = &FilesController{} func NewFilesController( - c *ControllerCommon, + c *types.ControllerCommon, getContext func() types.IListContext, git *commands.GitCommand, os *oscommands.OSCommand, @@ -344,7 +343,7 @@ func (self *FilesController) ignore(node *filetree.FileNode) error { } if node.GetIsTracked() { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.IgnoreTracked, Prompt: self.c.Tr.IgnoreTrackedPrompt, HandleConfirm: func() error { @@ -461,7 +460,7 @@ func (self *FilesController) HandleCommitPress() error { } func (self *FilesController) promptToStageAllAndRetry(retry func() error) error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.NoFilesStagedTitle, Prompt: self.c.Tr.NoFilesStagedPrompt, HandleConfirm: func() error { @@ -491,7 +490,7 @@ func (self *FilesController) handleAmendCommitPress() error { return self.c.ErrorMsg(self.c.Tr.NoCommitToAmend) } - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: strings.Title(self.c.Tr.AmendLastCommit), Prompt: self.c.Tr.SureToAmend, HandleConfirm: func() error { @@ -520,9 +519,9 @@ func (self *FilesController) HandleCommitEditorPress() error { } func (self *FilesController) handleStatusFilterPressed() error { - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.FilteringMenuTitle, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: self.c.Tr.FilterStagedFiles, OnPress: func() error { @@ -577,7 +576,7 @@ func (self *FilesController) switchToMerge() error { } func (self *FilesController) handleCustomCommand() error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.CustomCommand, FindSuggestionsFunc: self.suggestionsHelper.GetCustomCommandsHistorySuggestionsFunc(), HandleConfirm: func(command string) error { @@ -602,9 +601,9 @@ func (self *FilesController) handleCustomCommand() error { } func (self *FilesController) createStashMenu() error { - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.LcStashOptions, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: self.c.Tr.LcStashAllChanges, OnPress: func() error { @@ -665,7 +664,7 @@ func (self *FilesController) toggleTreeView() error { } func (self *FilesController) OpenMergeTool() error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.MergeToolTitle, Prompt: self.c.Tr.MergeToolPrompt, HandleConfirm: func() error { @@ -704,7 +703,7 @@ func (self *FilesController) handleStashSave(stashFunc func(message string) erro return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash) } - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.StashChanges, HandleConfirm: func(stashComment string) error { if err := stashFunc(stashComment); err != nil { diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 8bc6f5d9e..7b84fe999 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -9,7 +9,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -26,7 +25,7 @@ type ( ) type LocalCommitsController struct { - c *ControllerCommon + c *types.ControllerCommon getContext func() types.IListContext os *oscommands.OSCommand git *commands.GitCommand @@ -50,7 +49,7 @@ type LocalCommitsController struct { var _ types.IController = &LocalCommitsController{} func NewLocalCommitsController( - c *ControllerCommon, + c *types.ControllerCommon, getContext func() types.IListContext, os *oscommands.OSCommand, git *commands.GitCommand, @@ -241,7 +240,7 @@ func (self *LocalCommitsController) squashDown() error { return nil } - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.Squash, Prompt: self.c.Tr.SureSquashThisCommit, HandleConfirm: func() error { @@ -266,7 +265,7 @@ func (self *LocalCommitsController) fixup() error { return nil } - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.Fixup, Prompt: self.c.Tr.SureFixupThisCommit, HandleConfirm: func() error { @@ -293,7 +292,7 @@ func (self *LocalCommitsController) reword(commit *models.Commit) error { } // TODO: use the commit message panel here - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.LcRewordCommit, InitialContent: message, HandleConfirm: func(response string) error { @@ -339,7 +338,7 @@ func (self *LocalCommitsController) drop() error { return nil } - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.DeleteCommitTitle, Prompt: self.c.Tr.DeleteCommitPrompt, HandleConfirm: func() error { @@ -488,7 +487,7 @@ func (self *LocalCommitsController) handleCommitMoveUp() error { } func (self *LocalCommitsController) handleCommitAmendTo() error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.AmendCommitTitle, Prompt: self.c.Tr.AmendCommitPrompt, HandleConfirm: func() error { @@ -505,7 +504,7 @@ func (self *LocalCommitsController) handleCommitRevert(commit *models.Commit) er if commit.IsMerge() { return self.createRevertMergeCommitMenu(commit) } else { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.Actions.RevertCommit, Prompt: utils.ResolvePlaceholderString( self.c.Tr.ConfirmRevertCommit, @@ -524,7 +523,7 @@ func (self *LocalCommitsController) handleCommitRevert(commit *models.Commit) er } func (self *LocalCommitsController) createRevertMergeCommitMenu(commit *models.Commit) error { - menuItems := make([]*popup.MenuItem, len(commit.Parents)) + menuItems := make([]*types.MenuItem, len(commit.Parents)) for i, parentSha := range commit.Parents { i := i message, err := self.git.Commit.GetCommitMessageFirstLine(parentSha) @@ -532,7 +531,7 @@ func (self *LocalCommitsController) createRevertMergeCommitMenu(commit *models.C return self.c.Error(err) } - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayString: fmt.Sprintf("%s: %s", utils.SafeTruncate(parentSha, 8), message), OnPress: func() error { parentNumber := i + 1 @@ -545,7 +544,7 @@ func (self *LocalCommitsController) createRevertMergeCommitMenu(commit *models.C } } - return self.c.Menu(popup.CreateMenuOptions{Title: self.c.Tr.SelectParentCommitForMerge, Items: menuItems}) + return self.c.Menu(types.CreateMenuOptions{Title: self.c.Tr.SelectParentCommitForMerge, Items: menuItems}) } func (self *LocalCommitsController) afterRevertCommit() error { @@ -572,7 +571,7 @@ func (self *LocalCommitsController) handleCreateFixupCommit(commit *models.Commi }, ) - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.CreateFixupCommit, Prompt: prompt, HandleConfirm: func() error { @@ -594,7 +593,7 @@ func (self *LocalCommitsController) handleSquashAllAboveFixupCommits(commit *mod }, ) - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.SquashAboveCommits, Prompt: prompt, HandleConfirm: func() error { @@ -612,7 +611,7 @@ func (self *LocalCommitsController) handleTagCommit(commit *models.Commit) error } func (self *LocalCommitsController) handleCheckoutCommit(commit *models.Commit) error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.LcCheckoutCommit, Prompt: self.c.Tr.SureCheckoutThisCommit, HandleConfirm: func() error { @@ -669,9 +668,9 @@ func (self *LocalCommitsController) handleCopySelectedCommitMessageToClipboard(c } func (self *LocalCommitsController) handleOpenLogMenu() error { - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.LogMenuTitle, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: self.c.Tr.ToggleShowGitGraphAll, OnPress: func() error { @@ -696,9 +695,9 @@ func (self *LocalCommitsController) handleOpenLogMenu() error { return nil } } - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.LogMenuTitle, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: "always", OnPress: onPress("always"), @@ -728,9 +727,9 @@ func (self *LocalCommitsController) handleOpenLogMenu() error { } } - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.LogMenuTitle, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: "topological (topo-order)", OnPress: onPress("topo-order"), diff --git a/pkg/gui/controllers/menu_controller.go b/pkg/gui/controllers/menu_controller.go index fe545657b..e03666ad5 100644 --- a/pkg/gui/controllers/menu_controller.go +++ b/pkg/gui/controllers/menu_controller.go @@ -3,23 +3,22 @@ package controllers import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) type MenuController struct { - c *ControllerCommon + c *types.ControllerCommon getContext func() types.IListContext - getSelectedMenuItem func() *popup.MenuItem + getSelectedMenuItem func() *types.MenuItem } var _ types.IController = &MenuController{} func NewMenuController( - c *ControllerCommon, + c *types.ControllerCommon, getContext func() types.IListContext, - getSelectedMenuItem func() *popup.MenuItem, + getSelectedMenuItem func() *types.MenuItem, ) *MenuController { return &MenuController{ c: c, diff --git a/pkg/gui/controllers/remotes_controller.go b/pkg/gui/controllers/remotes_controller.go index c14f3e5ba..bc91f40e7 100644 --- a/pkg/gui/controllers/remotes_controller.go +++ b/pkg/gui/controllers/remotes_controller.go @@ -6,13 +6,12 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/context" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) type RemotesController struct { - c *ControllerCommon + c *types.ControllerCommon getContext func() types.IListContext git *commands.GitCommand @@ -24,7 +23,7 @@ type RemotesController struct { var _ types.IController = &RemotesController{} func NewRemotesController( - c *ControllerCommon, + c *types.ControllerCommon, getContext func() types.IListContext, git *commands.GitCommand, getContexts func() context.ContextTree, @@ -90,10 +89,10 @@ func (self *RemotesController) enter(remote *models.Remote) error { } func (self *RemotesController) add() error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.LcNewRemoteName, HandleConfirm: func(remoteName string) error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.LcNewRemoteUrl, HandleConfirm: func(remoteUrl string) error { self.c.LogAction(self.c.Tr.Actions.AddRemote) @@ -108,7 +107,7 @@ func (self *RemotesController) add() error { } func (self *RemotesController) remove(remote *models.Remote) error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.LcRemoveRemote, Prompt: self.c.Tr.LcRemoveRemotePrompt + " '" + remote.Name + "'?", HandleConfirm: func() error { @@ -130,7 +129,7 @@ func (self *RemotesController) edit(remote *models.Remote) error { }, ) - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: editNameMessage, InitialContent: remote.Name, HandleConfirm: func(updatedRemoteName string) error { @@ -154,7 +153,7 @@ func (self *RemotesController) edit(remote *models.Remote) error { url = urls[0] } - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: editUrlMessage, InitialContent: url, HandleConfirm: func(updatedRemoteUrl string) error { diff --git a/pkg/gui/controllers/submodules_controller.go b/pkg/gui/controllers/submodules_controller.go index a380154ae..851d11983 100644 --- a/pkg/gui/controllers/submodules_controller.go +++ b/pkg/gui/controllers/submodules_controller.go @@ -9,13 +9,12 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" ) type SubmodulesController struct { - c *ControllerCommon + c *types.ControllerCommon context types.IListContext git *commands.GitCommand @@ -26,7 +25,7 @@ type SubmodulesController struct { var _ types.IController = &SubmodulesController{} func NewSubmodulesController( - c *ControllerCommon, + c *types.ControllerCommon, context types.IListContext, git *commands.GitCommand, enterSubmodule func(submodule *models.SubmoduleConfig) error, @@ -93,17 +92,17 @@ func (self *SubmodulesController) enter(submodule *models.SubmoduleConfig) error } func (self *SubmodulesController) add() error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.LcNewSubmoduleUrl, HandleConfirm: func(submoduleUrl string) error { nameSuggestion := filepath.Base(strings.TrimSuffix(submoduleUrl, filepath.Ext(submoduleUrl))) - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.LcNewSubmoduleName, InitialContent: nameSuggestion, HandleConfirm: func(submoduleName string) error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.LcNewSubmodulePath, InitialContent: submoduleName, HandleConfirm: func(submodulePath string) error { @@ -125,7 +124,7 @@ func (self *SubmodulesController) add() error { } func (self *SubmodulesController) editURL(submodule *models.SubmoduleConfig) error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: fmt.Sprintf(self.c.Tr.LcUpdateSubmoduleUrl, submodule.Name), InitialContent: submodule.Url, HandleConfirm: func(newUrl string) error { @@ -155,9 +154,9 @@ func (self *SubmodulesController) init(submodule *models.SubmoduleConfig) error } func (self *SubmodulesController) openBulkActionsMenu() error { - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.LcBulkSubmoduleOptions, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayStrings: []string{self.c.Tr.LcBulkInitSubmodules, style.FgGreen.Sprint(self.git.Submodule.BulkInitCmdObj().ToString())}, OnPress: func() error { @@ -215,7 +214,7 @@ func (self *SubmodulesController) update(submodule *models.SubmoduleConfig) erro } func (self *SubmodulesController) remove(submodule *models.SubmoduleConfig) error { - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.RemoveSubmodule, Prompt: fmt.Sprintf(self.c.Tr.RemoveSubmodulePrompt, submodule.Name), HandleConfirm: func() error { diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index a2fda53a1..e84e3f731 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -8,7 +8,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -17,7 +16,7 @@ type SyncController struct { // case I would actually prefer a _zero_ letter variable name in the form of // struct embedding, but Go does not allow hiding public fields in an embedded struct // to the client - c *ControllerCommon + c *types.ControllerCommon git *commands.GitCommand getCheckedOutBranch func() *models.Branch @@ -29,7 +28,7 @@ type SyncController struct { var _ types.IController = &SyncController{} func NewSyncController( - c *ControllerCommon, + c *types.ControllerCommon, git *commands.GitCommand, getCheckedOutBranch func() *models.Branch, suggestionsHelper ISuggestionsHelper, @@ -160,7 +159,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error { func (self *SyncController) promptForUpstream(currentBranch *models.Branch, onConfirm func(string) error) error { suggestedRemote := self.getSuggestedRemote() - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.EnterUpstream, InitialContent: suggestedRemote + " " + currentBranch.Name, FindSuggestionsFunc: self.suggestionsHelper.GetRemoteBranchesSuggestionsFunc(" "), @@ -219,7 +218,7 @@ func (self *SyncController) pushAux(opts pushOpts) error { _ = self.c.ErrorMsg(self.c.Tr.UpdatesRejectedAndForcePushDisabled) return nil } - _ = self.c.Ask(popup.AskOpts{ + _ = self.c.Ask(types.AskOpts{ Title: self.c.Tr.ForcePush, Prompt: self.c.Tr.ForcePushPrompt, HandleConfirm: func() error { @@ -243,7 +242,7 @@ func (self *SyncController) requestToForcePush(opts pushOpts) error { return self.c.ErrorMsg(self.c.Tr.ForcePushDisabled) } - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.ForcePush, Prompt: self.c.Tr.ForcePushPrompt, HandleConfirm: func() error { diff --git a/pkg/gui/controllers/tags_controller.go b/pkg/gui/controllers/tags_controller.go index a8a60f8b8..c9967c2e2 100644 --- a/pkg/gui/controllers/tags_controller.go +++ b/pkg/gui/controllers/tags_controller.go @@ -5,35 +5,32 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/context" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) type TagsController struct { - c *ControllerCommon - getContext func() types.IListContext + c *types.ControllerCommon + getContext func() *context.TagsContext git *commands.GitCommand getContexts func() context.ContextTree refHelper IRefHelper suggestionsHelper ISuggestionsHelper - getSelectedTag func() *models.Tag switchToSubCommitsContext func(string) error } var _ types.IController = &TagsController{} func NewTagsController( - c *ControllerCommon, - getContext func() types.IListContext, + c *types.ControllerCommon, + getContext func() *context.TagsContext, git *commands.GitCommand, getContexts func() context.ContextTree, refHelper IRefHelper, suggestionsHelper ISuggestionsHelper, - getSelectedTag func() *models.Tag, switchToSubCommitsContext func(string) error, ) *TagsController { return &TagsController{ @@ -44,7 +41,6 @@ func NewTagsController( refHelper: refHelper, suggestionsHelper: suggestionsHelper, - getSelectedTag: getSelectedTag, switchToSubCommitsContext: switchToSubCommitsContext, } } @@ -107,7 +103,7 @@ func (self *TagsController) delete(tag *models.Tag) error { }, ) - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.DeleteTagTitle, Prompt: prompt, HandleConfirm: func() error { @@ -128,7 +124,7 @@ func (self *TagsController) push(tag *models.Tag) error { }, ) - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: title, InitialContent: "origin", FindSuggestionsFunc: self.suggestionsHelper.GetRemoteSuggestionsFunc(), @@ -151,9 +147,9 @@ func (self *TagsController) createResetMenu(tag *models.Tag) error { } func (self *TagsController) CreateTagMenu(commitSha string) error { - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.TagMenuTitle, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: self.c.Tr.LcLightweightTag, OnPress: func() error { @@ -178,10 +174,10 @@ func (self *TagsController) afterTagCreate() error { } func (self *TagsController) handleCreateAnnotatedTag(commitSha string) error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.TagNameTitle, HandleConfirm: func(tagName string) error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.TagMessageTitle, HandleConfirm: func(msg string) error { self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag) @@ -196,7 +192,7 @@ func (self *TagsController) handleCreateAnnotatedTag(commitSha string) error { } func (self *TagsController) handleCreateLightweightTag(commitSha string) error { - return self.c.Prompt(popup.PromptOpts{ + return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.TagNameTitle, HandleConfirm: func(tagName string) error { self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag) @@ -215,7 +211,7 @@ func (self *TagsController) create() error { func (self *TagsController) withSelectedTag(f func(tag *models.Tag) error) func() error { return func() error { - tag := self.getSelectedTag() + tag := self.getContext().GetSelectedTag() if tag == nil { return nil } diff --git a/pkg/gui/controllers/types.go b/pkg/gui/controllers/types.go index 21f774944..19e3769a5 100644 --- a/pkg/gui/controllers/types.go +++ b/pkg/gui/controllers/types.go @@ -2,31 +2,9 @@ package controllers import ( "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/commands/oscommands" - "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) -type IGuiCommon interface { - popup.IPopupHandler - - LogAction(action string) - LogCommand(cmdStr string, isCommandLine bool) - // we call this when we want to refetch some models and render the result. Internally calls PostRefreshUpdate - Refresh(types.RefreshOptions) error - // we call this when we've changed something in the view model but not the actual model, - // e.g. expanding or collapsing a folder in a file view. Calling 'Refresh' in this - // case would be overkill, although refresh will internally call 'PostRefreshUpdate' - PostRefreshUpdate(types.Context) error - RunSubprocessAndRefresh(oscommands.ICmdObj) error - PushContext(context types.Context, opts ...types.OnFocusOpts) error - PopContext() error - - GetAppState() *config.AppState - SaveAppState() error -} - type IRefHelper interface { CheckoutRef(ref string, options types.CheckoutRefOptions) error CreateGitResetMenu(ref string) error diff --git a/pkg/gui/controllers/undo_controller.go b/pkg/gui/controllers/undo_controller.go index 984b8e1a6..571be4251 100644 --- a/pkg/gui/controllers/undo_controller.go +++ b/pkg/gui/controllers/undo_controller.go @@ -5,7 +5,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -21,7 +20,7 @@ import ( // two user actions, meaning we end up undoing reflog entry C. Redoing works in a similar way. type UndoController struct { - c *ControllerCommon + c *types.ControllerCommon git *commands.GitCommand refHelper IRefHelper @@ -33,7 +32,7 @@ type UndoController struct { var _ types.IController = &UndoController{} func NewUndoController( - c *ControllerCommon, + c *types.ControllerCommon, git *commands.GitCommand, refHelper IRefHelper, workingTreeHelper IWorkingTreeHelper, @@ -235,7 +234,7 @@ func (self *UndoController) hardResetWithAutoStash(commitSha string, options har dirtyWorkingTree := self.workingTreeHelper.IsWorkingTreeDirty() if dirtyWorkingTree { // offer to autostash changes - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.AutoStashTitle, Prompt: self.c.Tr.AutoStashPrompt, HandleConfirm: func() error { diff --git a/pkg/gui/custom_commands.go b/pkg/gui/custom_commands.go index 3470797a3..351ee46e9 100644 --- a/pkg/gui/custom_commands.go +++ b/pkg/gui/custom_commands.go @@ -12,7 +12,6 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" @@ -49,7 +48,7 @@ func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (s SelectedLocalBranch: gui.getSelectedBranch(), SelectedRemoteBranch: gui.getSelectedRemoteBranch(), SelectedRemote: gui.getSelectedRemote(), - SelectedTag: gui.getSelectedTag(), + SelectedTag: gui.State.Contexts.Tags.GetSelectedTag(), SelectedStashEntry: gui.getSelectedStashEntry(), SelectedCommitFile: gui.getSelectedCommitFile(), SelectedCommitFilePath: gui.getSelectedCommitFilePath(), @@ -72,7 +71,7 @@ func (gui *Gui) inputPrompt(prompt config.CustomCommandPrompt, promptResponses [ return gui.c.Error(err) } - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: title, InitialContent: initialValue, HandleConfirm: func(str string) error { @@ -84,7 +83,7 @@ func (gui *Gui) inputPrompt(prompt config.CustomCommandPrompt, promptResponses [ func (gui *Gui) menuPrompt(prompt config.CustomCommandPrompt, promptResponses []string, responseIdx int, wrappedF func() error) error { // need to make a menu here some how - menuItems := make([]*popup.MenuItem, len(prompt.Options)) + menuItems := make([]*types.MenuItem, len(prompt.Options)) for i, option := range prompt.Options { option := option @@ -108,7 +107,7 @@ func (gui *Gui) menuPrompt(prompt config.CustomCommandPrompt, promptResponses [] return gui.c.Error(err) } - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayStrings: []string{name, style.FgYellow.Sprint(description)}, OnPress: func() error { promptResponses[responseIdx] = value @@ -122,7 +121,7 @@ func (gui *Gui) menuPrompt(prompt config.CustomCommandPrompt, promptResponses [] return gui.c.Error(err) } - return gui.c.Menu(popup.CreateMenuOptions{Title: title, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems}) } func (gui *Gui) GenerateMenuCandidates(commandOutput, filter, valueFormat, labelFormat string) ([]commandMenuEntry, error) { @@ -216,10 +215,10 @@ func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptR return gui.c.Error(err) } - menuItems := make([]*popup.MenuItem, len(candidates)) + menuItems := make([]*types.MenuItem, len(candidates)) for i := range candidates { i := i - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayStrings: []string{candidates[i].label}, OnPress: func() error { promptResponses[responseIdx] = candidates[i].value @@ -233,7 +232,7 @@ func (gui *Gui) menuPromptFromCommand(prompt config.CustomCommandPrompt, promptR return gui.c.Error(err) } - return gui.c.Menu(popup.CreateMenuOptions{Title: title, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems}) } func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand) func() error { diff --git a/pkg/gui/diffing.go b/pkg/gui/diffing.go index 2408cc79f..0448e3147 100644 --- a/pkg/gui/diffing.go +++ b/pkg/gui/diffing.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/gui/modes/diffing" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -107,10 +106,10 @@ func (gui *Gui) diffStr() string { func (gui *Gui) handleCreateDiffingMenuPanel() error { names := gui.currentDiffTerminals() - menuItems := []*popup.MenuItem{} + menuItems := []*types.MenuItem{} for _, name := range names { name := name - menuItems = append(menuItems, []*popup.MenuItem{ + menuItems = append(menuItems, []*types.MenuItem{ { DisplayString: fmt.Sprintf("%s %s", gui.c.Tr.LcDiff, name), OnPress: func() error { @@ -122,11 +121,11 @@ func (gui *Gui) handleCreateDiffingMenuPanel() error { }...) } - menuItems = append(menuItems, []*popup.MenuItem{ + menuItems = append(menuItems, []*types.MenuItem{ { DisplayString: gui.c.Tr.LcEnterRefToDiff, OnPress: func() error { - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: gui.c.Tr.LcEnteRefName, FindSuggestionsFunc: gui.suggestionsHelper.GetRefsSuggestionsFunc(), HandleConfirm: func(response string) error { @@ -139,7 +138,7 @@ func (gui *Gui) handleCreateDiffingMenuPanel() error { }...) if gui.State.Modes.Diffing.Active() { - menuItems = append(menuItems, []*popup.MenuItem{ + menuItems = append(menuItems, []*types.MenuItem{ { DisplayString: gui.c.Tr.LcSwapDiff, OnPress: func() error { @@ -157,5 +156,5 @@ func (gui *Gui) handleCreateDiffingMenuPanel() error { }...) } - return gui.c.Menu(popup.CreateMenuOptions{Title: gui.c.Tr.DiffingMenuTitle, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: gui.c.Tr.DiffingMenuTitle, Items: menuItems}) } diff --git a/pkg/gui/discard_changes_menu_panel.go b/pkg/gui/discard_changes_menu_panel.go index 473a4611f..5da349314 100644 --- a/pkg/gui/discard_changes_menu_panel.go +++ b/pkg/gui/discard_changes_menu_panel.go @@ -1,7 +1,6 @@ package gui import ( - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -11,9 +10,9 @@ func (gui *Gui) handleCreateDiscardMenu() error { return nil } - var menuItems []*popup.MenuItem + var menuItems []*types.MenuItem if node.File == nil { - menuItems = []*popup.MenuItem{ + menuItems = []*types.MenuItem{ { DisplayString: gui.c.Tr.LcDiscardAllChanges, OnPress: func() error { @@ -27,7 +26,7 @@ func (gui *Gui) handleCreateDiscardMenu() error { } if node.GetHasStagedChanges() && node.GetHasUnstagedChanges() { - menuItems = append(menuItems, &popup.MenuItem{ + menuItems = append(menuItems, &types.MenuItem{ DisplayString: gui.c.Tr.LcDiscardUnstagedChanges, OnPress: func() error { gui.c.LogAction(gui.c.Tr.Actions.DiscardUnstagedChangesInDirectory) @@ -46,7 +45,7 @@ func (gui *Gui) handleCreateDiscardMenu() error { if file.IsSubmodule(submodules) { submodule := file.SubmoduleConfig(submodules) - menuItems = []*popup.MenuItem{ + menuItems = []*types.MenuItem{ { DisplayString: gui.c.Tr.LcSubmoduleStashAndReset, OnPress: func() error { @@ -55,7 +54,7 @@ func (gui *Gui) handleCreateDiscardMenu() error { }, } } else { - menuItems = []*popup.MenuItem{ + menuItems = []*types.MenuItem{ { DisplayString: gui.c.Tr.LcDiscardAllChanges, OnPress: func() error { @@ -69,7 +68,7 @@ func (gui *Gui) handleCreateDiscardMenu() error { } if file.HasStagedChanges && file.HasUnstagedChanges { - menuItems = append(menuItems, &popup.MenuItem{ + menuItems = append(menuItems, &types.MenuItem{ DisplayString: gui.c.Tr.LcDiscardUnstagedChanges, OnPress: func() error { gui.c.LogAction(gui.c.Tr.Actions.DiscardAllUnstagedChangesInFile) @@ -84,5 +83,5 @@ func (gui *Gui) handleCreateDiscardMenu() error { } } - return gui.c.Menu(popup.CreateMenuOptions{Title: node.GetPath(), Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: node.GetPath(), Items: menuItems}) } diff --git a/pkg/gui/extras_panel.go b/pkg/gui/extras_panel.go index fd2998cb3..8b6789128 100644 --- a/pkg/gui/extras_panel.go +++ b/pkg/gui/extras_panel.go @@ -3,14 +3,14 @@ package gui import ( "io" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) handleCreateExtrasMenuPanel() error { - return gui.c.Menu(popup.CreateMenuOptions{ + return gui.c.Menu(types.CreateMenuOptions{ Title: gui.c.Tr.CommandLog, - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { DisplayString: gui.c.Tr.ToggleShowCommandLog, OnPress: func() error { diff --git a/pkg/gui/file_helper.go b/pkg/gui/file_helper.go index 1b50aac82..adf0e4dd0 100644 --- a/pkg/gui/file_helper.go +++ b/pkg/gui/file_helper.go @@ -4,16 +4,17 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/gui/controllers" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) type FileHelper struct { - c *controllers.ControllerCommon + c *types.ControllerCommon git *commands.GitCommand os *oscommands.OSCommand } func NewFileHelper( - c *controllers.ControllerCommon, + c *types.ControllerCommon, git *commands.GitCommand, os *oscommands.OSCommand, ) *FileHelper { diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 9c0fbd24e..4e2e062bd 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -7,7 +7,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -252,7 +251,7 @@ func (gui *Gui) refreshStateFiles() error { func (gui *Gui) promptToContinueRebase() error { gui.takeOverMergeConflictScrolling() - return gui.PopupHandler.Ask(popup.AskOpts{ + return gui.PopupHandler.Ask(types.AskOpts{ Title: "continue", Prompt: gui.Tr.ConflictsResolved, HandleConfirm: func() error { diff --git a/pkg/gui/filtering.go b/pkg/gui/filtering.go index df4fa848d..6d75b2e77 100644 --- a/pkg/gui/filtering.go +++ b/pkg/gui/filtering.go @@ -1,13 +1,12 @@ package gui import ( - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) validateNotInFilterMode() bool { if gui.State.Modes.Filtering.Active() { - _ = gui.c.Ask(popup.AskOpts{ + _ = gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.MustExitFilterModeTitle, Prompt: gui.c.Tr.MustExitFilterModePrompt, HandleConfirm: gui.exitFilterMode, diff --git a/pkg/gui/filtering_menu_panel.go b/pkg/gui/filtering_menu_panel.go index 39d39765e..71201859f 100644 --- a/pkg/gui/filtering_menu_panel.go +++ b/pkg/gui/filtering_menu_panel.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/jesseduffield/lazygit/pkg/gui/popup" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) handleCreateFilteringMenuPanel() error { @@ -22,10 +22,10 @@ func (gui *Gui) handleCreateFilteringMenuPanel() error { } } - menuItems := []*popup.MenuItem{} + menuItems := []*types.MenuItem{} if fileName != "" { - menuItems = append(menuItems, &popup.MenuItem{ + menuItems = append(menuItems, &types.MenuItem{ DisplayString: fmt.Sprintf("%s '%s'", gui.c.Tr.LcFilterBy, fileName), OnPress: func() error { return gui.setFiltering(fileName) @@ -33,10 +33,10 @@ func (gui *Gui) handleCreateFilteringMenuPanel() error { }) } - menuItems = append(menuItems, &popup.MenuItem{ + menuItems = append(menuItems, &types.MenuItem{ DisplayString: gui.c.Tr.LcFilterPathOption, OnPress: func() error { - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ FindSuggestionsFunc: gui.suggestionsHelper.GetFilePathSuggestionsFunc(), Title: gui.c.Tr.EnterFileName, HandleConfirm: func(response string) error { @@ -47,11 +47,11 @@ func (gui *Gui) handleCreateFilteringMenuPanel() error { }) if gui.State.Modes.Filtering.Active() { - menuItems = append(menuItems, &popup.MenuItem{ + menuItems = append(menuItems, &types.MenuItem{ DisplayString: gui.c.Tr.LcExitFilterMode, OnPress: gui.clearFiltering, }) } - return gui.c.Menu(popup.CreateMenuOptions{Title: gui.c.Tr.FilteringMenuTitle, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: gui.c.Tr.FilteringMenuTitle, Items: menuItems}) } diff --git a/pkg/gui/git_flow.go b/pkg/gui/git_flow.go index 171310785..eecd5328c 100644 --- a/pkg/gui/git_flow.go +++ b/pkg/gui/git_flow.go @@ -3,7 +3,7 @@ package gui import ( "fmt" - "github.com/jesseduffield/lazygit/pkg/gui/popup" + "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -21,7 +21,7 @@ func (gui *Gui) handleCreateGitFlowMenu() error { return func() error { title := utils.ResolvePlaceholderString(gui.c.Tr.NewGitFlowBranchPrompt, map[string]string{"branchType": branchType}) - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: title, HandleConfirm: func(name string) error { gui.c.LogAction(gui.c.Tr.Actions.GitFlowStart) @@ -33,9 +33,9 @@ func (gui *Gui) handleCreateGitFlowMenu() error { } } - return gui.c.Menu(popup.CreateMenuOptions{ + return gui.c.Menu(types.CreateMenuOptions{ Title: "git flow", - Items: []*popup.MenuItem{ + Items: []*types.MenuItem{ { // not localising here because it's one to one with the actual git flow commands DisplayString: fmt.Sprintf("finish branch '%s'", branch.Name), diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index fa2b3e256..c11820ec6 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -124,7 +124,7 @@ type Gui struct { suggestionsAsyncHandler *tasks.AsyncHandler - PopupHandler popup.IPopupHandler + PopupHandler types.IPopupHandler IsNewRepo bool @@ -143,7 +143,7 @@ type Gui struct { PrevLayout PrevLayout - c *controllers.ControllerCommon + c *types.ControllerCommon refHelper *RefHelper suggestionsHelper *SuggestionsHelper fileHelper *FileHelper @@ -189,7 +189,7 @@ type GuiRepoState struct { // Suggestions will sometimes appear when typing into a prompt Suggestions []*types.Suggestion - MenuItems []*popup.MenuItem + MenuItems []*types.MenuItem BisectInfo *git_commands.BisectInfo Updating bool Panels *panelStates @@ -284,10 +284,6 @@ type remoteBranchesState struct { listPanelState } -type tagsPanelState struct { - listPanelState -} - type commitPanelState struct { listPanelState @@ -336,7 +332,6 @@ type panelStates struct { Branches *branchPanelState Remotes *remotePanelState RemoteBranches *remoteBranchesState - Tags *tagsPanelState Commits *commitPanelState ReflogCommits *reflogCommitPanelState SubCommits *subCommitPanelState @@ -453,7 +448,6 @@ func (gui *Gui) resetState(filterPath string, reuseState bool) { Branches: &branchPanelState{listPanelState{SelectedLineIdx: 0}}, Remotes: &remotePanelState{listPanelState{SelectedLineIdx: 0}}, RemoteBranches: &remoteBranchesState{listPanelState{SelectedLineIdx: -1}}, - Tags: &tagsPanelState{listPanelState{SelectedLineIdx: -1}}, Commits: &commitPanelState{listPanelState: listPanelState{SelectedLineIdx: 0}, LimitCommits: true}, ReflogCommits: &reflogCommitPanelState{listPanelState{SelectedLineIdx: 0}}, SubCommits: &subCommitPanelState{listPanelState: listPanelState{SelectedLineIdx: 0}, refName: ""}, @@ -557,7 +551,7 @@ func NewGui( ) guiCommon := &guiCommon{gui: gui, IPopupHandler: gui.PopupHandler} - controllerCommon := &controllers.ControllerCommon{IGuiCommon: guiCommon, Common: cmn} + controllerCommon := &types.ControllerCommon{IGuiCommon: guiCommon, Common: cmn} // storing this stuff on the gui for now to ease refactoring // TODO: reset these controllers upon changing repos due to state changing @@ -589,12 +583,11 @@ func (gui *Gui) setControllers() { tagsController := controllers.NewTagsController( controllerCommon, - func() types.IListContext { return gui.State.Contexts.Tags }, + func() *context.TagsContext { return gui.State.Contexts.Tags }, gui.git, getContexts, refHelper, gui.suggestionsHelper, - gui.getSelectedTag, gui.switchToSubCommitsContext, ) @@ -921,7 +914,7 @@ func (gui *Gui) showIntroPopupMessage(done chan struct{}) error { return gui.c.SaveAppState() } - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: "", Prompt: gui.c.Tr.IntroPopupMessage, HandleConfirm: onConfirm, @@ -956,7 +949,7 @@ func (gui *Gui) startBackgroundFetch() { } err := gui.backgroundFetch() if err != nil && strings.Contains(err.Error(), "exit status 128") && isNew { - _ = gui.c.Ask(popup.AskOpts{ + _ = gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.NoAutomaticGitFetchTitle, Prompt: gui.c.Tr.NoAutomaticGitFetchBody, }) diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index 8db398489..ba9540178 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -3,18 +3,16 @@ package gui import ( "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/controllers" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) // hacking this by including the gui struct for now until we split more things out type guiCommon struct { gui *Gui - popup.IPopupHandler + types.IPopupHandler } -var _ controllers.IGuiCommon = &guiCommon{} +var _ types.IGuiCommon = &guiCommon{} func (self *guiCommon) LogAction(msg string) { self.gui.LogAction(msg) @@ -44,6 +42,10 @@ func (self *guiCommon) PopContext() error { return self.gui.returnFromContext() } +func (self *guiCommon) CurrentContext() types.Context { + return self.gui.currentContext() +} + func (self *guiCommon) GetAppState() *config.AppState { return self.gui.Config.GetAppState() } @@ -51,3 +53,11 @@ func (self *guiCommon) GetAppState() *config.AppState { func (self *guiCommon) SaveAppState() error { return self.gui.Config.SaveAppState() } + +func (self *guiCommon) Render() { + self.gui.render() +} + +func (self *guiCommon) OpenSearch() { + _ = self.gui.handleOpenSearch(self.gui.currentViewName()) +} diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 0e09022c5..b9197d1b4 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -1492,7 +1492,7 @@ func (gui *Gui) keybindings() error { bindings = append(bindings, gui.GetInitialKeybindings()...) for _, binding := range bindings { - if err := gui.g.SetKeybinding(binding.ViewName, binding.Contexts, binding.Key, binding.Modifier, gui.wrappedHandler(binding.Handler)); err != nil { + if err := gui.SetKeybinding(binding); err != nil { return err } } @@ -1508,3 +1508,29 @@ func (gui *Gui) keybindings() error { return nil } + +func (gui *Gui) wrappedHandler(f func() error) func(g *gocui.Gui, v *gocui.View) error { + return func(g *gocui.Gui, v *gocui.View) error { + return f() + } +} + +func (gui *Gui) SetKeybinding(binding *types.Binding) error { + handler := binding.Handler + if isMouseKey(binding.Key) { + handler = func() error { + // we ignore click events on views that aren't popup panels, when a popup panel is focused + if gui.popupPanelFocused() && gui.currentViewName() != binding.ViewName { + return nil + } + + return binding.Handler() + } + } + + return gui.g.SetKeybinding(binding.ViewName, binding.Contexts, binding.Key, binding.Modifier, gui.wrappedHandler(handler)) +} + +func isMouseKey(key interface{}) bool { + return key == gocui.MouseLeft || key == gocui.MouseRight || key == gocui.MouseMiddle || key == gocui.MouseRelease || key == gocui.MouseWheelUp || key == gocui.MouseWheelDown || key == gocui.MouseWheelLeft || key == gocui.MouseWheelRight +} diff --git a/pkg/gui/list_context.go b/pkg/gui/list_context.go index e94967ff4..6841dc569 100644 --- a/pkg/gui/list_context.go +++ b/pkg/gui/list_context.go @@ -5,6 +5,7 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/config" + "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -25,7 +26,7 @@ type ListContext struct { Gui *Gui - *BasicContext + *context.BaseContext } var _ types.IListContext = &ListContext{} @@ -46,7 +47,7 @@ func (self *ListContext) FocusLine() { if self.RenderSelection { _, originY := view.Origin() displayStrings := self.GetDisplayStrings(originY, view.InnerHeight()+1) - self.Gui.renderDisplayStringsAtPos(view, originY, displayStrings) + self.Gui.renderDisplayStringsInViewPort(view, displayStrings) } view.Footer = formatListFooter(self.GetPanelState().GetSelectedLineIdx(), self.GetItemsLength()) } @@ -101,16 +102,8 @@ func (self *ListContext) HandleFocusLost() error { } func (self *ListContext) HandleFocus(opts ...types.OnFocusOpts) error { - if self.Gui.popupPanelFocused() { - return nil - } - self.FocusLine() - if self.Gui.State.Modes.Diffing.Active() { - return self.Gui.renderDiff() - } - if self.OnFocus != nil { if err := self.OnFocus(opts...); err != nil { return err diff --git a/pkg/gui/list_context_config.go b/pkg/gui/list_context_config.go index 9b1ebdc49..8674c2f31 100644 --- a/pkg/gui/list_context_config.go +++ b/pkg/gui/list_context_config.go @@ -3,7 +3,10 @@ package gui import ( "log" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/git_commands" + "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" @@ -11,12 +14,12 @@ import ( func (gui *Gui) menuListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "menu", Key: "menu", Kind: types.PERSISTENT_POPUP, OnGetOptionsMap: gui.getMenuOptions, - }, + }), GetItemsLength: func() int { return gui.Views.Menu.LinesHeight() }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Menu }, Gui: gui, @@ -27,16 +30,16 @@ func (gui *Gui) menuListContext() types.IListContext { func (gui *Gui) filesListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "files", WindowName: "files", Key: FILES_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return gui.State.FileTreeViewModel.GetItemsLength() }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Files }, OnFocus: OnFocusWrapper(gui.onFocusFile), - OnRenderToMain: OnFocusWrapper(gui.filesRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.filesRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { lines := presentation.RenderFileTree(gui.State.FileTreeViewModel, gui.State.Modes.Diffing.Ref, gui.State.Submodules) @@ -56,15 +59,15 @@ func (gui *Gui) filesListContext() types.IListContext { func (gui *Gui) branchesListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "branches", WindowName: "branches", Key: LOCAL_BRANCHES_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.Branches) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Branches }, - OnRenderToMain: OnFocusWrapper(gui.branchesRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.branchesRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Modes.Diffing.Ref) @@ -78,15 +81,15 @@ func (gui *Gui) branchesListContext() types.IListContext { func (gui *Gui) remotesListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "branches", WindowName: "branches", Key: REMOTES_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.Remotes) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Remotes }, - OnRenderToMain: OnFocusWrapper(gui.remotesRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.remotesRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { return presentation.GetRemoteListDisplayStrings(gui.State.Remotes, gui.State.Modes.Diffing.Ref) @@ -100,15 +103,15 @@ func (gui *Gui) remotesListContext() types.IListContext { func (gui *Gui) remoteBranchesListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "branches", WindowName: "branches", Key: REMOTE_BRANCHES_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.RemoteBranches) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.RemoteBranches }, - OnRenderToMain: OnFocusWrapper(gui.remoteBranchesRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.remoteBranchesRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { return presentation.GetRemoteBranchListDisplayStrings(gui.State.RemoteBranches, gui.State.Modes.Diffing.Ref) @@ -120,41 +123,43 @@ func (gui *Gui) remoteBranchesListContext() types.IListContext { } } -func (gui *Gui) tagsListContext() types.IListContext { - return &ListContext{ - BasicContext: &BasicContext{ - ViewName: "branches", - WindowName: "branches", - Key: TAGS_CONTEXT_KEY, - Kind: types.SIDE_CONTEXT, - }, - GetItemsLength: func() int { return len(gui.State.Tags) }, - OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Tags }, - OnRenderToMain: OnFocusWrapper(gui.tagsRenderToMain), - Gui: gui, - GetDisplayStrings: func(startIdx int, length int) [][]string { +func (gui *Gui) withDiffModeCheck(f func() error) func() error { + return func() error { + if gui.State.Modes.Diffing.Active() { + return gui.renderDiff() + } + + return f() + } +} + +func (gui *Gui) tagsListContext() *context.TagsContext { + return context.NewTagsContext( + func() []*models.Tag { return gui.State.Tags }, + func() *gocui.View { return gui.Views.Branches }, + func(startIdx int, length int) [][]string { return presentation.GetTagListDisplayStrings(gui.State.Tags, gui.State.Modes.Diffing.Ref) }, - SelectedItem: func() (types.ListItem, bool) { - item := gui.getSelectedTag() - return item, item != nil - }, - } + nil, + OnFocusWrapper(gui.withDiffModeCheck(gui.tagsRenderToMain)), + nil, + gui.c, + ) } func (gui *Gui) branchCommitsListContext() types.IListContext { parseEmoji := gui.c.UserConfig.Git.ParseEmoji return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "commits", WindowName: "commits", Key: BRANCH_COMMITS_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.Commits) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Commits }, OnFocus: OnFocusWrapper(gui.onCommitFocus), - OnRenderToMain: OnFocusWrapper(gui.branchCommitsRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.branchCommitsRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { selectedCommitSha := "" @@ -188,15 +193,15 @@ func (gui *Gui) branchCommitsListContext() types.IListContext { func (gui *Gui) subCommitsListContext() types.IListContext { parseEmoji := gui.c.UserConfig.Git.ParseEmoji return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "branches", WindowName: "branches", Key: SUB_COMMITS_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.SubCommits) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.SubCommits }, - OnRenderToMain: OnFocusWrapper(gui.subCommitsRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.subCommitsRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { selectedCommitSha := "" @@ -249,15 +254,15 @@ func (gui *Gui) shouldShowGraph() bool { func (gui *Gui) reflogCommitsListContext() types.IListContext { parseEmoji := gui.c.UserConfig.Git.ParseEmoji return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "commits", WindowName: "commits", Key: REFLOG_COMMITS_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.FilteredReflogCommits) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.ReflogCommits }, - OnRenderToMain: OnFocusWrapper(gui.reflogCommitsRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.reflogCommitsRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { return presentation.GetReflogCommitListDisplayStrings( @@ -277,15 +282,15 @@ func (gui *Gui) reflogCommitsListContext() types.IListContext { func (gui *Gui) stashListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "stash", WindowName: "stash", Key: STASH_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.StashEntries) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Stash }, - OnRenderToMain: OnFocusWrapper(gui.stashRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.stashRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { return presentation.GetStashEntryListDisplayStrings(gui.State.StashEntries, gui.State.Modes.Diffing.Ref) @@ -299,16 +304,16 @@ func (gui *Gui) stashListContext() types.IListContext { func (gui *Gui) commitFilesListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "commitFiles", WindowName: "commits", Key: COMMIT_FILES_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return gui.State.CommitFileTreeViewModel.GetItemsLength() }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.CommitFiles }, OnFocus: OnFocusWrapper(gui.onCommitFileFocus), - OnRenderToMain: OnFocusWrapper(gui.commitFilesRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.commitFilesRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { if gui.State.CommitFileTreeViewModel.GetItemsLength() == 0 { @@ -332,15 +337,15 @@ func (gui *Gui) commitFilesListContext() types.IListContext { func (gui *Gui) submodulesListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "files", WindowName: "files", Key: SUBMODULES_CONTEXT_KEY, Kind: types.SIDE_CONTEXT, - }, + }), GetItemsLength: func() int { return len(gui.State.Submodules) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Submodules }, - OnRenderToMain: OnFocusWrapper(gui.submodulesRenderToMain), + OnRenderToMain: OnFocusWrapper(gui.withDiffModeCheck(gui.submodulesRenderToMain)), Gui: gui, GetDisplayStrings: func(startIdx int, length int) [][]string { return presentation.GetSubmoduleListDisplayStrings(gui.State.Submodules) @@ -354,12 +359,12 @@ func (gui *Gui) submodulesListContext() types.IListContext { func (gui *Gui) suggestionsListContext() types.IListContext { return &ListContext{ - BasicContext: &BasicContext{ + BaseContext: context.NewBaseContext(context.NewBaseContextOpts{ ViewName: "suggestions", WindowName: "suggestions", Key: SUGGESTIONS_CONTEXT_KEY, Kind: types.PERSISTENT_POPUP, - }, + }), GetItemsLength: func() int { return len(gui.State.Suggestions) }, OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Suggestions }, Gui: gui, diff --git a/pkg/gui/menu_panel.go b/pkg/gui/menu_panel.go index fc7f70329..3e20baebb 100644 --- a/pkg/gui/menu_panel.go +++ b/pkg/gui/menu_panel.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/jesseduffield/lazygit/pkg/gui/popup" + "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -24,10 +24,10 @@ func (gui *Gui) handleMenuClose() error { } // note: items option is mutated by this function -func (gui *Gui) createMenu(opts popup.CreateMenuOptions) error { +func (gui *Gui) createMenu(opts types.CreateMenuOptions) error { if !opts.HideCancel { // this is mutative but I'm okay with that for now - opts.Items = append(opts.Items, &popup.MenuItem{ + opts.Items = append(opts.Items, &types.MenuItem{ DisplayStrings: []string{gui.c.Tr.LcCancel}, OnPress: func() error { return nil @@ -69,7 +69,7 @@ func (gui *Gui) createMenu(opts popup.CreateMenuOptions) error { return gui.c.PushContext(gui.State.Contexts.Menu) } -func (gui *Gui) getSelectedMenuItem() *popup.MenuItem { +func (gui *Gui) getSelectedMenuItem() *types.MenuItem { if len(gui.State.MenuItems) == 0 { return nil } diff --git a/pkg/gui/options_menu_panel.go b/pkg/gui/options_menu_panel.go index 2623e6df0..8afcaeccb 100644 --- a/pkg/gui/options_menu_panel.go +++ b/pkg/gui/options_menu_panel.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" @@ -56,11 +55,11 @@ func (gui *Gui) handleCreateOptionsMenu() error { bindings := gui.getBindings(view) - menuItems := make([]*popup.MenuItem, len(bindings)) + menuItems := make([]*types.MenuItem, len(bindings)) for i, binding := range bindings { binding := binding // note to self, never close over loop variables - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayStrings: []string{GetKeyDisplay(binding.Key), gui.displayDescription(binding)}, OnPress: func() error { if binding.Key == nil { @@ -74,7 +73,7 @@ func (gui *Gui) handleCreateOptionsMenu() error { } } - return gui.c.Menu(popup.CreateMenuOptions{ + return gui.c.Menu(types.CreateMenuOptions{ Title: strings.Title(gui.c.Tr.LcMenu), Items: menuItems, HideCancel: true, diff --git a/pkg/gui/patch_options_panel.go b/pkg/gui/patch_options_panel.go index 5c321819a..8f8615e4a 100644 --- a/pkg/gui/patch_options_panel.go +++ b/pkg/gui/patch_options_panel.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -13,7 +12,7 @@ func (gui *Gui) handleCreatePatchOptionsMenu() error { return gui.c.ErrorMsg(gui.c.Tr.NoPatchError) } - menuItems := []*popup.MenuItem{ + menuItems := []*types.MenuItem{ { DisplayString: "reset patch", OnPress: gui.handleResetPatch, @@ -29,7 +28,7 @@ func (gui *Gui) handleCreatePatchOptionsMenu() error { } if gui.git.Patch.PatchManager.CanRebase && gui.git.Status.WorkingTreeState() == enums.REBASE_MODE_NONE { - menuItems = append(menuItems, []*popup.MenuItem{ + menuItems = append(menuItems, []*types.MenuItem{ { DisplayString: fmt.Sprintf("remove patch from original commit (%s)", gui.git.Patch.PatchManager.To), OnPress: gui.handleDeletePatchFromCommit, @@ -51,7 +50,7 @@ func (gui *Gui) handleCreatePatchOptionsMenu() error { menuItems = append( menuItems[:1], append( - []*popup.MenuItem{ + []*types.MenuItem{ { DisplayString: fmt.Sprintf("move patch to selected commit (%s)", selectedCommit.Sha), OnPress: gui.handleMovePatchToSelectedCommit, @@ -63,7 +62,7 @@ func (gui *Gui) handleCreatePatchOptionsMenu() error { } } - return gui.c.Menu(popup.CreateMenuOptions{Title: gui.c.Tr.PatchOptionsTitle, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: gui.c.Tr.PatchOptionsTitle, Items: menuItems}) } func (gui *Gui) getPatchCommitIndex() int { @@ -142,7 +141,7 @@ func (gui *Gui) handleMovePatchIntoWorkingTree() error { } if gui.workingTreeHelper.IsWorkingTreeDirty() { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.MustStashTitle, Prompt: gui.c.Tr.MustStashWarning, HandleConfirm: func() error { diff --git a/pkg/gui/popup/popup_handler.go b/pkg/gui/popup/popup_handler.go index f9291d5af..20a7c8d80 100644 --- a/pkg/gui/popup/popup_handler.go +++ b/pkg/gui/popup/popup_handler.go @@ -11,83 +11,27 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) -type IPopupHandler interface { - ErrorMsg(message string) error - Error(err error) error - Ask(opts AskOpts) error - Prompt(opts PromptOpts) error - WithLoaderPanel(message string, f func() error) error - WithWaitingStatus(message string, f func() error) error - Menu(opts CreateMenuOptions) error - Toast(message string) - GetPromptInput() string -} - -type CreateMenuOptions struct { - Title string - Items []*MenuItem - HideCancel bool -} - -type CreatePopupPanelOpts struct { - HasLoader bool - Editable bool - Title string - Prompt string - HandleConfirm func() error - HandleConfirmPrompt func(string) error - HandleClose func() error - - // 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 - - FindSuggestionsFunc func(string) []*types.Suggestion -} - -type AskOpts struct { - Title string - Prompt string - HandleConfirm func() error - HandleClose func() error - HandlersManageFocus bool -} - -type PromptOpts struct { - Title string - InitialContent string - FindSuggestionsFunc func(string) []*types.Suggestion - HandleConfirm func(string) error -} - -type MenuItem struct { - DisplayString string - DisplayStrings []string - OnPress func() error - // only applies when displayString is used - OpensMenu bool -} - type RealPopupHandler struct { *common.Common index int sync.Mutex - createPopupPanelFn func(CreatePopupPanelOpts) error + createPopupPanelFn func(types.CreatePopupPanelOpts) error onErrorFn func() error closePopupFn func() error - createMenuFn func(CreateMenuOptions) error + createMenuFn func(types.CreateMenuOptions) error withWaitingStatusFn func(message string, f func() error) error toastFn func(message string) getPromptInputFn func() string } -var _ IPopupHandler = &RealPopupHandler{} +var _ types.IPopupHandler = &RealPopupHandler{} func NewPopupHandler( common *common.Common, - createPopupPanelFn func(CreatePopupPanelOpts) error, + createPopupPanelFn func(types.CreatePopupPanelOpts) error, onErrorFn func() error, closePopupFn func() error, - createMenuFn func(CreateMenuOptions) error, + createMenuFn func(types.CreateMenuOptions) error, withWaitingStatusFn func(message string, f func() error) error, toastFn func(message string), getPromptInputFn func() string, @@ -105,7 +49,7 @@ func NewPopupHandler( } } -func (self *RealPopupHandler) Menu(opts CreateMenuOptions) error { +func (self *RealPopupHandler) Menu(opts types.CreateMenuOptions) error { return self.createMenuFn(opts) } @@ -135,18 +79,18 @@ func (self *RealPopupHandler) ErrorMsg(message string) error { return err } - return self.Ask(AskOpts{ + return self.Ask(types.AskOpts{ Title: self.Tr.Error, Prompt: coloredMessage, }) } -func (self *RealPopupHandler) Ask(opts AskOpts) error { +func (self *RealPopupHandler) Ask(opts types.AskOpts) error { self.Lock() self.index++ self.Unlock() - return self.createPopupPanelFn(CreatePopupPanelOpts{ + return self.createPopupPanelFn(types.CreatePopupPanelOpts{ Title: opts.Title, Prompt: opts.Prompt, HandleConfirm: opts.HandleConfirm, @@ -155,12 +99,12 @@ func (self *RealPopupHandler) Ask(opts AskOpts) error { }) } -func (self *RealPopupHandler) Prompt(opts PromptOpts) error { +func (self *RealPopupHandler) Prompt(opts types.PromptOpts) error { self.Lock() self.index++ self.Unlock() - return self.createPopupPanelFn(CreatePopupPanelOpts{ + return self.createPopupPanelFn(types.CreatePopupPanelOpts{ Title: opts.Title, Prompt: opts.InitialContent, Editable: true, @@ -176,7 +120,7 @@ func (self *RealPopupHandler) WithLoaderPanel(message string, f func() error) er index = self.index self.Unlock() - err := self.createPopupPanelFn(CreatePopupPanelOpts{ + err := self.createPopupPanelFn(types.CreatePopupPanelOpts{ Prompt: message, HasLoader: true, }) @@ -208,11 +152,11 @@ func (self *RealPopupHandler) GetPromptInput() string { type TestPopupHandler struct { OnErrorMsg func(message string) error - OnAsk func(opts AskOpts) error - OnPrompt func(opts PromptOpts) error + OnAsk func(opts types.AskOpts) error + OnPrompt func(opts types.PromptOpts) error } -var _ IPopupHandler = &TestPopupHandler{} +var _ types.IPopupHandler = &TestPopupHandler{} func (self *TestPopupHandler) Error(err error) error { return self.ErrorMsg(err.Error()) @@ -222,11 +166,11 @@ func (self *TestPopupHandler) ErrorMsg(message string) error { return self.OnErrorMsg(message) } -func (self *TestPopupHandler) Ask(opts AskOpts) error { +func (self *TestPopupHandler) Ask(opts types.AskOpts) error { return self.OnAsk(opts) } -func (self *TestPopupHandler) Prompt(opts PromptOpts) error { +func (self *TestPopupHandler) Prompt(opts types.PromptOpts) error { return self.OnPrompt(opts) } @@ -238,7 +182,7 @@ func (self *TestPopupHandler) WithWaitingStatus(message string, f func() error) return f() } -func (self *TestPopupHandler) Menu(opts CreateMenuOptions) error { +func (self *TestPopupHandler) Menu(opts types.CreateMenuOptions) error { panic("not yet implemented") } diff --git a/pkg/gui/pull_request_menu_panel.go b/pkg/gui/pull_request_menu_panel.go index 9973daeca..2dce784b9 100644 --- a/pkg/gui/pull_request_menu_panel.go +++ b/pkg/gui/pull_request_menu_panel.go @@ -5,18 +5,18 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/hosting_service" "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/popup" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutBranch *models.Branch) error { - menuItems := make([]*popup.MenuItem, 0, 4) + menuItems := make([]*types.MenuItem, 0, 4) fromToDisplayStrings := func(from string, to string) []string { return []string{fmt.Sprintf("%s → %s", from, to)} } - menuItemsForBranch := func(branch *models.Branch) []*popup.MenuItem { - return []*popup.MenuItem{ + menuItemsForBranch := func(branch *models.Branch) []*types.MenuItem { + return []*types.MenuItem{ { DisplayStrings: fromToDisplayStrings(branch.Name, gui.c.Tr.LcDefaultBranch), OnPress: func() error { @@ -26,7 +26,7 @@ func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutB { DisplayStrings: fromToDisplayStrings(branch.Name, gui.c.Tr.LcSelectBranch), OnPress: func() error { - return gui.c.Prompt(popup.PromptOpts{ + return gui.c.Prompt(types.PromptOpts{ Title: branch.Name + " →", FindSuggestionsFunc: gui.suggestionsHelper.GetBranchNameSuggestionsFunc(), HandleConfirm: func(targetBranchName string) error { @@ -40,7 +40,7 @@ func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutB if selectedBranch != checkedOutBranch { menuItems = append(menuItems, - &popup.MenuItem{ + &types.MenuItem{ DisplayStrings: fromToDisplayStrings(checkedOutBranch.Name, selectedBranch.Name), OnPress: func() error { return gui.createPullRequest(checkedOutBranch.Name, selectedBranch.Name) @@ -52,7 +52,7 @@ func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutB menuItems = append(menuItems, menuItemsForBranch(selectedBranch)...) - return gui.c.Menu(popup.CreateMenuOptions{Title: fmt.Sprintf(gui.c.Tr.CreatePullRequestOptions), Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: fmt.Sprintf(gui.c.Tr.CreatePullRequestOptions), Items: menuItems}) } func (gui *Gui) createPullRequest(from string, to string) error { diff --git a/pkg/gui/quitting.go b/pkg/gui/quitting.go index edf402159..4db28dcb1 100644 --- a/pkg/gui/quitting.go +++ b/pkg/gui/quitting.go @@ -4,7 +4,7 @@ import ( "os" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/gui/popup" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) // when a user runs lazygit with the LAZYGIT_NEW_DIR_FILE env variable defined @@ -73,7 +73,7 @@ func (gui *Gui) quit() error { } if gui.c.UserConfig.ConfirmOnQuit { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: "", Prompt: gui.c.Tr.ConfirmQuit, HandleConfirm: func() error { diff --git a/pkg/gui/rebase_options_panel.go b/pkg/gui/rebase_options_panel.go index 467665f84..897c389f8 100644 --- a/pkg/gui/rebase_options_panel.go +++ b/pkg/gui/rebase_options_panel.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -24,11 +23,11 @@ func (gui *Gui) handleCreateRebaseOptionsMenu() error { options = append(options, REBASE_OPTION_SKIP) } - menuItems := make([]*popup.MenuItem, len(options)) + menuItems := make([]*types.MenuItem, len(options)) for i, option := range options { // note to self. Never, EVER, close over loop variables in a function option := option - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayString: option, OnPress: func() error { return gui.genericMergeCommand(option) @@ -43,7 +42,7 @@ func (gui *Gui) handleCreateRebaseOptionsMenu() error { title = gui.c.Tr.RebaseOptionsTitle } - return gui.c.Menu(popup.CreateMenuOptions{Title: title, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems}) } func (gui *Gui) genericMergeCommand(command string) error { @@ -112,7 +111,7 @@ func (gui *Gui) checkMergeOrRebase(result error) error { // assume in this case that we're already done return nil } else if isMergeConflictErr(result.Error()) { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.FoundConflictsTitle, Prompt: gui.c.Tr.FoundConflicts, HandlersManageFocus: true, @@ -135,7 +134,7 @@ func (gui *Gui) checkMergeOrRebase(result error) error { func (gui *Gui) abortMergeOrRebaseWithConfirm() error { // prompt user to confirm that they want to abort, then do it mode := gui.workingTreeStateNoun() - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: fmt.Sprintf(gui.c.Tr.AbortTitle, mode), Prompt: fmt.Sprintf(gui.c.Tr.AbortPrompt, mode), HandleConfirm: func() error { diff --git a/pkg/gui/recent_repos_panel.go b/pkg/gui/recent_repos_panel.go index 337be3600..606f2d72f 100644 --- a/pkg/gui/recent_repos_panel.go +++ b/pkg/gui/recent_repos_panel.go @@ -7,8 +7,8 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/git_config" "github.com/jesseduffield/lazygit/pkg/env" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" + "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -17,10 +17,10 @@ func (gui *Gui) handleCreateRecentReposMenu() error { reposCount := utils.Min(len(recentRepoPaths), 20) // we won't show the current repo hence the -1 - menuItems := make([]*popup.MenuItem, reposCount-1) + menuItems := make([]*types.MenuItem, reposCount-1) for i, path := range recentRepoPaths[1:reposCount] { path := path // cos we're closing over the loop variable - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayStrings: []string{ filepath.Base(path), style.FgMagenta.Sprint(path), @@ -34,7 +34,7 @@ func (gui *Gui) handleCreateRecentReposMenu() error { } } - return gui.c.Menu(popup.CreateMenuOptions{Title: gui.c.Tr.RecentRepos, Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: gui.c.Tr.RecentRepos, Items: menuItems}) } func (gui *Gui) handleShowAllBranchLogs() error { diff --git a/pkg/gui/ref_helper.go b/pkg/gui/ref_helper.go index a6f930c96..b5a198bab 100644 --- a/pkg/gui/ref_helper.go +++ b/pkg/gui/ref_helper.go @@ -7,20 +7,19 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/gui/controllers" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" ) type RefHelper struct { - c *controllers.ControllerCommon + c *types.ControllerCommon git *commands.GitCommand getState func() *GuiRepoState } func NewRefHelper( - c *controllers.ControllerCommon, + c *types.ControllerCommon, git *commands.GitCommand, getState func() *GuiRepoState, ) *RefHelper { @@ -58,7 +57,7 @@ func (self *RefHelper) CheckoutRef(ref string, options types.CheckoutRefOptions) if strings.Contains(err.Error(), "Please commit your changes or stash them before you switch branch") { // offer to autostash changes - return self.c.Ask(popup.AskOpts{ + return self.c.Ask(types.AskOpts{ Title: self.c.Tr.AutoStashTitle, Prompt: self.c.Tr.AutoStashPrompt, @@ -115,10 +114,10 @@ func (self *RefHelper) ResetToRef(ref string, strength string, envVars []string) func (self *RefHelper) CreateGitResetMenu(ref string) error { strengths := []string{"soft", "mixed", "hard"} - menuItems := make([]*popup.MenuItem, len(strengths)) + menuItems := make([]*types.MenuItem, len(strengths)) for i, strength := range strengths { strength := strength - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayStrings: []string{ fmt.Sprintf("%s reset", strength), style.FgRed.Sprintf("reset --%s %s", strength, ref), @@ -130,7 +129,7 @@ func (self *RefHelper) CreateGitResetMenu(ref string) error { } } - return self.c.Menu(popup.CreateMenuOptions{ + return self.c.Menu(types.CreateMenuOptions{ Title: fmt.Sprintf("%s %s", self.c.Tr.LcResetTo, ref), Items: menuItems, }) diff --git a/pkg/gui/reflog_panel.go b/pkg/gui/reflog_panel.go index f562036ad..74254fa7b 100644 --- a/pkg/gui/reflog_panel.go +++ b/pkg/gui/reflog_panel.go @@ -3,7 +3,6 @@ package gui import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/controllers" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -90,7 +89,7 @@ func (gui *Gui) CheckoutReflogCommit() error { return nil } - err := gui.c.Ask(popup.AskOpts{ + err := gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.LcCheckoutCommit, Prompt: gui.c.Tr.SureCheckoutThisCommit, HandleConfirm: func() error { diff --git a/pkg/gui/remote_branches_panel.go b/pkg/gui/remote_branches_panel.go index 29e2e2f03..afbb10705 100644 --- a/pkg/gui/remote_branches_panel.go +++ b/pkg/gui/remote_branches_panel.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -54,7 +53,7 @@ func (gui *Gui) handleDeleteRemoteBranch() error { } message := fmt.Sprintf("%s '%s'?", gui.c.Tr.DeleteRemoteBranchMessage, remoteBranch.FullName()) - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.DeleteRemoteBranch, Prompt: message, HandleConfirm: func() error { @@ -88,7 +87,7 @@ func (gui *Gui) handleSetBranchUpstream() error { }, ) - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.SetUpstreamTitle, Prompt: message, HandleConfirm: func() error { diff --git a/pkg/gui/staging_panel.go b/pkg/gui/staging_panel.go index f04f1e3ff..bbb100961 100644 --- a/pkg/gui/staging_panel.go +++ b/pkg/gui/staging_panel.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/commands/patch" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -114,7 +113,7 @@ func (gui *Gui) handleResetSelection() error { } if !gui.c.UserConfig.Gui.SkipUnstageLineWarning { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.UnstageLinesTitle, Prompt: gui.c.Tr.UnstageLinesPrompt, HandleConfirm: func() error { diff --git a/pkg/gui/stash_panel.go b/pkg/gui/stash_panel.go index 994548b0e..50af13eef 100644 --- a/pkg/gui/stash_panel.go +++ b/pkg/gui/stash_panel.go @@ -3,7 +3,6 @@ package gui import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/controllers" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -66,7 +65,7 @@ func (gui *Gui) handleStashApply() error { return apply() } - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.StashApply, Prompt: gui.c.Tr.SureApplyStashEntry, HandleConfirm: func() error { @@ -97,7 +96,7 @@ func (gui *Gui) handleStashPop() error { return pop() } - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.StashPop, Prompt: gui.c.Tr.SurePopStashEntry, HandleConfirm: func() error { @@ -112,7 +111,7 @@ func (gui *Gui) handleStashDrop() error { return nil } - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.StashDrop, Prompt: gui.c.Tr.SureDropStashEntry, HandleConfirm: func() error { diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index 15c15987e..0d65a0035 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -7,9 +7,9 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/constants" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/style" + "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -139,17 +139,17 @@ func (gui *Gui) askForConfigFile(action func(file string) error) error { case 1: return action(confPaths[0]) default: - menuItems := make([]*popup.MenuItem, len(confPaths)) + menuItems := make([]*types.MenuItem, len(confPaths)) for i, file := range confPaths { i := i - menuItems[i] = &popup.MenuItem{ + menuItems[i] = &types.MenuItem{ DisplayString: file, OnPress: func() error { return action(confPaths[i]) }, } } - return gui.c.Menu(popup.CreateMenuOptions{ + return gui.c.Menu(types.CreateMenuOptions{ Title: gui.c.Tr.SelectConfigFile, Items: menuItems, HideCancel: true, diff --git a/pkg/gui/sub_commits_panel.go b/pkg/gui/sub_commits_panel.go index c3b83d122..6e392fcc9 100644 --- a/pkg/gui/sub_commits_panel.go +++ b/pkg/gui/sub_commits_panel.go @@ -4,7 +4,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/loaders" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/controllers" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -45,7 +44,7 @@ func (gui *Gui) handleCheckoutSubCommit() error { return nil } - err := gui.c.Ask(popup.AskOpts{ + err := gui.c.Ask(types.AskOpts{ Title: gui.c.Tr.LcCheckoutCommit, Prompt: gui.c.Tr.SureCheckoutThisCommit, HandleConfirm: func() error { diff --git a/pkg/gui/suggestions_helper.go b/pkg/gui/suggestions_helper.go index 97aabfbda..3d6d9cd79 100644 --- a/pkg/gui/suggestions_helper.go +++ b/pkg/gui/suggestions_helper.go @@ -23,7 +23,7 @@ import ( // exists for fetching a particular model. type SuggestionsHelper struct { - c *controllers.ControllerCommon + c *types.ControllerCommon getState func() *GuiRepoState refreshSuggestionsFn func() @@ -32,7 +32,7 @@ type SuggestionsHelper struct { var _ controllers.ISuggestionsHelper = &SuggestionsHelper{} func NewSuggestionsHelper( - c *controllers.ControllerCommon, + c *types.ControllerCommon, getState func() *GuiRepoState, refreshSuggestionsFn func(), ) *SuggestionsHelper { diff --git a/pkg/gui/tags_panel.go b/pkg/gui/tags_panel.go index 9e00dd122..957743188 100644 --- a/pkg/gui/tags_panel.go +++ b/pkg/gui/tags_panel.go @@ -1,21 +1,8 @@ package gui -import ( - "github.com/jesseduffield/lazygit/pkg/commands/models" -) - -func (self *Gui) getSelectedTag() *models.Tag { - selectedLine := self.State.Panels.Tags.SelectedLineIdx - if selectedLine == -1 || len(self.State.Tags) == 0 { - return nil - } - - return self.State.Tags[selectedLine] -} - func (self *Gui) tagsRenderToMain() error { var task updateTask - tag := self.getSelectedTag() + tag := self.State.Contexts.Tags.GetSelectedTag() if tag == nil { task = NewRenderStringTask("No tags") } else { @@ -31,7 +18,6 @@ func (self *Gui) tagsRenderToMain() error { }) } -// this is a controller: it can't access tags directly. Or can it? It should be able to get but not set. But that's exactly what I'm doing here, setting it. but through a mutator which encapsulates the event. func (self *Gui) refreshTags() error { tags, err := self.git.Loaders.Tags.GetTags() if err != nil { diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go new file mode 100644 index 000000000..9289c4f2d --- /dev/null +++ b/pkg/gui/types/common.go @@ -0,0 +1,94 @@ +package types + +import ( + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" + "github.com/jesseduffield/lazygit/pkg/common" + "github.com/jesseduffield/lazygit/pkg/config" +) + +// if Go let me do private struct embedding of structs with public fields (which it should) +// I would just do that. But alas. +type ControllerCommon struct { + *common.Common + IGuiCommon +} + +type IGuiCommon interface { + IPopupHandler + + LogAction(action string) + LogCommand(cmdStr string, isCommandLine bool) + // we call this when we want to refetch some models and render the result. Internally calls PostRefreshUpdate + Refresh(RefreshOptions) error + // we call this when we've changed something in the view model but not the actual model, + // e.g. expanding or collapsing a folder in a file view. Calling 'Refresh' in this + // case would be overkill, although refresh will internally call 'PostRefreshUpdate' + PostRefreshUpdate(Context) error + // this just re-renders the screen + Render() + RunSubprocessAndRefresh(oscommands.ICmdObj) error + PushContext(context Context, opts ...OnFocusOpts) error + PopContext() error + CurrentContext() Context + // enters search mode for the current view + OpenSearch() + + GetAppState() *config.AppState + SaveAppState() error +} + +type IPopupHandler interface { + ErrorMsg(message string) error + Error(err error) error + Ask(opts AskOpts) error + Prompt(opts PromptOpts) error + WithLoaderPanel(message string, f func() error) error + WithWaitingStatus(message string, f func() error) error + Menu(opts CreateMenuOptions) error + Toast(message string) + GetPromptInput() string +} + +type CreateMenuOptions struct { + Title string + Items []*MenuItem + HideCancel bool +} + +type CreatePopupPanelOpts struct { + HasLoader bool + Editable bool + Title string + Prompt string + HandleConfirm func() error + HandleConfirmPrompt func(string) error + HandleClose func() error + + // 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 + + FindSuggestionsFunc func(string) []*Suggestion +} + +type AskOpts struct { + Title string + Prompt string + HandleConfirm func() error + HandleClose func() error + HandlersManageFocus bool +} + +type PromptOpts struct { + Title string + InitialContent string + FindSuggestionsFunc func(string) []*Suggestion + HandleConfirm func(string) error +} + +type MenuItem struct { + DisplayString string + DisplayStrings []string + OnPress func() error + // only applies when displayString is used + OpensMenu bool +} diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 833d1cba6..eadcf41ad 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -12,23 +12,33 @@ const ( EXTRAS_CONTEXT ) -type Context interface { - HandleFocus(opts ...OnFocusOpts) error - HandleFocusLost() error - HandleRender() error - HandleRenderToMain() error +type ParentContexter interface { + SetParentContext(Context) + // we return a bool here to tell us whether or not the returned value just wraps a nil + GetParentContext() (Context, bool) +} + +type IBaseContext interface { + ParentContexter + GetKind() ContextKind GetViewName() string GetWindowName() string SetWindowName(string) GetKey() ContextKey - SetParentContext(Context) - // we return a bool here to tell us whether or not the returned value just wraps a nil - GetParentContext() (Context, bool) GetOptionsMap() map[string]string } +type Context interface { + IBaseContext + + HandleFocus(opts ...OnFocusOpts) error + HandleFocusLost() error + HandleRender() error + HandleRenderToMain() error +} + type OnFocusOpts struct { ClickedViewName string ClickedViewLineIdx int diff --git a/pkg/gui/updates.go b/pkg/gui/updates.go index f3dc14b1d..83642a81a 100644 --- a/pkg/gui/updates.go +++ b/pkg/gui/updates.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/gui/popup" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) showUpdatePrompt(newVersion string) error { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: "New version available!", Prompt: fmt.Sprintf("Download version %s? (enter/esc)", newVersion), HandleConfirm: func() error { @@ -65,7 +65,7 @@ func (gui *Gui) onUpdateFinish(statusId int, err error) error { } func (gui *Gui) createUpdateQuitConfirmation() error { - return gui.c.Ask(popup.AskOpts{ + return gui.c.Ask(types.AskOpts{ Title: "Currently Updating", Prompt: "An update is in progress. Are you sure you want to quit?", HandleConfirm: func() error { diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 29dd70048..42ff9d5d8 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -254,8 +254,9 @@ func (gui *Gui) renderDisplayStrings(v *gocui.View, displayStrings [][]string) { v.SetContent(list) } -func (gui *Gui) renderDisplayStringsAtPos(v *gocui.View, y int, displayStrings [][]string) { +func (gui *Gui) renderDisplayStringsInViewPort(v *gocui.View, displayStrings [][]string) { list := utils.RenderDisplayStrings(displayStrings) + _, y := v.Origin() v.OverwriteLines(y, list) } diff --git a/pkg/gui/workspace_reset_options_panel.go b/pkg/gui/workspace_reset_options_panel.go index 2b9fd97d1..205f8b9dd 100644 --- a/pkg/gui/workspace_reset_options_panel.go +++ b/pkg/gui/workspace_reset_options_panel.go @@ -3,7 +3,6 @@ package gui import ( "fmt" - "github.com/jesseduffield/lazygit/pkg/gui/popup" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -16,7 +15,7 @@ func (gui *Gui) handleCreateResetMenu() error { nukeStr = fmt.Sprintf("%s (%s)", nukeStr, gui.c.Tr.LcAndResetSubmodules) } - menuItems := []*popup.MenuItem{ + menuItems := []*types.MenuItem{ { DisplayStrings: []string{ gui.c.Tr.LcDiscardAllChangesToAllFiles, @@ -103,5 +102,5 @@ func (gui *Gui) handleCreateResetMenu() error { }, } - return gui.c.Menu(popup.CreateMenuOptions{Title: "", Items: menuItems}) + return gui.c.Menu(types.CreateMenuOptions{Title: "", Items: menuItems}) }