summaryrefslogtreecommitdiffstats
path: root/pkg/gui/gui.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/gui/gui.go')
-rw-r--r--pkg/gui/gui.go177
1 files changed, 132 insertions, 45 deletions
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index aed1d5430..4235f2eb0 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -8,6 +8,7 @@ import (
"sync"
"github.com/jesseduffield/gocui"
+ "github.com/jesseduffield/lazycore/pkg/boxlayout"
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
@@ -32,7 +33,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/integration/components"
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
- "github.com/jesseduffield/lazygit/pkg/snake"
"github.com/jesseduffield/lazygit/pkg/tasks"
"github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/updates"
@@ -58,18 +58,6 @@ const StartupPopupVersion = 5
// OverlappingEdges determines if panel edges overlap
var OverlappingEdges = false
-type ContextManager struct {
- ContextStack []types.Context
- sync.RWMutex
-}
-
-func NewContextManager() ContextManager {
- return ContextManager{
- ContextStack: []types.Context{},
- RWMutex: sync.RWMutex{},
- }
-}
-
type Repo string
// Gui wraps the gocui Gui object which handles rendering and events
@@ -117,12 +105,7 @@ type Gui struct {
// this tells us whether our views have been initially set up
ViewsSetup bool
- Views Views
-
- // if we've suspended the gui (e.g. because we've switched to a subprocess)
- // we typically want to pause some things that are running like background
- // file refreshes
- PauseBackgroundThreads bool
+ Views types.Views
// Log of the commands that get run, to be displayed to the user.
CmdLog []string
@@ -139,6 +122,8 @@ type Gui struct {
// flag as to whether or not the diff view should ignore whitespace
IgnoreWhitespaceInDiffView bool
+ IsRefreshingFiles bool
+
// we use this to decide whether we'll return to the original directory that
// lazygit was opened in, or if we'll retain the one we're currently in.
RetainOriginalDir bool
@@ -153,10 +138,52 @@ type Gui struct {
// process
InitialDir string
+ BackgroundRoutineMgr *BackgroundRoutineMgr
+ // for accessing the gui's state from outside this package
+ stateAccessor *StateAccessor
+
+ Updating bool
+
c *types.HelperCommon
helpers *helpers.Helpers
+}
+
+type StateAccessor struct {
+ gui *Gui
+}
+
+var _ types.IStateAccessor = new(StateAccessor)
+
+func (self *StateAccessor) GetIgnoreWhitespaceInDiffView() bool {
+ return self.gui.IgnoreWhitespaceInDiffView
+}
+
+func (self *StateAccessor) SetIgnoreWhitespaceInDiffView(value bool) {
+ self.gui.IgnoreWhitespaceInDiffView = value
+}
- snakeGame *snake.Game
+func (self *StateAccessor) GetRepoPathStack() *utils.StringStack {
+ return self.gui.RepoPathStack
+}
+
+func (self *StateAccessor) GetUpdating() bool {
+ return self.gui.Updating
+}
+
+func (self *StateAccessor) SetUpdating(value bool) {
+ self.gui.Updating = value
+}
+
+func (self *StateAccessor) GetRepoState() types.IRepoStateAccessor {
+ return self.gui.State
+}
+
+func (self *StateAccessor) GetIsRefreshingFiles() bool {
+ return self.gui.IsRefreshingFiles
+}
+
+func (self *StateAccessor) SetIsRefreshingFiles(value bool) {
+ self.gui.IsRefreshingFiles = value
}
// we keep track of some stuff from one render to the next to see if certain
@@ -174,16 +201,14 @@ type GuiRepoState struct {
// Suggestions will sometimes appear when typing into a prompt
Suggestions []*types.Suggestion
- Updating bool
SplitMainPanel bool
LimitCommits bool
- IsRefreshingFiles bool
- Searching searchingState
- StartupStage StartupStage // Allows us to not load everything at once
+ Searching searchingState
+ StartupStage types.StartupStage // Allows us to not load everything at once
- ContextManager ContextManager
- Contexts *context.ContextTree
+ ContextMgr ContextMgr
+ Contexts *context.ContextTree
// WindowViewNameMap is a mapping of windows to the current view of that window.
// Some views move between windows for example the commitFiles view and when cycling through
@@ -204,20 +229,38 @@ type GuiRepoState struct {
CurrentPopupOpts *types.CreatePopupPanelOpts
}
+var _ types.IRepoStateAccessor = new(GuiRepoState)
+
+func (self *GuiRepoState) GetViewsSetup() bool {
+ return self.ViewsSetup
+}
+
+func (self *GuiRepoState) GetWindowViewNameMap() *utils.ThreadSafeMap[string, string] {
+ return self.WindowViewNameMap
+}
+
+func (self *GuiRepoState) GetStartupStage() types.StartupStage {
+ return self.StartupStage
+}
+
+func (self *GuiRepoState) SetStartupStage(value types.StartupStage) {
+ self.StartupStage = value
+}
+
+func (self *GuiRepoState) GetCurrentPopupOpts() *types.CreatePopupPanelOpts {
+ return self.CurrentPopupOpts
+}
+
+func (self *GuiRepoState) SetCurrentPopupOpts(value *types.CreatePopupPanelOpts) {
+ self.CurrentPopupOpts = value
+}
+
type searchingState struct {
view *gocui.View
isSearching bool
searchString string
}
-// startup stages so we don't need to load everything at once
-type StartupStage int
-
-const (
- INITIAL StartupStage = iota
- COMPLETE
-)
-
func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, reuseState bool) error {
var err error
gui.git, err = commands.NewGitCommand(
@@ -278,8 +321,6 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs, reuseState bool) {
initialContext := initialContext(contextTree, startArgs)
initialScreenMode := initialScreenMode(startArgs, gui.Config)
- initialWindowViewNameMap := gui.initialWindowViewNameMap(contextTree)
-
gui.State = &GuiRepoState{
Model: &types.Model{
CommitFiles: nil,
@@ -298,9 +339,9 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs, reuseState bool) {
},
ScreenMode: initialScreenMode,
// TODO: put contexts in the context manager
- ContextManager: NewContextManager(),
+ ContextMgr: NewContextMgr(initialContext, gui),
Contexts: contextTree,
- WindowViewNameMap: initialWindowViewNameMap,
+ WindowViewNameMap: initialWindowViewNameMap(contextTree),
}
if err := gui.c.PushContext(initialContext); err != nil {
@@ -310,6 +351,16 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs, reuseState bool) {
gui.RepoStateMap[Repo(currentDir)] = gui.State
}
+func initialWindowViewNameMap(contextTree *context.ContextTree) *utils.ThreadSafeMap[string, string] {
+ result := utils.NewThreadSafeMap[string, string]()
+
+ for _, context := range contextTree.Flatten() {
+ result.Set(context.GetWindowName(), context.GetViewName())
+ }
+
+ return result
+}
+
func initialScreenMode(startArgs appTypes.StartArgs, config config.AppConfigurer) WindowMaximisation {
if startArgs.FilterPath != "" || startArgs.GitArg != appTypes.GitArgNone {
return SCREEN_HALF
@@ -391,7 +442,7 @@ func NewGui(
InitialDir: initialDir,
}
- gui.watchFilesForChanges()
+ gui.WatchFilesForChanges()
gui.PopupHandler = popup.NewPopupHandler(
cmn,
@@ -429,6 +480,9 @@ func NewGui(
icons.SetIconEnabled(gui.UserConfig.Gui.ShowIcons)
presentation.SetCustomBranches(gui.UserConfig.Gui.BranchColors)
+ gui.BackgroundRoutineMgr = &BackgroundRoutineMgr{gui: gui}
+ gui.stateAccessor = &StateAccessor{gui: gui}
+
return gui, nil
}
@@ -539,7 +593,7 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
gui.waitForIntro.Add(1)
- gui.startBackgroundRoutines()
+ gui.BackgroundRoutineMgr.startBackgroundRoutines()
gui.c.Log.Info("starting main loop")
@@ -565,11 +619,11 @@ func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error {
switch err {
case gocui.ErrQuit:
if gui.RetainOriginalDir {
- if err := gui.recordDirectory(gui.InitialDir); err != nil {
+ if err := gui.helpers.RecordDirectory.RecordDirectory(gui.InitialDir); err != nil {
return err
}
} else {
- if err := gui.recordCurrentDirectory(); err != nil {
+ if err := gui.helpers.RecordDirectory.RecordCurrentDirectory(); err != nil {
return err
}
}
@@ -639,7 +693,8 @@ func (gui *Gui) runSubprocessWithSuspense(subprocess oscommands.ICmdObj) (bool,
return false, gui.c.Error(err)
}
- gui.PauseBackgroundThreads = true
+ gui.BackgroundRoutineMgr.PauseBackgroundThreads(true)
+ defer gui.BackgroundRoutineMgr.PauseBackgroundThreads(false)
cmdErr := gui.runSubprocess(subprocess)
@@ -647,8 +702,6 @@ func (gui *Gui) runSubprocessWithSuspense(subprocess oscommands.ICmdObj) (bool,
return false, err
}
- gui.PauseBackgroundThreads = false
-
if cmdErr != nil {
return false, gui.c.Error(cmdErr)
}
@@ -751,3 +804,37 @@ func (gui *Gui) onUIThread(f func() error) {
return f()
})
}
+
+func (gui *Gui) startBackgroundRoutines() {
+ mgr := &BackgroundRoutineMgr{gui: gui}
+ mgr.startBackgroundRoutines()
+}
+
+func (gui *Gui) getWindowDimensions(informationStr string, appStatus string) map[string]boxlayout.Dimensions {
+ windowArranger := &WindowArranger{gui: gui}
+ 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()
+}