From db12853bbe825d69686ea71161497d1bbb120b8e Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Thu, 23 Mar 2023 18:47:29 +1100 Subject: lots of changes --- pkg/gui/app_status_manager.go | 132 ----------------- pkg/gui/arrangement.go | 97 ++++++------ pkg/gui/context.go | 40 +++-- pkg/gui/context/setup.go | 136 +++++++++++++++++ pkg/gui/context_config.go | 165 ++++----------------- pkg/gui/controllers.go | 59 +++++--- pkg/gui/controllers/basic_commits_controller.go | 26 ++-- pkg/gui/controllers/bisect_controller.go | 18 +-- pkg/gui/controllers/branches_controller.go | 44 +++--- pkg/gui/controllers/command_log_controller.go | 8 +- pkg/gui/controllers/commit_message_controller.go | 10 +- pkg/gui/controllers/commits_files_controller.go | 16 +- pkg/gui/controllers/common.go | 20 ++- pkg/gui/controllers/confirmation_controller.go | 10 +- pkg/gui/controllers/context_lines_controller.go | 8 +- pkg/gui/controllers/files_controller.go | 48 +++--- pkg/gui/controllers/files_remove_controller.go | 10 +- pkg/gui/controllers/git_flow_controller.go | 8 +- pkg/gui/controllers/global_controller.go | 8 +- pkg/gui/controllers/helpers/app_status_helper.go | 68 +++++++++ pkg/gui/controllers/helpers/helpers.go | 4 + pkg/gui/controllers/helpers/mode_helper.go | 159 ++++++++++++++++++++ pkg/gui/controllers/list_controller.go | 14 +- pkg/gui/controllers/local_commits_controller.go | 37 +++-- pkg/gui/controllers/menu_controller.go | 8 +- pkg/gui/controllers/merge_conflicts_controller.go | 16 +- pkg/gui/controllers/patch_building_controller.go | 16 +- pkg/gui/controllers/patch_explorer_controller.go | 14 +- pkg/gui/controllers/reflog_commits_controller.go | 10 +- pkg/gui/controllers/remote_branches_controller.go | 20 +-- pkg/gui/controllers/remotes_controller.go | 8 +- pkg/gui/controllers/snake_controller.go | 16 +- pkg/gui/controllers/staging_controller.go | 28 ++-- pkg/gui/controllers/stash_controller.go | 12 +- pkg/gui/controllers/status_controller.go | 24 +-- pkg/gui/controllers/sub_commits_controller.go | 10 +- pkg/gui/controllers/submodules_controller.go | 14 +- pkg/gui/controllers/suggestions_controller.go | 10 +- .../controllers/switch_to_diff_files_controller.go | 6 +- .../switch_to_sub_commits_controller.go | 12 +- pkg/gui/controllers/sync_controller.go | 20 +-- pkg/gui/controllers/tags_controller.go | 18 +-- pkg/gui/controllers/undo_controller.go | 16 +- pkg/gui/controllers/vertical_scroll_controller.go | 10 +- pkg/gui/controllers/workspace_reset_controller.go | 2 +- pkg/gui/extras_panel.go | 8 +- pkg/gui/filtering.go | 15 +- pkg/gui/filtering_menu_panel.go | 2 +- pkg/gui/gui.go | 76 +++++----- pkg/gui/gui_common.go | 22 ++- pkg/gui/information_panel.go | 21 +-- pkg/gui/layout.go | 3 +- pkg/gui/list_context_config.go | 76 ---------- pkg/gui/modes.go | 104 ------------- pkg/gui/popup/popup_handler.go | 7 +- pkg/gui/quitting.go | 6 +- pkg/gui/services/custom_commands/client.go | 12 +- .../services/custom_commands/handler_creator.go | 14 +- .../services/custom_commands/keybinding_creator.go | 9 +- .../custom_commands/session_state_loader.go | 38 ++--- pkg/gui/status/status_manager.go | 94 ++++++++++++ pkg/gui/types/common.go | 14 ++ pkg/gui/types/context.go | 11 ++ 63 files changed, 1024 insertions(+), 943 deletions(-) delete mode 100644 pkg/gui/app_status_manager.go create mode 100644 pkg/gui/context/setup.go create mode 100644 pkg/gui/controllers/helpers/app_status_helper.go create mode 100644 pkg/gui/controllers/helpers/mode_helper.go delete mode 100644 pkg/gui/list_context_config.go delete mode 100644 pkg/gui/modes.go create mode 100644 pkg/gui/status/status_manager.go (limited to 'pkg/gui') 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 &GitFlowCo