summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2020-08-19 19:07:14 +1000
committerJesse Duffield <jessedduffield@gmail.com>2020-08-23 14:29:18 +1000
commit2b812b01e9d80409a0bf212eb7208dcdd6f5c974 (patch)
tree4c1b0cd51ba170c92bc38410ec6005373736720b
parent2f5d5034dbe4523c44faa58ba6f30c2fef06c128 (diff)
more standardisation of rendering
-rw-r--r--pkg/gui/branches_panel.go2
-rw-r--r--pkg/gui/context.go343
-rw-r--r--pkg/gui/global_handlers.go26
-rw-r--r--pkg/gui/searching.go2
4 files changed, 212 insertions, 161 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index a783f49fe..b82301aaa 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -76,7 +76,7 @@ func (gui *Gui) refreshBranches() {
}
gui.State.Branches = builder.Build()
- if err := gui.rerenderIfVisible(gui.Contexts.Branches.Context); err != nil {
+ if err := gui.postRefreshUpdate(gui.Contexts.Branches.Context); err != nil {
gui.Log.Error(err)
}
diff --git a/pkg/gui/context.go b/pkg/gui/context.go
index a54625306..559cfa108 100644
--- a/pkg/gui/context.go
+++ b/pkg/gui/context.go
@@ -98,6 +98,164 @@ type ContextTree struct {
Search SimpleContextNode
}
+func (gui *Gui) allContexts() []Context {
+ return []Context{
+ gui.Contexts.Status.Context,
+ gui.Contexts.Files.Context,
+ gui.Contexts.Branches.Context,
+ gui.Contexts.Remotes.Context,
+ gui.Contexts.Remotes.Branches.Context,
+ gui.Contexts.BranchCommits.Context,
+ gui.Contexts.BranchCommits.Files.Context,
+ gui.Contexts.ReflogCommits.Context,
+ gui.Contexts.Stash.Context,
+ gui.Contexts.Menu.Context,
+ gui.Contexts.Confirmation.Context,
+ gui.Contexts.Credentials.Context,
+ gui.Contexts.CommitMessage.Context,
+ gui.Contexts.Normal.Context,
+ gui.Contexts.Staging.Context,
+ gui.Contexts.Merging.Context,
+ gui.Contexts.PatchBuilding.Context,
+ }
+}
+
+func (gui *Gui) contextTree() ContextTree {
+ return ContextTree{
+ Status: SimpleContextNode{
+ Context: BasicContext{
+ OnFocus: gui.handleStatusSelect,
+ Kind: SIDE_CONTEXT,
+ ViewName: "status",
+ Key: "status",
+ },
+ },
+ Files: SimpleContextNode{
+ Context: gui.filesListContext(),
+ },
+ Menu: SimpleContextNode{
+ Context: gui.menuListContext(),
+ },
+ Remotes: RemotesContextNode{
+ Context: gui.remotesListContext(),
+ Branches: SimpleContextNode{
+ Context: gui.remoteBranchesListContext(),
+ },
+ },
+ BranchCommits: CommitsContextNode{
+ Context: gui.branchCommitsListContext(),
+ Files: SimpleContextNode{
+ Context: gui.commitFilesListContext(),
+ },
+ },
+ ReflogCommits: SimpleContextNode{
+ Context: gui.reflogCommitsListContext(),
+ },
+ Branches: SimpleContextNode{
+ Context: gui.branchesListContext(),
+ },
+ Tags: SimpleContextNode{
+ Context: gui.tagsListContext(),
+ },
+ Stash: SimpleContextNode{
+ Context: gui.stashListContext(),
+ },
+ Normal: SimpleContextNode{
+ Context: BasicContext{
+ OnFocus: func() error {
+ return nil // TODO: should we do something here? We should allow for scrolling the panel
+ },
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: "normal",
+ },
+ },
+ Staging: SimpleContextNode{
+ Context: BasicContext{
+ // TODO: think about different situations where this arises
+ OnFocus: func() error {
+ return nil
+ // return gui.refreshStagingPanel(false, -1)
+ },
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: "staging",
+ },
+ },
+ PatchBuilding: SimpleContextNode{
+ Context: BasicContext{
+ // TODO: think about different situations where this arises
+ OnFocus: func() error {
+ return gui.refreshPatchBuildingPanel(-1)
+ },
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: "patch-building",
+ },
+ },
+ Merging: SimpleContextNode{
+ Context: BasicContext{
+ // TODO: think about different situations where this arises
+ OnFocus: func() error {
+ return gui.refreshMergePanel()
+ },
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: "merging",
+ },
+ },
+ Credentials: SimpleContextNode{
+ Context: BasicContext{
+ OnFocus: func() error { return gui.handleCredentialsViewFocused() },
+ Kind: PERSISTENT_POPUP,
+ ViewName: "credentials",
+ Key: "credentials",
+ },
+ },
+ Confirmation: SimpleContextNode{
+ Context: BasicContext{
+ OnFocus: func() error { return nil },
+ Kind: TEMPORARY_POPUP,
+ ViewName: "confirmation",
+ Key: "confirmation",
+ },
+ },
+ CommitMessage: SimpleContextNode{
+ Context: BasicContext{
+ OnFocus: func() error { return gui.handleCommitMessageFocused() },
+ Kind: PERSISTENT_POPUP,
+ ViewName: "commitMessage",
+ Key: "commit-message", // admittedly awkward to have view names in camelCase and contexts in kebab-case
+ },
+ },
+ Search: SimpleContextNode{
+ Context: BasicContext{
+ OnFocus: func() error { return nil },
+ Kind: PERSISTENT_POPUP,
+ ViewName: "search",
+ Key: "search",
+ },
+ },
+ }
+}
+
+func (gui *Gui) initialViewContextMap() map[string]Context {
+ return map[string]Context{
+ "status": gui.Contexts.Status.Context,
+ "files": gui.Contexts.Files.Context,
+ "branches": gui.Contexts.Branches.Context,
+ "commits": gui.Contexts.BranchCommits.Context,
+ "commitFiles": gui.Contexts.BranchCommits.Files.Context,
+ "stash": gui.Contexts.Stash.Context,
+ "menu": gui.Contexts.Menu.Context,
+ "confirmation": gui.Contexts.Confirmation.Context,
+ "credentials": gui.Contexts.Credentials.Context,
+ "commitMessage": gui.Contexts.CommitMessage.Context,
+ "main": gui.Contexts.Normal.Context,
+ "secondary": gui.Contexts.Normal.Context,
+ }
+}
+
func (gui *Gui) switchContext(c Context) error {
gui.g.Update(func(*gocui.Gui) error {
// push onto stack
@@ -168,14 +326,25 @@ func (gui *Gui) deactivateContext(c Context) error {
return nil
}
-func (gui *Gui) rerenderIfVisible(c Context) error {
+// postRefreshUpdate is to be called on a context after the state that it depends on has been refreshed
+// if the context's view is set to another context we do nothing.
+// if the context's view is the current view we trigger a focus; re-selecting the current item.
+func (gui *Gui) postRefreshUpdate(c Context) error {
v, err := gui.g.View(c.GetViewName())
if err != nil {
return nil
}
- if v.Context == c.GetKey() {
- if err := c.HandleRender(); err != nil {
+ if v.Context != c.GetKey() {
+ return nil
+ }
+
+ if err := c.HandleRender(); err != nil {
+ return err
+ }
+
+ if gui.currentViewName() == c.GetViewName() {
+ if err := c.HandleFocus(); err != nil {
return err
}
}
@@ -200,6 +369,8 @@ func (gui *Gui) activateContext(c Context) error {
}
}
+ gui.setViewAsActiveForWindow(viewName)
+
if viewName == "main" {
gui.changeMainViewsContext(c.GetKey())
} else {
@@ -253,142 +424,6 @@ func (gui *Gui) currentContextKey() string {
return gui.State.ContextStack[len(gui.State.ContextStack)-1].GetKey()
}
-func (gui *Gui) contextTree() ContextTree {
- return ContextTree{
- Status: SimpleContextNode{
- Context: BasicContext{
- OnFocus: gui.handleStatusSelect,
- Kind: SIDE_CONTEXT,
- ViewName: "status",
- Key: "status",
- },
- },
- Files: SimpleContextNode{
- Context: gui.filesListContext(),
- },
- Menu: SimpleContextNode{
- Context: gui.menuListContext(),
- },
- Remotes: RemotesContextNode{
- Context: gui.remotesListContext(),
- Branches: SimpleContextNode{
- Context: gui.remoteBranchesListContext(),
- },
- },
- BranchCommits: CommitsContextNode{
- Context: gui.branchCommitsListContext(),
- Files: SimpleContextNode{
- Context: gui.commitFilesListContext(),
- },
- },
- ReflogCommits: SimpleContextNode{
- Context: gui.reflogCommitsListContext(),
- },
- Branches: SimpleContextNode{
- Context: gui.branchesListContext(),
- },
- Tags: SimpleContextNode{
- Context: gui.tagsListContext(),
- },
- Stash: SimpleContextNode{
- Context: gui.stashListContext(),
- },
- Normal: SimpleContextNode{
- Context: BasicContext{
- OnFocus: func() error {
- return nil // TODO: should we do something here? We should allow for scrolling the panel
- },
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: "normal",
- },
- },
- Staging: SimpleContextNode{
- Context: BasicContext{
- // TODO: think about different situations where this arises
- OnFocus: func() error {
- return nil
- // return gui.refreshStagingPanel(false, -1)
- },
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: "staging",
- },
- },
- PatchBuilding: SimpleContextNode{
- Context: BasicContext{
- // TODO: think about different situations where this arises
- OnFocus: func() error {
- return gui.refreshPatchBuildingPanel(-1)
- },
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: "patch-building",
- },
- },
- Merging: SimpleContextNode{
- Context: BasicContext{
- // TODO: think about different situations where this arises
- OnFocus: func() error {
- return gui.refreshMergePanel()
- },
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: "merging",
- },
- },
- Credentials: SimpleContextNode{
- Context: BasicContext{
- OnFocus: func() error { return gui.handleCredentialsViewFocused() },
- Kind: PERSISTENT_POPUP,
- ViewName: "credentials",
- Key: "credentials",
- },
- },
- Confirmation: SimpleContextNode{
- Context: BasicContext{
- OnFocus: func() error { return nil },
- Kind: TEMPORARY_POPUP,
- ViewName: "confirmation",
- Key: "confirmation",
- },
- },
- CommitMessage: SimpleContextNode{
- Context: BasicContext{
- OnFocus: func() error { return gui.handleCommitMessageFocused() },
- Kind: PERSISTENT_POPUP,
- ViewName: "commitMessage",
- Key: "commit-message", // admittedly awkward to have view names in camelCase and contexts in kebab-case
- },
- },
- Search: SimpleContextNode{
- Context: BasicContext{
- OnFocus: func() error { return nil },
- Kind: PERSISTENT_POPUP,
- ViewName: "search",
- Key: "search",
- },
- },
- }
-}
-
-func (gui *Gui) initialViewContextMap() map[string]Context {
- return map[string]Context{
- "status": gui.Contexts.Status.Context,
- "files": gui.Contexts.Files.Context,
- "branches": gui.Contexts.Branches.Context,
- "commits": gui.Contexts.BranchCommits.Context,
- "commitFiles": gui.Contexts.BranchCommits.Files.Context,
- "stash": gui.Contexts.Stash.Context,
- "menu": gui.Contexts.Menu.Context,
- "confirmation": gui.Contexts.Confirmation.Context,
- "credentials": gui.Contexts.Credentials.Context,
- "commitMessage": gui.Contexts.CommitMessage.Context,
- "main": gui.Contexts.Normal.Context,
- "secondary": gui.Contexts.Normal.Context,
- }
-}
-
func (gui *Gui) setInitialViewContexts() {
// arguably we should only have our ViewContextMap and we should do away with
// contexts on views, or vice versa
@@ -417,9 +452,6 @@ func (gui *Gui) getFocusLayout() func(g *gocui.Gui) error {
return err
}
- if err := gui.onViewFocus(newView); err != nil {
- return err
- }
previousView = newView
}
return nil
@@ -449,12 +481,6 @@ func (gui *Gui) onViewFocusLost(v *gocui.View, newView *gocui.View) error {
return nil
}
-func (gui *Gui) onViewFocus(newView *gocui.View) error {
- gui.setViewAsActiveForWindow(newView.Name())
-
- return nil
-}
-
// changeContext is a helper function for when we want to change a 'main' context
// which currently just means a context that affects both the main and secondary views
// other views can have their context changed directly but this function helps
@@ -553,7 +579,24 @@ type tabContext struct {
contexts []Context
}
-func (gui *Gui) handleContextRefresh(c Context) {
- // if context is not the current context of it's view, return
+func (gui *Gui) contextForContextKey(contextKey string) Context {
+ for _, context := range gui.allContexts() {
+ if context.GetKey() == contextKey {
+ return context
+ }
+ }
+
+ panic(fmt.Sprintf("context now found for key %s", contextKey))
+}
+
+func (gui *Gui) rerenderView(viewName string) error {
+ v, err := gui.g.View(viewName)
+ if err != nil {
+ return nil
+ }
+
+ contextKey := v.Context
+ context := gui.contextForContextKey(contextKey)
+ return context.HandleRender()
}
diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go
index ef98b98e6..d37fb8dea 100644
--- a/pkg/gui/global_handlers.go
+++ b/pkg/gui/global_handlers.go
@@ -9,15 +9,23 @@ import (
"github.com/jesseduffield/lazygit/pkg/utils"
)
+// 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) viewsWithScreenModeDependentContent() []string {
+ return []string{"branches", "commits"}
+}
+
func (gui *Gui) nextScreenMode(g *gocui.Gui, v *gocui.View) error {
gui.State.ScreenMode = utils.NextIntInCycle([]int{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)
// commits render differently depending on whether we're in fullscreen more or not
if err := gui.refreshCommitsViewWithSelection(); err != nil {
return err
}
- // same with branches
- if err := gui.refreshBranchesViewWithSelection(); err != nil {
- return err
+
+ for _, viewName := range gui.viewsWithScreenModeDependentContent() {
+ if err := gui.rerenderView(viewName); err != nil {
+ return err
+ }
}
return nil
@@ -25,13 +33,11 @@ func (gui *Gui) nextScreenMode(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) prevScreenMode(g *gocui.Gui, v *gocui.View) error {
gui.State.ScreenMode = utils.PrevIntInCycle([]int{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)
- // commits render differently depending on whether we're in fullscreen more or not
- if err := gui.refreshCommitsViewWithSelection(); err != nil {
- return err
- }
- // same with branches
- if err := gui.refreshBranchesViewWithSelection(); err != nil {
- return err
+
+ for _, viewName := range gui.viewsWithScreenModeDependentContent() {
+ if err := gui.rerenderView(viewName); err != nil {
+ return err
+ }
}
return nil
diff --git a/pkg/gui/searching.go b/pkg/gui/searching.go
index 261815824..ddf595a5f 100644
--- a/pkg/gui/searching.go
+++ b/pkg/gui/searching.go
@@ -11,7 +11,9 @@ import (
func (gui *Gui) handleOpenSearch(g *gocui.Gui, v *gocui.View) error {
gui.State.Searching.isSearching = true
gui.State.Searching.view = v
+
gui.renderString("search", "")
+
if err := gui.switchContext(gui.Contexts.Search.Context); err != nil {
return err
}