mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	lots of changes
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
| } | ||||
|   | ||||
							
								
								
									
										136
									
								
								pkg/gui/context/setup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								pkg/gui/context/setup.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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"), | ||||
| 	} | ||||
| } | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| 	} | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
| 	}) | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										68
									
								
								pkg/gui/controllers/helpers/app_status_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								pkg/gui/controllers/helpers/app_status_helper.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
| @@ -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{}, | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										159
									
								
								pkg/gui/controllers/helpers/mode_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								pkg/gui/controllers/helpers/mode_helper.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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}}) | ||||
| } | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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() | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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() | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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{ | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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() | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|  | ||||
|   | ||||
| @@ -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, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										104
									
								
								pkg/gui/modes.go
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								pkg/gui/modes.go
									
									
									
									
									
								
							| @@ -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), | ||||
| 	) | ||||
| } | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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() | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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{ | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
| 		} | ||||
|   | ||||
| @@ -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(), | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										94
									
								
								pkg/gui/status/status_manager.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								pkg/gui/status/status_manager.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| 	}) | ||||
| } | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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)) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user