summaryrefslogtreecommitdiffstats
path: root/pkg/gui
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2021-04-11 13:17:20 +1000
committerJesse Duffield <jessedduffield@gmail.com>2021-04-11 17:07:49 +1000
commitcf78b86cb5eae4c502a747238aba983bf9eb298f (patch)
treec81eb86f8a291b7b91046e754f5ddfef77afff43 /pkg/gui
parent4f03d7733ab186d357064f343915ac48ca059940 (diff)
more support for command log and more code reuse for contexts
Diffstat (limited to 'pkg/gui')
-rw-r--r--pkg/gui/basic_context.go77
-rw-r--r--pkg/gui/context.go320
-rw-r--r--pkg/gui/context_config.go261
-rw-r--r--pkg/gui/extras_panel.go10
-rw-r--r--pkg/gui/list_context.go406
-rw-r--r--pkg/gui/list_context_config.go389
-rw-r--r--pkg/gui/menu_panel.go6
-rw-r--r--pkg/gui/searching.go1
8 files changed, 749 insertions, 721 deletions
diff --git a/pkg/gui/basic_context.go b/pkg/gui/basic_context.go
new file mode 100644
index 000000000..78cf85144
--- /dev/null
+++ b/pkg/gui/basic_context.go
@@ -0,0 +1,77 @@
+package gui
+
+type BasicContext struct {
+ OnFocus func() error
+ OnFocusLost func() error
+ OnRender func() error
+ Kind ContextKind
+ Key ContextKey
+ ViewName string
+ WindowName string
+ OnGetOptionsMap func() map[string]string
+
+ ParentContext Context
+ // we can't know on the calling end whether a Context is actually a nil value without reflection, so we're storing this flag here to tell us. There has got to be a better way around this
+ hasParent bool
+}
+
+func (c *BasicContext) GetOptionsMap() map[string]string {
+ if c.OnGetOptionsMap != nil {
+ return c.OnGetOptionsMap()
+ }
+ return nil
+}
+
+func (c *BasicContext) SetParentContext(context Context) {
+ c.ParentContext = context
+ c.hasParent = true
+}
+
+func (c *BasicContext) GetParentContext() (Context, bool) {
+ return c.ParentContext, c.hasParent
+}
+
+func (c *BasicContext) SetWindowName(windowName string) {
+ c.WindowName = windowName
+}
+
+func (c *BasicContext) GetWindowName() string {
+ windowName := c.WindowName
+
+ if windowName != "" {
+ return windowName
+ }
+
+ // TODO: actually set this for everything so we don't default to the view name
+ return c.ViewName
+}
+
+func (c *BasicContext) HandleRender() error {
+ if c.OnRender != nil {
+ return c.OnRender()
+ }
+ return nil
+}
+
+func (c *BasicContext) GetViewName() string {
+ return c.ViewName
+}
+
+func (c *BasicContext) HandleFocus() error {
+ return c.OnFocus()
+}
+
+func (c *BasicContext) HandleFocusLost() error {
+ if c.OnFocusLost != nil {
+ return c.OnFocusLost()
+ }
+ return nil
+}
+
+func (c *BasicContext) GetKind() ContextKind {
+ return c.Kind
+}
+
+func (c *BasicContext) GetKey() ContextKey {
+ return c.Key
+}
diff --git a/pkg/gui/context.go b/pkg/gui/context.go
index ec3656720..42add3e70 100644
--- a/pkg/gui/context.go
+++ b/pkg/gui/context.go
@@ -13,111 +13,9 @@ const (
MAIN_CONTEXT
TEMPORARY_POPUP
PERSISTENT_POPUP
+ EXTRAS_CONTEXT
)
-type ContextKey string
-
-const (
- STATUS_CONTEXT_KEY ContextKey = "status"
- FILES_CONTEXT_KEY ContextKey = "files"
- LOCAL_BRANCHES_CONTEXT_KEY ContextKey = "localBranches"
- REMOTES_CONTEXT_KEY ContextKey = "remotes"
- REMOTE_BRANCHES_CONTEXT_KEY ContextKey = "remoteBranches"
- TAGS_CONTEXT_KEY ContextKey = "tags"
- BRANCH_COMMITS_CONTEXT_KEY ContextKey = "commits"
- REFLOG_COMMITS_CONTEXT_KEY ContextKey = "reflogCommits"
- SUB_COMMITS_CONTEXT_KEY ContextKey = "subCommits"
- COMMIT_FILES_CONTEXT_KEY ContextKey = "commitFiles"
- STASH_CONTEXT_KEY ContextKey = "stash"
- MAIN_NORMAL_CONTEXT_KEY ContextKey = "normal"
- MAIN_MERGING_CONTEXT_KEY ContextKey = "merging"
- MAIN_PATCH_BUILDING_CONTEXT_KEY ContextKey = "patchBuilding"
- MAIN_STAGING_CONTEXT_KEY ContextKey = "staging"
- MENU_CONTEXT_KEY ContextKey = "menu"
- CREDENTIALS_CONTEXT_KEY ContextKey = "credentials"
- CONFIRMATION_CONTEXT_KEY ContextKey = "confirmation"
- SEARCH_CONTEXT_KEY ContextKey = "search"
- COMMIT_MESSAGE_CONTEXT_KEY ContextKey = "commitMessage"
- SUBMODULES_CONTEXT_KEY ContextKey = "submodules"
- SUGGESTIONS_CONTEXT_KEY ContextKey = "suggestions"
-)
-
-var allContextKeys = []ContextKey{
- STATUS_CONTEXT_KEY,
- FILES_CONTEXT_KEY,
- LOCAL_BRANCHES_CONTEXT_KEY,
- REMOTES_CONTEXT_KEY,
- REMOTE_BRANCHES_CONTEXT_KEY,
- TAGS_CONTEXT_KEY,
- BRANCH_COMMITS_CONTEXT_KEY,
- REFLOG_COMMITS_CONTEXT_KEY,
- SUB_COMMITS_CONTEXT_KEY,
- COMMIT_FILES_CONTEXT_KEY,
- STASH_CONTEXT_KEY,
- MAIN_NORMAL_CONTEXT_KEY,
- MAIN_MERGING_CONTEXT_KEY,
- MAIN_PATCH_BUILDING_CONTEXT_KEY,
- MAIN_STAGING_CONTEXT_KEY,
- MENU_CONTEXT_KEY,
- CREDENTIALS_CONTEXT_KEY,
- CONFIRMATION_CONTEXT_KEY,
- SEARCH_CONTEXT_KEY,
- COMMIT_MESSAGE_CONTEXT_KEY,
- SUBMODULES_CONTEXT_KEY,
- SUGGESTIONS_CONTEXT_KEY,
-}
-
-type ContextTree struct {
- Status Context
- Files *ListContext
- Submodules *ListContext
- Menu *ListContext
- Branches *ListContext
- Remotes *ListContext
- RemoteBranches *ListContext
- Tags *ListContext
- BranchCommits *ListContext
- CommitFiles *ListContext
- ReflogCommits *ListContext
- SubCommits *ListContext
- Stash *ListContext
- Suggestions *ListContext
- Normal Context
- Staging Context
- PatchBuilding Context
- Merging Context
- Credentials Context
- Confirmation Context
- CommitMessage Context
- Search Context
-}
-
-func (gui *Gui) allContexts() []Context {
- return []Context{
- gui.State.Contexts.Status,
- gui.State.Contexts.Files,
- gui.State.Contexts.Submodules,
- gui.State.Contexts.Branches,
- gui.State.Contexts.Remotes,
- gui.State.Contexts.RemoteBranches,
- gui.State.Contexts.Tags,
- gui.State.Contexts.BranchCommits,
- gui.State.Contexts.CommitFiles,
- gui.State.Contexts.ReflogCommits,
- gui.State.Contexts.Stash,
- gui.State.Contexts.Menu,
- gui.State.Contexts.Confirmation,
- gui.State.Contexts.Credentials,
- gui.State.Contexts.CommitMessage,
- gui.State.Contexts.Normal,
- gui.State.Contexts.Staging,
- gui.State.Contexts.Merging,
- gui.State.Contexts.PatchBuilding,
- gui.State.Contexts.SubCommits,
- gui.State.Contexts.Suggestions,
- }
-}
-
type Context interface {
HandleFocus() error
HandleFocusLost() error
@@ -134,170 +32,6 @@ type Context interface {
GetOptionsMap() map[string]string
}
-type BasicContext struct {
- OnFocus func() error
- OnFocusLost func() error
- OnRender func() error
- OnGetOptionsMap func() map[string]string
- Kind ContextKind
- Key ContextKey
- ViewName string
-}
-
-func (c BasicContext) GetOptionsMap() map[string]string {
- if c.OnGetOptionsMap != nil {
- return c.OnGetOptionsMap()
- }
- return nil
-}
-
-func (c BasicContext) SetWindowName(windowName string) {
- panic("can't set window name on basic context")
-}
-
-func (c BasicContext) GetWindowName() string {
- // TODO: fix this up
- return c.GetViewName()
-}
-
-func (c BasicContext) SetParentContext(Context) {
- panic("can't set parent context on basic context")
-}
-
-func (c BasicContext) GetParentContext() (Context, bool) {
- return nil, false
-}
-
-func (c BasicContext) HandleRender() error {
- if c.OnRender != nil {
- return c.OnRender()
- }
- return nil
-}
-
-func (c BasicContext) GetViewName() string {
- return c.ViewName
-}
-
-func (c BasicContext) HandleFocus() error {
- return c.OnFocus()
-}
-
-func (c BasicContext) HandleFocusLost() error {
- if c.OnFocusLost != nil {
- return c.OnFocusLost()
- }
- return nil
-}
-
-func (c BasicContext) GetKind() ContextKind {
- return c.Kind
-}
-
-func (c BasicContext) GetKey() ContextKey {
- return c.Key
-}
-
-func (gui *Gui) contextTree() ContextTree {
- return ContextTree{
- Status: BasicContext{
- OnFocus: gui.handleStatusSelect,
- Kind: SIDE_CONTEXT,
- ViewName: "status",
- Key: STATUS_CONTEXT_KEY,
- },
- Files: gui.filesListContext(),
- Submodules: gui.submodulesListContext(),
- Menu: gui.menuListContext(),
- Remotes: gui.remotesListContext(),
- RemoteBranches: gui.remoteBranchesListContext(),
- BranchCommits: gui.branchCommitsListContext(),
- CommitFiles: gui.commitFilesListContext(),
- ReflogCommits: gui.reflogCommitsListContext(),
- SubCommits: gui.subCommitsListContext(),
- Branches: gui.branchesListContext(),
- Tags: gui.tagsListContext(),
- Stash: gui.stashListContext(),
- Normal: 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: MAIN_NORMAL_CONTEXT_KEY,
- },
- Staging: BasicContext{
- OnFocus: func() error {
- return nil
- // TODO: centralise the code here
- // return gui.refreshStagingPanel(false, -1)
- },
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: MAIN_STAGING_CONTEXT_KEY,
- },
- PatchBuilding: BasicContext{
- OnFocus: func() error {
- return nil
- // TODO: centralise the code here
- // return gui.refreshPatchBuildingPanel(-1)
- },
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: MAIN_PATCH_BUILDING_CONTEXT_KEY,
- },
- Merging: BasicContext{
- OnFocus: gui.refreshMergePanelWithLock,
- Kind: MAIN_CONTEXT,
- ViewName: "main",
- Key: MAIN_MERGING_CONTEXT_KEY,
- OnGetOptionsMap: gui.getMergingOptions,
- },
- Credentials: BasicContext{
- OnFocus: gui.handleCredentialsViewFocused,
- Kind: PERSISTENT_POPUP,
- ViewName: "credentials",
- Key: CREDENTIALS_CONTEXT_KEY,
- },
- Confirmation: BasicContext{
- OnFocus: func() error { return nil },
- Kind: TEMPORARY_POPUP,
- ViewName: "confirmation",
- Key: CONFIRMATION_CONTEXT_KEY,
- },
- Suggestions: gui.suggestionsListContext(),
- CommitMessage: BasicContext{
- OnFocus: gui.handleCommitMessageFocused,
- Kind: PERSISTENT_POPUP,
- ViewName: "commitMessage",
- Key: COMMIT_MESSAGE_CONTEXT_KEY,
- },
- Search: BasicContext{
- OnFocus: func() error { return nil },
- Kind: PERSISTENT_POPUP,
- ViewName: "search",
- Key: SEARCH_CONTEXT_KEY,
- },
- }
-}
-
-func (tree ContextTree) initialViewContextMap() map[string]Context {
- return map[string]Context{
- "status": tree.Status,
- "files": tree.Files,
- "branches": tree.Branches,
- "commits": tree.BranchCommits,
- "commitFiles": tree.CommitFiles,
- "stash": tree.Stash,
- "menu": tree.Menu,
- "confirmation": tree.Confirmation,
- "credentials": tree.Credentials,
- "commitMessage": tree.CommitMessage,
- "main": tree.Normal,
- "secondary": tree.Normal,
- }
-}
-
func (gui *Gui) popupViewNames() []string {
result := []string{}
for _, context := range gui.allContexts() {
@@ -309,52 +43,6 @@ func (gui *Gui) popupViewNames() []string {
return result
}
-func (tree ContextTree) initialViewTabContextMap() map[string][]tabContext {
- return map[string][]tabContext{
- "branches": {
- {
- tab: "Local Branches",
- contexts: []Context{tree.Branches},
- },
- {
- tab: "Remotes",
- contexts: []Context{
- tree.Remotes,
- tree.RemoteBranches,
- },
- },
- {
- tab: "Tags",
- contexts: []Context{tree.Tags},
- },
- },
- "commits": {
- {
- tab: "Commits",
- contexts: []Context{tree.BranchCommits},
- },
- {
- tab: "Reflog",
- contexts: []Context{
- tree.ReflogCommits,
- },
- },
- },
- "files": {
- {
- tab: "Files",
- contexts: []Context{tree.Files},
- },
- {
- tab: "Submodules",
- contexts: []Context{
- tree.Submodules,
- },
- },
- },
- }
-}
-
func (gui *Gui) currentContextKeyIgnoringPopups() ContextKey {
gui.State.ContextManager.RLock()
defer gui.State.ContextManager.RUnlock()
@@ -416,7 +104,7 @@ func (gui *Gui) pushContextDirect(c Context) error {
}
}
gui.State.ContextManager.ContextStack = []Context{c}
- } else if len(gui.State.ContextManager.ContextStack) == 0 || gui.State.ContextManager.ContextStack[len(gui.State.ContextManager.ContextStack)-1].GetKey() != c.GetKey() {
+ } else if len(gui.State.ContextManager.ContextStack) == 0 || gui.currentContextWithoutLock().GetKey() != c.GetKey() {
// Do not append if the one at the end is the same context (e.g. opening a menu from a menu)
// In that case we'll just close the menu entirely when the user hits escape.
@@ -580,6 +268,10 @@ func (gui *Gui) currentContext() Context {
gui.State.ContextManager.RLock()
defer gui.State.ContextManager.RUnlock()
+ return gui.currentContextWithoutLock()
+}
+
+func (gui *Gui) currentContextWithoutLock() Context {
if len(gui.State.ContextManager.ContextStack) == 0 {
return gui.defaultSideContext()
}
diff --git a/pkg/gui/context_config.go b/pkg/gui/context_config.go
new file mode 100644
index 000000000..611988e2b
--- /dev/null
+++ b/pkg/gui/context_config.go
@@ -0,0 +1,261 @@
+package gui
+
+type ContextKey string
+
+const (
+ STATUS_CONTEXT_KEY ContextKey = "status"
+ FILES_CONTEXT_KEY ContextKey = "files"
+ LOCAL_BRANCHES_CONTEXT_KEY ContextKey = "localBranches"
+ REMOTES_CONTEXT_KEY ContextKey = "remotes"
+ REMOTE_BRANCHES_CONTEXT_KEY ContextKey = "remoteBranches"
+ TAGS_CONTEXT_KEY ContextKey = "tags"
+ BRANCH_COMMITS_CONTEXT_KEY ContextKey = "commits"
+ REFLOG_COMMITS_CONTEXT_KEY ContextKey = "reflogCommits"
+ SUB_COMMITS_CONTEXT_KEY ContextKey = "subCommits"
+ COMMIT_FILES_CONTEXT_KEY ContextKey = "commitFiles"
+ STASH_CONTEXT_KEY ContextKey = "stash"
+ MAIN_NORMAL_CONTEXT_KEY ContextKey = "normal"
+ MAIN_MERGING_CONTEXT_KEY ContextKey = "merging"
+ MAIN_PATCH_BUILDING_CONTEXT_KEY ContextKey = "patchBuilding"
+ MAIN_STAGING_CONTEXT_KEY ContextKey = "staging"
+ MENU_CONTEXT_KEY ContextKey = "menu"
+ CREDENTIALS_CONTEXT_KEY ContextKey = "credentials"
+ CONFIRMATION_CONTEXT_KEY ContextKey = "confirmation"
+ SEARCH_CONTEXT_KEY ContextKey = "search"
+ COMMIT_MESSAGE_CONTEXT_KEY ContextKey = "commitMessage"
+ SUBMODULES_CONTEXT_KEY ContextKey = "submodules"
+ SUGGESTIONS_CONTEXT_KEY ContextKey = "suggestions"
+ COMMAND_LOG_CONTEXT_KEY ContextKey = "cmdLog"
+)
+
+var allContextKeys = []ContextKey{
+ STATUS_CONTEXT_KEY,
+ FILES_CONTEXT_KEY,
+ LOCAL_BRANCHES_CONTEXT_KEY,
+ REMOTES_CONTEXT_KEY,
+ REMOTE_BRANCHES_CONTEXT_KEY,
+ TAGS_CONTEXT_KEY,
+ BRANCH_COMMITS_CONTEXT_KEY,
+ REFLOG_COMMITS_CONTEXT_KEY,
+ SUB_COMMITS_CONTEXT_KEY,
+ COMMIT_FILES_CONTEXT_KEY,
+ STASH_CONTEXT_KEY,
+ MAIN_NORMAL_CONTEXT_KEY,
+ MAIN_MERGING_CONTEXT_KEY,
+ MAIN_PATCH_BUILDING_CONTEXT_KEY,
+ MAIN_STAGING_CONTEXT_KEY,
+ MENU_CONTEXT_KEY,
+ CREDENTIALS_CONTEXT_KEY,
+ CONFIRMATION_CONTEXT_KEY,
+ SEARCH_CONTEXT_KEY,
+ COMMIT_MESSAGE_CONTEXT_KEY,
+ SUBMODULES_CONTEXT_KEY,
+ SUGGESTIONS_CONTEXT_KEY,
+ COMMAND_LOG_CONTEXT_KEY,
+}
+
+type ContextTree struct {
+ Status Context
+ Files *ListContext
+ Submodules *ListContext
+ Menu *ListContext
+ Branches *ListContext
+ Remotes *ListContext
+ RemoteBranches *ListContext
+ Tags *ListContext
+ BranchCommits *ListContext
+ CommitFiles *ListContext
+ ReflogCommits *ListContext
+ SubCommits *ListContext
+ Stash *ListContext
+ Suggestions *ListContext
+ Normal Context
+ Staging Context
+ PatchBuilding Context
+ Merging Context
+ Credentials Context
+ Confirmation Context
+ CommitMessage Context
+ Search Context
+ CommandLog Context
+}
+
+func (gui *Gui) allContexts() []Context {
+ return []Context{
+ gui.State.Contexts.Status,
+ gui.State.Contexts.Files,
+ gui.State.Contexts.Submodules,
+ gui.State.Contexts.Branches,
+ gui.State.Contexts.Remotes,
+ gui.State.Contexts.RemoteBranches,
+ gui.State.Contexts.Tags,
+ gui.State.Contexts.BranchCommits,
+ gui.State.Contexts.CommitFiles,
+ gui.State.Contexts.ReflogCommits,
+ gui.State.Contexts.Stash,
+ gui.State.Contexts.Menu,
+ gui.State.Contexts.Confirmation,
+ gui.State.Contexts.Credentials,
+ gui.State.Contexts.CommitMessage,
+ gui.State.Contexts.Normal,
+ gui.State.Contexts.Staging,
+ gui.State.Contexts.Merging,
+ gui.State.Contexts.PatchBuilding,
+ gui.State.Contexts.SubCommits,
+ gui.State.Contexts.Suggestions,
+ gui.State.Contexts.CommandLog,
+ }
+}
+
+func (gui *Gui) contextTree() ContextTree {
+ return ContextTree{
+ Status: &BasicContext{
+ OnFocus: gui.handleStatusSelect,
+ Kind: SIDE_CONTEXT,
+ ViewName: "status",
+ Key: STATUS_CONTEXT_KEY,
+ },
+ Files: gui.filesListContext(),
+ Submodules: gui.submodulesListContext(),
+ Menu: gui.menuListContext(),
+ Remotes: gui.remotesListContext(),
+ RemoteBranches: gui.remoteBranchesListContext(),
+ BranchCommits: gui.branchCommitsListContext(),
+ CommitFiles: gui.commitFilesListContext(),
+ ReflogCommits: gui.reflogCommitsListContext(),
+ SubCommits: gui.subCommitsListContext(),
+ Branches: gui.branchesListContext(),
+ Tags: gui.tagsListContext(),
+ Stash: gui.stashListContext(),
+ Normal: &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: MAIN_NORMAL_CONTEXT_KEY,
+ },
+ Staging: &BasicContext{
+ OnFocus: func() error {
+ return nil
+ // TODO: centralise the code here
+ // return gui.refreshStagingPanel(false, -1)
+ },
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: MAIN_STAGING_CONTEXT_KEY,
+ },
+ PatchBuilding: &BasicContext{
+ OnFocus: func() error {
+ return nil
+ // TODO: centralise the code here
+ // return gui.refreshPatchBuildingPanel(-1)
+ },
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: MAIN_PATCH_BUILDING_CONTEXT_KEY,
+ },
+ Merging: &BasicContext{
+ OnFocus: gui.refreshMergePanelWithLock,
+ Kind: MAIN_CONTEXT,
+ ViewName: "main",
+ Key: MAIN_MERGING_CONTEXT_KEY,
+ OnGetOptionsMap: gui.getMergingOptions,
+ },
+ Credentials: &BasicContext{
+ OnFocus: gui.handleCredentialsViewFocused,
+ Kind: PERSISTENT_POPUP,
+ ViewName: "credentials",
+ Key: CREDENTIALS_CONTEXT_KEY,
+ },
+ Confirmation: &BasicContext{
+ OnFocus: func() error { return nil },
+ Kind: TEMPORARY_POPUP,
+ ViewName: "confirmation",
+ Key: CONFIRMATION_CONTEXT_KEY,
+ },
+ Suggestions: gui.suggestionsListContext(),
+ CommitMessage: &BasicContext{
+ OnFocus: gui.handleCommitMessageFocused,
+ Kind: PERSISTENT_POPUP,
+ ViewName: "commitMessage",
+ Key: COMMIT_MESSAGE_CONTEXT_KEY,
+ },
+ Search: &BasicContext{
+ OnFocus: func() error { return nil },
+ Kind: PERSISTENT_POPUP,
+ ViewName: "search",
+ Key: SEARCH_CONTEXT_KEY,
+ },
+ CommandLog: &BasicContext{
+ OnFocus: func() error { return nil },
+ Kind: EXTRAS_CONTEXT,
+ ViewName: "extras",
+ Key: COMMAND_LOG_CONTEXT_KEY,
+ },
+ }
+}
+
+func (tree ContextTree) initialViewContextMap() map[string]Context {
+ return map[string]Context{
+ "status": tree.Status,
+ "files": tree.Files,
+ "branches": tree.Branches,
+ "commits": tree.BranchCommits,
+ "commitFiles": tree.CommitFiles,
+ "stash": tree.Stash,
+ "menu": tree.Menu,
+ "confirmation": tree.Confirmation,
+ "credentials": tree.Credentials,
+ "commitMessage": tree.CommitMessage,
+ "main": tree.Normal,
+ "secondary": tree.Normal,
+ "extras": tree.CommandLog,
+ }
+}
+
+func (tree ContextTree) initialViewTabContextMap() map[string][]tabContext {
+ return map[string][]tabContext{
+ "branches": {
+ {
+ tab: "Local Branches",
+ contexts: []Context{tree.Branches},
+ },
+ {
+ tab: "Remotes",
+ contexts: []Context{
+ tree.Remotes,
+ tree.RemoteBranches,
+ },
+ },
+ {
+ tab: "Tags",
+ contexts: []Context{tree.Tags},
+ },
+ },
+ "commits": {
+ {
+ tab: "Commits",
+ contexts: []Context{tree.BranchCommits},
+ },
+ {
+ tab: "Reflog",
+ contexts: []Context{
+ tree.ReflogCommits,
+ },
+ },
+ },
+ "files": {
+ {
+ tab: "Files",
+ contexts: []Context{tree.Files},
+ },
+ {
+ tab: "Submodules",
+ contexts: []Context{
+ tree.Submodules,
+ },
+ },
+ },
+ }
+}
diff --git a/pkg/gui/extras_panel.go b/pkg/gui/extras_panel.go
index 976cf5b43..d5c4b6070 100644
--- a/pkg/gui/extras_panel.go
+++ b/pkg/gui/extras_panel.go
@@ -3,12 +3,20 @@ package gui
func (gui *Gui) handleCreateExtrasMenuPanel() error {
menuItems := []*menuItem{
{
- displayString: "Toggle show/hide command log",
+ displayString: gui.Tr.ToggleShowCommandLog,
onPress: func() error {
gui.ShowExtrasWindow = !gui.ShowExtrasWindow
return nil
},
},
+ {
+ displayString: gui.Tr.FocusCommandLog,
+ onPress: func() error {
+ gui.ShowExtrasWindow = true
+ gui.State.Contexts.CommandLog.SetParentContext(gui.currentSideContext())
+ return gui.pushContext(gui.State.Contexts.CommandLog)
+ },
+ },
}
return gui.createMenu(gui.Tr.DiffingMenuTitle, menuItems, createMenuOptions{showCancel: true})
diff --git a/pkg/gui/list_context.go b/pkg/gui/list_context.go
index 356d6661c..dc9425d20 100644
--- a/pkg/gui/list_context.go
+++ b/pkg/gui/list_context.go
@@ -1,21 +1,11 @@
package gui
-import (
- "github.com/fatih/color"
- "github.com/jesseduffield/gocui"
- "github.com/jesseduffield/lazygit/pkg/gui/presentation"
- "github.com/jesseduffield/lazygit/pkg/utils"
-)
-
type ListContext struct {
- ViewName string
- ContextKey ContextKey
GetItemsLength func() int
GetDisplayStrings func() [][]string
OnFocus func() error
OnFocusLost func() error
OnClickSelectedItem func() error
- OnGetOptionsMap func() map[string]string
// the boolean here tells us whether the item is nil. This is needed because you can't work it out on the calling end once the pointer is wrapped in an interface (unless you want to use reflection)
SelectedItem func() (ListItem, bool)
@@ -23,11 +13,8 @@ type ListContext struct {
Gui *Gui
ResetMainViewOriginOnFocus bool
- Kind ContextKind
- ParentContext Context
- // we can't know on the calling end whether a Context is actually a nil value without reflection, so we're storing this flag here to tell us. There has got to be a better way around this.
- hasParent bool
- WindowName string
+
+ *BasicContext
}
type IListPanelState interface {
@@ -47,30 +34,6 @@ func (lc *ListContext) GetSelectedItem() (ListItem, bool) {
return lc.SelectedItem()
}
-func (lc *ListContext) SetWindowName(windowName string) {
- lc.WindowName = windowName
-}
-
-func (lc *ListContext) GetWindowName() string {
- windowName := lc.WindowName
-
- if windowName != "" {
- return windowName
- }
-
- // TODO: actually set this for everything so we don't default to the view name
- return lc.ViewName
-}
-
-func (lc *ListContext) SetParentContext(c Context) {
- lc.ParentContext = c
- lc.hasParent = true
-}
-
-func (lc *ListContext) GetParentContext() (Context, bool) {
- return lc.ParentContext, lc.hasParent
-}
-
func (lc *ListContext) GetSelectedItemId() string {
item, ok := lc.SelectedItem()
@@ -81,13 +44,6 @@ func (lc *ListContext) GetSelectedItemId() string {
return item.ID()
}
-func (lc *ListContext) GetOptionsMap() map[string]string {
- if lc.OnGetOptionsMap != nil {
- return lc.OnGetOptionsMap()
- }
- return nil
-}
-
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
func (lc *ListContext) OnRender() error {
view, err := lc.Gui.g.View(lc.ViewName)
@@ -103,18 +59,6 @@ func (lc *ListContext) OnRender() error {
return nil
}
-func (lc *ListContext) GetKey() ContextKey {
- return lc.ContextKey
-}
-
-func (lc *ListContext) GetKind() ContextKind {
- return lc.Kind
-}
-
-func (lc *ListContext) GetViewName() string {
- return lc.ViewName
-}
-
func (lc *ListContext) HandleFocusLost() error {
if lc.OnFocusLost != nil {
return lc.OnFocusLost()
@@ -252,349 +196,3 @@ func (lc *ListContext) onSearchSelect(selectedLineIdx int) error {
lc.GetPanelState().SetSelectedLineIdx(selectedLineIdx)
return lc.HandleFocus()
}
-
-func (gui *Gui) menuListContext() *ListContext {
- return &ListContext{
- ViewName: "menu",
- ContextKey: "menu",
- GetItemsLength: func() int { return gui.Views.Menu.LinesHeight() },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Menu },
- OnFocus: gui.handleMenuSelect,
- OnClickSelectedItem: gui.onMenuPress,
- Gui: gui,
- ResetMainViewOriginOnFocus: false,
- Kind: PERSISTENT_POPUP,
- OnGetOptionsMap: gui.getMenuOptions,
-
- // no GetDisplayStrings field because we do a custom render on menu creation
- }
-}
-
-func (gui *Gui) filesListContext() *ListContext {
- return &ListContext{
- ViewName: "files",
- ContextKey: FILES_CONTEXT_KEY,
- GetItemsLength: func() int { return gui.State.FileManager.GetItemsLength() },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Files },
- OnFocus: gui.focusAndSelectFile,
- OnClickSelectedItem: gui.handleFilePress,
- Gui: gui,
- ResetMainViewOriginOnFocus: false,
- Kind: SIDE_CONTEXT,
- GetDisplayStrings: func() [][]string {
- lines := gui.State.FileManager.Render(gui.State.Modes.Diffing.Ref, gui.State.Submodules)
- mappedLines := make([][]string, len(lines))
- for i, line := range lines {
- mappedLines[i] = []string{line}
- }
-
- return mappedLines
- },
- SelectedItem: func() (ListItem, bool) {
- item := gui.getSelectedFileNode()
- return item, item != nil
- },
- }
-}
-
-func (gui *Gui) branchesListContext() *ListContext {
- return &ListContext{
- ViewName: "branches",
- ContextKey: LOCAL_BRANCHES_CONTEXT_KEY,
- GetItemsLength: func() int { return len(gui.State.Branches) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Branches },
- OnFocus: gui.handleBranchSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
- Kind: SIDE_CONTEXT,
- GetDisplayStrings: func() [][]string {
- return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Modes.Diffing.Ref)
- },
- SelectedItem: func() (ListItem, bool) {
- item := gui.getSelectedBranch()
- return item, item != nil
- },
- }
-}
-
-func (gui *Gui) remotesListContext() *ListContext {
- return &ListContext{
- ViewName: "branches",
- ContextKey: REMOTES_CONTEXT_KEY,
- GetItemsLength: func() int { return len(gui.State.Remotes) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Remotes },
- OnFocus: gui.handleRemoteSelect,
- OnClickSelectedItem: gui.handleRemoteEnter,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
- Kind: SIDE_CONTEXT,
- GetDisplayStrings: func() [][]string {
- return presentation.GetRemoteListDisplayStrings(gui.State.Remotes, gui.State.Modes.Diffing.Ref)
- },
- SelectedItem: func() (ListItem, bool) {
- item := gui.getSelectedRemote()
- return item, item != nil
- },
- }
-}
-
-func (gui *Gui) remoteBranchesListContext() *ListContext {
- return &ListContext{
- ViewName: "branches",
- ContextKey: REMOTE_BRANCHES_CONTEXT_KEY,
- GetItemsLength: func() int { return len(gui.State.RemoteBranches) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.RemoteBranches },
- OnFocus: gui.handleRemoteBranchSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
- Kind: SIDE_CONTEXT,
- GetDisplayStrings: func() [][]string {
- return presentation.GetRemoteBranchListDisplayStrings(gui.State.RemoteBranches, gui.State.Modes.Diffing.Ref)
- },
- SelectedItem: func() (ListItem, bool) {
- item := gui.getSelectedRemoteBranch()
- return item, item != nil
- },
- }
-}
-
-func (gui *Gui) tagsListContext() *ListContext {
- return &ListContext{
- ViewName: "branches",
- ContextKey: TAGS_CONTEXT_KEY,
- GetItemsLength: func() int { return len(gui.State.Tags) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Tags },
- OnFocus: gui.handleTagSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
- Kind: SIDE_CONTEXT,
- GetDisplayStrings: func() [][]string {
- return presentation.GetTagListDisplayStrings(gui.State.Tags, gui.State.Modes.Diffing.Ref)
- },
- SelectedItem: func() (ListItem, bool) {
- item := gui.getSelectedTag()
- return item, item != nil
- },
- }
-}
-
-func (gui *Gui) branchCommitsListContext() *ListContext {
- return &ListContext{
- ViewName: "commits",
- ContextKey: BRANCH_COMMITS_CONTEXT_KEY,
- GetItemsLength: func() int { return len(gui.State.Commits) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Commits },
- OnFocus: gui.handleCommitSelect,
- OnClickSelec