diff --git a/pkg/gui/app_status_manager.go b/pkg/gui/app_status_manager.go deleted file mode 100644 index 02ba7779a..000000000 --- a/pkg/gui/app_status_manager.go +++ /dev/null @@ -1,132 +0,0 @@ -package gui - -import ( - "time" - - "github.com/jesseduffield/generics/slices" - "github.com/jesseduffield/lazygit/pkg/utils" - "github.com/sasha-s/go-deadlock" -) - -// statusManager's job is to handle rendering of loading states and toast notifications -// that you see at the bottom left of the screen. -type statusManager struct { - statuses []appStatus - nextId int - mutex deadlock.Mutex -} - -type appStatus struct { - message string - statusType string - id int -} - -func (m *statusManager) removeStatus(id int) { - m.mutex.Lock() - defer m.mutex.Unlock() - - m.statuses = slices.Filter(m.statuses, func(status appStatus) bool { - return status.id != id - }) -} - -func (m *statusManager) addWaitingStatus(message string) int { - m.mutex.Lock() - defer m.mutex.Unlock() - - m.nextId += 1 - id := m.nextId - - newStatus := appStatus{ - message: message, - statusType: "waiting", - id: id, - } - m.statuses = append([]appStatus{newStatus}, m.statuses...) - - return id -} - -func (m *statusManager) addToastStatus(message string) int { - m.mutex.Lock() - defer m.mutex.Unlock() - - m.nextId++ - id := m.nextId - - newStatus := appStatus{ - message: message, - statusType: "toast", - id: id, - } - m.statuses = append([]appStatus{newStatus}, m.statuses...) - - go func() { - time.Sleep(time.Second * 2) - - m.removeStatus(id) - }() - - return id -} - -func (m *statusManager) getStatusString() string { - if len(m.statuses) == 0 { - return "" - } - topStatus := m.statuses[0] - if topStatus.statusType == "waiting" { - return topStatus.message + " " + utils.Loader() - } - return topStatus.message -} - -func (m *statusManager) showStatus() bool { - return len(m.statuses) > 0 -} - -func (gui *Gui) toast(message string) { - gui.statusManager.addToastStatus(message) - - gui.renderAppStatus() -} - -func (gui *Gui) renderAppStatus() { - go utils.Safe(func() { - ticker := time.NewTicker(time.Millisecond * 50) - defer ticker.Stop() - for range ticker.C { - appStatus := gui.statusManager.getStatusString() - gui.c.OnUIThread(func() error { - gui.c.SetViewContent(gui.Views.AppStatus, appStatus) - return nil - }) - - if appStatus == "" { - return - } - } - }) -} - -// withWaitingStatus wraps a function and shows a waiting status while the function is still executing -func (gui *Gui) withWaitingStatus(message string, f func() error) error { - go utils.Safe(func() { - id := gui.statusManager.addWaitingStatus(message) - - defer func() { - gui.statusManager.removeStatus(id) - }() - - gui.renderAppStatus() - - if err := f(); err != nil { - gui.c.OnUIThread(func() error { - return gui.c.Error(err) - }) - } - }) - - return nil -} diff --git a/pkg/gui/arrangement.go b/pkg/gui/arrangement.go index 5177d4683..2b1a5333d 100644 --- a/pkg/gui/arrangement.go +++ b/pkg/gui/arrangement.go @@ -3,6 +3,7 @@ package gui import ( "github.com/jesseduffield/lazycore/pkg/boxlayout" "github.com/jesseduffield/lazygit/pkg/gui/context" + "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/mattn/go-runewidth" @@ -14,11 +15,28 @@ import ( const INFO_SECTION_PADDING = " " type WindowArranger struct { - gui *Gui + c *helpers.HelperCommon + windowHelper *helpers.WindowHelper + modeHelper *helpers.ModeHelper + appStatusHelper *helpers.AppStatusHelper +} + +func NewWindowArranger( + c *helpers.HelperCommon, + windowHelper *helpers.WindowHelper, + modeHelper *helpers.ModeHelper, + appStatusHelper *helpers.AppStatusHelper, +) *WindowArranger { + return &WindowArranger{ + c: c, + windowHelper: windowHelper, + modeHelper: modeHelper, + appStatusHelper: appStatusHelper, + } } func (self *WindowArranger) getWindowDimensions(informationStr string, appStatus string) map[string]boxlayout.Dimensions { - width, height := self.gui.g.Size() + width, height := self.c.GocuiGui().Size() sideSectionWeight, mainSectionWeight := self.getMidSectionWeights() @@ -35,7 +53,12 @@ func (self *WindowArranger) getWindowDimensions(informationStr string, appStatus extrasWindowSize := self.getExtrasWindowSize(height) - showInfoSection := self.gui.c.UserConfig.Gui.ShowBottomLine || self.gui.State.Searching.isSearching || self.gui.isAnyModeActive() || self.gui.statusManager.showStatus() + self.c.Modes().Filtering.Active() + + showInfoSection := self.c.UserConfig.Gui.ShowBottomLine || + self.c.State().GetRepoState().IsSearching() || + self.modeHelper.IsAnyModeActive() || + self.appStatusHelper.HasStatus() infoSectionSize := 0 if showInfoSection { infoSectionSize = 1 @@ -96,11 +119,11 @@ func MergeMaps[K comparable, V any](maps ...map[K]V) map[K]V { } func (self *WindowArranger) mainSectionChildren() []*boxlayout.Box { - currentWindow := self.gui.helpers.Window.CurrentWindow() + currentWindow := self.windowHelper.CurrentWindow() // if we're not in split mode we can just show the one main panel. Likewise if // the main panel is focused and we're in full-screen mode - if !self.gui.isMainPanelSplit() || (self.gui.State.ScreenMode == types.SCREEN_FULL && currentWindow == "main") { + if !self.c.State().GetRepoState().GetSplitMainPanel() || (self.c.State().GetRepoState().GetScreenMode() == types.SCREEN_FULL && currentWindow == "main") { return []*boxlayout.Box{ { Window: "main", @@ -122,10 +145,10 @@ func (self *WindowArranger) mainSectionChildren() []*boxlayout.Box { } func (self *WindowArranger) getMidSectionWeights() (int, int) { - currentWindow := self.gui.helpers.Window.CurrentWindow() + currentWindow := self.windowHelper.CurrentWindow() // we originally specified this as a ratio i.e. .20 would correspond to a weight of 1 against 4 - sidePanelWidthRatio := self.gui.c.UserConfig.Gui.SidePanelWidth + sidePanelWidthRatio := self.c.UserConfig.Gui.SidePanelWidth // we could make this better by creating ratios like 2:3 rather than always 1:something mainSectionWeight := int(1/sidePanelWidthRatio) - 1 sideSectionWeight := 1 @@ -134,14 +157,16 @@ func (self *WindowArranger) getMidSectionWeights() (int, int) { mainSectionWeight = 5 // need to shrink side panel to make way for main panels if side-by-side } + screenMode := self.c.State().GetRepoState().GetScreenMode() + if currentWindow == "main" { - if self.gui.State.ScreenMode == types.SCREEN_HALF || self.gui.State.ScreenMode == types.SCREEN_FULL { + if screenMode == types.SCREEN_HALF || screenMode == types.SCREEN_FULL { sideSectionWeight = 0 } } else { - if self.gui.State.ScreenMode == types.SCREEN_HALF { + if screenMode == types.SCREEN_HALF { mainSectionWeight = 1 - } else if self.gui.State.ScreenMode == types.SCREEN_FULL { + } else if screenMode == types.SCREEN_FULL { mainSectionWeight = 0 } } @@ -150,7 +175,7 @@ func (self *WindowArranger) getMidSectionWeights() (int, int) { } func (self *WindowArranger) infoSectionChildren(informationStr string, appStatus string) []*boxlayout.Box { - if self.gui.State.Searching.isSearching { + if self.c.State().GetRepoState().IsSearching() { return []*boxlayout.Box{ { Window: "searchPrefix", @@ -166,7 +191,7 @@ func (self *WindowArranger) infoSectionChildren(informationStr string, appStatus appStatusBox := &boxlayout.Box{Window: "appStatus"} optionsBox := &boxlayout.Box{Window: "options"} - if !self.gui.c.UserConfig.Gui.ShowBottomLine { + if !self.c.UserConfig.Gui.ShowBottomLine { optionsBox.Weight = 0 appStatusBox.Weight = 1 } else { @@ -176,7 +201,7 @@ func (self *WindowArranger) infoSectionChildren(informationStr string, appStatus result := []*boxlayout.Box{appStatusBox, optionsBox} - if self.gui.c.UserConfig.Gui.ShowBottomLine || self.gui.isAnyModeActive() { + if self.c.UserConfig.Gui.ShowBottomLine || self.modeHelper.IsAnyModeActive() { result = append(result, &boxlayout.Box{ Window: "information", // unlike appStatus, informationStr has various colors so we need to decolorise before taking the length @@ -188,12 +213,12 @@ func (self *WindowArranger) infoSectionChildren(informationStr string, appStatus } func (self *WindowArranger) splitMainPanelSideBySide() bool { - if !self.gui.isMainPanelSplit() { + if !self.c.State().GetRepoState().GetSplitMainPanel() { return false } - mainPanelSplitMode := self.gui.c.UserConfig.Gui.MainPanelSplitMode - width, height := self.gui.g.Size() + mainPanelSplitMode := self.c.UserConfig.Gui.MainPanelSplitMode + width, height := self.c.GocuiGui().Size() switch mainPanelSplitMode { case "vertical": @@ -210,17 +235,17 @@ func (self *WindowArranger) splitMainPanelSideBySide() bool { } func (self *WindowArranger) getExtrasWindowSize(screenHeight int) int { - if !self.gui.ShowExtrasWindow { + if !self.c.State().GetShowExtrasWindow() { return 0 } var baseSize int - if self.gui.c.CurrentStaticContext().GetKey() == context.COMMAND_LOG_CONTEXT_KEY { + if self.c.CurrentStaticContext().GetKey() == context.COMMAND_LOG_CONTEXT_KEY { baseSize = 1000 // my way of saying 'fill the available space' } else if screenHeight < 40 { baseSize = 1 } else { - baseSize = self.gui.c.UserConfig.Gui.CommandLogSize + baseSize = self.c.UserConfig.Gui.CommandLogSize } frameSize := 2 @@ -232,16 +257,14 @@ func (self *WindowArranger) getExtrasWindowSize(screenHeight int) int { // the default behaviour when accordion mode is NOT in effect. If it is in effect // then when it's accessed it will have weight 2, not 1. func (self *WindowArranger) getDefaultStashWindowBox() *boxlayout.Box { - self.gui.State.ContextMgr.RLock() - defer self.gui.State.ContextMgr.RUnlock() - - box := &boxlayout.Box{Window: "stash"} stashWindowAccessed := false - for _, context := range self.gui.State.ContextMgr.ContextStack { + self.c.Context().ForEach(func(context types.Context) { if context.GetWindowName() == "stash" { stashWindowAccessed = true } - } + }) + + box := &boxlayout.Box{Window: "stash"} // if the stash window is anywhere in our stack we should enlargen it if stashWindowAccessed { box.Weight = 1 @@ -253,9 +276,10 @@ func (self *WindowArranger) getDefaultStashWindowBox() *boxlayout.Box { } func (self *WindowArranger) sidePanelChildren(width int, height int) []*boxlayout.Box { - currentWindow := self.currentSideWindowName() + currentWindow := self.c.CurrentSideContext().GetWindowName() - if self.gui.State.ScreenMode == types.SCREEN_FULL || self.gui.State.ScreenMode == types.SCREEN_HALF { + screenMode := self.c.State().GetRepoState().GetScreenMode() + if screenMode == types.SCREEN_FULL || screenMode == types.SCREEN_HALF { fullHeightBox := func(window string) *boxlayout.Box { if window == currentWindow { return &boxlayout.Box{ @@ -278,7 +302,7 @@ func (self *WindowArranger) sidePanelChildren(width int, height int) []*boxlayou fullHeightBox("stash"), } } else if height >= 28 { - accordionMode := self.gui.c.UserConfig.Gui.ExpandFocusedSidePanel + accordionMode := self.c.UserConfig.Gui.ExpandFocusedSidePanel accordionBox := func(defaultBox *boxlayout.Box) *boxlayout.Box { if accordionMode && defaultBox.Window == currentWindow { return &boxlayout.Box{ @@ -329,20 +353,3 @@ func (self *WindowArranger) sidePanelChildren(width int, height int) []*boxlayou } } } - -func (self *WindowArranger) currentSideWindowName() string { - // there is always one and only one cyclable context in the context stack. We'll look from top to bottom - self.gui.State.ContextMgr.RLock() - defer self.gui.State.ContextMgr.RUnlock() - - for idx := range self.gui.State.ContextMgr.ContextStack { - reversedIdx := len(self.gui.State.ContextMgr.ContextStack) - 1 - idx - context := self.gui.State.ContextMgr.ContextStack[reversedIdx] - - if context.GetKind() == types.SIDE_CONTEXT { - return context.GetWindowName() - } - } - - return "files" // default -} diff --git a/pkg/gui/context.go b/pkg/gui/context.go index 3adafd710..3550e9eef 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -20,17 +20,17 @@ type ContextMgr struct { gui *Gui } -func NewContextMgr(initialContext types.Context, gui *Gui) ContextMgr { - return ContextMgr{ - ContextStack: []types.Context{}, +func NewContextMgr(initialContext types.Context, gui *Gui) *ContextMgr { + return &ContextMgr{ + ContextStack: []types.Context{initialContext}, RWMutex: sync.RWMutex{}, gui: gui, } } -// use replaceContext when you don't want to return to the original context upon +// use when you don't want to return to the original context upon // hitting escape: you want to go that context's parent instead. -func (self *ContextMgr) replaceContext(c types.Context) error { +func (self *ContextMgr) Replace(c types.Context) error { if !c.IsFocusable() { return nil } @@ -49,9 +49,9 @@ func (self *ContextMgr) replaceContext(c types.Context) error { return self.activateContext(c, types.OnFocusOpts{}) } -func (self *ContextMgr) pushContext(c types.Context, opts ...types.OnFocusOpts) error { +func (self *ContextMgr) Push(c types.Context, opts ...types.OnFocusOpts) error { if len(opts) > 1 { - return errors.New("cannot pass multiple opts to pushContext") + return errors.New("cannot pass multiple opts to Push") } singleOpts := types.OnFocusOpts{} @@ -135,7 +135,7 @@ func (self *ContextMgr) pushToContextStack(c types.Context) ([]types.Context, ty return contextsToDeactivate, c } -func (self *ContextMgr) popContext() error { +func (self *ContextMgr) Pop() error { self.Lock() if len(self.ContextStack) == 1 { @@ -213,7 +213,7 @@ func (self *ContextMgr) activateContext(c types.Context, opts types.OnFocusOpts) return nil } -func (self *ContextMgr) currentContext() types.Context { +func (self *ContextMgr) Current() types.Context { self.RLock() defer self.RUnlock() @@ -229,17 +229,12 @@ func (self *ContextMgr) currentContextWithoutLock() types.Context { } // Note that this could return the 'status' context which is not itself a list context. -func (self *ContextMgr) currentSideContext() types.Context { +func (self *ContextMgr) CurrentSide() types.Context { self.RLock() defer self.RUnlock() stack := self.ContextStack - // on startup the stack can be empty so we'll return an empty string in that case - if len(stack) == 0 { - return self.gui.defaultSideContext() - } - // find the first context in the stack with the type of types.SIDE_CONTEXT for i := range stack { context := stack[len(stack)-1-i] @@ -253,7 +248,7 @@ func (self *ContextMgr) currentSideContext() types.Context { } // static as opposed to popup -func (self *ContextMgr) currentStaticContext() types.Context { +func (self *ContextMgr) CurrentStatic() types.Context { self.RLock() defer self.RUnlock() @@ -278,3 +273,16 @@ func (self *ContextMgr) currentStaticContextWithoutLock() types.Context { return self.gui.defaultSideContext() } + +func (self *ContextMgr) ForEach(f func(types.Context)) { + self.RLock() + defer self.RUnlock() + + for _, context := range self.gui.State.ContextMgr.ContextStack { + f(context) + } +} + +func (self *ContextMgr) IsCurrent(c types.Context) bool { + return self.Current().GetKey() == c.GetKey() +} diff --git a/pkg/gui/context/setup.go b/pkg/gui/context/setup.go new file mode 100644 index 000000000..f6a07ddd2 --- /dev/null +++ b/pkg/gui/context/setup.go @@ -0,0 +1,136 @@ +package context + +import "github.com/jesseduffield/lazygit/pkg/gui/types" + +func NewContextTree(c *ContextCommon) *ContextTree { + commitFilesContext := NewCommitFilesContext(c) + + return &ContextTree{ + Global: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.GLOBAL_CONTEXT, + View: nil, // TODO: see if this breaks anything + WindowName: "", + Key: GLOBAL_CONTEXT_KEY, + Focusable: false, + HasUncontrolledBounds: true, // setting to true because the global context doesn't even have a view + }), + ), + Status: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.SIDE_CONTEXT, + View: c.Views().Status, + WindowName: "status", + Key: STATUS_CONTEXT_KEY, + Focusable: true, + }), + ), + Files: NewWorkingTreeContext(c), + Submodules: NewSubmodulesContext(c), + Menu: NewMenuContext(c), + Remotes: NewRemotesContext(c), + RemoteBranches: NewRemoteBranchesContext(c), + LocalCommits: NewLocalCommitsContext(c), + CommitFiles: commitFilesContext, + ReflogCommits: NewReflogCommitsContext(c), + SubCommits: NewSubCommitsContext(c), + Branches: NewBranchesContext(c), + Tags: NewTagsContext(c), + Stash: NewStashContext(c), + Suggestions: NewSuggestionsContext(c), + Normal: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + View: c.Views().Main, + WindowName: "main", + Key: NORMAL_MAIN_CONTEXT_KEY, + Focusable: false, + }), + ), + NormalSecondary: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + View: c.Views().Secondary, + WindowName: "secondary", + Key: NORMAL_SECONDARY_CONTEXT_KEY, + Focusable: false, + }), + ), + Staging: NewPatchExplorerContext( + c.Views().Staging, + "main", + STAGING_MAIN_CONTEXT_KEY, + func() []int { return nil }, + c, + ), + StagingSecondary: NewPatchExplorerContext( + c.Views().StagingSecondary, + "secondary", + STAGING_SECONDARY_CONTEXT_KEY, + func() []int { return nil }, + c, + ), + CustomPatchBuilder: NewPatchExplorerContext( + c.Views().PatchBuilding, + "main", + PATCH_BUILDING_MAIN_CONTEXT_KEY, + func() []int { + filename := commitFilesContext.GetSelectedPath() + includedLineIndices, err := c.Git().Patch.PatchBuilder.GetFileIncLineIndices(filename) + if err != nil { + c.Log.Error(err) + return nil + } + + return includedLineIndices + }, + c, + ), + CustomPatchBuilderSecondary: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + View: c.Views().PatchBuildingSecondary, + WindowName: "secondary", + Key: PATCH_BUILDING_SECONDARY_CONTEXT_KEY, + Focusable: false, + }), + ), + MergeConflicts: NewMergeConflictsContext( + c, + ), + Confirmation: NewConfirmationContext(c), + CommitMessage: NewCommitMessageContext(c), + Search: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.PERSISTENT_POPUP, + View: c.Views().Search, + WindowName: "search", + Key: SEARCH_CONTEXT_KEY, + Focusable: true, + }), + ), + CommandLog: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.EXTRAS_CONTEXT, + View: c.Views().Extras, + WindowName: "extras", + Key: COMMAND_LOG_CONTEXT_KEY, + Focusable: true, + }), + ), + Snake: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.SIDE_CONTEXT, + View: c.Views().Snake, + WindowName: "files", + Key: SNAKE_CONTEXT_KEY, + Focusable: true, + }), + ), + Options: NewDisplayContext(OPTIONS_CONTEXT_KEY, c.Views().Options, "options"), + AppStatus: NewDisplayContext(APP_STATUS_CONTEXT_KEY, c.Views().AppStatus, "appStatus"), + SearchPrefix: NewDisplayContext(SEARCH_PREFIX_CONTEXT_KEY, c.Views().SearchPrefix, "searchPrefix"), + Information: NewDisplayContext(INFORMATION_CONTEXT_KEY, c.Views().Information, "information"), + Limit: NewDisplayContext(LIMIT_CONTEXT_KEY, c.Views().Limit, "limit"), + } +} diff --git a/pkg/gui/context_config.go b/pkg/gui/context_config.go index 8e59732c8..4dcddb3ea 100644 --- a/pkg/gui/context_config.go +++ b/pkg/gui/context_config.go @@ -7,134 +7,11 @@ import ( ) func (gui *Gui) contextTree() *context.ContextTree { - return &context.ContextTree{ - Global: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.GLOBAL_CONTEXT, - View: nil, // TODO: see if this breaks anything - WindowName: "", - Key: context.GLOBAL_CONTEXT_KEY, - Focusable: false, - HasUncontrolledBounds: true, // setting to true because the global context doesn't even have a view - }), - ), - Status: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.SIDE_CONTEXT, - View: gui.Views.Status, - WindowName: "status", - Key: context.STATUS_CONTEXT_KEY, - Focusable: true, - }), - ), - Snake: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.SIDE_CONTEXT, - View: gui.Views.Snake, - WindowName: "files", - Key: context.SNAKE_CONTEXT_KEY, - Focusable: true, - }), - ), - Files: gui.filesListContext(), - Submodules: gui.submodulesListContext(), - Menu: gui.menuListContext(), - Remotes: gui.remotesListContext(), - RemoteBranches: gui.remoteBranchesListContext(), - LocalCommits: gui.branchCommitsListContext(), - CommitFiles: gui.commitFilesListContext(), - ReflogCommits: gui.reflogCommitsListContext(), - SubCommits: gui.subCommitsListContext(), - Branches: gui.branchesListContext(), - Tags: gui.tagsListContext(), - Stash: gui.stashListContext(), - Suggestions: gui.suggestionsListContext(), - Normal: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.MAIN_CONTEXT, - View: gui.Views.Main, - WindowName: "main", - Key: context.NORMAL_MAIN_CONTEXT_KEY, - Focusable: false, - }), - ), - NormalSecondary: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.MAIN_CONTEXT, - View: gui.Views.Secondary, - WindowName: "secondary", - Key: context.NORMAL_SECONDARY_CONTEXT_KEY, - Focusable: false, - }), - ), - Staging: context.NewPatchExplorerContext( - gui.Views.Staging, - "main", - context.STAGING_MAIN_CONTEXT_KEY, - func() []int { return nil }, - gui.contextCommon, - ), - StagingSecondary: context.NewPatchExplorerContext( - gui.Views.StagingSecondary, - "secondary", - context.STAGING_SECONDARY_CONTEXT_KEY, - func() []int { return nil }, - gui.contextCommon, - ), - CustomPatchBuilder: context.NewPatchExplorerContext( - gui.Views.PatchBuilding, - "main", - context.PATCH_BUILDING_MAIN_CONTEXT_KEY, - func() []int { - filename := gui.State.Contexts.CommitFiles.GetSelectedPath() - includedLineIndices, err := gui.git.Patch.PatchBuilder.GetFileIncLineIndices(filename) - if err != nil { - gui.Log.Error(err) - return nil - } - - return includedLineIndices - }, - gui.contextCommon, - ), - CustomPatchBuilderSecondary: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.MAIN_CONTEXT, - View: gui.Views.PatchBuildingSecondary, - WindowName: "secondary", - Key: context.PATCH_BUILDING_SECONDARY_CONTEXT_KEY, - Focusable: false, - }), - ), - MergeConflicts: context.NewMergeConflictsContext( - gui.contextCommon, - ), - Confirmation: context.NewConfirmationContext(gui.contextCommon), - CommitMessage: context.NewCommitMessageContext(gui.contextCommon), - Search: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.PERSISTENT_POPUP, - View: gui.Views.Search, - WindowName: "search", - Key: context.SEARCH_CONTEXT_KEY, - Focusable: true, - }), - ), - CommandLog: context.NewSimpleContext( - context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.EXTRAS_CONTEXT, - View: gui.Views.Extras, - WindowName: "extras", - Key: context.COMMAND_LOG_CONTEXT_KEY, - Focusable: true, - }), - ), - Options: context.NewDisplayContext(context.OPTIONS_CONTEXT_KEY, gui.Views.Options, "options"), - AppStatus: context.NewDisplayContext(context.APP_STATUS_CONTEXT_KEY, gui.Views.AppStatus, "appStatus"), - SearchPrefix: context.NewDisplayContext(context.SEARCH_PREFIX_CONTEXT_KEY, gui.Views.SearchPrefix, "searchPrefix"), - Information: context.NewDisplayContext(context.INFORMATION_CONTEXT_KEY, gui.Views.Information, "information"), - Limit: context.NewDisplayContext(context.LIMIT_CONTEXT_KEY, gui.Views.Limit, "limit"), + contextCommon := &context.ContextCommon{ + IGuiCommon: gui.c.IGuiCommon, + Common: gui.c.Common, } + return context.NewContextTree(contextCommon) } // using this wrapper for when an onFocus function doesn't care about any potential @@ -145,14 +22,6 @@ func OnFocusWrapper(f func() error) func(opts types.OnFocusOpts) error { } } -func (gui *Gui) getPatchExplorerContexts() []types.IPatchExplorerContext { - return []types.IPatchExplorerContext{ - gui.State.Contexts.Staging, - gui.State.Contexts.StagingSecondary, - gui.State.Contexts.CustomPatchBuilder, - } -} - func (gui *Gui) popupViewNames() []string { popups := slices.Filter(gui.State.Contexts.Flatten(), func(c types.Context) bool { return c.GetKind() == types.PERSISTENT_POPUP || c.GetKind() == types.TEMPORARY_POPUP @@ -176,3 +45,29 @@ func (gui *Gui) TransientContexts() []types.Context { return context.IsTransient() }) } + +func (gui *Gui) getListContexts() []types.IListContext { + return []types.IListContext{ + gui.State.Contexts.Menu, + gui.State.Contexts.Files, + gui.State.Contexts.Branches, + gui.State.Contexts.Remotes, + gui.State.Contexts.RemoteBranches, + gui.State.Contexts.Tags, + gui.State.Contexts.LocalCommits, + gui.State.Contexts.ReflogCommits, + gui.State.Contexts.SubCommits, + gui.State.Contexts.Stash, + gui.State.Contexts.CommitFiles, + gui.State.Contexts.Submodules, + gui.State.Contexts.Suggestions, + } +} + +func (gui *Gui) getPatchExplorerContexts() []types.IPatchExplorerContext { + return []types.IPatchExplorerContext{ + gui.State.Contexts.Staging, + gui.State.Contexts.StagingSecondary, + gui.State.Contexts.CustomPatchBuilder, + } +} diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index 8ec2303d4..75366fcdd 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -8,9 +8,14 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/controllers" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands" + "github.com/jesseduffield/lazygit/pkg/gui/status" "github.com/jesseduffield/lazygit/pkg/gui/types" ) +func (gui *Gui) Helpers() *helpers.Helpers { + return gui.helpers +} + func (gui *Gui) resetControllers() { helperCommon := gui.c refsHelper := helpers.NewRefsHelper(helperCommon) @@ -28,27 +33,30 @@ func (gui *Gui) resetControllers() { stagingHelper := helpers.NewStagingHelper(helperCommon) mergeConflictsHelper := helpers.NewMergeConflictsHelper(helperCommon) refreshHelper := helpers.NewRefreshHelper(helperCommon, refsHelper, rebaseHelper, patchBuildingHelper, stagingHelper, mergeConflictsHelper, gui.fileWatcher) + diffHelper := helpers.NewDiffHelper(helperCommon) + cherryPickHelper := helpers.NewCherryPickHelper( + helperCommon, + rebaseHelper, + ) + bisectHelper := helpers.NewBisectHelper(helperCommon) gui.helpers = &helpers.Helpers{ - Refs: refsHelper, - Host: helpers.NewHostHelper(helperCommon), - PatchBuilding: patchBuildingHelper, - Staging: stagingHelper, - Bisect: helpers.NewBisectHelper(helperCommon), - Suggestions: suggestionsHelper, - Files: helpers.NewFilesHelper(helperCommon), - WorkingTree: helpers.NewWorkingTreeHelper(helperCommon, refsHelper, setCommitMessage, getSavedCommitMessage), - Tags: helpers.NewTagsHelper(helperCommon), - GPG: gpgHelper, - MergeAndRebase: rebaseHelper, - MergeConflicts: mergeConflictsHelper, - CherryPick: helpers.NewCherryPickHelper( - helperCommon, - rebaseHelper, - ), + Refs: refsHelper, + Host: helpers.NewHostHelper(helperCommon), + PatchBuilding: patchBuildingHelper, + Staging: stagingHelper, + Bisect: bisectHelper, + Suggestions: suggestionsHelper, + Files: helpers.NewFilesHelper(helperCommon), + WorkingTree: helpers.NewWorkingTreeHelper(helperCommon, refsHelper, setCommitMessage, getSavedCommitMessage), + Tags: helpers.NewTagsHelper(helperCommon), + GPG: helpers.NewGpgHelper(helperCommon), + MergeAndRebase: rebaseHelper, + MergeConflicts: mergeConflictsHelper, + CherryPick: cherryPickHelper, Upstream: helpers.NewUpstreamHelper(helperCommon, suggestionsHelper.GetRemoteBranchesSuggestionsFunc), AmendHelper: helpers.NewAmendHelper(helperCommon, gpgHelper), Snake: helpers.NewSnakeHelper(helperCommon), - Diff: helpers.NewDiffHelper(helperCommon), + Diff: diffHelper, Repos: helpers.NewRecentReposHelper(helperCommon, recordDirectoryHelper, gui.onNewRepo), RecordDirectory: recordDirectoryHelper, Update: helpers.NewUpdateHelper(helperCommon, gui.Updater), @@ -56,17 +64,26 @@ func (gui *Gui) resetControllers() { View: viewHelper, Refresh: refreshHelper, Confirmation: helpers.NewConfirmationHelper(helperCommon), + Mode: helpers.NewModeHelper( + helperCommon, + diffHelper, + patchBuildingHelper, + cherryPickHelper, + rebaseHelper, + bisectHelper, + ), + AppStatus: helpers.NewAppStatusHelper( + helperCommon, + func() *status.StatusManager { return gui.statusManager }, + ), } gui.CustomCommandsClient = custom_commands.NewClient( helperCommon, - gui.os, - gui.git, - gui.State.Contexts, gui.helpers, ) - common := controllers.NewControllerCommon(helperCommon, gui.helpers) + common := controllers.NewControllerCommon(helperCommon, gui) syncController := controllers.NewSyncController( common, diff --git a/pkg/gui/controllers/basic_commits_controller.go b/pkg/gui/controllers/basic_commits_controller.go index 340b14c0b..f2c794abc 100644 --- a/pkg/gui/controllers/basic_commits_controller.go +++ b/pkg/gui/controllers/basic_commits_controller.go @@ -20,15 +20,15 @@ type ContainsCommits interface { type BasicCommitsController struct { baseController - *controllerCommon + c *ControllerCommon context ContainsCommits } -func NewBasicCommitsController(controllerCommon *controllerCommon, context ContainsCommits) *BasicCommitsController { +func NewBasicCommitsController(controllerCommon *ControllerCommon, context ContainsCommits) *BasicCommitsController { return &BasicCommitsController{ - baseController: baseController{}, - controllerCommon: controllerCommon, - context: context, + baseController: baseController{}, + c: controllerCommon, + context: context, } } @@ -73,7 +73,7 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [ }, { Key: opts.GetKey(opts.Config.Commits.ResetCherryPick), - Handler: self.helpers.CherryPick.Reset, + Handler: self.c.Helpers().CherryPick.Reset, Description: self.c.Tr.LcResetCherryPick, }, } @@ -150,7 +150,7 @@ func (self *BasicCommitsController) copyCommitSHAToClipboard(commit *models.Comm } func (self *BasicCommitsController) copyCommitURLToClipboard(commit *models.Commit) error { - url, err := self.helpers.Host.GetCommitURL(commit.Sha) + url, err := self.c.Helpers().Host.GetCommitURL(commit.Sha) if err != nil { return err } @@ -212,7 +212,7 @@ func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models. } func (self *BasicCommitsController) openInBrowser(commit *models.Commit) error { - url, err := self.helpers.Host.GetCommitURL(commit.Sha) + url, err := self.c.Helpers().Host.GetCommitURL(commit.Sha) if err != nil { return self.c.Error(err) } @@ -226,11 +226,11 @@ func (self *BasicCommitsController) openInBrowser(commit *models.Commit) error { } func (self *BasicCommitsController) newBranch(commit *models.Commit) error { - return self.helpers.Refs.NewBranch(commit.RefName(), commit.Description(), "") + return self.c.Helpers().Refs.NewBranch(commit.RefName(), commit.Description(), "") } func (self *BasicCommitsController) createResetMenu(commit *models.Commit) error { - return self.helpers.Refs.CreateGitResetMenu(commit.Sha) + return self.c.Helpers().Refs.CreateGitResetMenu(commit.Sha) } func (self *BasicCommitsController) checkout(commit *models.Commit) error { @@ -239,15 +239,15 @@ func (self *BasicCommitsController) checkout(commit *models.Commit) error { Prompt: self.c.Tr.SureCheckoutThisCommit, HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.CheckoutCommit) - return self.helpers.Refs.CheckoutRef(commit.Sha, types.CheckoutRefOptions{}) + return self.c.Helpers().Refs.CheckoutRef(commit.Sha, types.CheckoutRefOptions{}) }, }) } func (self *BasicCommitsController) copy(commit *models.Commit) error { - return self.helpers.CherryPick.Copy(commit, self.context.GetCommits(), self.context) + return self.c.Helpers().CherryPick.Copy(commit, self.context.GetCommits(), self.context) } func (self *BasicCommitsController) copyRange(*models.Commit) error { - return self.helpers.CherryPick.CopyRange(self.context.GetSelectedLineIdx(), self.context.GetCommits(), self.context) + return self.c.Helpers().CherryPick.CopyRange(self.context.GetSelectedLineIdx(), self.context.GetCommits(), self.context) } diff --git a/pkg/gui/controllers/bisect_controller.go b/pkg/gui/controllers/bisect_controller.go index 6531b1409..9aab43ee7 100644 --- a/pkg/gui/controllers/bisect_controller.go +++ b/pkg/gui/controllers/bisect_controller.go @@ -12,17 +12,17 @@ import ( type BisectController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &BisectController{} func NewBisectController( - common *controllerCommon, + common *ControllerCommon, ) *BisectController { return &BisectController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -105,7 +105,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c { Label: self.c.Tr.Bisect.ResetOption, OnPress: func() error { - return self.helpers.Bisect.Reset() + return self.c.Helpers().Bisect.Reset() }, Key: 'r', }, @@ -133,7 +133,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo, return self.c.Error(err) } - return self.helpers.Bisect.PostBisectCommandRefresh() + return self.c.Helpers().Bisect.PostBisectCommandRefresh() }, Key: 'b', }, @@ -149,7 +149,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo, return self.c.Error(err) } - return self.helpers.Bisect.PostBisectCommandRefresh() + return self.c.Helpers().Bisect.PostBisectCommandRefresh() }, Key: 'g', }, @@ -177,7 +177,7 @@ func (self *BisectController) showBisectCompleteMessage(candidateShas []string) return self.c.Error(err) } - return self.helpers.Bisect.PostBisectCommandRefresh() + return self.c.Helpers().Bisect.PostBisectCommandRefresh() }, }) } @@ -211,7 +211,7 @@ func (self *BisectController) afterBisectMarkRefresh(selectCurrent bool, waitToR } else { selectFn() - return self.helpers.Bisect.PostBisectCommandRefresh() + return self.c.Helpers().Bisect.PostBisectCommandRefresh() } } diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go index 03e088368..a39fe18e2 100644 --- a/pkg/gui/controllers/branches_controller.go +++ b/pkg/gui/controllers/branches_controller.go @@ -14,17 +14,17 @@ import ( type BranchesController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &BranchesController{} func NewBranchesController( - common *controllerCommon, + common *ControllerCommon, ) *BranchesController { return &BranchesController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -113,7 +113,7 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty func (self *BranchesController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask branch := self.context().GetSelected() if branch == nil { @@ -161,8 +161,8 @@ func (self *BranchesController) setUpstream(selectedBranch *models.Branch) error { LabelColumns: []string{self.c.Tr.LcSetUpstream}, OnPress: func() error { - return self.helpers.Upstream.PromptForUpstreamWithoutInitialContent(selectedBranch, func(upstream string) error { - upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream) + return self.c.Helpers().Upstream.PromptForUpstreamWithoutInitialContent(selectedBranch, func(upstream string) error { + upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream) if err != nil { return self.c.Error(err) } @@ -197,12 +197,12 @@ func (self *BranchesController) context() *context.BranchesContext { } func (self *BranchesController) press(selectedBranch *models.Branch) error { - if selectedBranch == self.helpers.Refs.GetCheckedOutRef() { + if selectedBranch == self.c.Helpers().Refs.GetCheckedOutRef() { return self.c.ErrorMsg(self.c.Tr.AlreadyCheckedOutBranch) } self.c.LogAction(self.c.Tr.Actions.CheckoutBranch) - return self.helpers.Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{}) + return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{}) } func (self *BranchesController) handleCreatePullRequest(selectedBranch *models.Branch) error { @@ -210,7 +210,7 @@ func (self *BranchesController) handleCreatePullRequest(selectedBranch *models.B } func (self *BranchesController) handleCreatePullRequestMenu(selectedBranch *models.Branch) error { - checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() + checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef() return self.createPullRequestMenu(selectedBranch, checkedOutBranch) } @@ -224,7 +224,7 @@ func (self *BranchesController) copyPullRequestURL() error { return self.c.Error(errors.New(self.c.Tr.NoBranchOnRemote)) } - url, err := self.helpers.Host.GetPullRequestURL(branch.Name, "") + url, err := self.c.Helpers().Host.GetPullRequestURL(branch.Name, "") if err != nil { return self.c.Error(err) } @@ -259,10 +259,10 @@ func (self *BranchesController) forceCheckout() error { func (self *BranchesController) checkoutByName() error { return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.BranchName + ":", - FindSuggestionsFunc: self.helpers.Suggestions.GetRefsSuggestionsFunc(), + FindSuggestionsFunc: self.c.Helpers().Suggestions.GetRefsSuggestionsFunc(), HandleConfirm: func(response string) error { self.c.LogAction("Checkout branch") - return self.helpers.Refs.CheckoutRef(response, types.CheckoutRefOptions{ + return self.c.Helpers().Refs.CheckoutRef(response, types.CheckoutRefOptions{ OnRefNotFound: func(ref string) error { return self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.BranchNotFoundTitle, @@ -293,7 +293,7 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er } func (self *BranchesController) delete(branch *models.Branch) error { - checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() + checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef() if checkedOutBranch.Name == branch.Name { return self.c.ErrorMsg(self.c.Tr.CantDeleteCheckOutBranch) } @@ -334,12 +334,12 @@ func (self *BranchesController) deleteWithForce(selectedBranch *models.Branch, f func (self *BranchesController) merge() error { selectedBranchName := self.context().GetSelected().Name - return self.helpers.MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName) + return self.c.Helpers().MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName) } func (self *BranchesController) rebase() error { selectedBranchName := self.context().GetSelected().Name - return self.helpers.MergeAndRebase.RebaseOntoRef(selectedBranchName) + return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName) } func (self *BranchesController) fastForward(branch *models.Branch) error { @@ -364,7 +364,7 @@ func (self *BranchesController) fastForward(branch *models.Branch) error { ) return self.c.WithLoaderPanel(message, func() error { - if branch == self.helpers.Refs.GetCheckedOutRef() { + if branch == self.c.Helpers().Refs.GetCheckedOutRef() { self.c.LogAction(action) err := self.c.Git().Sync.Pull( @@ -393,11 +393,11 @@ func (self *BranchesController) fastForward(branch *models.Branch) error { } func (self *BranchesController) createTag(branch *models.Branch) error { - return self.helpers.Tags.CreateTagMenu(branch.FullRefName(), func() {}) + return self.c.Helpers().Tags.CreateTagMenu(branch.FullRefName(), func() {}) } func (self *BranchesController) createResetMenu(selectedBranch *models.Branch) error { - return self.helpers.Refs.CreateGitResetMenu(selectedBranch.Name) + return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.Name) } func (self *BranchesController) rename(branch *models.Branch) error { @@ -444,7 +444,7 @@ func (self *BranchesController) rename(branch *models.Branch) error { } func (self *BranchesController) newBranch(selectedBranch *models.Branch) error { - return self.helpers.Refs.NewBranch(selectedBranch.FullRefName(), selectedBranch.RefName(), "") + return self.c.Helpers().Refs.NewBranch(selectedBranch.FullRefName(), selectedBranch.RefName(), "") } func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Branch, checkedOutBranch *models.Branch) error { @@ -467,7 +467,7 @@ func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Bra OnPress: func() error { return self.c.Prompt(types.PromptOpts{ Title: branch.Name + " →", - FindSuggestionsFunc: self.helpers.Suggestions.GetBranchNameSuggestionsFunc(), + FindSuggestionsFunc: self.c.Helpers().Suggestions.GetBranchNameSuggestionsFunc(), HandleConfirm: func(targetBranchName string) error { return self.createPullRequest(branch.Name, targetBranchName) }, @@ -495,7 +495,7 @@ func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Bra } func (self *BranchesController) createPullRequest(from string, to string) error { - url, err := self.helpers.Host.GetPullRequestURL(from, to) + url, err := self.c.Helpers().Host.GetPullRequestURL(from, to) if err != nil { return self.c.Error(err) } diff --git a/pkg/gui/controllers/command_log_controller.go b/pkg/gui/controllers/command_log_controller.go index 3e6e7c11a..0c3479914 100644 --- a/pkg/gui/controllers/command_log_controller.go +++ b/pkg/gui/controllers/command_log_controller.go @@ -6,17 +6,17 @@ import ( type CommandLogController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &CommandLogController{} func NewCommandLogController( - common *controllerCommon, + common *ControllerCommon, ) *CommandLogController { return &CommandLogController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } diff --git a/pkg/gui/controllers/commit_message_controller.go b/pkg/gui/controllers/commit_message_controller.go index 1b28ec887..481d65c4c 100644 --- a/pkg/gui/controllers/commit_message_controller.go +++ b/pkg/gui/controllers/commit_message_controller.go @@ -7,7 +7,7 @@ import ( type CommitMessageController struct { baseController - *controllerCommon + c *ControllerCommon getCommitMessage func() string onCommitAttempt func(message string) @@ -17,14 +17,14 @@ type CommitMessageController struct { var _ types.IController = &CommitMessageController{} func NewCommitMessageController( - common *controllerCommon, + common *ControllerCommon, getCommitMessage func() string, onCommitAttempt func(message string), onCommitSuccess func(), ) *CommitMessageController { return &CommitMessageController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, getCommitMessage: getCommitMessage, onCommitAttempt: onCommitAttempt, @@ -80,7 +80,7 @@ func (self *CommitMessageController) confirm() error { self.c.LogAction(self.c.Tr.Actions.Commit) _ = self.c.PopContext() - return self.helpers.GPG.WithGpgHandling(cmdObj, self.c.Tr.CommittingStatus, func() error { + return self.c.Helpers().GPG.WithGpgHandling(cmdObj, self.c.Tr.CommittingStatus, func() error { self.onCommitSuccess() return nil }) diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 34e859211..8ef5f2c57 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -11,17 +11,17 @@ import ( type CommitFilesController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &CommitFilesController{} func NewCommitFilesController( - common *controllerCommon, + common *ControllerCommon, ) *CommitFilesController { return &CommitFilesController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -120,7 +120,7 @@ func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error } func (self *CommitFilesController) discard(node *filetree.CommitFileNode) error { - if ok, err := self.helpers.PatchBuilding.ValidateNormalWorkingTreeState(); !ok { + if ok, err := self.c.Helpers().PatchBuilding.ValidateNormalWorkingTreeState(); !ok { return err } @@ -131,7 +131,7 @@ func (self *CommitFilesController) discard(node *filetree.CommitFileNode) error return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func() error { self.c.LogAction(self.c.Tr.Actions.DiscardOldFileChange) if err := self.c.Git().Rebase.DiscardOldFileChanges(self.c.Model().Commits, self.c.Contexts().LocalCommits.GetSelectedLineIdx(), node.GetPath()); err != nil { - if err := self.helpers.MergeAndRebase.CheckMergeOrRebase(err); err != nil { + if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err); err != nil { return err } } @@ -143,7 +143,7 @@ func (self *CommitFilesController) discard(node *filetree.CommitFileNode) error } func (self *CommitFilesController) open(node *filetree.CommitFileNode) error { - return self.helpers.Files.OpenFile(node.GetPath()) + return self.c.Helpers().Files.OpenFile(node.GetPath()) } func (self *CommitFilesController) edit(node *filetree.CommitFileNode) error { @@ -151,7 +151,7 @@ func (self *CommitFilesController) edit(node *filetree.CommitFileNode) error { return self.c.ErrorMsg(self.c.Tr.ErrCannotEditDirectory) } - return self.helpers.Files.EditFile(node.GetPath()) + return self.c.Helpers().Files.EditFile(node.GetPath()) } func (self *CommitFilesController) toggleForPatch(node *filetree.CommitFileNode) error { diff --git a/pkg/gui/controllers/common.go b/pkg/gui/controllers/common.go index 1c14b7f4e..3498ad59d 100644 --- a/pkg/gui/controllers/common.go +++ b/pkg/gui/controllers/common.go @@ -4,17 +4,21 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" ) -type controllerCommon struct { - c *helpers.HelperCommon - helpers *helpers.Helpers +type ControllerCommon struct { + *helpers.HelperCommon + IGetHelpers +} + +type IGetHelpers interface { + Helpers() *helpers.Helpers } func NewControllerCommon( c *helpers.HelperCommon, - helpers *helpers.Helpers, -) *controllerCommon { - return &controllerCommon{ - c: c, - helpers: helpers, + IGetHelpers IGetHelpers, +) *ControllerCommon { + return &ControllerCommon{ + HelperCommon: c, + IGetHelpers: IGetHelpers, } } diff --git a/pkg/gui/controllers/confirmation_controller.go b/pkg/gui/controllers/confirmation_controller.go index 09496f721..09af35586 100644 --- a/pkg/gui/controllers/confirmation_controller.go +++ b/pkg/gui/controllers/confirmation_controller.go @@ -7,17 +7,17 @@ import ( type ConfirmationController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &ConfirmationController{} func NewConfirmationController( - common *controllerCommon, + common *ControllerCommon, ) *ConfirmationController { return &ConfirmationController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -51,7 +51,7 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [ func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) error { return func(types.OnFocusLostOpts) error { - self.helpers.Confirmation.DeactivateConfirmationPrompt() + self.c.Helpers().Confirmation.DeactivateConfirmationPrompt() return nil } } diff --git a/pkg/gui/controllers/context_lines_controller.go b/pkg/gui/controllers/context_lines_controller.go index 913b763d0..5ec2d3167 100644 --- a/pkg/gui/controllers/context_lines_controller.go +++ b/pkg/gui/controllers/context_lines_controller.go @@ -24,17 +24,17 @@ var CONTEXT_KEYS_SHOWING_DIFFS = []types.ContextKey{ type ContextLinesController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &ContextLinesController{} func NewContextLinesController( - common *controllerCommon, + common *ControllerCommon, ) *ContextLinesController { return &ContextLinesController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 7d040704a..165878459 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -13,7 +13,7 @@ import ( type FilesController struct { baseController // nolint: unused - *controllerCommon + c *ControllerCommon setCommitMessage func(message string) getSavedCommitMessage func() string @@ -22,12 +22,12 @@ type FilesController struct { var _ types.IController = &FilesController{} func NewFilesController( - common *controllerCommon, + common *ControllerCommon, setCommitMessage func(message string), getSavedCommitMessage func() string, ) *FilesController { return &FilesController{ - controllerCommon: common, + c: common, setCommitMessage: setCommitMessage, getSavedCommitMessage: getSavedCommitMessage, } @@ -47,12 +47,12 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types }, { Key: opts.GetKey(opts.Config.Files.CommitChanges), - Handler: self.helpers.WorkingTree.HandleCommitPress, + Handler: self.c.Helpers().WorkingTree.HandleCommitPress, Description: self.c.Tr.CommitChanges, }, { Key: opts.GetKey(opts.Config.Files.CommitChangesWithoutHook), - Handler: self.helpers.WorkingTree.HandleWIPCommitPress, + Handler: self.c.Helpers().WorkingTree.HandleWIPCommitPress, Description: self.c.Tr.LcCommitChangesWithoutHook, }, { @@ -62,7 +62,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types }, { Key: opts.GetKey(opts.Config.Files.CommitChangesWithEditor), - Handler: self.helpers.WorkingTree.HandleCommitEditorPress, + Handler: self.c.Helpers().WorkingTree.HandleCommitEditorPress, Description: self.c.Tr.CommitChangesWithEditor, }, { @@ -126,7 +126,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types }, { Key: opts.GetKey(opts.Config.Files.OpenMergeTool), - Handler: self.helpers.WorkingTree.OpenMergeTool, + Handler: self.c.Helpers().WorkingTree.OpenMergeTool, Description: self.c.Tr.LcOpenMergeTool, }, { @@ -174,7 +174,7 @@ func (self *FilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []* func (self *FilesController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { node := self.context().GetSelected() if node == nil { @@ -188,17 +188,17 @@ func (self *FilesController) GetOnRenderToMain() func() error { } if node.File != nil && node.File.HasInlineMergeConflicts { - hasConflicts, err := self.helpers.MergeConflicts.SetMergeState(node.GetPath()) + hasConflicts, err := self.c.Helpers().MergeConflicts.SetMergeState(node.GetPath()) if err != nil { return err } if hasConflicts { - return self.helpers.MergeConflicts.Render(false) + return self.c.Helpers().MergeConflicts.Render(false) } } - self.helpers.MergeConflicts.ResetMergeState() + self.c.Helpers().MergeConflicts.ResetMergeState() pair := self.c.MainViewPairs().Normal if node.File != nil { @@ -444,7 +444,7 @@ func (self *FilesController) EnterFile(opts types.OnFocusOpts) error { submoduleConfigs := self.c.Model().Submodules if file.IsSubmodule(submoduleConfigs) { submoduleConfig := file.SubmoduleConfig(submoduleConfigs) - return self.helpers.Repos.EnterSubmodule(submoduleConfig) + return self.c.Helpers().Repos.EnterSubmodule(submoduleConfig) } if file.HasInlineMergeConflicts { @@ -624,15 +624,15 @@ func (self *FilesController) handleAmendCommitPress() error { return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle) } - if !self.helpers.WorkingTree.AnyStagedFiles() { - return self.helpers.WorkingTree.PromptToStageAllAndRetry(self.handleAmendCommitPress) + if !self.c.Helpers().WorkingTree.AnyStagedFiles() { + return self.c.Helpers().WorkingTree.PromptToStageAllAndRetry(self.handleAmendCommitPress) } if len(self.c.Model().Commits) == 0 { return self.c.ErrorMsg(self.c.Tr.NoCommitToAmend) } - return self.helpers.AmendHelper.AmendHead() + return self.c.Helpers().AmendHelper.AmendHead() } func (self *FilesController) handleStatusFilterPressed() error { @@ -671,7 +671,7 @@ func (self *FilesController) edit(node *filetree.FileNode) error { return self.c.ErrorMsg(self.c.Tr.ErrCannotEditDirectory) } - return self.helpers.Files.EditFile(node.GetPath()) + return self.c.Helpers().Files.EditFile(node.GetPath()) } func (self *FilesController) Open() error { @@ -680,7 +680,7 @@ func (self *FilesController) Open() error { return nil } - return self.helpers.Files.OpenFile(node.GetPath()) + return self.c.Helpers().Files.OpenFile(node.GetPath()) } func (self *FilesController) switchToMerge() error { @@ -689,7 +689,7 @@ func (self *FilesController) switchToMerge() error { return nil } - return self.helpers.MergeConflicts.SwitchToMerge(file.Name) + return self.c.Helpers().MergeConflicts.SwitchToMerge(file.Name) } func (self *FilesController) createStashMenu() error { @@ -699,7 +699,7 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.LcStashAllChanges, OnPress: func() error { - if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { return self.c.ErrorMsg(self.c.Tr.NoFilesToStash) } return self.handleStashSave(self.c.Git().Stash.Save, self.c.Tr.Actions.StashAllChanges) @@ -709,7 +709,7 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.LcStashAllChangesKeepIndex, OnPress: func() error { - if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { return self.c.ErrorMsg(self.c.Tr.NoFilesToStash) } // if there are no staged files it behaves the same as Stash.Save @@ -728,7 +728,7 @@ func (self *FilesController) createStashMenu() error { Label: self.c.Tr.LcStashStagedChanges, OnPress: func() error { // there must be something in staging otherwise the current implementation mucks the stash up - if !self.helpers.WorkingTree.AnyStagedFiles() { + if !self.c.Helpers().WorkingTree.AnyStagedFiles() { return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash) } return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges) @@ -738,10 +738,10 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.LcStashUnstagedChanges, OnPress: func() error { - if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { return self.c.ErrorMsg(self.c.Tr.NoFilesToStash) } - if self.helpers.WorkingTree.AnyStagedFiles() { + if self.c.Helpers().WorkingTree.AnyStagedFiles() { return self.handleStashSave(self.c.Git().Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges) } // ordinary stash @@ -758,7 +758,7 @@ func (self *FilesController) stash() error { } func (self *FilesController) createResetToUpstreamMenu() error { - return self.helpers.Refs.CreateGitResetMenu("@{upstream}") + return self.c.Helpers().Refs.CreateGitResetMenu("@{upstream}") } func (self *FilesController) handleToggleDirCollapsed() error { diff --git a/pkg/gui/controllers/files_remove_controller.go b/pkg/gui/controllers/files_remove_controller.go index 17d673e15..35093273c 100644 --- a/pkg/gui/controllers/files_remove_controller.go +++ b/pkg/gui/controllers/files_remove_controller.go @@ -12,17 +12,17 @@ import ( type FilesRemoveController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &FilesRemoveController{} func NewFilesRemoveController( - common *controllerCommon, + common *ControllerCommon, ) *FilesRemoveController { return &FilesRemoveController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -148,7 +148,7 @@ func (self *FilesRemoveController) ResetSubmodule(submodule *models.SubmoduleCon return self.c.WithWaitingStatus(self.c.Tr.LcResettingSubmoduleStatus, func() error { self.c.LogAction(self.c.Tr.Actions.ResetSubmodule) - file := self.helpers.WorkingTree.FileForSubmodule(submodule) + file := self.c.Helpers().WorkingTree.FileForSubmodule(submodule) if file != nil { if err := self.c.Git().WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil { return self.c.Error(err) diff --git a/pkg/gui/controllers/git_flow_controller.go b/pkg/gui/controllers/git_flow_controller.go index 6456f38bc..cba4c7ddc 100644 --- a/pkg/gui/controllers/git_flow_controller.go +++ b/pkg/gui/controllers/git_flow_controller.go @@ -11,17 +11,17 @@ import ( type GitFlowController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &GitFlowController{} func NewGitFlowController( - common *controllerCommon, + common *ControllerCommon, ) *GitFlowController { return &GitFlowController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } diff --git a/pkg/gui/controllers/global_controller.go b/pkg/gui/controllers/global_controller.go index db6645ade..1f5d26e3f 100644 --- a/pkg/gui/controllers/global_controller.go +++ b/pkg/gui/controllers/global_controller.go @@ -12,15 +12,15 @@ import ( type GlobalController struct { baseController - *controllerCommon + c *ControllerCommon } func NewGlobalController( - common *controllerCommon, + common *ControllerCommon, ) *GlobalController { return &GlobalController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } diff --git a/pkg/gui/controllers/helpers/app_status_helper.go b/pkg/gui/controllers/helpers/app_status_helper.go new file mode 100644 index 000000000..f125ebf7b --- /dev/null +++ b/pkg/gui/controllers/helpers/app_status_helper.go @@ -0,0 +1,68 @@ +package helpers + +import ( + "time" + + "github.com/jesseduffield/lazygit/pkg/gui/status" + "github.com/jesseduffield/lazygit/pkg/utils" +) + +type AppStatusHelper struct { + c *HelperCommon + + statusMgr func() *status.StatusManager +} + +func NewAppStatusHelper(c *HelperCommon, statusMgr func() *status.StatusManager) *AppStatusHelper { + return &AppStatusHelper{ + c: c, + statusMgr: statusMgr, + } +} + +func (self *AppStatusHelper) Toast(message string) { + self.statusMgr().AddToastStatus(message) + + self.renderAppStatus() +} + +// withWaitingStatus wraps a function and shows a waiting status while the function is still executing +func (self *AppStatusHelper) WithWaitingStatus(message string, f func() error) { + go utils.Safe(func() { + self.statusMgr().WithWaitingStatus(message, func() { + self.renderAppStatus() + + if err := f(); err != nil { + self.c.OnUIThread(func() error { + return self.c.Error(err) + }) + } + }) + }) +} + +func (self *AppStatusHelper) HasStatus() bool { + return self.statusMgr().HasStatus() +} + +func (self *AppStatusHelper) GetStatusString() string { + return self.statusMgr().GetStatusString() +} + +func (self *AppStatusHelper) renderAppStatus() { + go utils.Safe(func() { + ticker := time.NewTicker(time.Millisecond * 50) + defer ticker.Stop() + for range ticker.C { + appStatus := self.statusMgr().GetStatusString() + self.c.OnUIThread(func() error { + self.c.SetViewContent(self.c.Views().AppStatus, appStatus) + return nil + }) + + if appStatus == "" { + return + } + } + }) +} diff --git a/pkg/gui/controllers/helpers/helpers.go b/pkg/gui/controllers/helpers/helpers.go index c250a09b5..a1da39032 100644 --- a/pkg/gui/controllers/helpers/helpers.go +++ b/pkg/gui/controllers/helpers/helpers.go @@ -42,6 +42,8 @@ type Helpers struct { View *ViewHelper Refresh *RefreshHelper Confirmation *ConfirmationHelper + Mode *ModeHelper + AppStatus *AppStatusHelper } func NewStubHelpers() *Helpers { @@ -70,5 +72,7 @@ func NewStubHelpers() *Helpers { View: &ViewHelper{}, Refresh: &RefreshHelper{}, Confirmation: &ConfirmationHelper{}, + Mode: &ModeHelper{}, + AppStatus: &AppStatusHelper{}, } } diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go new file mode 100644 index 000000000..a97625ac7 --- /dev/null +++ b/pkg/gui/controllers/helpers/mode_helper.go @@ -0,0 +1,159 @@ +package helpers + +import ( + "fmt" + + "github.com/jesseduffield/generics/slices" + "github.com/jesseduffield/lazygit/pkg/commands/types/enums" + "github.com/jesseduffield/lazygit/pkg/gui/presentation" + "github.com/jesseduffield/lazygit/pkg/gui/style" + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type ModeHelper struct { + c *HelperCommon + + diffHelper *DiffHelper + patchBuildingHelper *PatchBuildingHelper + cherryPickHelper *CherryPickHelper + mergeAndRebaseHelper *MergeAndRebaseHelper + bisectHelper *BisectHelper +} + +func NewModeHelper( + c *HelperCommon, + diffHelper *DiffHelper, + patchBuildingHelper *PatchBuildingHelper, + cherryPickHelper *CherryPickHelper, + mergeAndRebaseHelper *MergeAndRebaseHelper, + bisectHelper *BisectHelper, +) *ModeHelper { + return &ModeHelper{ + c: c, + diffHelper: diffHelper, + patchBuildingHelper: patchBuildingHelper, + cherryPickHelper: cherryPickHelper, + mergeAndRebaseHelper: mergeAndRebaseHelper, + bisectHelper: bisectHelper, + } +} + +type ModeStatus struct { + IsActive func() bool + Description func() string + Reset func() error +} + +func (self *ModeHelper) Statuses() []ModeStatus { + return []ModeStatus{ + { + IsActive: self.c.Modes().Diffing.Active, + Description: func() string { + return self.withResetButton( + fmt.Sprintf( + "%s %s", + self.c.Tr.LcShowingGitDiff, + "git diff "+self.diffHelper.DiffStr(), + ), + style.FgMagenta, + ) + }, + Reset: self.diffHelper.ExitDiffMode, + }, + { + IsActive: self.c.Git().Patch.PatchBuilder.Active, + Description: func() string { + return self.withResetButton(self.c.Tr.LcBuildingPatch, style.FgYellow.SetBold()) + }, + Reset: self.patchBuildingHelper.Reset, + }, + { + IsActive: self.c.Modes().Filtering.Active, + Description: func() string { + return self.withResetButton( + fmt.Sprintf( + "%s '%s'", + self.c.Tr.LcFilteringBy, + self.c.Modes().Filtering.GetPath(), + ), + style.FgRed, + ) + }, + Reset: self.ExitFilterMode, + }, + { + IsActive: self.c.Modes().CherryPicking.Active, + Description: func() string { + copiedCount := len(self.c.Modes().CherryPicking.CherryPickedCommits) + text := self.c.Tr.LcCommitsCopied + if copiedCount == 1 { + text = self.c.Tr.LcCommitCopied + } + + return self.withResetButton( + fmt.Sprintf( + "%d %s", + copiedCount, + text, + ), + style.FgCyan, + ) + }, + Reset: self.cherryPickHelper.Reset, + }, + { + IsActive: func() bool { + return self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE + }, + Description: func() string { + workingTreeState := self.c.Git().Status.WorkingTreeState() + return self.withResetButton( + presentation.FormatWorkingTreeState(workingTreeState), style.FgYellow, + ) + }, + Reset: self.mergeAndRebaseHelper.AbortMergeOrRebaseWithConfirm, + }, + { + IsActive: func() bool { + return self.c.Model().BisectInfo.Started() + }, + Description: func() string { + return self.withResetButton("bisecting", style.FgGreen) + }, + Reset: self.bisectHelper.Reset, + }, + } +} + +func (self *ModeHelper) withResetButton(content string, textStyle style.TextStyle) string { + return textStyle.Sprintf( + "%s %s", + content, + style.AttrUnderline.Sprint(self.c.Tr.ResetInParentheses), + ) +} + +func (self *ModeHelper) GetActiveMode() (ModeStatus, bool) { + return slices.Find(self.Statuses(), func(mode ModeStatus) bool { + return mode.IsActive() + }) +} + +func (self *ModeHelper) IsAnyModeActive() bool { + return slices.Some(self.Statuses(), func(mode ModeStatus) bool { + return mode.IsActive() + }) +} + +func (self *ModeHelper) ExitFilterMode() error { + return self.ClearFiltering() +} + +func (self *ModeHelper) ClearFiltering() error { + self.c.Modes().Filtering.Reset() + if self.c.State().GetRepoState().GetScreenMode() == types.SCREEN_HALF { + self.c.State().GetRepoState().SetScreenMode(types.SCREEN_NORMAL) + } + + return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}}) +} diff --git a/pkg/gui/controllers/list_controller.go b/pkg/gui/controllers/list_controller.go index 0afb45d18..0a6de821a 100644 --- a/pkg/gui/controllers/list_controller.go +++ b/pkg/gui/controllers/list_controller.go @@ -6,26 +6,26 @@ import ( ) type ListControllerFactory struct { - *controllerCommon + c *ControllerCommon } -func NewListControllerFactory(c *controllerCommon) *ListControllerFactory { +func NewListControllerFactory(c *ControllerCommon) *ListControllerFactory { return &ListControllerFactory{ - controllerCommon: c, + c: c, } } func (self *ListControllerFactory) Create(context types.IListContext) *ListController { return &ListController{ - baseController: baseController{}, - controllerCommon: self.controllerCommon, - context: context, + baseController: baseController{}, + c: self.c, + context: context, } } type ListController struct { baseController - *controllerCommon + c *ControllerCommon context types.IListContext } diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 561b4b136..c7a3491df 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -7,7 +7,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/context" - "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/samber/lo" @@ -22,7 +21,7 @@ type ( type LocalCommitsController struct { baseController - *controllerCommon + c *ControllerCommon pullFiles PullFilesFn } @@ -30,13 +29,13 @@ type LocalCommitsController struct { var _ types.IController = &LocalCommitsController{} func NewLocalCommitsController( - common *controllerCommon, + common *ControllerCommon, pullFiles PullFilesFn, ) *LocalCommitsController { return &LocalCommitsController{ - baseController: baseController{}, - controllerCommon: common, - pullFiles: pullFiles, + baseController: baseController{}, + c: common, + pullFiles: pullFiles, } } @@ -156,7 +155,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [ func (self *LocalCommitsController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask commit := self.context().GetSelected() if commit == nil { @@ -185,7 +184,7 @@ func (self *LocalCommitsController) GetOnRenderToMain() func() error { } } -func secondaryPatchPanelUpdateOpts(c *helpers.HelperCommon) *types.ViewUpdateOpts { +func secondaryPatchPanelUpdateOpts(c *ControllerCommon) *types.ViewUpdateOpts { if c.Git().Patch.PatchBuilder.Active() { patch := c.Git().Patch.PatchBuilder.RenderAggregatedPatch(false) @@ -350,7 +349,7 @@ func (self *LocalCommitsController) edit(commit *models.Commit) error { return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func() error { self.c.LogAction(self.c.Tr.Actions.EditCommit) err := self.c.Git().Rebase.InteractiveRebaseBreakAfter(self.c.Model().Commits, self.context().GetSelectedLineIdx()) - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) }) } @@ -370,7 +369,7 @@ func (self *LocalCommitsController) pick(commit *models.Commit) error { func (self *LocalCommitsController) interactiveRebase(action string) error { err := self.c.Git().Rebase.InteractiveRebase(self.c.Model().Commits, self.context().GetSelectedLineIdx(), action) - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) } // handleMidRebaseCommand sees if the selected commit is in fact a rebasing @@ -454,7 +453,7 @@ func (self *LocalCommitsController) moveDown(commit *models.Commit) error { if err == nil { self.context().MoveSelectedLine(1) } - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) }) } @@ -492,13 +491,13 @@ func (self *LocalCommitsController) moveUp(commit *models.Commit) error { if err == nil { self.context().MoveSelectedLine(-1) } - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) }) } func (self *LocalCommitsController) amendTo(commit *models.Commit) error { if self.isHeadCommit() { - if err := self.helpers.AmendHelper.AmendHead(); err != nil { + if err := self.c.Helpers().AmendHelper.AmendHead(); err != nil { return err } return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) @@ -515,14 +514,14 @@ func (self *LocalCommitsController) amendTo(commit *models.Commit) error { return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func() error { self.c.LogAction(self.c.Tr.Actions.AmendCommit) err := self.c.Git().Rebase.AmendTo(commit) - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) }) }, }) } func (self *LocalCommitsController) amendAttribute(commit *models.Commit) error { - if self.git.Status.WorkingTreeState() != enums.REBASE_MODE_NONE && !self.isHeadCommit() { + if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE && !self.isHeadCommit() { return self.c.ErrorMsg(self.c.Tr.AlreadyRebasing) } @@ -559,7 +558,7 @@ func (self *LocalCommitsController) resetAuthor() error { func (self *LocalCommitsController) setAuthor() error { return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.SetAuthorPromptTitle, - FindSuggestionsFunc: self.helpers.Suggestions.GetAuthorsSuggestionsFunc(), + FindSuggestionsFunc: self.c.Helpers().Suggestions.GetAuthorsSuggestionsFunc(), HandleConfirm: func(value string) error { return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func() error { self.c.LogAction(self.c.Tr.Actions.SetCommitAuthor) @@ -662,14 +661,14 @@ func (self *LocalCommitsController) squashAllAboveFixupCommits(commit *models.Co return self.c.WithWaitingStatus(self.c.Tr.SquashingStatus, func() error { self.c.LogAction(self.c.Tr.Actions.SquashAllAboveFixupCommits) err := self.c.Git().Rebase.SquashAllAboveFixupCommits(commit) - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) }) }, }) } func (self *LocalCommitsController) createTag(commit *models.Commit) error { - return self.helpers.Tags.CreateTagMenu(commit.Sha, func() {}) + return self.c.Helpers().Tags.CreateTagMenu(commit.Sha, func() {}) } func (self *LocalCommitsController) openSearch() error { @@ -826,7 +825,7 @@ func (self *LocalCommitsController) context() *context.LocalCommitsContext { } func (self *LocalCommitsController) paste() error { - return self.helpers.CherryPick.Paste() + return self.c.Helpers().CherryPick.Paste() } func (self *LocalCommitsController) isHeadCommit() bool { diff --git a/pkg/gui/controllers/menu_controller.go b/pkg/gui/controllers/menu_controller.go index f641b9083..b687778ac 100644 --- a/pkg/gui/controllers/menu_controller.go +++ b/pkg/gui/controllers/menu_controller.go @@ -7,17 +7,17 @@ import ( type MenuController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &MenuController{} func NewMenuController( - common *controllerCommon, + common *ControllerCommon, ) *MenuController { return &MenuController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } diff --git a/pkg/gui/controllers/merge_conflicts_controller.go b/pkg/gui/controllers/merge_conflicts_controller.go index fa5fa7e12..2d85040de 100644 --- a/pkg/gui/controllers/merge_conflicts_controller.go +++ b/pkg/gui/controllers/merge_conflicts_controller.go @@ -11,17 +11,17 @@ import ( type MergeConflictsController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &MergeConflictsController{} func NewMergeConflictsController( - common *controllerCommon, + common *ControllerCommon, ) *MergeConflictsController { return &MergeConflictsController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -97,7 +97,7 @@ func (self *MergeConflictsController) GetKeybindings(opts types.KeybindingsOpts) }, { Key: opts.GetKey(opts.Config.Files.OpenMergeTool), - Handler: self.helpers.WorkingTree.OpenMergeTool, + Handler: self.c.Helpers().WorkingTree.OpenMergeTool, Description: self.c.Tr.LcOpenMergeTool, }, { @@ -145,7 +145,7 @@ func (self *MergeConflictsController) GetOnFocus() func(types.OnFocusOpts) error return func(types.OnFocusOpts) error { self.c.Views().MergeConflicts.Wrap = false - return self.helpers.MergeConflicts.Render(true) + return self.c.Helpers().MergeConflicts.Render(true) } } @@ -187,11 +187,11 @@ func (self *MergeConflictsController) Escape() error { func (self *MergeConflictsController) HandleEditFile() error { lineNumber := self.context().GetState().GetSelectedLine() - return self.helpers.Files.EditFileAtLine(self.context().GetState().GetPath(), lineNumber) + return self.c.Helpers().Files.EditFileAtLine(self.context().GetState().GetPath(), lineNumber) } func (self *MergeConflictsController) HandleOpenFile() error { - return self.helpers.Files.OpenFile(self.context().GetState().GetPath()) + return self.c.Helpers().Files.OpenFile(self.context().GetState().GetPath()) } func (self *MergeConflictsController) HandleScrollLeft() error { diff --git a/pkg/gui/controllers/patch_building_controller.go b/pkg/gui/controllers/patch_building_controller.go index 2c1728db2..4f2bd44cb 100644 --- a/pkg/gui/controllers/patch_building_controller.go +++ b/pkg/gui/controllers/patch_building_controller.go @@ -8,17 +8,17 @@ import ( type PatchBuildingController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &PatchBuildingController{} func NewPatchBuildingController( - common *controllerCommon, + common *ControllerCommon, ) *PatchBuildingController { return &PatchBuildingController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -64,7 +64,7 @@ func (self *PatchBuildingController) GetOnFocus() func(types.OnFocusOpts) error // no need to change wrap on the secondary view because it can't be interacted with self.c.Views().PatchBuilding.Wrap = false - return self.helpers.PatchBuilding.RefreshPatchBuildingPanel(opts) + return self.c.Helpers().PatchBuilding.RefreshPatchBuildingPanel(opts) } } @@ -90,7 +90,7 @@ func (self *PatchBuildingController) OpenFile() error { return nil } - return self.helpers.Files.OpenFile(path) + return self.c.Helpers().Files.OpenFile(path) } func (self *PatchBuildingController) EditFile() error { @@ -104,7 +104,7 @@ func (self *PatchBuildingController) EditFile() error { } lineNumber := self.context().GetState().CurrentLineNumber() - return self.helpers.Files.EditFileAtLine(path, lineNumber) + return self.c.Helpers().Files.EditFileAtLine(path, lineNumber) } func (self *PatchBuildingController) ToggleSelectionAndRefresh() error { @@ -154,5 +154,5 @@ func (self *PatchBuildingController) toggleSelection() error { } func (self *PatchBuildingController) Escape() error { - return self.helpers.PatchBuilding.Escape() + return self.c.Helpers().PatchBuilding.Escape() } diff --git a/pkg/gui/controllers/patch_explorer_controller.go b/pkg/gui/controllers/patch_explorer_controller.go index bcb90a796..e81cfe1c9 100644 --- a/pkg/gui/controllers/patch_explorer_controller.go +++ b/pkg/gui/controllers/patch_explorer_controller.go @@ -6,26 +6,26 @@ import ( ) type PatchExplorerControllerFactory struct { - *controllerCommon + c *ControllerCommon } -func NewPatchExplorerControllerFactory(c *controllerCommon) *PatchExplorerControllerFactory { +func NewPatchExplorerControllerFactory(c *ControllerCommon) *PatchExplorerControllerFactory { return &PatchExplorerControllerFactory{ - controllerCommon: c, + c: c, } } func (self *PatchExplorerControllerFactory) Create(context types.IPatchExplorerContext) *PatchExplorerController { return &PatchExplorerController{ - baseController: baseController{}, - controllerCommon: self.controllerCommon, - context: context, + baseController: baseController{}, + c: self.c, + context: context, } } type PatchExplorerController struct { baseController - *controllerCommon + c *ControllerCommon context types.IPatchExplorerContext } diff --git a/pkg/gui/controllers/reflog_commits_controller.go b/pkg/gui/controllers/reflog_commits_controller.go index ddc34a263..735e0434f 100644 --- a/pkg/gui/controllers/reflog_commits_controller.go +++ b/pkg/gui/controllers/reflog_commits_controller.go @@ -7,17 +7,17 @@ import ( type ReflogCommitsController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &ReflogCommitsController{} func NewReflogCommitsController( - common *controllerCommon, + common *ControllerCommon, ) *ReflogCommitsController { return &ReflogCommitsController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -31,7 +31,7 @@ func (self *ReflogCommitsController) context() *context.ReflogCommitsContext { func (self *ReflogCommitsController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { commit := self.context().GetSelected() var task types.UpdateTask if commit == nil { diff --git a/pkg/gui/controllers/remote_branches_controller.go b/pkg/gui/controllers/remote_branches_controller.go index 91ff8bd7b..c6ee1dd57 100644 --- a/pkg/gui/controllers/remote_branches_controller.go +++ b/pkg/gui/controllers/remote_branches_controller.go @@ -12,17 +12,17 @@ import ( type RemoteBranchesController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &RemoteBranchesController{} func NewRemoteBranchesController( - common *controllerCommon, + common *ControllerCommon, ) *RemoteBranchesController { return &RemoteBranchesController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -75,7 +75,7 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts) func (self *RemoteBranchesController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask remoteBranch := self.context().GetSelected() if remoteBranch == nil { @@ -140,19 +140,19 @@ func (self *RemoteBranchesController) delete(selectedBranch *models.RemoteBranch } func (self *RemoteBranchesController) merge(selectedBranch *models.RemoteBranch) error { - return self.helpers.MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranch.FullName()) + return self.c.Helpers().MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranch.FullName()) } func (self *RemoteBranchesController) rebase(selectedBranch *models.RemoteBranch) error { - return self.helpers.MergeAndRebase.RebaseOntoRef(selectedBranch.FullName()) + return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranch.FullName()) } func (self *RemoteBranchesController) createResetMenu(selectedBranch *models.RemoteBranch) error { - return self.helpers.Refs.CreateGitResetMenu(selectedBranch.FullName()) + return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.FullName()) } func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.RemoteBranch) error { - checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() + checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef() message := utils.ResolvePlaceholderString( self.c.Tr.SetUpstreamMessage, @@ -180,5 +180,5 @@ func (self *RemoteBranchesController) newLocalBranch(selectedBranch *models.Remo // will set to the remote's branch name without the remote name nameSuggestion := strings.SplitAfterN(selectedBranch.RefName(), "/", 2)[1] - return self.helpers.Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), nameSuggestion) + return self.c.Helpers().Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), nameSuggestion) } diff --git a/pkg/gui/controllers/remotes_controller.go b/pkg/gui/controllers/remotes_controller.go index 83f06d5a4..3d6b4b09d 100644 --- a/pkg/gui/controllers/remotes_controller.go +++ b/pkg/gui/controllers/remotes_controller.go @@ -13,7 +13,7 @@ import ( type RemotesController struct { baseController - *controllerCommon + c *ControllerCommon setRemoteBranches func([]*models.RemoteBranch) } @@ -21,12 +21,12 @@ type RemotesController struct { var _ types.IController = &RemotesController{} func NewRemotesController( - common *controllerCommon, + common *ControllerCommon, setRemoteBranches func([]*models.RemoteBranch), ) *RemotesController { return &RemotesController{ baseController: baseController{}, - controllerCommon: common, + c: common, setRemoteBranches: setRemoteBranches, } } @@ -72,7 +72,7 @@ func (self *RemotesController) context() *context.RemotesContext { func (self *RemotesController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask remote := self.context().GetSelected() if remote == nil { diff --git a/pkg/gui/controllers/snake_controller.go b/pkg/gui/controllers/snake_controller.go index f73962d5e..074a4a6fb 100644 --- a/pkg/gui/controllers/snake_controller.go +++ b/pkg/gui/controllers/snake_controller.go @@ -7,17 +7,17 @@ import ( type SnakeController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &SnakeController{} func NewSnakeController( - common *controllerCommon, + common *ControllerCommon, ) *SnakeController { return &SnakeController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -54,22 +54,22 @@ func (self *SnakeController) Context() types.Context { func (self *SnakeController) GetOnFocus() func(types.OnFocusOpts) error { return func(types.OnFocusOpts) error { - self.helpers.Snake.StartGame() + self.c.Helpers().Snake.StartGame() return nil } } func (self *SnakeController) GetOnFocusLost() func(types.OnFocusLostOpts) error { return func(types.OnFocusLostOpts) error { - self.helpers.Snake.ExitGame() - self.helpers.Window.MoveToTopOfWindow(self.c.Contexts().Submodules) + self.c.Helpers().Snake.ExitGame() + self.c.Helpers().Window.MoveToTopOfWindow(self.c.Contexts().Submodules) return nil } } func (self *SnakeController) SetDirection(direction snake.Direction) func() error { return func() error { - self.helpers.Snake.SetDirection(direction) + self.c.Helpers().Snake.SetDirection(direction) return nil } } diff --git a/pkg/gui/controllers/staging_controller.go b/pkg/gui/controllers/staging_controller.go index cefaf28a5..da31ce23b 100644 --- a/pkg/gui/controllers/staging_controller.go +++ b/pkg/gui/controllers/staging_controller.go @@ -10,7 +10,7 @@ import ( type StagingController struct { baseController - *controllerCommon + c *ControllerCommon context types.IPatchExplorerContext otherContext types.IPatchExplorerContext @@ -22,17 +22,17 @@ type StagingController struct { var _ types.IController = &StagingController{} func NewStagingController( - common *controllerCommon, + common *ControllerCommon, context types.IPatchExplorerContext, otherContext types.IPatchExplorerContext, staged bool, ) *StagingController { return &StagingController{ - baseController: baseController{}, - controllerCommon: common, - context: context, - otherContext: otherContext, - staged: staged, + baseController: baseController{}, + c: common, + context: context, + otherContext: otherContext, + staged: staged, } } @@ -75,17 +75,17 @@ func (self *StagingController) GetKeybindings(opts types.KeybindingsOpts) []*typ }, { Key: opts.GetKey(opts.Config.Files.CommitChanges), - Handler: self.helpers.WorkingTree.HandleCommitPress, + Handler: self.c.Helpers().WorkingTree.HandleCommitPress, Description: self.c.Tr.CommitChanges, }, { Key: opts.GetKey(opts.Config.Files.CommitChangesWithoutHook), - Handler: self.helpers.WorkingTree.HandleWIPCommitPress, + Handler: self.c.Helpers().WorkingTree.HandleWIPCommitPress, Description: self.c.Tr.LcCommitChangesWithoutHook, }, { Key: opts.GetKey(opts.Config.Files.CommitChangesWithEditor), - Handler: self.helpers.WorkingTree.HandleCommitEditorPress, + Handler: self.c.Helpers().WorkingTree.HandleCommitEditorPress, Description: self.c.Tr.CommitChangesWithEditor, }, } @@ -104,7 +104,7 @@ func (self *StagingController) GetOnFocus() func(types.OnFocusOpts) error { self.c.Views().Staging.Wrap = false self.c.Views().StagingSecondary.Wrap = false - return self.helpers.Staging.RefreshStagingPanel(opts) + return self.c.Helpers().Staging.RefreshStagingPanel(opts) } } @@ -132,7 +132,7 @@ func (self *StagingController) OpenFile() error { return nil } - return self.helpers.Files.OpenFile(path) + return self.c.Helpers().Files.OpenFile(path) } func (self *StagingController) EditFile() error { @@ -146,7 +146,7 @@ func (self *StagingController) EditFile() error { } lineNumber := self.context.GetState().CurrentLineNumber() - return self.helpers.Files.EditFileAtLine(path, lineNumber) + return self.c.Helpers().Files.EditFileAtLine(path, lineNumber) } func (self *StagingController) Escape() error { @@ -269,7 +269,7 @@ func (self *StagingController) editHunk() error { lineOffset := 3 lineIdxInHunk := state.GetSelectedLineIdx() - hunkStartIdx - if err := self.helpers.Files.EditFileAtLineAndWait(patchFilepath, lineIdxInHunk+lineOffset); err != nil { + if err := self.c.Helpers().Files.EditFileAtLineAndWait(patchFilepath, lineIdxInHunk+lineOffset); err != nil { return err } diff --git a/pkg/gui/controllers/stash_controller.go b/pkg/gui/controllers/stash_controller.go index 377b029c3..3e1b65ce8 100644 --- a/pkg/gui/controllers/stash_controller.go +++ b/pkg/gui/controllers/stash_controller.go @@ -9,17 +9,17 @@ import ( type StashController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &StashController{} func NewStashController( - common *controllerCommon, + common *ControllerCommon, ) *StashController { return &StashController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -57,7 +57,7 @@ func (self *StashController) GetKeybindings(opts types.KeybindingsOpts) []*types func (self *StashController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask stashEntry := self.context().GetSelected() if stashEntry == nil { @@ -165,7 +165,7 @@ func (self *StashController) postStashRefresh() error { } func (self *StashController) handleNewBranchOffStashEntry(stashEntry *models.StashEntry) error { - return self.helpers.Refs.NewBranch(stashEntry.RefName(), stashEntry.Description(), "") + return self.c.Helpers().Refs.NewBranch(stashEntry.RefName(), stashEntry.Description(), "") } func (self *StashController) handleRenameStashEntry(stashEntry *models.StashEntry) error { diff --git a/pkg/gui/controllers/status_controller.go b/pkg/gui/controllers/status_controller.go index a347fd9d4..f78a83321 100644 --- a/pkg/gui/controllers/status_controller.go +++ b/pkg/gui/controllers/status_controller.go @@ -16,17 +16,17 @@ import ( type StatusController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &StatusController{} func NewStatusController( - common *controllerCommon, + common *ControllerCommon, ) *StatusController { return &StatusController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -49,7 +49,7 @@ func (self *StatusController) GetKeybindings(opts types.KeybindingsOpts) []*type }, { Key: opts.GetKey(opts.Config.Status.RecentRepos), - Handler: self.helpers.Repos.CreateRecentReposMenu, + Handler: self.c.Helpers().Repos.CreateRecentReposMenu, Description: self.c.Tr.SwitchRepo, }, { @@ -96,7 +96,7 @@ func (self *StatusController) Context() types.Context { func (self *StatusController) onClick() error { // TODO: move into some abstraction (status is currently not a listViewContext where a lot of this code lives) - currentBranch := self.helpers.Refs.GetCheckedOutRef() + currentBranch := self.c.Helpers().Refs.GetCheckedOutRef() if currentBranch == nil { // need to wait for branches to refresh return nil @@ -114,14 +114,14 @@ func (self *StatusController) onClick() error { case enums.REBASE_MODE_REBASING, enums.REBASE_MODE_MERGING: workingTreeStatus := fmt.Sprintf("(%s)", presentation.FormatWorkingTreeState(workingTreeState)) if cursorInSubstring(cx, upstreamStatus+" ", workingTreeStatus) { - return self.helpers.MergeAndRebase.CreateRebaseOptionsMenu() + return self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu() } if cursorInSubstring(cx, upstreamStatus+" "+workingTreeStatus+" ", repoName) { - return self.helpers.Repos.CreateRecentReposMenu() + return self.c.Helpers().Repos.CreateRecentReposMenu() } default: if cursorInSubstring(cx, upstreamStatus+" ", repoName) { - return self.helpers.Repos.CreateRecentReposMenu() + return self.c.Helpers().Repos.CreateRecentReposMenu() } } @@ -173,11 +173,11 @@ func (self *StatusController) askForConfigFile(action func(file string) error) e } func (self *StatusController) openConfig() error { - return self.askForConfigFile(self.helpers.Files.OpenFile) + return self.askForConfigFile(self.c.Helpers().Files.OpenFile) } func (self *StatusController) editConfig() error { - return self.askForConfigFile(self.helpers.Files.EditFile) + return self.askForConfigFile(self.c.Helpers().Files.EditFile) } func (self *StatusController) showAllBranchLogs() error { @@ -194,5 +194,5 @@ func (self *StatusController) showAllBranchLogs() error { } func (self *StatusController) handleCheckForUpdate() error { - return self.helpers.Update.CheckForUpdateInForeground() + return self.c.Helpers().Update.CheckForUpdateInForeground() } diff --git a/pkg/gui/controllers/sub_commits_controller.go b/pkg/gui/controllers/sub_commits_controller.go index 33f967830..e887b29d6 100644 --- a/pkg/gui/controllers/sub_commits_controller.go +++ b/pkg/gui/controllers/sub_commits_controller.go @@ -8,17 +8,17 @@ import ( type SubCommitsController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &SubCommitsController{} func NewSubCommitsController( - common *controllerCommon, + common *ControllerCommon, ) *SubCommitsController { return &SubCommitsController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -32,7 +32,7 @@ func (self *SubCommitsController) context() *context.SubCommitsContext { func (self *SubCommitsController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { commit := self.context().GetSelected() var task types.UpdateTask if commit == nil { diff --git a/pkg/gui/controllers/submodules_controller.go b/pkg/gui/controllers/submodules_controller.go index 8f76355f8..9a9f5af6b 100644 --- a/pkg/gui/controllers/submodules_controller.go +++ b/pkg/gui/controllers/submodules_controller.go @@ -13,17 +13,17 @@ import ( type SubmodulesController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &SubmodulesController{} func NewSubmodulesController( - controllerCommon *controllerCommon, + controllerCommon *ControllerCommon, ) *SubmodulesController { return &SubmodulesController{ - baseController: baseController{}, - controllerCommon: controllerCommon, + baseController: baseController{}, + c: controllerCommon, } } @@ -79,7 +79,7 @@ func (self *SubmodulesController) GetOnClick() func() error { func (self *SubmodulesController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask submodule := self.context().GetSelected() if submodule == nil { @@ -92,7 +92,7 @@ func (self *SubmodulesController) GetOnRenderToMain() func() error { style.FgCyan.Sprint(submodule.Url), ) - file := self.helpers.WorkingTree.FileForSubmodule(submodule) + file := self.c.Helpers().WorkingTree.FileForSubmodule(submodule) if file == nil { task = types.NewRenderStringTask(prefix) } else { @@ -113,7 +113,7 @@ func (self *SubmodulesController) GetOnRenderToMain() func() error { } func (self *SubmodulesController) enter(submodule *models.SubmoduleConfig) error { - return self.helpers.Repos.EnterSubmodule(submodule) + return self.c.Helpers().Repos.EnterSubmodule(submodule) } func (self *SubmodulesController) add() error { diff --git a/pkg/gui/controllers/suggestions_controller.go b/pkg/gui/controllers/suggestions_controller.go index 5772e35b6..17b8915a1 100644 --- a/pkg/gui/controllers/suggestions_controller.go +++ b/pkg/gui/controllers/suggestions_controller.go @@ -7,17 +7,17 @@ import ( type SuggestionsController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &SuggestionsController{} func NewSuggestionsController( - common *controllerCommon, + common *ControllerCommon, ) *SuggestionsController { return &SuggestionsController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -42,7 +42,7 @@ func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) [] func (self *SuggestionsController) GetOnFocusLost() func(types.OnFocusLostOpts) error { return func(types.OnFocusLostOpts) error { - self.helpers.Confirmation.DeactivateConfirmationPrompt() + self.c.Helpers().Confirmation.DeactivateConfirmationPrompt() return nil } } diff --git a/pkg/gui/controllers/switch_to_diff_files_controller.go b/pkg/gui/controllers/switch_to_diff_files_controller.go index fa6ccdc0d..8aa929587 100644 --- a/pkg/gui/controllers/switch_to_diff_files_controller.go +++ b/pkg/gui/controllers/switch_to_diff_files_controller.go @@ -17,19 +17,19 @@ type CanSwitchToDiffFiles interface { type SwitchToDiffFilesController struct { baseController - *controllerCommon + c *ControllerCommon context CanSwitchToDiffFiles diffFilesContext *context.CommitFilesContext } func NewSwitchToDiffFilesController( - controllerCommon *controllerCommon, + c *ControllerCommon, context CanSwitchToDiffFiles, diffFilesContext *context.CommitFilesContext, ) *SwitchToDiffFilesController { return &SwitchToDiffFilesController{ baseController: baseController{}, - controllerCommon: controllerCommon, + c: c, context: context, diffFilesContext: diffFilesContext, } diff --git a/pkg/gui/controllers/switch_to_sub_commits_controller.go b/pkg/gui/controllers/switch_to_sub_commits_controller.go index 28966c68f..c66151190 100644 --- a/pkg/gui/controllers/switch_to_sub_commits_controller.go +++ b/pkg/gui/controllers/switch_to_sub_commits_controller.go @@ -15,22 +15,22 @@ type CanSwitchToSubCommits interface { type SwitchToSubCommitsController struct { baseController - *controllerCommon + c *ControllerCommon context CanSwitchToSubCommits setSubCommits func([]*models.Commit) } func NewSwitchToSubCommitsController( - controllerCommon *controllerCommon, + controllerCommon *ControllerCommon, setSubCommits func([]*models.Commit), context CanSwitchToSubCommits, ) *SwitchToSubCommitsController { return &SwitchToSubCommitsController{ - baseController: baseController{}, - controllerCommon: controllerCommon, - context: context, - setSubCommits: setSubCommits, + baseController: baseController{}, + c: controllerCommon, + context: context, + setSubCommits: setSubCommits, } } diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index 916266ec0..120d9fdac 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -11,17 +11,17 @@ import ( type SyncController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &SyncController{} func NewSyncController( - common *controllerCommon, + common *ControllerCommon, ) *SyncController { return &SyncController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -56,7 +56,7 @@ func (self *SyncController) HandlePull() error { func (self *SyncController) branchCheckedOut(f func(*models.Branch) error) func() error { return func() error { - currentBranch := self.helpers.Refs.GetCheckedOutRef() + currentBranch := self.c.Helpers().Refs.GetCheckedOutRef() if currentBranch == nil { // need to wait for branches to refresh return nil @@ -79,8 +79,8 @@ func (self *SyncController) push(currentBranch *models.Branch) error { if self.c.Git().Config.GetPushToCurrent() { return self.pushAux(pushOpts{setUpstream: true}) } else { - return self.helpers.Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error { - upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream) + return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error { + upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream) if err != nil { return self.c.Error(err) } @@ -100,7 +100,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error { // if we have no upstream branch we need to set that first if !currentBranch.IsTrackingRemote() { - return self.helpers.Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error { + return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error { if err := self.setCurrentBranchUpstream(upstream); err != nil { return self.c.Error(err) } @@ -113,7 +113,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error { } func (self *SyncController) setCurrentBranchUpstream(upstream string) error { - upstreamRemote, upstreamBranch, err := self.helpers.Upstream.ParseUpstream(upstream) + upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream) if err != nil { return err } @@ -154,7 +154,7 @@ func (self *SyncController) pullWithLock(opts PullFilesOptions) error { }, ) - return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) + return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err) } type pushOpts struct { diff --git a/pkg/gui/controllers/tags_controller.go b/pkg/gui/controllers/tags_controller.go index 6dd3653f8..39fedc58e 100644 --- a/pkg/gui/controllers/tags_controller.go +++ b/pkg/gui/controllers/tags_controller.go @@ -9,17 +9,17 @@ import ( type TagsController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &TagsController{} func NewTagsController( - common *controllerCommon, + common *ControllerCommon, ) *TagsController { return &TagsController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -58,7 +58,7 @@ func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types. func (self *TagsController) GetOnRenderToMain() func() error { return func() error { - return self.helpers.Diff.WithDiffModeCheck(func() error { + return self.c.Helpers().Diff.WithDiffModeCheck(func() error { var task types.UpdateTask tag := self.context().GetSelected() if tag == nil { @@ -81,7 +81,7 @@ func (self *TagsController) GetOnRenderToMain() func() error { func (self *TagsController) checkout(tag *models.Tag) error { self.c.LogAction(self.c.Tr.Actions.CheckoutTag) - if err := self.helpers.Refs.CheckoutRef(tag.Name, types.CheckoutRefOptions{}); err != nil { + if err := self.c.Helpers().Refs.CheckoutRef(tag.Name, types.CheckoutRefOptions{}); err != nil { return err } return self.c.PushContext(self.c.Contexts().Branches) @@ -119,7 +119,7 @@ func (self *TagsController) push(tag *models.Tag) error { return self.c.Prompt(types.PromptOpts{ Title: title, InitialContent: "origin", - FindSuggestionsFunc: self.helpers.Suggestions.GetRemoteSuggestionsFunc(), + FindSuggestionsFunc: self.c.Helpers().Suggestions.GetRemoteSuggestionsFunc(), HandleConfirm: func(response string) error { return self.c.WithWaitingStatus(self.c.Tr.PushingTagStatus, func() error { self.c.LogAction(self.c.Tr.Actions.PushTag) @@ -135,12 +135,12 @@ func (self *TagsController) push(tag *models.Tag) error { } func (self *TagsController) createResetMenu(tag *models.Tag) error { - return self.helpers.Refs.CreateGitResetMenu(tag.Name) + return self.c.Helpers().Refs.CreateGitResetMenu(tag.Name) } func (self *TagsController) create() error { // leaving commit SHA blank so that we're just creating the tag for the current commit - return self.helpers.Tags.CreateTagMenu("", func() { self.context().SetSelectedLineIdx(0) }) + return self.c.Helpers().Tags.CreateTagMenu("", func() { self.context().SetSelectedLineIdx(0) }) } func (self *TagsController) withSelectedTag(f func(tag *models.Tag) error) func() error { diff --git a/pkg/gui/controllers/undo_controller.go b/pkg/gui/controllers/undo_controller.go index d1558759c..bb87bf89d 100644 --- a/pkg/gui/controllers/undo_controller.go +++ b/pkg/gui/controllers/undo_controller.go @@ -20,17 +20,17 @@ import ( type UndoController struct { baseController - *controllerCommon + c *ControllerCommon } var _ types.IController = &UndoController{} func NewUndoController( - common *controllerCommon, + common *ControllerCommon, ) *UndoController { return &UndoController{ - baseController: baseController{}, - controllerCommon: common, + baseController: baseController{}, + c: common, } } @@ -104,7 +104,7 @@ func (self *UndoController) reflogUndo() error { Prompt: fmt.Sprintf(self.c.Tr.CheckoutPrompt, action.from), HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.Undo) - return self.helpers.Refs.CheckoutRef(action.from, types.CheckoutRefOptions{ + return self.c.Helpers().Refs.CheckoutRef(action.from, types.CheckoutRefOptions{ EnvVars: undoEnvVars, WaitingStatus: undoingStatus, }) @@ -156,7 +156,7 @@ func (self *UndoController) reflogRedo() error { Prompt: fmt.Sprintf(self.c.Tr.CheckoutPrompt, action.to), HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.Redo) - return self.helpers.Refs.CheckoutRef(action.to, types.CheckoutRefOptions{ + return self.c.Helpers().Refs.CheckoutRef(action.to, types.CheckoutRefOptions{ EnvVars: redoEnvVars, WaitingStatus: redoingStatus, }) @@ -233,14 +233,14 @@ type hardResetOptions struct { // only to be used in the undo flow for now (does an autostash) func (self *UndoController) hardResetWithAutoStash(commitSha string, options hardResetOptions) error { reset := func() error { - if err := self.helpers.Refs.ResetToRef(commitSha, "hard", options.EnvVars); err != nil { + if err := self.c.Helpers().Refs.ResetToRef(commitSha, "hard", options.EnvVars); err != nil { return self.c.Error(err) } return nil } // if we have any modified tracked files we need to ask the user if they want us to stash for them - dirtyWorkingTree := self.helpers.WorkingTree.IsWorkingTreeDirty() + dirtyWorkingTree := self.c.Helpers().WorkingTree.IsWorkingTreeDirty() if dirtyWorkingTree { // offer to autostash changes return self.c.Confirm(types.ConfirmOpts{ diff --git a/pkg/gui/controllers/vertical_scroll_controller.go b/pkg/gui/controllers/vertical_scroll_controller.go index 388574df6..90958fadd 100644 --- a/pkg/gui/controllers/vertical_scroll_controller.go +++ b/pkg/gui/controllers/vertical_scroll_controller.go @@ -9,13 +9,13 @@ import ( // given we have no fields here, arguably we shouldn't even need this factory // struct, but we're maintaining consistency with the other files. type VerticalScrollControllerFactory struct { - controllerCommon *controllerCommon + c *ControllerCommon viewBufferManagerMap *map[string]*tasks.ViewBufferManager } -func NewVerticalScrollControllerFactory(c *controllerCommon, viewBufferManagerMap *map[string]*tasks.ViewBufferManager) *VerticalScrollControllerFactory { +func NewVerticalScrollControllerFactory(c *ControllerCommon, viewBufferManagerMap *map[string]*tasks.ViewBufferManager) *VerticalScrollControllerFactory { return &VerticalScrollControllerFactory{ - controllerCommon: c, + c: c, viewBufferManagerMap: viewBufferManagerMap, } } @@ -23,7 +23,7 @@ func NewVerticalScrollControllerFactory(c *controllerCommon, viewBufferManagerMa func (self *VerticalScrollControllerFactory) Create(context types.Context) types.IController { return &VerticalScrollController{ baseController: baseController{}, - controllerCommon: self.controllerCommon, + c: self.c, context: context, viewBufferManagerMap: self.viewBufferManagerMap, } @@ -31,7 +31,7 @@ func (self *VerticalScrollControllerFactory) Create(context types.Context) types type VerticalScrollController struct { baseController - *controllerCommon + c *ControllerCommon context types.Context viewBufferManagerMap *map[string]*tasks.ViewBufferManager diff --git a/pkg/gui/controllers/workspace_reset_controller.go b/pkg/gui/controllers/workspace_reset_controller.go index c6e916683..5104b5ac8 100644 --- a/pkg/gui/controllers/workspace_reset_controller.go +++ b/pkg/gui/controllers/workspace_reset_controller.go @@ -72,7 +72,7 @@ func (self *FilesController) createResetMenu() error { Tooltip: self.c.Tr.DiscardStagedChangesDescription, OnPress: func() error { self.c.LogAction(self.c.Tr.Actions.RemoveStagedFiles) - if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash) } if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil { diff --git a/pkg/gui/extras_panel.go b/pkg/gui/extras_panel.go index 3ac5d6915..927250627 100644 --- a/pkg/gui/extras_panel.go +++ b/pkg/gui/extras_panel.go @@ -16,13 +16,13 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error { Label: gui.c.Tr.ToggleShowCommandLog, OnPress: func() error { currentContext := gui.c.CurrentStaticContext() - if gui.ShowExtrasWindow && currentContext.GetKey() == context.COMMAND_LOG_CONTEXT_KEY { + if gui.c.State().GetShowExtrasWindow() && currentContext.GetKey() == context.COMMAND_LOG_CONTEXT_KEY { if err := gui.c.PopContext(); err != nil { return err } } - show := !gui.ShowExtrasWindow - gui.ShowExtrasWindow = show + show := !gui.c.State().GetShowExtrasWindow() + gui.c.State().SetShowExtrasWindow(show) gui.c.GetAppState().HideCommandLog = !show _ = gui.c.SaveAppState() return nil @@ -37,7 +37,7 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error { } func (gui *Gui) handleFocusCommandLog() error { - gui.ShowExtrasWindow = true + gui.c.State().SetShowExtrasWindow(true) // TODO: is this necessary? Can't I just call 'return from context'? gui.State.Contexts.CommandLog.SetParentContext(gui.c.CurrentSideContext()) return gui.c.PushContext(gui.State.Contexts.CommandLog) diff --git a/pkg/gui/filtering.go b/pkg/gui/filtering.go index 99aa6638e..8edfb90ec 100644 --- a/pkg/gui/filtering.go +++ b/pkg/gui/filtering.go @@ -9,7 +9,7 @@ func (gui *Gui) validateNotInFilterMode() bool { _ = gui.c.Confirm(types.ConfirmOpts{ Title: gui.c.Tr.MustExitFilterModeTitle, Prompt: gui.c.Tr.MustExitFilterModePrompt, - HandleConfirm: gui.exitFilterMode, + HandleConfirm: gui.helpers.Mode.ExitFilterMode, }) return false @@ -17,19 +17,6 @@ func (gui *Gui) validateNotInFilterMode() bool { return true } -func (gui *Gui) exitFilterMode() error { - return gui.clearFiltering() -} - -func (gui *Gui) clearFiltering() error { - gui.State.Modes.Filtering.Reset() - if gui.State.ScreenMode == types.SCREEN_HALF { - gui.State.ScreenMode = types.SCREEN_NORMAL - } - - return gui.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}}) -} - func (gui *Gui) setFiltering(path string) error { gui.State.Modes.Filtering.SetPath(path) if gui.State.ScreenMode == types.SCREEN_NORMAL { diff --git a/pkg/gui/filtering_menu_panel.go b/pkg/gui/filtering_menu_panel.go index dba6e8e8c..caccd2ce9 100644 --- a/pkg/gui/filtering_menu_panel.go +++ b/pkg/gui/filtering_menu_panel.go @@ -49,7 +49,7 @@ func (gui *Gui) handleCreateFilteringMenuPanel() error { if gui.State.Modes.Filtering.Active() { menuItems = append(menuItems, &types.MenuItem{ Label: gui.c.Tr.LcExitFilterMode, - OnPress: gui.clearFiltering, + OnPress: gui.helpers.Mode.ClearFiltering, }) } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 0ab45b526..2f143d162 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -30,6 +30,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/presentation/graph" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" "github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands" + "github.com/jesseduffield/lazygit/pkg/gui/status" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/integration/components" @@ -67,7 +68,7 @@ type Gui struct { RepoStateMap map[Repo]*GuiRepoState Config config.AppConfigurer Updater *updates.Updater - statusManager *statusManager + statusManager *status.StatusManager waitForIntro sync.WaitGroup fileWatcher *fileWatcher viewBufferManagerMap map[string]*tasks.ViewBufferManager @@ -127,9 +128,8 @@ type Gui struct { Updating bool - c *helpers.HelperCommon - contextCommon *context.ContextCommon - helpers *helpers.Helpers + c *helpers.HelperCommon + helpers *helpers.Helpers } type StateAccessor struct { @@ -170,6 +170,14 @@ func (self *StateAccessor) SetIsRefreshingFiles(value bool) { self.gui.IsRefreshingFiles = value } +func (self *StateAccessor) GetShowExtrasWindow() bool { + return self.gui.ShowExtrasWindow +} + +func (self *StateAccessor) SetShowExtrasWindow(value bool) { + self.gui.ShowExtrasWindow = value +} + // we keep track of some stuff from one render to the next to see if certain // things have changed type PrevLayout struct { @@ -188,7 +196,7 @@ type GuiRepoState struct { Searching searchingState StartupStage types.StartupStage // Allows us to not load everything at once - ContextMgr ContextMgr + ContextMgr *ContextMgr Contexts *context.ContextTree // WindowViewNameMap is a mapping of windows to the current view of that window. @@ -240,6 +248,22 @@ func (self *GuiRepoState) GetScreenMode() types.WindowMaximisation { return self.ScreenMode } +func (self *GuiRepoState) SetScreenMode(value types.WindowMaximisation) { + self.ScreenMode = value +} + +func (self *GuiRepoState) IsSearching() bool { + return self.Searching.isSearching +} + +func (self *GuiRepoState) SetSplitMainPanel(value bool) { + self.SplitMainPanel = value +} + +func (self *GuiRepoState) GetSplitMainPanel() bool { + return self.SplitMainPanel +} + type searchingState struct { view *gocui.View isSearching bool @@ -405,7 +429,7 @@ func NewGui( gitVersion: gitVersion, Config: config, Updater: updater, - statusManager: &statusManager{}, + statusManager: status.NewStatusManager(), viewBufferManagerMap: map[string]*tasks.ViewBufferManager{}, viewPtmxMap: map[string]*os.File{}, showRecentRepos: showRecentRepos, @@ -438,17 +462,16 @@ func NewGui( return gui.helpers.Confirmation.CreatePopupPanel(ctx, opts) }, func() error { return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) }, - gui.popContext, - gui.currentContext, + func() error { return gui.State.ContextMgr.Pop() }, + func() types.Context { return gui.State.ContextMgr.Current() }, gui.createMenu, - gui.withWaitingStatus, - gui.toast, + func(message string, f func() error) { gui.helpers.AppStatus.WithWaitingStatus(message, f) }, + func(message string) { gui.helpers.AppStatus.Toast(message) }, func() string { return gui.Views.Confirmation.TextArea.GetContent() }, ) guiCommon := &guiCommon{gui: gui, IPopupHandler: gui.PopupHandler} helperCommon := &helpers.HelperCommon{IGuiCommon: guiCommon, Common: cmn, IGetContexts: gui} - contextCommon := &context.ContextCommon{IGuiCommon: guiCommon, Common: cmn} credentialsHelper := helpers.NewCredentialsHelper(helperCommon) @@ -467,8 +490,6 @@ func NewGui( // TODO: reset these controllers upon changing repos due to state changing gui.c = helperCommon - gui.contextCommon = contextCommon - authors.SetCustomAuthors(gui.UserConfig.Gui.AuthorColors) icons.SetIconEnabled(gui.UserConfig.Gui.ShowIcons) presentation.SetCustomBranches(gui.UserConfig.Gui.BranchColors) @@ -804,30 +825,15 @@ func (gui *Gui) startBackgroundRoutines() { } func (gui *Gui) getWindowDimensions(informationStr string, appStatus string) map[string]boxlayout.Dimensions { - windowArranger := &WindowArranger{gui: gui} + windowArranger := NewWindowArranger( + gui.c, + gui.helpers.Window, + gui.helpers.Mode, + gui.helpers.AppStatus, + ) return windowArranger.getWindowDimensions(informationStr, appStatus) } -func (gui *Gui) replaceContext(c types.Context) error { - return gui.State.ContextMgr.replaceContext(c) -} - -func (gui *Gui) pushContext(c types.Context, opts ...types.OnFocusOpts) error { - return gui.State.ContextMgr.pushContext(c, opts...) -} - func (gui *Gui) popContext() error { - return gui.State.ContextMgr.popContext() -} - -func (gui *Gui) currentContext() types.Context { - return gui.State.ContextMgr.currentContext() -} - -func (gui *Gui) currentSideContext() types.Context { - return gui.State.ContextMgr.currentSideContext() -} - -func (gui *Gui) currentStaticContext() types.Context { - return gui.State.ContextMgr.currentStaticContext() + return gui.State.ContextMgr.Pop() } diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index e4b8b3981..7c26c655d 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -41,31 +41,35 @@ func (self *guiCommon) RunSubprocess(cmdObj oscommands.ICmdObj) (bool, error) { } func (self *guiCommon) PushContext(context types.Context, opts ...types.OnFocusOpts) error { - return self.gui.pushContext(context, opts...) + return self.gui.State.ContextMgr.Push(context, opts...) } func (self *guiCommon) PopContext() error { - return self.gui.popContext() + return self.gui.State.ContextMgr.Pop() } func (self *guiCommon) ReplaceContext(context types.Context) error { - return self.gui.replaceContext(context) + return self.gui.State.ContextMgr.Replace(context) } func (self *guiCommon) CurrentContext() types.Context { - return self.gui.currentContext() + return self.gui.State.ContextMgr.Current() } func (self *guiCommon) CurrentStaticContext() types.Context { - return self.gui.currentStaticContext() + return self.gui.State.ContextMgr.CurrentStatic() } func (self *guiCommon) CurrentSideContext() types.Context { - return self.gui.currentSideContext() + return self.gui.State.ContextMgr.CurrentSide() } func (self *guiCommon) IsCurrentContext(c types.Context) bool { - return self.CurrentContext().GetKey() == c.GetKey() + return self.gui.State.ContextMgr.IsCurrent(c) +} + +func (self *guiCommon) Context() types.IContextMgr { + return self.gui.State.ContextMgr } func (self *guiCommon) GetAppState() *config.AppState { @@ -148,3 +152,7 @@ func (self *guiCommon) State() types.IStateAccessor { func (self *guiCommon) KeybindingsOpts() types.KeybindingsOpts { return self.gui.keybindingOpts() } + +func (self *guiCommon) IsAnyModeActive() bool { + return self.IsAnyModeActive() +} diff --git a/pkg/gui/information_panel.go b/pkg/gui/information_panel.go index 1577e3a2e..5de212b4d 100644 --- a/pkg/gui/information_panel.go +++ b/pkg/gui/information_panel.go @@ -3,15 +3,14 @@ package gui import ( "fmt" - "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/constants" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/mattn/go-runewidth" ) func (gui *Gui) informationStr() string { - if activeMode, ok := gui.getActiveMode(); ok { - return activeMode.description() + if activeMode, ok := gui.helpers.Mode.GetActiveMode(); ok { + return activeMode.Description() } if gui.g.Mouse { @@ -23,18 +22,6 @@ func (gui *Gui) informationStr() string { } } -func (gui *Gui) getActiveMode() (modeStatus, bool) { - return slices.Find(gui.modeStatuses(), func(mode modeStatus) bool { - return mode.isActive() - }) -} - -func (gui *Gui) isAnyModeActive() bool { - return slices.Some(gui.modeStatuses(), func(mode modeStatus) bool { - return mode.isActive() - }) -} - func (gui *Gui) handleInfoClick() error { if !gui.g.Mouse { return nil @@ -45,11 +32,11 @@ func (gui *Gui) handleInfoClick() error { cx, _ := view.Cursor() width, _ := view.Size() - if activeMode, ok := gui.getActiveMode(); ok { + if activeMode, ok := gui.helpers.Mode.GetActiveMode(); ok { if width-cx > runewidth.StringWidth(gui.c.Tr.ResetInParentheses) { return nil } - return activeMode.reset() + return activeMode.Reset() } // if we're not in an active mode we show the donate button diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 96570069c..ee8e127a1 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -23,7 +23,8 @@ func (gui *Gui) layout(g *gocui.Gui) error { width, height := g.Size() informationStr := gui.informationStr() - appStatus := gui.statusManager.getStatusString() + + appStatus := gui.helpers.AppStatus.GetStatusString() viewDimensions := gui.getWindowDimensions(informationStr, appStatus) diff --git a/pkg/gui/list_context_config.go b/pkg/gui/list_context_config.go deleted file mode 100644 index a0fd1a751..000000000 --- a/pkg/gui/list_context_config.go +++ /dev/null @@ -1,76 +0,0 @@ -package gui - -import ( - "github.com/jesseduffield/lazygit/pkg/gui/context" - "github.com/jesseduffield/lazygit/pkg/gui/types" -) - -func (gui *Gui) menuListContext() *context.MenuContext { - return context.NewMenuContext(gui.contextCommon) -} - -func (gui *Gui) filesListContext() *context.WorkingTreeContext { - return context.NewWorkingTreeContext(gui.contextCommon) -} - -func (gui *Gui) branchesListContext() *context.BranchesContext { - return context.NewBranchesContext(gui.contextCommon) -} - -func (gui *Gui) remotesListContext() *context.RemotesContext { - return context.NewRemotesContext(gui.contextCommon) -} - -func (gui *Gui) remoteBranchesListContext() *context.RemoteBranchesContext { - return context.NewRemoteBranchesContext(gui.contextCommon) -} - -func (gui *Gui) tagsListContext() *context.TagsContext { - return context.NewTagsContext(gui.contextCommon) -} - -func (gui *Gui) branchCommitsListContext() *context.LocalCommitsContext { - return context.NewLocalCommitsContext(gui.contextCommon) -} - -func (gui *Gui) subCommitsListContext() *context.SubCommitsContext { - return context.NewSubCommitsContext(gui.contextCommon) -} - -func (gui *Gui) reflogCommitsListContext() *context.ReflogCommitsContext { - return context.NewReflogCommitsContext(gui.contextCommon) -} - -func (gui *Gui) stashListContext() *context.StashContext { - return context.NewStashContext(gui.contextCommon) -} - -func (gui *Gui) commitFilesListContext() *context.CommitFilesContext { - return context.NewCommitFilesContext(gui.contextCommon) -} - -func (gui *Gui) submodulesListContext() *context.SubmodulesContext { - return context.NewSubmodulesContext(gui.contextCommon) -} - -func (gui *Gui) suggestionsListContext() *context.SuggestionsContext { - return context.NewSuggestionsContext(gui.contextCommon) -} - -func (gui *Gui) getListContexts() []types.IListContext { - return []types.IListContext{ - gui.State.Contexts.Menu, - gui.State.Contexts.Files, - gui.State.Contexts.Branches, - gui.State.Contexts.Remotes, - gui.State.Contexts.RemoteBranches, - gui.State.Contexts.Tags, - gui.State.Contexts.LocalCommits, - gui.State.Contexts.ReflogCommits, - gui.State.Contexts.SubCommits, - gui.State.Contexts.Stash, - gui.State.Contexts.CommitFiles, - gui.State.Contexts.Submodules, - gui.State.Contexts.Suggestions, - } -} diff --git a/pkg/gui/modes.go b/pkg/gui/modes.go deleted file mode 100644 index 15e78c117..000000000 --- a/pkg/gui/modes.go +++ /dev/null @@ -1,104 +0,0 @@ -package gui - -import ( - "fmt" - - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" - "github.com/jesseduffield/lazygit/pkg/gui/presentation" - "github.com/jesseduffield/lazygit/pkg/gui/style" -) - -type modeStatus struct { - isActive func() bool - description func() string - reset func() error -} - -func (gui *Gui) modeStatuses() []modeStatus { - return []modeStatus{ - { - isActive: gui.State.Modes.Diffing.Active, - description: func() string { - return gui.withResetButton( - fmt.Sprintf( - "%s %s", - gui.c.Tr.LcShowingGitDiff, - "git diff "+gui.helpers.Diff.DiffStr(), - ), - style.FgMagenta, - ) - }, - reset: gui.helpers.Diff.ExitDiffMode, - }, - { - isActive: gui.git.Patch.PatchBuilder.Active, - description: func() string { - return gui.withResetButton(gui.c.Tr.LcBuildingPatch, style.FgYellow.SetBold()) - }, - reset: gui.helpers.PatchBuilding.Reset, - }, - { - isActive: gui.State.Modes.Filtering.Active, - description: func() string { - return gui.withResetButton( - fmt.Sprintf( - "%s '%s'", - gui.c.Tr.LcFilteringBy, - gui.State.Modes.Filtering.GetPath(), - ), - style.FgRed, - ) - }, - reset: gui.exitFilterMode, - }, - { - isActive: gui.State.Modes.CherryPicking.Active, - description: func() string { - copiedCount := len(gui.State.Modes.CherryPicking.CherryPickedCommits) - text := gui.c.Tr.LcCommitsCopied - if copiedCount == 1 { - text = gui.c.Tr.LcCommitCopied - } - - return gui.withResetButton( - fmt.Sprintf( - "%d %s", - copiedCount, - text, - ), - style.FgCyan, - ) - }, - reset: gui.helpers.CherryPick.Reset, - }, - { - isActive: func() bool { - return gui.git.Status.WorkingTreeState() != enums.REBASE_MODE_NONE - }, - description: func() string { - workingTreeState := gui.git.Status.WorkingTreeState() - return gui.withResetButton( - presentation.FormatWorkingTreeState(workingTreeState), style.FgYellow, - ) - }, - reset: gui.helpers.MergeAndRebase.AbortMergeOrRebaseWithConfirm, - }, - { - isActive: func() bool { - return gui.State.Model.BisectInfo.Started() - }, - description: func() string { - return gui.withResetButton("bisecting", style.FgGreen) - }, - reset: gui.helpers.Bisect.Reset, - }, - } -} - -func (gui *Gui) withResetButton(content string, textStyle style.TextStyle) string { - return textStyle.Sprintf( - "%s %s", - content, - style.AttrUnderline.Sprint(gui.c.Tr.ResetInParentheses), - ) -} diff --git a/pkg/gui/popup/popup_handler.go b/pkg/gui/popup/popup_handler.go index 4e50b6326..633e91a55 100644 --- a/pkg/gui/popup/popup_handler.go +++ b/pkg/gui/popup/popup_handler.go @@ -22,7 +22,7 @@ type PopupHandler struct { popContextFn func() error currentContextFn func() types.Context createMenuFn func(types.CreateMenuOptions) error - withWaitingStatusFn func(message string, f func() error) error + withWaitingStatusFn func(message string, f func() error) toastFn func(message string) getPromptInputFn func() string } @@ -36,7 +36,7 @@ func NewPopupHandler( popContextFn func() error, currentContextFn func() types.Context, createMenuFn func(types.CreateMenuOptions) error, - withWaitingStatusFn func(message string, f func() error) error, + withWaitingStatusFn func(message string, f func() error), toastFn func(message string), getPromptInputFn func() string, ) *PopupHandler { @@ -63,7 +63,8 @@ func (self *PopupHandler) Toast(message string) { } func (self *PopupHandler) WithWaitingStatus(message string, f func() error) error { - return self.withWaitingStatusFn(message, f) + self.withWaitingStatusFn(message, f) + return nil } func (self *PopupHandler) Error(err error) error { diff --git a/pkg/gui/quitting.go b/pkg/gui/quitting.go index 41c23f268..749866de0 100644 --- a/pkg/gui/quitting.go +++ b/pkg/gui/quitting.go @@ -24,9 +24,9 @@ func (gui *Gui) handleTopLevelReturn() error { return gui.c.PushContext(parentContext) } - for _, mode := range gui.modeStatuses() { - if mode.isActive() { - return mode.reset() + for _, mode := range gui.helpers.Mode.Statuses() { + if mode.IsActive() { + return mode.Reset() } } diff --git a/pkg/gui/services/custom_commands/client.go b/pkg/gui/services/custom_commands/client.go index 4db916a66..4cacba385 100644 --- a/pkg/gui/services/custom_commands/client.go +++ b/pkg/gui/services/custom_commands/client.go @@ -1,10 +1,7 @@ package custom_commands import ( - "github.com/jesseduffield/lazygit/pkg/commands" - "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/config" - "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -19,14 +16,11 @@ type Client struct { func NewClient( c *helpers.HelperCommon, - os *oscommands.OSCommand, - git *commands.GitCommand, - contexts *context.ContextTree, helpers *helpers.Helpers, ) *Client { - sessionStateLoader := NewSessionStateLoader(contexts, helpers) - handlerCreator := NewHandlerCreator(c, os, git, sessionStateLoader) - keybindingCreator := NewKeybindingCreator(contexts) + sessionStateLoader := NewSessionStateLoader(c, helpers.Refs) + handlerCreator := NewHandlerCreator(c, sessionStateLoader) + keybindingCreator := NewKeybindingCreator(c) customCommands := c.UserConfig.CustomCommands return &Client{ diff --git a/pkg/gui/services/custom_commands/handler_creator.go b/pkg/gui/services/custom_commands/handler_creator.go index 2772d0c1a..6ec005a37 100644 --- a/pkg/gui/services/custom_commands/handler_creator.go +++ b/pkg/gui/services/custom_commands/handler_creator.go @@ -5,8 +5,6 @@ import ( "text/template" "github.com/jesseduffield/generics/slices" - "github.com/jesseduffield/lazygit/pkg/commands" - "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/style" @@ -17,8 +15,6 @@ import ( // takes a custom command and returns a function that will be called when the corresponding user-defined keybinding is pressed type HandlerCreator struct { c *helpers.HelperCommon - os *oscommands.OSCommand - git *commands.GitCommand sessionStateLoader *SessionStateLoader resolver *Resolver menuGenerator *MenuGenerator @@ -26,8 +22,6 @@ type HandlerCreator struct { func NewHandlerCreator( c *helpers.HelperCommon, - os *oscommands.OSCommand, - git *commands.GitCommand, sessionStateLoader *SessionStateLoader, ) *HandlerCreator { resolver := NewResolver(c.Common) @@ -35,8 +29,6 @@ func NewHandlerCreator( return &HandlerCreator{ c: c, - os: os, - git: git, sessionStateLoader: sessionStateLoader, resolver: resolver, menuGenerator: menuGenerator, @@ -144,7 +136,7 @@ func (self *HandlerCreator) confirmPrompt(prompt *config.CustomCommandPrompt, ha func (self *HandlerCreator) menuPromptFromCommand(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error { // Run and save output - message, err := self.git.Custom.RunWithOutput(prompt.Command) + message, err := self.c.Git().Custom.RunWithOutput(prompt.Command) if err != nil { return self.c.Error(err) } @@ -181,7 +173,7 @@ func (self *HandlerCreator) getResolveTemplateFn(form map[string]string, promptR } funcs := template.FuncMap{ - "quote": self.os.Quote, + "quote": self.c.OS().Quote, } return func(templateStr string) (string, error) { return utils.ResolveTemplate(templateStr, objects, funcs) } @@ -194,7 +186,7 @@ func (self *HandlerCreator) finalHandler(customCommand config.CustomCommand, ses return self.c.Error(err) } - cmdObj := self.os.Cmd.NewShell(cmdStr) + cmdObj := self.c.OS().Cmd.NewShell(cmdStr) if customCommand.Subprocess { return self.c.RunSubprocessAndRefresh(cmdObj) diff --git a/pkg/gui/services/custom_commands/keybinding_creator.go b/pkg/gui/services/custom_commands/keybinding_creator.go index 7251225fe..2482f03f2 100644 --- a/pkg/gui/services/custom_commands/keybinding_creator.go +++ b/pkg/gui/services/custom_commands/keybinding_creator.go @@ -8,18 +8,19 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/context" + "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/types" ) // KeybindingCreator takes a custom command along with its handler and returns a corresponding keybinding type KeybindingCreator struct { - contexts *context.ContextTree + c *helpers.HelperCommon } -func NewKeybindingCreator(contexts *context.ContextTree) *KeybindingCreator { +func NewKeybindingCreator(c *helpers.HelperCommon) *KeybindingCreator { return &KeybindingCreator{ - contexts: contexts, + c: c, } } @@ -62,7 +63,7 @@ func (self *KeybindingCreator) getViewNameAndContexts(customCommand config.Custo } func (self *KeybindingCreator) contextForContextKey(contextKey types.ContextKey) (types.Context, bool) { - for _, context := range self.contexts.Flatten() { + for _, context := range self.c.Contexts().Flatten() { if context.GetKey() == contextKey { return context, true } diff --git a/pkg/gui/services/custom_commands/session_state_loader.go b/pkg/gui/services/custom_commands/session_state_loader.go index 42f3403ec..2ef7a44bd 100644 --- a/pkg/gui/services/custom_commands/session_state_loader.go +++ b/pkg/gui/services/custom_commands/session_state_loader.go @@ -2,21 +2,21 @@ package custom_commands import ( "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" ) // loads the session state at the time that a custom command is invoked, for use // in the custom command's template strings type SessionStateLoader struct { - contexts *context.ContextTree - helpers *helpers.Helpers + c *helpers.HelperCommon + helpers *helpers.Helpers + refsHelper *helpers.RefsHelper } -func NewSessionStateLoader(contexts *context.ContextTree, helpers *helpers.Helpers) *SessionStateLoader { +func NewSessionStateLoader(c *helpers.HelperCommon, refsHelper *helpers.RefsHelper) *SessionStateLoader { return &SessionStateLoader{ - contexts: contexts, - helpers: helpers, + c: c, + refsHelper: refsHelper, } } @@ -39,18 +39,18 @@ type SessionState struct { func (self *SessionStateLoader) call() *SessionState { return &SessionState{ - SelectedFile: self.contexts.Files.GetSelectedFile(), - SelectedPath: self.contexts.Files.GetSelectedPath(), - SelectedLocalCommit: self.contexts.LocalCommits.GetSelected(), - SelectedReflogCommit: self.contexts.ReflogCommits.GetSelected(), - SelectedLocalBranch: self.contexts.Branches.GetSelected(), - SelectedRemoteBranch: self.contexts.RemoteBranches.GetSelected(), - SelectedRemote: self.contexts.Remotes.GetSelected(), - SelectedTag: self.contexts.Tags.GetSelected(), - SelectedStashEntry: self.contexts.Stash.GetSelected(), - SelectedCommitFile: self.contexts.CommitFiles.GetSelectedFile(), - SelectedCommitFilePath: self.contexts.CommitFiles.GetSelectedPath(), - SelectedSubCommit: self.contexts.SubCommits.GetSelected(), - CheckedOutBranch: self.helpers.Refs.GetCheckedOutRef(), + SelectedFile: self.c.Contexts().Files.GetSelectedFile(), + SelectedPath: self.c.Contexts().Files.GetSelectedPath(), + SelectedLocalCommit: self.c.Contexts().LocalCommits.GetSelected(), + SelectedReflogCommit: self.c.Contexts().ReflogCommits.GetSelected(), + SelectedLocalBranch: self.c.Contexts().Branches.GetSelected(), + SelectedRemoteBranch: self.c.Contexts().RemoteBranches.GetSelected(), + SelectedRemote: self.c.Contexts().Remotes.GetSelected(), + SelectedTag: self.c.Contexts().Tags.GetSelected(), + SelectedStashEntry: self.c.Contexts().Stash.GetSelected(), + SelectedCommitFile: self.c.Contexts().CommitFiles.GetSelectedFile(), + SelectedCommitFilePath: self.c.Contexts().CommitFiles.GetSelectedPath(), + SelectedSubCommit: self.c.Contexts().SubCommits.GetSelected(), + CheckedOutBranch: self.refsHelper.GetCheckedOutRef(), } } diff --git a/pkg/gui/status/status_manager.go b/pkg/gui/status/status_manager.go new file mode 100644 index 000000000..78e4d37e3 --- /dev/null +++ b/pkg/gui/status/status_manager.go @@ -0,0 +1,94 @@ +package status + +import ( + "time" + + "github.com/jesseduffield/generics/slices" + "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/sasha-s/go-deadlock" +) + +// StatusManager's job is to handle queuing of loading states and toast notifications +// that you see at the bottom left of the screen. +type StatusManager struct { + statuses []appStatus + nextId int + mutex deadlock.Mutex +} + +type appStatus struct { + message string + statusType string + id int +} + +func NewStatusManager() *StatusManager { + return &StatusManager{} +} + +func (self *StatusManager) WithWaitingStatus(message string, f func()) { + self.mutex.Lock() + + self.nextId += 1 + id := self.nextId + + newStatus := appStatus{ + message: message, + statusType: "waiting", + id: id, + } + self.statuses = append([]appStatus{newStatus}, self.statuses...) + + self.mutex.Unlock() + + f() + + self.removeStatus(id) +} + +func (self *StatusManager) AddToastStatus(message string) int { + self.mutex.Lock() + defer self.mutex.Unlock() + + self.nextId++ + id := self.nextId + + newStatus := appStatus{ + message: message, + statusType: "toast", + id: id, + } + self.statuses = append([]appStatus{newStatus}, self.statuses...) + + go func() { + time.Sleep(time.Second * 2) + + self.removeStatus(id) + }() + + return id +} + +func (self *StatusManager) GetStatusString() string { + if len(self.statuses) == 0 { + return "" + } + topStatus := self.statuses[0] + if topStatus.statusType == "waiting" { + return topStatus.message + " " + utils.Loader() + } + return topStatus.message +} + +func (self *StatusManager) HasStatus() bool { + return len(self.statuses) > 0 +} + +func (self *StatusManager) removeStatus(id int) { + self.mutex.Lock() + defer self.mutex.Unlock() + + self.statuses = slices.Filter(self.statuses, func(status appStatus) bool { + return status.id != id + }) +} diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 81c2cb385..dcccc1747 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -60,6 +60,9 @@ type IGuiCommon interface { CurrentStaticContext() Context CurrentSideContext() Context IsCurrentContext(Context) bool + // TODO: replace the above context-based methods with just using Context() e.g. replace PushContext() with Context().Push() + Context() IContextMgr + // enters search mode for the current view OpenSearch() @@ -81,6 +84,7 @@ type IGuiCommon interface { Git() *commands.GitCommand OS() *oscommands.OSCommand Model() *Model + Modes() *Modes Mutexes() Mutexes @@ -90,6 +94,10 @@ type IGuiCommon interface { KeybindingsOpts() KeybindingsOpts } +type IModeMgr interface { + IsAnyModeActive() bool +} + type IPopupHandler interface { // Shows a popup with a (localized) "Error" caption and the given error message (in red). // @@ -220,6 +228,8 @@ type IStateAccessor interface { SetUpdating(bool) SetIsRefreshingFiles(bool) GetIsRefreshingFiles() bool + GetShowExtrasWindow() bool + SetShowExtrasWindow(bool) } type IRepoStateAccessor interface { @@ -230,6 +240,10 @@ type IRepoStateAccessor interface { GetCurrentPopupOpts() *CreatePopupPanelOpts SetCurrentPopupOpts(*CreatePopupPanelOpts) GetScreenMode() WindowMaximisation + SetScreenMode(WindowMaximisation) + IsSearching() bool + SetSplitMainPanel(bool) + GetSplitMainPanel() bool } // startup stages so we don't need to load everything at once diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index ef57e06bc..7ed0db1b2 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -198,3 +198,14 @@ type ListItem interface { // Description is something we would show in a message e.g. '123as14: push blah' for a commit Description() string } + +type IContextMgr interface { + Push(context Context, opts ...OnFocusOpts) error + Pop() error + Replace(context Context) error + Current() Context + CurrentStatic() Context + CurrentSide() Context + IsCurrent(c Context) bool + ForEach(func(Context)) +}