diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index aa03c9880..b9a25ea67 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -1,21 +1,23 @@ package gui +import "github.com/jesseduffield/lazygit/pkg/gui/types" + func (gui *Gui) branchesRenderToMain() error { - var task updateTask + var task types.UpdateTask branch := gui.State.Contexts.Branches.GetSelected() if branch == nil { - task = NewRenderStringTask(gui.c.Tr.NoBranchesThisRepo) + task = types.NewRenderStringTask(gui.c.Tr.NoBranchesThisRepo) } else { cmdObj := gui.git.Branch.GetGraphCmdObj(branch.FullRefName()) - task = NewRunPtyTask(cmdObj.GetCmd()) + task = types.NewRunPtyTask(cmdObj.GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: gui.c.Tr.LogTitle, - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: gui.c.Tr.LogTitle, + Task: task, }, }) } diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index 213f2e2ae..0849ab310 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -16,20 +16,20 @@ func (gui *Gui) commitFilesRenderToMain() error { from, reverse := gui.State.Modes.Diffing.GetFromAndReverseArgsForDiff(ref.ParentRefName()) cmdObj := gui.git.WorkingTree.ShowFileDiffCmdObj(from, to, reverse, node.GetPath(), false) - task := NewRunPtyTask(cmdObj.GetCmd()) + task := types.NewRunPtyTask(cmdObj.GetCmd()) - pair := gui.normalMainContextPair() + pair := gui.c.MainViewPairs().Normal if node.File != nil { - pair = gui.patchBuildingMainContextPair() + pair = gui.c.MainViewPairs().PatchBuilding } - return gui.refreshMainViews(refreshMainOpts{ - pair: pair, - main: &viewUpdateOpts{ - title: gui.Tr.Patch, - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: pair, + Main: &types.ViewUpdateOpts{ + Title: gui.Tr.Patch, + Task: task, }, - secondary: gui.secondaryPatchPanelUpdateOpts(), + Secondary: gui.secondaryPatchPanelUpdateOpts(), }) } diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index ee40b927a..19434b9fb 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -2,6 +2,7 @@ package gui import ( "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -29,32 +30,32 @@ func (gui *Gui) onCommitFocus() error { } func (gui *Gui) branchCommitsRenderToMain() error { - var task updateTask + var task types.UpdateTask commit := gui.State.Contexts.LocalCommits.GetSelected() if commit == nil { - task = NewRenderStringTask(gui.c.Tr.NoCommitsThisBranch) + task = types.NewRenderStringTask(gui.c.Tr.NoCommitsThisBranch) } else { cmdObj := gui.git.Commit.ShowCmdObj(commit.Sha, gui.State.Modes.Filtering.GetPath()) - task = NewRunPtyTask(cmdObj.GetCmd()) + task = types.NewRunPtyTask(cmdObj.GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Patch", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Patch", + Task: task, }, - secondary: gui.secondaryPatchPanelUpdateOpts(), + Secondary: gui.secondaryPatchPanelUpdateOpts(), }) } -func (gui *Gui) secondaryPatchPanelUpdateOpts() *viewUpdateOpts { +func (gui *Gui) secondaryPatchPanelUpdateOpts() *types.ViewUpdateOpts { if gui.git.Patch.PatchManager.Active() { patch := gui.git.Patch.PatchManager.RenderAggregatedPatchColored(false) - return &viewUpdateOpts{ - task: NewRenderStringWithoutScrollTask(patch), - title: gui.Tr.CustomPatch, + return &types.ViewUpdateOpts{ + Task: types.NewRenderStringWithoutScrollTask(patch), + Title: gui.Tr.CustomPatch, } } diff --git a/pkg/gui/diffing.go b/pkg/gui/diffing.go index fd0d32a02..f5fbde2a2 100644 --- a/pkg/gui/diffing.go +++ b/pkg/gui/diffing.go @@ -18,13 +18,13 @@ func (gui *Gui) renderDiff() error { cmdObj := gui.os.Cmd.New( fmt.Sprintf("git diff --submodule --no-ext-diff --color %s", gui.diffStr()), ) - task := NewRunPtyTask(cmdObj.GetCmd()) + task := types.NewRunPtyTask(cmdObj.GetCmd()) - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Diff", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Diff", + Task: task, }, }) } diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 8530ef382..128ebfe72 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -4,6 +4,7 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/filetree" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) getSelectedFileNode() *filetree.FileNode { @@ -22,11 +23,11 @@ func (gui *Gui) filesRenderToMain() error { node := gui.getSelectedFileNode() if node == nil { - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: gui.c.Tr.DiffTitle, - task: NewRenderStringTask(gui.c.Tr.NoChangedFiles), + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: gui.c.Tr.DiffTitle, + Task: types.NewRenderStringTask(gui.c.Tr.NoChangedFiles), }, }) } @@ -44,9 +45,9 @@ func (gui *Gui) filesRenderToMain() error { gui.helpers.MergeConflicts.ResetMergeState() - pair := gui.normalMainContextPair() + pair := gui.c.MainViewPairs().Normal if node.File != nil { - pair = gui.stagingMainContextPair() + pair = gui.c.MainViewPairs().Staging } split := gui.c.UserConfig.Gui.SplitDiff == "always" || (node.GetHasUnstagedChanges() && node.GetHasStagedChanges()) @@ -57,11 +58,11 @@ func (gui *Gui) filesRenderToMain() error { if mainShowsStaged { title = gui.c.Tr.StagedChanges } - refreshOpts := refreshMainOpts{ - pair: pair, - main: &viewUpdateOpts{ - task: NewRunPtyTask(cmdObj.GetCmd()), - title: title, + refreshOpts := types.RefreshMainOpts{ + Pair: pair, + Main: &types.ViewUpdateOpts{ + Task: types.NewRunPtyTask(cmdObj.GetCmd()), + Title: title, }, } @@ -73,13 +74,13 @@ func (gui *Gui) filesRenderToMain() error { title = gui.c.Tr.UnstagedChanges } - refreshOpts.secondary = &viewUpdateOpts{ - title: title, - task: NewRunPtyTask(cmdObj.GetCmd()), + refreshOpts.Secondary = &types.ViewUpdateOpts{ + Title: title, + Task: types.NewRunPtyTask(cmdObj.GetCmd()), } } - return gui.refreshMainViews(refreshOpts) + return gui.c.RenderToMainViews(refreshOpts) } func (gui *Gui) getSetTextareaTextFn(getView func() *gocui.View) func(string) { diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index 2b7226034..835aa4f54 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -89,3 +89,16 @@ func (self *guiCommon) OpenSearch() { func (self *guiCommon) OnUIThread(f func() error) { self.gui.onUIThread(f) } + +func (self *guiCommon) RenderToMainViews(opts types.RefreshMainOpts) error { + return self.gui.refreshMainViews(opts) +} + +func (self *guiCommon) MainViewPairs() types.MainViewPairs { + return types.MainViewPairs{ + Normal: self.gui.normalMainContextPair(), + Staging: self.gui.stagingMainContextPair(), + PatchBuilding: self.gui.patchBuildingMainContextPair(), + MergeConflicts: self.gui.mergingMainContextPair(), + } +} diff --git a/pkg/gui/main_panels.go b/pkg/gui/main_panels.go index a2449e9f8..625391480 100644 --- a/pkg/gui/main_panels.go +++ b/pkg/gui/main_panels.go @@ -1,124 +1,48 @@ package gui import ( - "os/exec" - "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/types" ) -type viewUpdateOpts struct { - title string - - task updateTask -} - -type refreshMainOpts struct { - pair MainContextPair - main *viewUpdateOpts - secondary *viewUpdateOpts -} - -type updateTask interface { - IsUpdateTask() -} - -type renderStringTask struct { - str string -} - -func (t *renderStringTask) IsUpdateTask() {} - -func NewRenderStringTask(str string) *renderStringTask { - return &renderStringTask{str: str} -} - -type renderStringWithoutScrollTask struct { - str string -} - -func (t *renderStringWithoutScrollTask) IsUpdateTask() {} - -func NewRenderStringWithoutScrollTask(str string) *renderStringWithoutScrollTask { - return &renderStringWithoutScrollTask{str: str} -} - -type renderStringWithScrollTask struct { - str string - originX int - originY int -} - -func (t *renderStringWithScrollTask) IsUpdateTask() {} - -func NewRenderStringWithScrollTask(str string, originX int, originY int) *renderStringWithScrollTask { - return &renderStringWithScrollTask{str: str, originX: originX, originY: originY} -} - -type runCommandTask struct { - cmd *exec.Cmd - prefix string -} - -func (t *runCommandTask) IsUpdateTask() {} - -func NewRunCommandTask(cmd *exec.Cmd) *runCommandTask { - return &runCommandTask{cmd: cmd} -} - -func NewRunCommandTaskWithPrefix(cmd *exec.Cmd, prefix string) *runCommandTask { - return &runCommandTask{cmd: cmd, prefix: prefix} -} - -type runPtyTask struct { - cmd *exec.Cmd - prefix string -} - -func (t *runPtyTask) IsUpdateTask() {} - -func NewRunPtyTask(cmd *exec.Cmd) *runPtyTask { - return &runPtyTask{cmd: cmd} -} - -func (gui *Gui) runTaskForView(view *gocui.View, task updateTask) error { +func (gui *Gui) runTaskForView(view *gocui.View, task types.UpdateTask) error { switch v := task.(type) { - case *renderStringTask: - return gui.newStringTask(view, v.str) + case *types.RenderStringTask: + return gui.newStringTask(view, v.Str) - case *renderStringWithoutScrollTask: - return gui.newStringTaskWithoutScroll(view, v.str) + case *types.RenderStringWithoutScrollTask: + return gui.newStringTaskWithoutScroll(view, v.Str) - case *renderStringWithScrollTask: - return gui.newStringTaskWithScroll(view, v.str, v.originX, v.originY) + case *types.RenderStringWithScrollTask: + return gui.newStringTaskWithScroll(view, v.Str, v.OriginX, v.OriginY) - case *runCommandTask: - return gui.newCmdTask(view, v.cmd, v.prefix) + case *types.RunCommandTask: + return gui.newCmdTask(view, v.Cmd, v.Prefix) - case *runPtyTask: - return gui.newPtyTask(view, v.cmd, v.prefix) + case *types.RunPtyTask: + return gui.newPtyTask(view, v.Cmd, v.Prefix) } return nil } -func (gui *Gui) moveMainContextPairToTop(pair MainContextPair) { - gui.setWindowContext(pair.main) - gui.moveToTopOfWindow(pair.main) - if pair.secondary != nil { - gui.setWindowContext(pair.secondary) - gui.moveToTopOfWindow(pair.secondary) +func (gui *Gui) moveMainContextPairToTop(pair types.MainContextPair) { + gui.setWindowContext(pair.Main) + gui.moveToTopOfWindow(pair.Main) + if pair.Secondary != nil { + gui.setWindowContext(pair.Secondary) + gui.moveToTopOfWindow(pair.Secondary) } } -func (gui *Gui) refreshMainView(opts *viewUpdateOpts, context types.Context) error { +func (gui *Gui) RefreshMainView(opts *types.ViewUpdateOpts, context types.Context) error { view := context.GetView() - if opts.title != "" { - view.Title = opts.title + if opts.Title != "" { + view.Title = opts.Title } - if err := gui.runTaskForView(view, opts.task); err != nil { + if err := gui.runTaskForView(view, opts.Task); err != nil { gui.c.Log.Error(err) return nil } @@ -126,41 +50,36 @@ func (gui *Gui) refreshMainView(opts *viewUpdateOpts, context types.Context) err return nil } -type MainContextPair struct { - main types.Context - secondary types.Context +func (gui *Gui) normalMainContextPair() types.MainContextPair { + return types.NewMainContextPair( + gui.State.Contexts.Normal, + gui.State.Contexts.NormalSecondary, + ) } -func (gui *Gui) normalMainContextPair() MainContextPair { - return MainContextPair{ - main: gui.State.Contexts.Normal, - secondary: gui.State.Contexts.NormalSecondary, - } +func (gui *Gui) stagingMainContextPair() types.MainContextPair { + return types.NewMainContextPair( + gui.State.Contexts.Staging, + gui.State.Contexts.StagingSecondary, + ) } -func (gui *Gui) stagingMainContextPair() MainContextPair { - return MainContextPair{ - main: gui.State.Contexts.Staging, - secondary: gui.State.Contexts.StagingSecondary, - } +func (gui *Gui) patchBuildingMainContextPair() types.MainContextPair { + return types.NewMainContextPair( + gui.State.Contexts.CustomPatchBuilder, + gui.State.Contexts.CustomPatchBuilderSecondary, + ) } -func (gui *Gui) patchBuildingMainContextPair() MainContextPair { - return MainContextPair{ - main: gui.State.Contexts.CustomPatchBuilder, - secondary: gui.State.Contexts.CustomPatchBuilderSecondary, - } +func (gui *Gui) mergingMainContextPair() types.MainContextPair { + return types.NewMainContextPair( + gui.State.Contexts.MergeConflicts, + nil, + ) } -func (gui *Gui) mergingMainContextPair() MainContextPair { - return MainContextPair{ - main: gui.State.Contexts.MergeConflicts, - secondary: nil, - } -} - -func (gui *Gui) allMainContextPairs() []MainContextPair { - return []MainContextPair{ +func (gui *Gui) allMainContextPairs() []types.MainContextPair { + return []types.MainContextPair{ gui.normalMainContextPair(), gui.stagingMainContextPair(), gui.patchBuildingMainContextPair(), @@ -168,34 +87,34 @@ func (gui *Gui) allMainContextPairs() []MainContextPair { } } -func (gui *Gui) refreshMainViews(opts refreshMainOpts) error { +func (gui *Gui) refreshMainViews(opts types.RefreshMainOpts) error { // need to reset scroll positions of all other main views for _, pair := range gui.allMainContextPairs() { - if pair.main != opts.pair.main { - _ = pair.main.GetView().SetOrigin(0, 0) + if pair.Main != opts.Pair.Main { + _ = pair.Main.GetView().SetOrigin(0, 0) } - if pair.secondary != nil && pair.secondary != opts.pair.secondary { - _ = pair.secondary.GetView().SetOrigin(0, 0) + if pair.Secondary != nil && pair.Secondary != opts.Pair.Secondary { + _ = pair.Secondary.GetView().SetOrigin(0, 0) } } - if opts.main != nil { - if err := gui.refreshMainView(opts.main, opts.pair.main); err != nil { + if opts.Main != nil { + if err := gui.RefreshMainView(opts.Main, opts.Pair.Main); err != nil { return err } } - if opts.secondary != nil { - if err := gui.refreshMainView(opts.secondary, opts.pair.secondary); err != nil { + if opts.Secondary != nil { + if err := gui.RefreshMainView(opts.Secondary, opts.Pair.Secondary); err != nil { return err } - } else if opts.pair.secondary != nil { - opts.pair.secondary.GetView().Clear() + } else if opts.Pair.Secondary != nil { + opts.Pair.Secondary.GetView().Clear() } - gui.moveMainContextPairToTop(opts.pair) + gui.moveMainContextPairToTop(opts.Pair) - gui.splitMainPanel(opts.secondary != nil) + gui.splitMainPanel(opts.Secondary != nil) return nil } diff --git a/pkg/gui/recent_repos_panel.go b/pkg/gui/recent_repos_panel.go index c416a2b38..73d6e54c5 100644 --- a/pkg/gui/recent_repos_panel.go +++ b/pkg/gui/recent_repos_panel.go @@ -107,13 +107,13 @@ func (gui *Gui) handleCreateRecentReposMenu() error { func (gui *Gui) handleShowAllBranchLogs() error { cmdObj := gui.git.Branch.AllBranchesLogCmdObj() - task := NewRunPtyTask(cmdObj.GetCmd()) + task := types.NewRunPtyTask(cmdObj.GetCmd()) - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: gui.c.Tr.LogTitle, - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: gui.c.Tr.LogTitle, + Task: task, }, }) } diff --git a/pkg/gui/reflog_panel.go b/pkg/gui/reflog_panel.go index f605591c2..cb84177da 100644 --- a/pkg/gui/reflog_panel.go +++ b/pkg/gui/reflog_panel.go @@ -1,21 +1,23 @@ package gui +import "github.com/jesseduffield/lazygit/pkg/gui/types" + func (gui *Gui) reflogCommitsRenderToMain() error { commit := gui.State.Contexts.ReflogCommits.GetSelected() - var task updateTask + var task types.UpdateTask if commit == nil { - task = NewRenderStringTask("No reflog history") + task = types.NewRenderStringTask("No reflog history") } else { cmdObj := gui.git.Commit.ShowCmdObj(commit.Sha, gui.State.Modes.Filtering.GetPath()) - task = NewRunPtyTask(cmdObj.GetCmd()) + task = types.NewRunPtyTask(cmdObj.GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Reflog Entry", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Reflog Entry", + Task: task, }, }) } diff --git a/pkg/gui/refresh.go b/pkg/gui/refresh.go index f7f1b2743..d09583389 100644 --- a/pkg/gui/refresh.go +++ b/pkg/gui/refresh.go @@ -618,15 +618,15 @@ func (gui *Gui) refreshStagingPanel(focusOpts types.OnFocusOpts) error { return gui.c.PushContext(mainContext, focusOpts) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.stagingMainContextPair(), - main: &viewUpdateOpts{ - task: NewRenderStringWithoutScrollTask(mainContent), - title: gui.Tr.UnstagedChanges, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Staging, + Main: &types.ViewUpdateOpts{ + Task: types.NewRenderStringWithoutScrollTask(mainContent), + Title: gui.Tr.UnstagedChanges, }, - secondary: &viewUpdateOpts{ - task: NewRenderStringWithoutScrollTask(secondaryContent), - title: gui.Tr.StagedChanges, + Secondary: &types.ViewUpdateOpts{ + Task: types.NewRenderStringWithoutScrollTask(secondaryContent), + Title: gui.Tr.StagedChanges, }, }) } @@ -680,15 +680,15 @@ func (gui *Gui) refreshPatchBuildingPanel(opts types.OnFocusOpts) error { mainContent := context.GetContentToRender(true) - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.patchBuildingMainContextPair(), - main: &viewUpdateOpts{ - task: NewRenderStringWithoutScrollTask(mainContent), - title: gui.Tr.Patch, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().PatchBuilding, + Main: &types.ViewUpdateOpts{ + Task: types.NewRenderStringWithoutScrollTask(mainContent), + Title: gui.Tr.Patch, }, - secondary: &viewUpdateOpts{ - task: NewRenderStringWithoutScrollTask(secondaryDiff), - title: gui.Tr.CustomPatch, + Secondary: &types.ViewUpdateOpts{ + Task: types.NewRenderStringWithoutScrollTask(secondaryDiff), + Title: gui.Tr.CustomPatch, }, }) } @@ -696,18 +696,18 @@ func (gui *Gui) refreshPatchBuildingPanel(opts types.OnFocusOpts) error { func (gui *Gui) refreshMergePanel(isFocused bool) error { content := gui.State.Contexts.MergeConflicts.GetContentToRender(isFocused) - var task updateTask + var task types.UpdateTask if gui.State.Contexts.MergeConflicts.IsUserScrolling() { - task = NewRenderStringWithoutScrollTask(content) + task = types.NewRenderStringWithoutScrollTask(content) } else { originY := gui.State.Contexts.MergeConflicts.GetOriginY() - task = NewRenderStringWithScrollTask(content, 0, originY) + task = types.NewRenderStringWithScrollTask(content, 0, originY) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.mergingMainContextPair(), - main: &viewUpdateOpts{ - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().MergeConflicts, + Main: &types.ViewUpdateOpts{ + Task: task, }, }) } diff --git a/pkg/gui/remote_branches_panel.go b/pkg/gui/remote_branches_panel.go index e9d7bf2b5..6e9a8e779 100644 --- a/pkg/gui/remote_branches_panel.go +++ b/pkg/gui/remote_branches_panel.go @@ -1,20 +1,22 @@ package gui +import "github.com/jesseduffield/lazygit/pkg/gui/types" + func (gui *Gui) remoteBranchesRenderToMain() error { - var task updateTask + var task types.UpdateTask remoteBranch := gui.State.Contexts.RemoteBranches.GetSelected() if remoteBranch == nil { - task = NewRenderStringTask("No branches for this remote") + task = types.NewRenderStringTask("No branches for this remote") } else { cmdObj := gui.git.Branch.GetGraphCmdObj(remoteBranch.FullRefName()) - task = NewRunCommandTask(cmdObj.GetCmd()) + task = types.NewRunCommandTask(cmdObj.GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Remote Branch", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Remote Branch", + Task: task, }, }) } diff --git a/pkg/gui/remotes_panel.go b/pkg/gui/remotes_panel.go index e306d69b0..edaade8a8 100644 --- a/pkg/gui/remotes_panel.go +++ b/pkg/gui/remotes_panel.go @@ -5,24 +5,25 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/gui/style" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) // list panel functions func (gui *Gui) remotesRenderToMain() error { - var task updateTask + var task types.UpdateTask remote := gui.State.Contexts.Remotes.GetSelected() if remote == nil { - task = NewRenderStringTask("No remotes") + task = types.NewRenderStringTask("No remotes") } else { - task = NewRenderStringTask(fmt.Sprintf("%s\nUrls:\n%s", style.FgGreen.Sprint(remote.Name), strings.Join(remote.Urls, "\n"))) + task = types.NewRenderStringTask(fmt.Sprintf("%s\nUrls:\n%s", style.FgGreen.Sprint(remote.Name), strings.Join(remote.Urls, "\n"))) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Remote", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Remote", + Task: task, }, }) } diff --git a/pkg/gui/stash_panel.go b/pkg/gui/stash_panel.go index 897a76864..439d8205e 100644 --- a/pkg/gui/stash_panel.go +++ b/pkg/gui/stash_panel.go @@ -1,19 +1,21 @@ package gui +import "github.com/jesseduffield/lazygit/pkg/gui/types" + func (gui *Gui) stashRenderToMain() error { - var task updateTask + var task types.UpdateTask stashEntry := gui.State.Contexts.Stash.GetSelected() if stashEntry == nil { - task = NewRenderStringTask(gui.c.Tr.NoStashEntries) + task = types.NewRenderStringTask(gui.c.Tr.NoStashEntries) } else { - task = NewRunPtyTask(gui.git.Stash.ShowStashEntryCmdObj(stashEntry.Index).GetCmd()) + task = types.NewRunPtyTask(gui.git.Stash.ShowStashEntryCmdObj(stashEntry.Index).GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Stash", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Stash", + Task: task, }, }) } diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index b2a014bef..75f69b736 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -87,11 +87,11 @@ func (gui *Gui) statusRenderToMain() error { style.FgMagenta.Sprintf("Become a sponsor: %s", constants.Links.Donate), // caffeine ain't free }, "\n\n") - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: gui.c.Tr.StatusTitle, - task: NewRenderStringTask(dashboardString), + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: gui.c.Tr.StatusTitle, + Task: types.NewRenderStringTask(dashboardString), }, }) } diff --git a/pkg/gui/sub_commits_panel.go b/pkg/gui/sub_commits_panel.go index 0d913e68d..ae3f4e905 100644 --- a/pkg/gui/sub_commits_panel.go +++ b/pkg/gui/sub_commits_panel.go @@ -1,23 +1,25 @@ package gui +import "github.com/jesseduffield/lazygit/pkg/gui/types" + // list panel functions func (gui *Gui) subCommitsRenderToMain() error { commit := gui.State.Contexts.SubCommits.GetSelected() - var task updateTask + var task types.UpdateTask if commit == nil { - task = NewRenderStringTask("No commits") + task = types.NewRenderStringTask("No commits") } else { cmdObj := gui.git.Commit.ShowCmdObj(commit.Sha, gui.State.Modes.Filtering.GetPath()) - task = NewRunPtyTask(cmdObj.GetCmd()) + task = types.NewRunPtyTask(cmdObj.GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Commit", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Commit", + Task: task, }, }) } diff --git a/pkg/gui/submodules_panel.go b/pkg/gui/submodules_panel.go index 339d91821..163234153 100644 --- a/pkg/gui/submodules_panel.go +++ b/pkg/gui/submodules_panel.go @@ -6,13 +6,14 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/style" + "github.com/jesseduffield/lazygit/pkg/gui/types" ) func (gui *Gui) submodulesRenderToMain() error { - var task updateTask + var task types.UpdateTask submodule := gui.State.Contexts.Submodules.GetSelected() if submodule == nil { - task = NewRenderStringTask("No submodules") + task = types.NewRenderStringTask("No submodules") } else { prefix := fmt.Sprintf( "Name: %s\nPath: %s\nUrl: %s\n\n", @@ -23,18 +24,18 @@ func (gui *Gui) submodulesRenderToMain() error { file := gui.helpers.WorkingTree.FileForSubmodule(submodule) if file == nil { - task = NewRenderStringTask(prefix) + task = types.NewRenderStringTask(prefix) } else { cmdObj := gui.git.WorkingTree.WorktreeFileDiffCmdObj(file, false, !file.HasUnstagedChanges && file.HasStagedChanges, gui.IgnoreWhitespaceInDiffView) - task = NewRunCommandTaskWithPrefix(cmdObj.GetCmd(), prefix) + task = types.NewRunCommandTaskWithPrefix(cmdObj.GetCmd(), prefix) } } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Submodule", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Submodule", + Task: task, }, }) } diff --git a/pkg/gui/tags_panel.go b/pkg/gui/tags_panel.go index c9c8a9d92..af09e4242 100644 --- a/pkg/gui/tags_panel.go +++ b/pkg/gui/tags_panel.go @@ -1,20 +1,22 @@ package gui +import "github.com/jesseduffield/lazygit/pkg/gui/types" + func (gui *Gui) tagsRenderToMain() error { - var task updateTask + var task types.UpdateTask tag := gui.State.Contexts.Tags.GetSelected() if tag == nil { - task = NewRenderStringTask("No tags") + task = types.NewRenderStringTask("No tags") } else { cmdObj := gui.git.Branch.GetGraphCmdObj(tag.FullRefName()) - task = NewRunCommandTask(cmdObj.GetCmd()) + task = types.NewRunCommandTask(cmdObj.GetCmd()) } - return gui.refreshMainViews(refreshMainOpts{ - pair: gui.normalMainContextPair(), - main: &viewUpdateOpts{ - title: "Tag", - task: task, + return gui.c.RenderToMainViews(types.RefreshMainOpts{ + Pair: gui.c.MainViewPairs().Normal, + Main: &types.ViewUpdateOpts{ + Title: "Tag", + Task: task, }, }) } diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index dba7ba7f4..ab8f6b2b8 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -28,6 +28,12 @@ type IGuiCommon interface { PostRefreshUpdate(Context) error // this just re-renders the screen Render() + // allows rendering to main views (i.e. the ones to the right of the side panel) + // in such a way that avoids concurrency issues when there are slow commands + // to display the output of + RenderToMainViews(opts RefreshMainOpts) error + // used purely for the sake of RenderToMainViews to provide the pair of main views we want to render to + MainViewPairs() MainViewPairs // returns true if command completed successfully RunSubprocess(cmdObj oscommands.ICmdObj) (bool, error) diff --git a/pkg/gui/types/rendering.go b/pkg/gui/types/rendering.go new file mode 100644 index 000000000..b4e7bedcb --- /dev/null +++ b/pkg/gui/types/rendering.go @@ -0,0 +1,95 @@ +package types + +import ( + "os/exec" +) + +type MainContextPair struct { + Main Context + Secondary Context +} + +func NewMainContextPair(main Context, secondary Context) MainContextPair { + return MainContextPair{Main: main, Secondary: secondary} +} + +type MainViewPairs struct { + Normal MainContextPair + MergeConflicts MainContextPair + Staging MainContextPair + PatchBuilding MainContextPair +} + +type ViewUpdateOpts struct { + Title string + + Task UpdateTask +} + +type RefreshMainOpts struct { + Pair MainContextPair + Main *ViewUpdateOpts + Secondary *ViewUpdateOpts +} + +type UpdateTask interface { + IsUpdateTask() +} + +type RenderStringTask struct { + Str string +} + +func (t *RenderStringTask) IsUpdateTask() {} + +func NewRenderStringTask(str string) *RenderStringTask { + return &RenderStringTask{Str: str} +} + +type RenderStringWithoutScrollTask struct { + Str string +} + +func (t *RenderStringWithoutScrollTask) IsUpdateTask() {} + +func NewRenderStringWithoutScrollTask(str string) *RenderStringWithoutScrollTask { + return &RenderStringWithoutScrollTask{Str: str} +} + +type RenderStringWithScrollTask struct { + Str string + OriginX int + OriginY int +} + +func (t *RenderStringWithScrollTask) IsUpdateTask() {} + +func NewRenderStringWithScrollTask(str string, originX int, originY int) *RenderStringWithScrollTask { + return &RenderStringWithScrollTask{Str: str, OriginX: originX, OriginY: originY} +} + +type RunCommandTask struct { + Cmd *exec.Cmd + Prefix string +} + +func (t *RunCommandTask) IsUpdateTask() {} + +func NewRunCommandTask(cmd *exec.Cmd) *RunCommandTask { + return &RunCommandTask{Cmd: cmd} +} + +func NewRunCommandTaskWithPrefix(cmd *exec.Cmd, prefix string) *RunCommandTask { + return &RunCommandTask{Cmd: cmd, Prefix: prefix} +} + +type RunPtyTask struct { + Cmd *exec.Cmd + Prefix string +} + +func (t *RunPtyTask) IsUpdateTask() {} + +func NewRunPtyTask(cmd *exec.Cmd) *RunPtyTask { + return &RunPtyTask{Cmd: cmd} +}