1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-02-09 13:47:11 +02:00

working again

This commit is contained in:
Jesse Duffield 2022-02-05 16:56:36 +11:00
parent 482bdc4f1e
commit 145c69d9ae
19 changed files with 297 additions and 189 deletions

View File

@ -46,10 +46,16 @@ func (gui *Gui) commitFilesRenderToMain() error {
cmdObj := gui.git.WorkingTree.ShowFileDiffCmdObj(from, to, reverse, node.GetPath(), false)
task := NewRunPtyTask(cmdObj.GetCmd())
mainContext := gui.State.Contexts.Normal
if node.File != nil {
mainContext = gui.State.Contexts.PatchBuilding
}
return gui.refreshMainViews(refreshMainOpts{
main: &viewUpdateOpts{
title: "Patch",
task: task,
title: "Patch",
task: task,
context: mainContext,
},
secondary: gui.secondaryPatchPanelUpdateOpts(),
})

View File

@ -11,7 +11,7 @@ import (
func (gui *Gui) popupViewNames() []string {
result := []string{}
for _, context := range gui.allContexts() {
for _, context := range gui.State.Contexts.Flatten() {
if context.GetKind() == types.PERSISTENT_POPUP || context.GetKind() == types.TEMPORARY_POPUP {
result = append(result, context.GetViewName())
}
@ -44,6 +44,10 @@ func (gui *Gui) replaceContext(c types.Context) error {
gui.State.ContextManager.Lock()
defer gui.State.ContextManager.Unlock()
if !c.IsFocusable() {
return nil
}
if len(gui.State.ContextManager.ContextStack) == 0 {
gui.State.ContextManager.ContextStack = []types.Context{c}
} else {
@ -60,8 +64,9 @@ func (gui *Gui) pushContext(c types.Context, opts ...types.OnFocusOpts) error {
return errors.New("cannot pass multiple opts to pushContext")
}
if c.GetKey() == context.GLOBAL_CONTEXT_KEY {
return errors.New("Cannot push global context")
if !c.IsFocusable() {
panic(c.GetKey())
return nil
}
gui.State.ContextManager.Lock()
@ -97,7 +102,7 @@ func (gui *Gui) pushContext(c types.Context, opts ...types.OnFocusOpts) error {
// want to switch to: you only know the view that you want to switch to. It will
// look up the context currently active for that view and switch to that context
func (gui *Gui) pushContextWithView(viewName string) error {
return gui.c.PushContext(gui.State.ViewContextMap[viewName])
return gui.c.PushContext(gui.State.ViewContextMap.Get(viewName))
}
func (gui *Gui) returnFromContext() error {
@ -152,7 +157,7 @@ func (gui *Gui) deactivateContext(c types.Context) error {
// 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 types.Context) error {
if gui.State.ViewContextMap[c.GetViewName()].GetKey() != c.GetKey() {
if gui.State.ViewContextMap.Get(c.GetViewName()).GetKey() != c.GetKey() {
return nil
}
@ -175,7 +180,7 @@ func (gui *Gui) activateContext(c types.Context, opts ...types.OnFocusOpts) erro
if err != nil {
return err
}
originalViewContextKey := gui.State.ViewContextMap[viewName].GetKey()
originalViewContextKey := gui.State.ViewContextMap.Get(viewName).GetKey()
gui.setWindowContext(c)
gui.setViewTabForContext(c)
@ -200,7 +205,7 @@ func (gui *Gui) activateContext(c types.Context, opts ...types.OnFocusOpts) erro
}
}
gui.State.ViewContextMap[viewName] = c
gui.ViewContextMapSet(viewName, c)
gui.g.Cursor = v.Editable
@ -215,12 +220,19 @@ func (gui *Gui) activateContext(c types.Context, opts ...types.OnFocusOpts) erro
return err
}
// TODO: consider removing this and instead depending on the .Context field of views
gui.State.ViewContextMap[c.GetViewName()] = c
return nil
}
// also setting context on view for now. We'll need to pick one of these two approaches to stick with.
func (gui *Gui) ViewContextMapSet(viewName string, c types.Context) {
gui.State.ViewContextMap.Set(viewName, c)
view, err := gui.g.View(viewName)
if err != nil {
panic(err)
}
view.Context = string(c.GetKey())
}
// // currently unused
// func (gui *Gui) renderContextStack() string {
// result := ""
@ -369,8 +381,8 @@ func (gui *Gui) changeMainViewsContext(c types.Context) {
switch c.GetKey() {
case context.MAIN_NORMAL_CONTEXT_KEY, context.MAIN_PATCH_BUILDING_CONTEXT_KEY, context.MAIN_STAGING_CONTEXT_KEY, context.MAIN_MERGING_CONTEXT_KEY:
gui.State.ViewContextMap[gui.Views.Main.Name()] = c
gui.State.ViewContextMap[gui.Views.Secondary.Name()] = c
gui.ViewContextMapSet(gui.Views.Main.Name(), c)
gui.ViewContextMapSet(gui.Views.Secondary.Name(), c)
default:
panic(fmt.Sprintf("unknown context for main: %s", c.GetKey()))
}
@ -416,18 +428,8 @@ func (gui *Gui) setViewTabForContext(c types.Context) {
}
}
func (gui *Gui) mustContextForContextKey(contextKey types.ContextKey) types.Context {
context, ok := gui.contextForContextKey(contextKey)
if !ok {
panic(fmt.Sprintf("context not found for key %s", contextKey))
}
return context
}
func (gui *Gui) contextForContextKey(contextKey types.ContextKey) (types.Context, bool) {
for _, context := range gui.allContexts() {
for _, context := range gui.State.Contexts.Flatten() {
if context.GetKey() == contextKey {
return context, true
}
@ -437,13 +439,7 @@ func (gui *Gui) contextForContextKey(contextKey types.ContextKey) (types.Context
}
func (gui *Gui) rerenderView(view *gocui.View) error {
context, ok := gui.State.ViewContextMap[view.Name()]
if !ok {
panic("no context set against view " + view.Name())
}
return context.HandleRender()
return gui.State.ViewContextMap.Get(view.Name()).HandleRender()
}
func (gui *Gui) getSideContextSelectedItemId() string {
@ -456,7 +452,7 @@ func (gui *Gui) getSideContextSelectedItemId() string {
}
func (gui *Gui) isContextVisible(c types.Context) bool {
return gui.State.WindowViewNameMap[c.GetWindowName()] == c.GetViewName() && gui.State.ViewContextMap[c.GetViewName()].GetKey() == c.GetKey()
return gui.State.WindowViewNameMap[c.GetWindowName()] == c.GetViewName() && gui.State.ViewContextMap.Get(c.GetViewName()).GetKey() == c.GetKey()
}
// currently unused

View File

@ -15,6 +15,8 @@ type BaseContext struct {
keybindingsFns []types.KeybindingsFn
mouseKeybindingsFns []types.MouseKeybindingsFn
focusable bool
*ParentContextMgr
}
@ -25,6 +27,7 @@ type NewBaseContextOpts struct {
Key types.ContextKey
ViewName string
WindowName string
Focusable bool
OnGetOptionsMap func() map[string]string
}
@ -36,6 +39,7 @@ func NewBaseContext(opts NewBaseContextOpts) *BaseContext {
ViewName: opts.ViewName,
windowName: opts.WindowName,
onGetOptionsMap: opts.OnGetOptionsMap,
focusable: opts.Focusable,
ParentContextMgr: &ParentContextMgr{},
}
}
@ -96,3 +100,7 @@ func (self *BaseContext) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocu
return bindings
}
func (self *BaseContext) IsFocusable() bool {
return self.focusable
}

View File

@ -31,6 +31,7 @@ func NewCommitFilesContext(
WindowName: "commits",
Key: COMMIT_FILES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
})
self := &CommitFilesContext{}

View File

@ -30,7 +30,7 @@ const (
)
var AllContextKeys = []types.ContextKey{
GLOBAL_CONTEXT_KEY,
GLOBAL_CONTEXT_KEY, // not focusable
STATUS_CONTEXT_KEY,
FILES_CONTEXT_KEY,
LOCAL_BRANCHES_CONTEXT_KEY,
@ -42,10 +42,10 @@ var AllContextKeys = []types.ContextKey{
SUB_COMMITS_CONTEXT_KEY,
COMMIT_FILES_CONTEXT_KEY,
STASH_CONTEXT_KEY,
MAIN_NORMAL_CONTEXT_KEY,
MAIN_NORMAL_CONTEXT_KEY, // not focusable
MAIN_MERGING_CONTEXT_KEY,
MAIN_PATCH_BUILDING_CONTEXT_KEY,
MAIN_STAGING_CONTEXT_KEY,
MAIN_STAGING_CONTEXT_KEY, // not focusable for secondary view
MENU_CONTEXT_KEY,
CREDENTIALS_CONTEXT_KEY,
CONFIRMATION_CONTEXT_KEY,
@ -83,24 +83,50 @@ type ContextTree struct {
CommandLog types.Context
}
func (tree ContextTree) InitialViewContextMap() map[string]types.Context {
return map[string]types.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 (self *ContextTree) Flatten() []types.Context {
return []types.Context{
self.Global,
self.Status,
self.Files,
self.Submodules,
self.Branches,
self.Remotes,
self.RemoteBranches,
self.Tags,
self.BranchCommits,
self.CommitFiles,
self.ReflogCommits,
self.Stash,
self.Menu,
self.Confirmation,
self.Credentials,
self.CommitMessage,
self.Normal,
self.Staging,
self.Merging,
self.PatchBuilding,
self.SubCommits,
self.Suggestions,
self.CommandLog,
}
}
type ViewContextMap struct {
content map[string]types.Context
}
func NewViewContextMap() *ViewContextMap {
return &ViewContextMap{content: map[string]types.Context{}}
}
func (self *ViewContextMap) Get(viewName string) types.Context {
return self.content[viewName]
}
func (self *ViewContextMap) Set(viewName string, context types.Context) {
self.content[viewName] = context
}
type TabContext struct {
Tab string
Contexts []types.Context

View File

@ -31,6 +31,7 @@ func NewTagsContext(
WindowName: "branches",
Key: TAGS_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
})
self := &TagsContext{}

View File

@ -31,6 +31,7 @@ func NewWorkingTreeContext(
WindowName: "files",
Key: FILES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
})
self := &WorkingTreeContext{}

View File

@ -5,7 +5,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
func (gui *Gui) allContexts() []types.Context {
func (gui *Gui) allContexts2() []types.Context {
return []types.Context{
gui.State.Contexts.Global,
gui.State.Contexts.Status,
@ -41,6 +41,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "",
WindowName: "",
Key: context.GLOBAL_CONTEXT_KEY,
Focusable: false,
}),
NewSimpleContextOpts{
OnRenderToMain: OnFocusWrapper(gui.statusRenderToMain),
@ -52,6 +53,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "status",
WindowName: "status",
Key: context.STATUS_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{
OnRenderToMain: OnFocusWrapper(gui.statusRenderToMain),
@ -76,6 +78,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "main",
WindowName: "main",
Key: context.MAIN_NORMAL_CONTEXT_KEY,
Focusable: false,
}),
NewSimpleContextOpts{
OnFocus: func(opts ...types.OnFocusOpts) error {
@ -89,6 +92,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "main",
WindowName: "main",
Key: context.MAIN_STAGING_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocus: func(opts ...types.OnFocusOpts) error {
@ -112,6 +116,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "main",
WindowName: "main",
Key: context.MAIN_PATCH_BUILDING_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocus: func(opts ...types.OnFocusOpts) error {
@ -131,6 +136,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
WindowName: "main",
Key: context.MAIN_MERGING_CONTEXT_KEY,
OnGetOptionsMap: gui.getMergingOptions,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocus: OnFocusWrapper(func() error { return gui.renderConflictsWithLock(true) }),
@ -142,6 +148,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "credentials",
WindowName: "credentials",
Key: context.CREDENTIALS_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocus: OnFocusWrapper(gui.handleAskFocused),
@ -153,6 +160,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "confirmation",
WindowName: "confirmation",
Key: context.CONFIRMATION_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocus: OnFocusWrapper(gui.handleAskFocused),
@ -164,6 +172,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "commitMessage",
WindowName: "commitMessage",
Key: context.COMMIT_MESSAGE_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocus: OnFocusWrapper(gui.handleCommitMessageFocused),
@ -175,6 +184,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
ViewName: "search",
WindowName: "search",
Key: context.SEARCH_CONTEXT_KEY,
Focusable: true,
}),
NewSimpleContextOpts{},
),
@ -185,6 +195,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
WindowName: "extras",
Key: context.COMMAND_LOG_CONTEXT_KEY,
OnGetOptionsMap: gui.getMergingOptions,
Focusable: true,
}),
NewSimpleContextOpts{
OnFocusLost: func() error {

View File

@ -55,9 +55,15 @@ func (gui *Gui) filesRenderToMain() error {
cmdObj := gui.git.WorkingTree.WorktreeFileDiffCmdObj(node, false, !node.GetHasUnstagedChanges() && node.GetHasStagedChanges(), gui.IgnoreWhitespaceInDiffView)
mainContext := gui.State.Contexts.Normal
if node.File != nil {
mainContext = gui.State.Contexts.Staging
}
refreshOpts := refreshMainOpts{main: &viewUpdateOpts{
title: gui.c.Tr.UnstagedChanges,
task: NewRunPtyTask(cmdObj.GetCmd()),
title: gui.c.Tr.UnstagedChanges,
task: NewRunPtyTask(cmdObj.GetCmd()),
context: mainContext,
}}
if node.GetHasUnstagedChanges() {
@ -65,8 +71,9 @@ func (gui *Gui) filesRenderToMain() error {
cmdObj := gui.git.WorkingTree.WorktreeFileDiffCmdObj(node, false, true, gui.IgnoreWhitespaceInDiffView)
refreshOpts.secondary = &viewUpdateOpts{
title: gui.c.Tr.StagedChanges,
task: NewRunPtyTask(cmdObj.GetCmd()),
title: gui.c.Tr.StagedChanges,
task: NewRunPtyTask(cmdObj.GetCmd()),
context: mainContext,
}
}
} else {

View File

@ -193,7 +193,7 @@ type GuiRepoState struct {
MainContext types.ContextKey // used to keep the main and secondary views' contexts in sync
ContextManager ContextManager
Contexts *context.ContextTree
ViewContextMap map[string]types.Context
ViewContextMap *context.ViewContextMap
ViewTabContextMap map[string][]context.TabContext
// WindowViewNameMap is a mapping of windows to the current view of that window.
@ -417,13 +417,23 @@ func (gui *Gui) resetState(filterPath string, reuseState bool) {
}
}
contexts := gui.contextTree()
contextTree := gui.contextTree()
screenMode := SCREEN_NORMAL
var initialContext types.IListContext = contexts.Files
var initialContext types.IListContext = contextTree.Files
if filterPath != "" {
screenMode = SCREEN_HALF
initialContext = contexts.BranchCommits
initialContext = contextTree.BranchCommits
}
viewContextMap := context.NewViewContextMap()
for viewName, context := range initialViewContextMapping(contextTree) {
viewContextMap.Set(viewName, context)
view, err := gui.g.View(viewName)
if err != nil {
panic(err)
}
view.Context = string(context.GetKey())
}
gui.State = &GuiRepoState{
@ -461,17 +471,35 @@ func (gui *Gui) resetState(filterPath string, reuseState bool) {
CherryPicking: cherrypicking.New(),
Diffing: diffing.New(),
},
ViewContextMap: contexts.InitialViewContextMap(),
ViewTabContextMap: contexts.InitialViewTabContextMap(),
ViewContextMap: viewContextMap,
ViewTabContextMap: contextTree.InitialViewTabContextMap(),
ScreenMode: screenMode,
// TODO: put contexts in the context manager
ContextManager: NewContextManager(initialContext),
Contexts: contexts,
Contexts: contextTree,
}
gui.RepoStateMap[Repo(currentDir)] = gui.State
}
func initialViewContextMapping(contextTree *context.ContextTree) map[string]types.Context {
return map[string]types.Context{
"status": contextTree.Status,
"files": contextTree.Files,
"branches": contextTree.Branches,
"commits": contextTree.BranchCommits,
"commitFiles": contextTree.CommitFiles,
"stash": contextTree.Stash,
"menu": contextTree.Menu,
"confirmation": contextTree.Confirmation,
"credentials": contextTree.Credentials,
"commitMessage": contextTree.CommitMessage,
"main": contextTree.Normal,
"secondary": contextTree.Normal,
"extras": contextTree.CommandLog,
}
}
// for now the split view will always be on
// NewGui builds a new gui handler
func NewGui(
@ -760,6 +788,10 @@ func (gui *Gui) Run(filterPath string) error {
gui.g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout()))
if err := gui.createAllViews(); err != nil {
return err
}
// onNewRepo must be called after g.SetManager because SetManager deletes keybindings
if err := gui.onNewRepo(filterPath, false); err != nil {
return err
@ -777,6 +809,120 @@ func (gui *Gui) Run(filterPath string) error {
return gui.g.MainLoop()
}
func (gui *Gui) createAllViews() error {
viewNameMappings := []struct {
viewPtr **gocui.View
name string
}{
{viewPtr: &gui.Views.Status, name: "status"},
{viewPtr: &gui.Views.Files, name: "files"},
{viewPtr: &gui.Views.Branches, name: "branches"},
{viewPtr: &gui.Views.Commits, name: "commits"},
{viewPtr: &gui.Views.Stash, name: "stash"},
{viewPtr: &gui.Views.CommitFiles, name: "commitFiles"},
{viewPtr: &gui.Views.Main, name: "main"},
{viewPtr: &gui.Views.Secondary, name: "secondary"},
{viewPtr: &gui.Views.Options, name: "options"},
{viewPtr: &gui.Views.AppStatus, name: "appStatus"},
{viewPtr: &gui.Views.Information, name: "information"},
{viewPtr: &gui.Views.Search, name: "search"},
{viewPtr: &gui.Views.SearchPrefix, name: "searchPrefix"},
{viewPtr: &gui.Views.CommitMessage, name: "commitMessage"},
{viewPtr: &gui.Views.Credentials, name: "credentials"},
{viewPtr: &gui.Views.Menu, name: "menu"},
{viewPtr: &gui.Views.Suggestions, name: "suggestions"},
{viewPtr: &gui.Views.Confirmation, name: "confirmation"},
{viewPtr: &gui.Views.Limit, name: "limit"},
{viewPtr: &gui.Views.Extras, name: "extras"},
}
var err error
for _, mapping := range viewNameMappings {
*mapping.viewPtr, err = gui.prepareView(mapping.name)
if err != nil && err.Error() != UNKNOWN_VIEW_ERROR_MSG {
return err
}
}
gui.Views.Options.Frame = false
gui.Views.Options.FgColor = theme.OptionsColor
gui.Views.SearchPrefix.BgColor = gocui.ColorDefault
gui.Views.SearchPrefix.FgColor = gocui.ColorGreen
gui.Views.SearchPrefix.Frame = false
gui.setViewContent(gui.Views.SearchPrefix, SEARCH_PREFIX)
gui.Views.Stash.Title = gui.c.Tr.StashTitle
gui.Views.Stash.FgColor = theme.GocuiDefaultTextColor
gui.Views.Commits.Title = gui.c.Tr.CommitsTitle
gui.Views.Commits.FgColor = theme.GocuiDefaultTextColor
gui.Views.CommitFiles.Title = gui.c.Tr.CommitFiles
gui.Views.CommitFiles.FgColor = theme.GocuiDefaultTextColor
gui.Views.Branches.Title = gui.c.Tr.BranchesTitle
gui.Views.Branches.FgColor = theme.GocuiDefaultTextColor
gui.Views.Files.Highlight = true
gui.Views.Files.Title = gui.c.Tr.FilesTitle
gui.Views.Files.FgColor = theme.GocuiDefaultTextColor
gui.Views.Secondary.Title = gui.c.Tr.DiffTitle
gui.Views.Secondary.Wrap = true
gui.Views.Secondary.FgColor = theme.GocuiDefaultTextColor
gui.Views.Secondary.IgnoreCarriageReturns = true
gui.Views.Main.Title = gui.c.Tr.DiffTitle
gui.Views.Main.Wrap = true
gui.Views.Main.FgColor = theme.GocuiDefaultTextColor
gui.Views.Main.IgnoreCarriageReturns = true
gui.Views.Limit.Title = gui.c.Tr.NotEnoughSpace
gui.Views.Limit.Wrap = true
gui.Views.Status.Title = gui.c.Tr.StatusTitle
gui.Views.Status.FgColor = theme.GocuiDefaultTextColor
gui.Views.Search.BgColor = gocui.ColorDefault
gui.Views.Search.FgColor = gocui.ColorGreen
gui.Views.Search.Frame = false
gui.Views.Search.Editable = true
gui.Views.AppStatus.BgColor = gocui.ColorDefault
gui.Views.AppStatus.FgColor = gocui.ColorCyan
gui.Views.AppStatus.Frame = false
gui.Views.AppStatus.Visible = false
gui.Views.CommitMessage.Visible = false
gui.Views.CommitMessage.Title = gui.c.Tr.CommitMessage
gui.Views.CommitMessage.FgColor = theme.GocuiDefaultTextColor
gui.Views.CommitMessage.Editable = true
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
gui.Views.Confirmation.Visible = false
gui.Views.Credentials.Visible = false
gui.Views.Credentials.Title = gui.c.Tr.CredentialsUsername
gui.Views.Credentials.FgColor = theme.GocuiDefaultTextColor
gui.Views.Credentials.Editable = true
gui.Views.Suggestions.Visible = false
gui.Views.Menu.Visible = false
gui.Views.Information.BgColor = gocui.ColorDefault
gui.Views.Information.FgColor = gocui.ColorGreen
gui.Views.Information.Frame = false
gui.Views.Extras.Title = gui.c.Tr.CommandLog
gui.Views.Extras.FgColor = theme.GocuiDefaultTextColor
gui.Views.Extras.Autoscroll = true
gui.Views.Extras.Wrap = true
return nil
}
func (gui *Gui) RunAndHandleError(filterPath string) error {
gui.stopChan = make(chan struct{})
return utils.SafeWithError(func() error {

View File

@ -1348,7 +1348,7 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
}
mouseKeybindings := []*gocui.ViewMouseBinding{}
for _, c := range gui.allContexts() {
for _, c := range gui.State.Contexts.Flatten() {
viewName := c.GetViewName()
contextKey := c.GetKey()
for _, binding := range c.GetKeybindings(keybindingsOpts) {

View File

@ -7,130 +7,12 @@ import (
const SEARCH_PREFIX = "search: "
func (gui *Gui) createAllViews() error {
viewNameMappings := []struct {
viewPtr **gocui.View
name string
}{
{viewPtr: &gui.Views.Status, name: "status"},
{viewPtr: &gui.Views.Files, name: "files"},
{viewPtr: &gui.Views.Branches, name: "branches"},
{viewPtr: &gui.Views.Commits, name: "commits"},
{viewPtr: &gui.Views.Stash, name: "stash"},
{viewPtr: &gui.Views.CommitFiles, name: "commitFiles"},
{viewPtr: &gui.Views.Main, name: "main"},
{viewPtr: &gui.Views.Secondary, name: "secondary"},
{viewPtr: &gui.Views.Options, name: "options"},
{viewPtr: &gui.Views.AppStatus, name: "appStatus"},
{viewPtr: &gui.Views.Information, name: "information"},
{viewPtr: &gui.Views.Search, name: "search"},
{viewPtr: &gui.Views.SearchPrefix, name: "searchPrefix"},
{viewPtr: &gui.Views.CommitMessage, name: "commitMessage"},
{viewPtr: &gui.Views.Credentials, name: "credentials"},
{viewPtr: &gui.Views.Menu, name: "menu"},
{viewPtr: &gui.Views.Suggestions, name: "suggestions"},
{viewPtr: &gui.Views.Confirmation, name: "confirmation"},
{viewPtr: &gui.Views.Limit, name: "limit"},
{viewPtr: &gui.Views.Extras, name: "extras"},
}
var err error
for _, mapping := range viewNameMappings {
*mapping.viewPtr, err = gui.prepareView(mapping.name)
if err != nil && err.Error() != UNKNOWN_VIEW_ERROR_MSG {
return err
}
}
gui.Views.Options.Frame = false
gui.Views.Options.FgColor = theme.OptionsColor
gui.Views.SearchPrefix.BgColor = gocui.ColorDefault
gui.Views.SearchPrefix.FgColor = gocui.ColorGreen
gui.Views.SearchPrefix.Frame = false
gui.setViewContent(gui.Views.SearchPrefix, SEARCH_PREFIX)
gui.Views.Stash.Title = gui.c.Tr.StashTitle
gui.Views.Stash.FgColor = theme.GocuiDefaultTextColor
gui.Views.Commits.Title = gui.c.Tr.CommitsTitle
gui.Views.Commits.FgColor = theme.GocuiDefaultTextColor
gui.Views.CommitFiles.Title = gui.c.Tr.CommitFiles
gui.Views.CommitFiles.FgColor = theme.GocuiDefaultTextColor
gui.Views.Branches.Title = gui.c.Tr.BranchesTitle
gui.Views.Branches.FgColor = theme.GocuiDefaultTextColor
gui.Views.Files.Highlight = true
gui.Views.Files.Title = gui.c.Tr.FilesTitle
gui.Views.Files.FgColor = theme.GocuiDefaultTextColor
gui.Views.Secondary.Title = gui.c.Tr.DiffTitle
gui.Views.Secondary.Wrap = true
gui.Views.Secondary.FgColor = theme.GocuiDefaultTextColor
gui.Views.Secondary.IgnoreCarriageReturns = true
gui.Views.Main.Title = gui.c.Tr.DiffTitle
gui.Views.Main.Wrap = true
gui.Views.Main.FgColor = theme.GocuiDefaultTextColor
gui.Views.Main.IgnoreCarriageReturns = true
gui.Views.Limit.Title = gui.c.Tr.NotEnoughSpace
gui.Views.Limit.Wrap = true
gui.Views.Status.Title = gui.c.Tr.StatusTitle
gui.Views.Status.FgColor = theme.GocuiDefaultTextColor
gui.Views.Search.BgColor = gocui.ColorDefault
gui.Views.Search.FgColor = gocui.ColorGreen
gui.Views.Search.Frame = false
gui.Views.Search.Editable = true
gui.Views.AppStatus.BgColor = gocui.ColorDefault
gui.Views.AppStatus.FgColor = gocui.ColorCyan
gui.Views.AppStatus.Frame = false
gui.Views.AppStatus.Visible = false
gui.Views.CommitMessage.Visible = false
gui.Views.CommitMessage.Title = gui.c.Tr.CommitMessage
gui.Views.CommitMessage.FgColor = theme.GocuiDefaultTextColor
gui.Views.CommitMessage.Editable = true
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
gui.Views.Confirmation.Visible = false
gui.Views.Credentials.Visible = false
gui.Views.Credentials.Title = gui.c.Tr.CredentialsUsername
gui.Views.Credentials.FgColor = theme.GocuiDefaultTextColor
gui.Views.Credentials.Editable = true
gui.Views.Suggestions.Visible = false
gui.Views.Menu.Visible = false
gui.Views.Information.BgColor = gocui.ColorDefault
gui.Views.Information.FgColor = gocui.ColorGreen
gui.Views.Information.Frame = false
gui.Views.Extras.Title = gui.c.Tr.CommandLog
gui.Views.Extras.FgColor = theme.GocuiDefaultTextColor
gui.Views.Extras.Autoscroll = true
gui.Views.Extras.Wrap = true
gui.printCommandLogHeader()
if _, err := gui.g.SetCurrentView(gui.defaultSideContext().GetViewName()); err != nil {
return err
}
return nil
}
// layout is called for every screen re-render e.g. when the screen is resized
func (gui *Gui) layout(g *gocui.Gui) error {
if !gui.ViewsSetup {
if err := gui.createAllViews(); err != nil {
gui.printCommandLogHeader()
if _, err := gui.g.SetCurrentView(gui.defaultSideContext().GetViewName()); err != nil {
return err
}
}

View File

@ -19,6 +19,7 @@ func (gui *Gui) menuListContext() types.IListContext {
Key: "menu",
Kind: types.PERSISTENT_POPUP,
OnGetOptionsMap: gui.getMenuOptions,
Focusable: true,
}),
GetItemsLength: func() int { return gui.Views.Menu.LinesHeight() },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Menu },
@ -55,6 +56,7 @@ func (gui *Gui) branchesListContext() types.IListContext {
WindowName: "branches",
Key: context.LOCAL_BRANCHES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.Branches) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Branches },
@ -80,6 +82,7 @@ func (gui *Gui) remotesListContext() types.IListContext {
WindowName: "branches",
Key: context.REMOTES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.Remotes) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Remotes },
@ -105,6 +108,7 @@ func (gui *Gui) remoteBranchesListContext() types.IListContext {
WindowName: "branches",
Key: context.REMOTE_BRANCHES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.RemoteBranches) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.RemoteBranches },
@ -155,6 +159,7 @@ func (gui *Gui) branchCommitsListContext() types.IListContext {
WindowName: "commits",
Key: context.BRANCH_COMMITS_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.Commits) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Commits },
@ -201,6 +206,7 @@ func (gui *Gui) subCommitsListContext() types.IListContext {
WindowName: "branches",
Key: context.SUB_COMMITS_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.SubCommits) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.SubCommits },
@ -265,6 +271,7 @@ func (gui *Gui) reflogCommitsListContext() types.IListContext {
WindowName: "commits",
Key: context.REFLOG_COMMITS_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.FilteredReflogCommits) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.ReflogCommits },
@ -296,6 +303,7 @@ func (gui *Gui) stashListContext() types.IListContext {
WindowName: "stash",
Key: context.STASH_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.StashEntries) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Stash },
@ -345,6 +353,7 @@ func (gui *Gui) submodulesListContext() types.IListContext {
WindowName: "files",
Key: context.SUBMODULES_CONTEXT_KEY,
Kind: types.SIDE_CONTEXT,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Model.Submodules) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Submodules },
@ -370,6 +379,7 @@ func (gui *Gui) suggestionsListContext() types.IListContext {
WindowName: "suggestions",
Key: context.SUGGESTIONS_CONTEXT_KEY,
Kind: types.PERSISTENT_POPUP,
Focusable: true,
}),
GetItemsLength: func() int { return len(gui.State.Suggestions) },
OnGetPanelState: func() types.IListPanelState { return gui.State.Panels.Suggestions },

View File

@ -4,6 +4,7 @@ import (
"os/exec"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
type viewUpdateOpts struct {
@ -16,6 +17,8 @@ type viewUpdateOpts struct {
highlight bool
task updateTask
context types.Context
}
type refreshMainOpts struct {
@ -100,6 +103,11 @@ func (gui *Gui) refreshMainView(opts *viewUpdateOpts, view *gocui.View) error {
view.Title = opts.title
view.Wrap = !opts.noWrap
view.Highlight = opts.highlight
context := opts.context
if context == nil {
context = gui.State.Contexts.Normal
}
gui.ViewContextMapSet(view.Name(), context)
if err := gui.runTaskForView(view, opts.task); err != nil {
gui.c.Log.Error(err)

View File

@ -153,9 +153,10 @@ func (gui *Gui) renderConflicts(hasFocus bool) error {
return gui.refreshMainViews(refreshMainOpts{
main: &viewUpdateOpts{
title: gui.c.Tr.MergeConflictsTitle,
task: NewRenderStringWithoutScrollTask(content),
noWrap: true,
title: gui.c.Tr.MergeConflictsTitle,
task: NewRenderStringWithoutScrollTask(content),
context: gui.State.Contexts.Merging,
noWrap: true,
},
})
}

View File

@ -136,6 +136,7 @@ func (gui *Gui) secondaryPatchPanelUpdateOpts() *viewUpdateOpts {
title: "Custom Patch",
noWrap: true,
highlight: true,
context: gui.State.Contexts.PatchBuilding,
task: NewRenderStringWithoutScrollTask(patch),
}
}

View File

@ -31,6 +31,7 @@ type IBaseContext interface {
GetWindowName() string
SetWindowName(string)
GetKey() ContextKey
IsFocusable() bool
GetOptionsMap() map[string]string

View File

@ -1441,7 +1441,7 @@ func (g *Gui) matchView(v *View, kb *keybinding) bool {
return true
}
for _, context := range kb.contexts {
if context == g.currentContext {
if context == v.Context {
return true
}
}

View File

@ -149,6 +149,8 @@ type View struct {
// ParentView is the view which catches events bubbled up from the given view if there's no matching handler
ParentView *View
Context string // this is for assigning keybindings to a view only in certain contexts
searcher *searcher
// KeybindOnEdit should be set to true when you want to execute keybindings even when the view is editable