From f8c9ce33c2cdbefac27e6af409a10aa539d4037a Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Thu, 23 Mar 2023 22:05:25 +1100 Subject: [PATCH] move more actions into controller --- pkg/gui/context.go | 34 +++++++++- pkg/gui/context/list_context_trait.go | 2 + pkg/gui/context/patch_explorer_context.go | 2 + pkg/gui/context_config.go | 26 ------- pkg/gui/controllers.go | 2 +- pkg/gui/controllers/global_controller.go | 37 +++++++++- pkg/gui/controllers/screen_mode_actions.go | 79 ++++++++++++++++++++++ pkg/gui/global_handlers.go | 63 ----------------- pkg/gui/gui.go | 4 +- pkg/gui/keybindings.go | 26 ------- pkg/gui/layout.go | 4 +- pkg/gui/types/context.go | 4 ++ 12 files changed, 160 insertions(+), 123 deletions(-) create mode 100644 pkg/gui/controllers/screen_mode_actions.go diff --git a/pkg/gui/context.go b/pkg/gui/context.go index 3550e9eef..4c403973f 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -18,13 +18,20 @@ type ContextMgr struct { ContextStack []types.Context sync.RWMutex gui *Gui + + allContexts *context.ContextTree } -func NewContextMgr(initialContext types.Context, gui *Gui) *ContextMgr { +func NewContextMgr( + initialContext types.Context, + gui *Gui, + allContexts *context.ContextTree, +) *ContextMgr { return &ContextMgr{ ContextStack: []types.Context{initialContext}, RWMutex: sync.RWMutex{}, gui: gui, + allContexts: allContexts, } } @@ -286,3 +293,28 @@ func (self *ContextMgr) ForEach(f func(types.Context)) { func (self *ContextMgr) IsCurrent(c types.Context) bool { return self.Current().GetKey() == c.GetKey() } + +// all list contexts +func (self *ContextMgr) AllList() []types.IListContext { + var listContexts []types.IListContext + + for _, context := range self.allContexts.Flatten() { + if listContext, ok := context.(types.IListContext); ok { + listContexts = append(listContexts, listContext) + } + } + + return listContexts +} + +func (self *ContextMgr) AllPatchExplorer() []types.IPatchExplorerContext { + var listContexts []types.IPatchExplorerContext + + for _, context := range self.allContexts.Flatten() { + if listContext, ok := context.(types.IPatchExplorerContext); ok { + listContexts = append(listContexts, listContext) + } + } + + return listContexts +} diff --git a/pkg/gui/context/list_context_trait.go b/pkg/gui/context/list_context_trait.go index d47a15c9c..74ff2f388 100644 --- a/pkg/gui/context/list_context_trait.go +++ b/pkg/gui/context/list_context_trait.go @@ -15,6 +15,8 @@ type ListContextTrait struct { getDisplayStrings func(startIdx int, length int) [][]string } +func (self *ListContextTrait) IsListContext() {} + func (self *ListContextTrait) GetList() types.IList { return self.list } diff --git a/pkg/gui/context/patch_explorer_context.go b/pkg/gui/context/patch_explorer_context.go index ccffb4f7e..1c986ee1d 100644 --- a/pkg/gui/context/patch_explorer_context.go +++ b/pkg/gui/context/patch_explorer_context.go @@ -45,6 +45,8 @@ func NewPatchExplorerContext( } } +func (self *PatchExplorerContext) IsPatchExplorerContext() {} + func (self *PatchExplorerContext) GetState() *patch_exploring.State { return self.state } diff --git a/pkg/gui/context_config.go b/pkg/gui/context_config.go index 4dcddb3ea..a81e01bf5 100644 --- a/pkg/gui/context_config.go +++ b/pkg/gui/context_config.go @@ -45,29 +45,3 @@ func (gui *Gui) TransientContexts() []types.Context { return context.IsTransient() }) } - -func (gui *Gui) getListContexts() []types.IListContext { - return []types.IListContext{ - gui.State.Contexts.Menu, - gui.State.Contexts.Files, - gui.State.Contexts.Branches, - gui.State.Contexts.Remotes, - gui.State.Contexts.RemoteBranches, - gui.State.Contexts.Tags, - gui.State.Contexts.LocalCommits, - gui.State.Contexts.ReflogCommits, - gui.State.Contexts.SubCommits, - gui.State.Contexts.Stash, - gui.State.Contexts.CommitFiles, - gui.State.Contexts.Submodules, - gui.State.Contexts.Suggestions, - } -} - -func (gui *Gui) getPatchExplorerContexts() []types.IPatchExplorerContext { - return []types.IPatchExplorerContext{ - gui.State.Contexts.Staging, - gui.State.Contexts.StagingSecondary, - gui.State.Contexts.CustomPatchBuilder, - } -} diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index 95568f2c0..b4af4db7a 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -314,7 +314,7 @@ func (gui *Gui) resetControllers() { // this must come last so that we've got our click handlers defined against the context listControllerFactory := controllers.NewListControllerFactory(common) - for _, context := range gui.getListContexts() { + for _, context := range gui.c.Context().AllList() { controllers.AttachControllers(context, listControllerFactory.Create(context)) } } diff --git a/pkg/gui/controllers/global_controller.go b/pkg/gui/controllers/global_controller.go index 02d312331..964172b92 100644 --- a/pkg/gui/controllers/global_controller.go +++ b/pkg/gui/controllers/global_controller.go @@ -31,9 +31,34 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type Description: self.c.Tr.ViewPatchOptions, OpensMenu: true, }, + { + Key: opts.GetKey(opts.Config.Universal.CreateRebaseOptionsMenu), + Handler: self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu, + Description: self.c.Tr.ViewMergeRebaseOptions, + OpensMenu: true, + }, + { + Key: opts.GetKey(opts.Config.Universal.Refresh), + Handler: self.refresh, + Description: self.c.Tr.LcRefresh, + }, + { + Key: opts.GetKey(opts.Config.Universal.NextScreenMode), + Handler: self.nextScreenMode, + Description: self.c.Tr.LcNextScreenMode, + }, + { + Key: opts.GetKey(opts.Config.Universal.PrevScreenMode), + Handler: self.prevScreenMode, + Description: self.c.Tr.LcPrevScreenMode, + }, } } +func (self *GlobalController) Context() types.Context { + return nil +} + func (self *GlobalController) customCommand() error { return (&CustomCommandAction{c: self.c}).Call() } @@ -42,6 +67,14 @@ func (self *GlobalController) createCustomPatchOptionsMenu() error { return (&CustomPatchOptionsMenuAction{c: self.c}).Call() } -func (self *GlobalController) Context() types.Context { - return nil +func (self *GlobalController) refresh() error { + return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) +} + +func (self *GlobalController) nextScreenMode() error { + return (&ScreenModeActions{c: self.c}).Next() +} + +func (self *GlobalController) prevScreenMode() error { + return (&ScreenModeActions{c: self.c}).Prev() } diff --git a/pkg/gui/controllers/screen_mode_actions.go b/pkg/gui/controllers/screen_mode_actions.go new file mode 100644 index 000000000..d31154636 --- /dev/null +++ b/pkg/gui/controllers/screen_mode_actions.go @@ -0,0 +1,79 @@ +package controllers + +import ( + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type ScreenModeActions struct { + c *ControllerCommon +} + +func (self *ScreenModeActions) Next() error { + self.c.State().GetRepoState().SetScreenMode( + nextIntInCycle( + []types.WindowMaximisation{types.SCREEN_NORMAL, types.SCREEN_HALF, types.SCREEN_FULL}, + self.c.State().GetRepoState().GetScreenMode(), + ), + ) + + return self.rerenderViewsWithScreenModeDependentContent() +} + +func (self *ScreenModeActions) Prev() error { + self.c.State().GetRepoState().SetScreenMode( + prevIntInCycle( + []types.WindowMaximisation{types.SCREEN_NORMAL, types.SCREEN_HALF, types.SCREEN_FULL}, + self.c.State().GetRepoState().GetScreenMode(), + ), + ) + + return self.rerenderViewsWithScreenModeDependentContent() +} + +// these views need to be re-rendered when the screen mode changes. The commits view, +// for example, will show authorship information in half and full screen mode. +func (self *ScreenModeActions) rerenderViewsWithScreenModeDependentContent() error { + // for now we re-render all list views. + for _, context := range self.c.Context().AllList() { + if err := self.rerenderView(context.GetView()); err != nil { + return err + } + } + + return nil +} + +func (self *ScreenModeActions) rerenderView(view *gocui.View) error { + context, ok := self.c.Helpers().View.ContextForView(view.Name()) + if !ok { + self.c.Log.Errorf("no context found for view %s", view.Name()) + return nil + } + + return context.HandleRender() +} + +func nextIntInCycle(sl []types.WindowMaximisation, current types.WindowMaximisation) types.WindowMaximisation { + for i, val := range sl { + if val == current { + if i == len(sl)-1 { + return sl[0] + } + return sl[i+1] + } + } + return sl[0] +} + +func prevIntInCycle(sl []types.WindowMaximisation, current types.WindowMaximisation) types.WindowMaximisation { + for i, val := range sl { + if val == current { + if i > 0 { + return sl[i-1] + } + return sl[len(sl)-1] + } + } + return sl[len(sl)-1] +} diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go index 0bf705ba8..fc07b5846 100644 --- a/pkg/gui/global_handlers.go +++ b/pkg/gui/global_handlers.go @@ -11,55 +11,6 @@ import ( const HORIZONTAL_SCROLL_FACTOR = 3 -// these views need to be re-rendered when the screen mode changes. The commits view, -// for example, will show authorship information in half and full screen mode. -func (gui *Gui) rerenderViewsWithScreenModeDependentContent() error { - // for now we re-render all list views. - for _, context := range gui.getListContexts() { - if err := gui.rerenderView(context.GetView()); err != nil { - return err - } - } - - return nil -} - -func nextIntInCycle(sl []types.WindowMaximisation, current types.WindowMaximisation) types.WindowMaximisation { - for i, val := range sl { - if val == current { - if i == len(sl)-1 { - return sl[0] - } - return sl[i+1] - } - } - return sl[0] -} - -func prevIntInCycle(sl []types.WindowMaximisation, current types.WindowMaximisation) types.WindowMaximisation { - for i, val := range sl { - if val == current { - if i > 0 { - return sl[i-1] - } - return sl[len(sl)-1] - } - } - return sl[len(sl)-1] -} - -func (gui *Gui) nextScreenMode() error { - gui.State.ScreenMode = nextIntInCycle([]types.WindowMaximisation{types.SCREEN_NORMAL, types.SCREEN_HALF, types.SCREEN_FULL}, gui.State.ScreenMode) - - return gui.rerenderViewsWithScreenModeDependentContent() -} - -func (gui *Gui) prevScreenMode() error { - gui.State.ScreenMode = prevIntInCycle([]types.WindowMaximisation{types.SCREEN_NORMAL, types.SCREEN_HALF, types.SCREEN_FULL}, gui.State.ScreenMode) - - return gui.rerenderViewsWithScreenModeDependentContent() -} - func (gui *Gui) scrollUpView(view *gocui.View) { view.ScrollUp(gui.c.UserConfig.Gui.ScrollHeight) } @@ -157,10 +108,6 @@ func (gui *Gui) scrollDownConfirmationPanel() error { return nil } -func (gui *Gui) handleRefresh() error { - return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) -} - func (gui *Gui) handleCopySelectedSideContextItemToClipboard() error { // important to note that this assumes we've selected an item in a side context currentSideContext := gui.c.CurrentSideContext() @@ -190,13 +137,3 @@ func (gui *Gui) handleCopySelectedSideContextItemToClipboard() error { return nil } - -func (gui *Gui) rerenderView(view *gocui.View) error { - context, ok := gui.helpers.View.ContextForView(view.Name()) - if !ok { - gui.Log.Errorf("no context found for view %s", view.Name()) - return nil - } - - return context.HandleRender() -} diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index c0448cacd..45c3ff44e 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -347,8 +347,8 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs, reuseState bool) { Diffing: diffing.New(), }, ScreenMode: initialScreenMode, - // TODO: put contexts in the context manager - ContextMgr: NewContextMgr(initialContext, gui), + // TODO: only use contexts from context manager + ContextMgr: NewContextMgr(initialContext, gui, contextTree), Contexts: contextTree, WindowViewNameMap: initialWindowViewNameMap(contextTree), } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 31ab09667..57251e3bc 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -134,19 +134,6 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi Modifier: gocui.ModNone, Handler: self.scrollDownMain, }, - { - ViewName: "", - Key: opts.GetKey(opts.Config.Universal.CreateRebaseOptionsMenu), - Handler: self.helpers.MergeAndRebase.CreateRebaseOptionsMenu, - Description: self.c.Tr.ViewMergeRebaseOptions, - OpensMenu: true, - }, - { - ViewName: "", - Key: opts.GetKey(opts.Config.Universal.Refresh), - Handler: self.handleRefresh, - Description: self.c.Tr.LcRefresh, - }, { ViewName: "", Key: opts.GetKey(opts.Config.Universal.OptionMenu), @@ -162,19 +149,6 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi Description: self.c.Tr.LcOpenMenu, Handler: self.handleCreateOptionsMenu, }, - { - ViewName: "", - Key: opts.GetKey(opts.Config.Universal.NextScreenMode), - Handler: self.nextScreenMode, - Description: self.c.Tr.LcNextScreenMode, - }, - { - ViewName: "", - Key: opts.GetKey(opts.Config.Universal.PrevScreenMode), - Handler: self.prevScreenMode, - Description: self.c.Tr.LcPrevScreenMode, - }, - { ViewName: "files", Key: opts.GetKey(opts.Config.Universal.CopyToClipboard), diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index c8a89d3cb..2f51b7432 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -124,7 +124,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { gui.State.ViewsSetup = true } - for _, listContext := range gui.getListContexts() { + for _, listContext := range gui.c.Context().AllList() { view, err := gui.g.View(listContext.GetViewName()) if err != nil { continue @@ -138,7 +138,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { view.SetOnSelectItem(gui.onSelectItemWrapper(listContext.OnSearchSelect)) } - for _, context := range gui.getPatchExplorerContexts() { + for _, context := range gui.c.Context().AllPatchExplorer() { context := context context.GetView().SetOnSelectItem(gui.onSelectItemWrapper( func(selectedLineIdx int) error { diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 7ed0db1b2..bb8630bff 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -106,6 +106,7 @@ type IListContext interface { OnSearchSelect(selectedLineIdx int) error FocusLine() + IsListContext() // used for type switch } type IPatchExplorerContext interface { @@ -120,6 +121,7 @@ type IPatchExplorerContext interface { GetContentToRender(isFocused bool) string NavigateTo(isFocused bool, selectedLineIdx int) error GetMutex() *deadlock.Mutex + IsPatchExplorerContext() // used for type switch } type IViewTrait interface { @@ -208,4 +210,6 @@ type IContextMgr interface { CurrentSide() Context IsCurrent(c Context) bool ForEach(func(Context)) + AllList() []IListContext + AllPatchExplorer() []IPatchExplorerContext }