From 198cbee498e9201b1f12514f909eb3da98db5ec7 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 16 Feb 2019 12:07:27 +1100 Subject: [PATCH] introduce panel contexts and more work on rebasing --- pkg/gui/branches_panel.go | 4 + pkg/gui/files_panel.go | 23 ++- pkg/gui/gui.go | 83 ++++++--- pkg/gui/keybindings.go | 315 ++++++++++++++++++++------------- pkg/gui/menu_panel.go | 13 +- pkg/gui/merge_panel.go | 47 +++-- pkg/gui/options_menu_panel.go | 2 +- pkg/gui/staging_panel.go | 17 +- pkg/gui/view_helpers.go | 45 +---- pkg/i18n/english.go | 3 + scripts/generate_cheatsheet.go | 6 +- 11 files changed, 326 insertions(+), 232 deletions(-) diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 6fc6d192c..54f7de305 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -112,6 +112,10 @@ func (gui *Gui) handleRebase(g *gocui.Gui, v *gocui.View) error { } if err := gui.GitCommand.RebaseBranch(selectedBranch); err != nil { + if !strings.Contains(err.Error(), "When you have resolved this problem") { + return gui.createErrorPanel(gui.g, err.Error()) + } + if err := gui.refreshSidePanels(g); err != nil { return err } diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index a27fb7dc3..57217249a 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -40,11 +40,12 @@ func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View, alreadySelected bo } if file.HasMergeConflicts { - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } else { - if _, err := gui.g.SetViewOnBottom("merging"); err != nil { - return err - } + // TODO: set title appropriately + // if _, err := gui.g.SetViewOnBottom("merging"); err != nil { + // return err + // } } content := gui.GitCommand.Diff(file, false) @@ -143,8 +144,10 @@ func (gui *Gui) handleEnterFile(g *gocui.Gui, v *gocui.View) error { if !file.HasUnstagedChanges { return gui.createErrorPanel(g, gui.Tr.SLocalize("FileStagingRequirements")) } - stagingView := gui.getStagingView() - if err := gui.switchFocus(g, v, stagingView); err != nil { + if err := gui.changeContext("main", "staging"); err != nil { + return err + } + if err := gui.switchFocus(g, v, gui.getMainView()); err != nil { return err } return gui.refreshStagingPanel() @@ -434,7 +437,13 @@ func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error { if !file.HasMergeConflicts { return gui.createErrorPanel(g, gui.Tr.SLocalize("FileNoMergeCons")) } - return gui.switchFocus(g, v, gui.getMergingView()) + if err := gui.changeContext("main", "merging"); err != nil { + return err + } + if err := gui.switchFocus(g, v, gui.getMainView()); err != nil { + return err + } + return gui.refreshMergePanel() } func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index eef5e5ab5..04653200d 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -134,6 +134,7 @@ type guiState struct { Updating bool Panels *panelStates WorkingTreeState string // one of "merging", "rebasing", "normal" + Contexts map[string]string } // NewGui builds a new gui handler @@ -210,6 +211,40 @@ func max(a, b int) int { return b } +// getFocusLayout returns a manager function for when view gain and lose focus +func (gui *Gui) getFocusLayout() func(g *gocui.Gui) error { + var focusedView *gocui.View + return func(g *gocui.Gui) error { + v := gui.g.CurrentView() + if v != focusedView { + if err := gui.onFocusLost(focusedView); err != nil { + return err + } + if err := gui.onFocus(v); err != nil { + return err + } + focusedView = v + } + return nil + } +} + +func (gui *Gui) onFocusLost(v *gocui.View) error { + if v == nil { + return nil + } + gui.Log.Info(v.Name() + " focus lost") + return nil +} + +func (gui *Gui) onFocus(v *gocui.View) error { + if v == nil { + return nil + } + gui.Log.Info(v.Name() + " focus gained") + 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 { g.Highlight = true @@ -268,30 +303,30 @@ func (gui *Gui) layout(g *gocui.Gui) error { v.FgColor = gocui.ColorWhite } - v, err = g.SetView("staging", leftSideWidth+panelSpacing, 0, width-1, optionsTop, gocui.LEFT) - if err != nil { - if err != gocui.ErrUnknownView { - return err - } - v.Title = gui.Tr.SLocalize("StagingTitle") - v.Highlight = true - v.FgColor = gocui.ColorWhite - if _, err := g.SetViewOnBottom("staging"); err != nil { - return err - } - } + // v, err = g.SetView("staging", leftSideWidth+panelSpacing, 0, width-1, optionsTop, gocui.LEFT) + // if err != nil { + // if err.Error() != "unknown view" { + // return err + // } + // v.Title = gui.Tr.SLocalize("StagingTitle") + // v.Highlight = true + // v.FgColor = gocui.ColorWhite + // if _, err := g.SetViewOnBottom("staging"); err != nil { + // return err + // } + // } - v, err = g.SetView("merging", leftSideWidth+panelSpacing, 0, width-1, optionsTop, gocui.LEFT) - if err != nil { - if err != gocui.ErrUnknownView { - return err - } - v.Title = gui.Tr.SLocalize("MergingTitle") - v.FgColor = gocui.ColorWhite - if _, err := g.SetViewOnBottom("merging"); err != nil { - return err - } - } + // v, err = g.SetView("merging", leftSideWidth+panelSpacing, 0, width-1, optionsTop, gocui.LEFT) + // if err != nil { + // if err.Error() != "unknown view" { + // return err + // } + // v.Title = gui.Tr.SLocalize("MergingTitle") + // v.FgColor = gocui.ColorWhite + // if _, err := g.SetViewOnBottom("merging"); err != nil { + // return err + // } + // } if v, err := g.SetView("status", 0, 0, leftSideWidth, statusFilesBoundary, gocui.BOTTOM|gocui.RIGHT); err != nil { if err.Error() != "unknown view" { @@ -539,7 +574,7 @@ func (gui *Gui) Run() error { gui.goEvery(time.Second*10, gui.refreshFiles) gui.goEvery(time.Millisecond*50, gui.renderAppStatus) - g.SetManagerFunc(gui.layout) + g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout())) if err = gui.keybindings(g); err != nil { return err diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 8ddd3aaa4..5fe53ec8a 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -44,8 +44,8 @@ func (b *Binding) GetKey() string { return string(key) } -// GetKeybindings is a function. -func (gui *Gui) GetKeybindings() []*Binding { +// GetInitialKeybindings is a function. +func (gui *Gui) GetInitialKeybindings() []*Binding { bindings := []*Binding{ { ViewName: "", @@ -226,69 +226,6 @@ func (gui *Gui) GetKeybindings() []*Binding { Modifier: gocui.ModNone, Handler: gui.handleGitFetch, Description: gui.Tr.SLocalize("fetch"), - }, { - ViewName: "merging", - Key: gocui.KeyEsc, - Modifier: gocui.ModNone, - Handler: gui.handleEscapeMerge, - }, { - ViewName: "merging", - Key: gocui.KeySpace, - Modifier: gocui.ModNone, - Handler: gui.handlePickHunk, - Description: gui.Tr.SLocalize("PickHunk"), - }, { - ViewName: "merging", - Key: 'b', - Modifier: gocui.ModNone, - Handler: gui.handlePickBothHunks, - Description: gui.Tr.SLocalize("PickBothHunks"), - }, { - ViewName: "merging", - Key: gocui.KeyArrowLeft, - Modifier: gocui.ModNone, - Handler: gui.handleSelectPrevConflict, - }, { - ViewName: "merging", - Key: gocui.KeyArrowRight, - Modifier: gocui.ModNone, - Handler: gui.handleSelectNextConflict, - }, { - ViewName: "merging", - Key: gocui.KeyArrowUp, - Modifier: gocui.ModNone, - Handler: gui.handleSelectTop, - }, { - ViewName: "merging", - Key: gocui.KeyArrowDown, - Modifier: gocui.ModNone, - Handler: gui.handleSelectBottom, - }, { - ViewName: "merging", - Key: 'h', - Modifier: gocui.ModNone, - Handler: gui.handleSelectPrevConflict, - }, { - ViewName: "merging", - Key: 'l', - Modifier: gocui.ModNone, - Handler: gui.handleSelectNextConflict, - }, { - ViewName: "merging", - Key: 'k', - Modifier: gocui.ModNone, - Handler: gui.handleSelectTop, - }, { - ViewName: "merging", - Key: 'j', - Modifier: gocui.ModNone, - Handler: gui.handleSelectBottom, - }, { - ViewName: "merging", - Key: 'z', - Modifier: gocui.ModNone, - Handler: gui.handlePopFileSnapshot, - Description: gui.Tr.SLocalize("Undo"), }, { ViewName: "branches", Key: gocui.KeySpace, @@ -421,64 +358,6 @@ func (gui *Gui) GetKeybindings() []*Binding { Key: 'q', Modifier: gocui.ModNone, Handler: gui.handleMenuClose, - }, { - ViewName: "staging", - Key: gocui.KeyEsc, - Modifier: gocui.ModNone, - Handler: gui.handleStagingEscape, - Description: gui.Tr.SLocalize("EscapeStaging"), - }, { - ViewName: "staging", - Key: gocui.KeyArrowUp, - Modifier: gocui.ModNone, - Handler: gui.handleStagingPrevLine, - }, { - ViewName: "staging", - Key: gocui.KeyArrowDown, - Modifier: gocui.ModNone, - Handler: gui.handleStagingNextLine, - }, { - ViewName: "staging", - Key: 'k', - Modifier: gocui.ModNone, - Handler: gui.handleStagingPrevLine, - }, { - ViewName: "staging", - Key: 'j', - Modifier: gocui.ModNone, - Handler: gui.handleStagingNextLine, - }, { - ViewName: "staging", - Key: gocui.KeyArrowLeft, - Modifier: gocui.ModNone, - Handler: gui.handleStagingPrevHunk, - }, { - ViewName: "staging", - Key: gocui.KeyArrowRight, - Modifier: gocui.ModNone, - Handler: gui.handleStagingNextHunk, - }, { - ViewName: "staging", - Key: 'h', - Modifier: gocui.ModNone, - Handler: gui.handleStagingPrevHunk, - }, { - ViewName: "staging", - Key: 'l', - Modifier: gocui.ModNone, - Handler: gui.handleStagingNextHunk, - }, { - ViewName: "staging", - Key: gocui.KeySpace, - Modifier: gocui.ModNone, - Handler: gui.handleStageLine, - Description: gui.Tr.SLocalize("StageLine"), - }, { - ViewName: "staging", - Key: 'a', - Modifier: gocui.ModNone, - Handler: gui.handleStageHunk, - Description: gui.Tr.SLocalize("StageHunk"), }, } @@ -515,13 +394,201 @@ func (gui *Gui) GetKeybindings() []*Binding { return bindings } +func (gui *Gui) GetCurrentKeybindings() []*Binding { + bindings := gui.GetInitialKeybindings() + viewName := gui.currentViewName(gui.g) + currentContext := gui.State.Contexts[viewName] + contextBindings := gui.getContextMap()[viewName][currentContext] + + return append(bindings, contextBindings...) +} + func (gui *Gui) keybindings(g *gocui.Gui) error { - bindings := gui.GetKeybindings() + bindings := gui.GetInitialKeybindings() for _, binding := range bindings { if err := g.SetKeybinding(binding.ViewName, binding.Key, binding.Modifier, binding.Handler); err != nil { return err } } + if err := gui.setInitialContexts(); err != nil { + return err + } return nil } + +func (gui *Gui) setInitialContexts() error { + contextMap := gui.getContextMap() + + initialContexts := map[string]string{ + "main": "merging", + } + + for viewName, context := range initialContexts { + bindings := contextMap[viewName][context] + for _, binding := range bindings { + if err := gui.g.SetKeybinding(binding.ViewName, binding.Key, binding.Modifier, binding.Handler); err != nil { + return err + } + } + } + + gui.State.Contexts = initialContexts + + return nil +} + +func (gui *Gui) changeContext(viewName, context string) error { + // todo: store somewhere permanently + if gui.State.Contexts[viewName] == context { + return nil + } + + contextMap := gui.getContextMap() + + gui.g.DeleteKeybindings(viewName) + + bindings := contextMap[viewName][context] + for _, binding := range bindings { + if err := gui.g.SetKeybinding(viewName, binding.Key, binding.Modifier, binding.Handler); err != nil { + return err + } + } + gui.State.Contexts[viewName] = context + + return nil +} + +func (gui *Gui) getContextMap() map[string]map[string][]*Binding { + return map[string]map[string][]*Binding{ + "main": { + "staging": { + { + ViewName: "main", + Key: gocui.KeyEsc, + Modifier: gocui.ModNone, + Handler: gui.handleStagingEscape, + Description: gui.Tr.SLocalize("EscapeStaging"), + }, { + ViewName: "main", + Key: gocui.KeyArrowUp, + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevLine, + }, { + ViewName: "main", + Key: gocui.KeyArrowDown, + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextLine, + }, { + ViewName: "main", + Key: 'k', + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevLine, + }, { + ViewName: "main", + Key: 'j', + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextLine, + }, { + ViewName: "main", + Key: gocui.KeyArrowLeft, + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevHunk, + }, { + ViewName: "main", + Key: gocui.KeyArrowRight, + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextHunk, + }, { + ViewName: "main", + Key: 'h', + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevHunk, + }, { + ViewName: "main", + Key: 'l', + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextHunk, + }, { + ViewName: "main", + Key: gocui.KeySpace, + Modifier: gocui.ModNone, + Handler: gui.handleStageLine, + Description: gui.Tr.SLocalize("StageLine"), + }, { + ViewName: "main", + Key: 'a', + Modifier: gocui.ModNone, + Handler: gui.handleStageHunk, + Description: gui.Tr.SLocalize("StageHunk"), + }, + }, + "merging": { + { + ViewName: "main", + Key: gocui.KeyEsc, + Modifier: gocui.ModNone, + Handler: gui.handleEscapeMerge, + }, { + ViewName: "main", + Key: gocui.KeySpace, + Modifier: gocui.ModNone, + Handler: gui.handlePickHunk, + Description: gui.Tr.SLocalize("PickHunk"), + }, { + ViewName: "main", + Key: 'b', + Modifier: gocui.ModNone, + Handler: gui.handlePickBothHunks, + Description: gui.Tr.SLocalize("PickBothHunks"), + }, { + ViewName: "main", + Key: gocui.KeyArrowLeft, + Modifier: gocui.ModNone, + Handler: gui.handleSelectPrevConflict, + }, { + ViewName: "main", + Key: gocui.KeyArrowRight, + Modifier: gocui.ModNone, + Handler: gui.handleSelectNextConflict, + }, { + ViewName: "main", + Key: gocui.KeyArrowUp, + Modifier: gocui.ModNone, + Handler: gui.handleSelectTop, + }, { + ViewName: "main", + Key: gocui.KeyArrowDown, + Modifier: gocui.ModNone, + Handler: gui.handleSelectBottom, + }, { + ViewName: "main", + Key: 'h', + Modifier: gocui.ModNone, + Handler: gui.handleSelectPrevConflict, + }, { + ViewName: "main", + Key: 'l', + Modifier: gocui.ModNone, + Handler: gui.handleSelectNextConflict, + }, { + ViewName: "main", + Key: 'k', + Modifier: gocui.ModNone, + Handler: gui.handleSelectTop, + }, { + ViewName: "main", + Key: 'j', + Modifier: gocui.ModNone, + Handler: gui.handleSelectBottom, + }, { + ViewName: "main", + Key: 'z', + Modifier: gocui.ModNone, + Handler: gui.handlePopFileSnapshot, + Description: gui.Tr.SLocalize("Undo"), + }, + }, + }, + } +} diff --git a/pkg/gui/menu_panel.go b/pkg/gui/menu_panel.go index 4feb416ec..847069446 100644 --- a/pkg/gui/menu_panel.go +++ b/pkg/gui/menu_panel.go @@ -68,9 +68,12 @@ func (gui *Gui) createMenu(title string, items interface{}, handlePress func(int if err := handlePress(selectedLine); err != nil { return err } - if _, err := gui.g.SetViewOnBottom("menu"); err != nil { - return err + if _, err := gui.g.View("menu"); err == nil { + if _, err := gui.g.SetViewOnBottom("menu"); err != nil { + return err + } } + return gui.returnFocus(gui.g, menuView) } @@ -79,8 +82,10 @@ func (gui *Gui) createMenu(title string, items interface{}, handlePress func(int } gui.g.Update(func(g *gocui.Gui) error { - if _, err := g.SetViewOnTop("menu"); err != nil { - return err + if _, err := gui.g.View("menu"); err == nil { + if _, err := g.SetViewOnTop("menu"); err != nil { + return err + } } currentView := gui.g.CurrentView() return gui.switchFocus(gui.g, currentView, menuView) diff --git a/pkg/gui/merge_panel.go b/pkg/gui/merge_panel.go index 07ba55894..59922e087 100644 --- a/pkg/gui/merge_panel.go +++ b/pkg/gui/merge_panel.go @@ -68,12 +68,12 @@ func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflic func (gui *Gui) handleSelectTop(g *gocui.Gui, v *gocui.View) error { gui.State.Panels.Merging.ConflictTop = true - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } func (gui *Gui) handleSelectBottom(g *gocui.Gui, v *gocui.View) error { gui.State.Panels.Merging.ConflictTop = false - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error { @@ -81,7 +81,7 @@ func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error { return nil } gui.State.Panels.Merging.ConflictIndex++ - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error { @@ -89,7 +89,7 @@ func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error { return nil } gui.State.Panels.Merging.ConflictIndex-- - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } func (gui *Gui) isIndexToDelete(i int, conflict commands.Conflict, pick string) bool { @@ -150,7 +150,7 @@ func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error { return err } ioutil.WriteFile(gitFile.Name, []byte(prevContent), 0644) - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error { @@ -171,7 +171,7 @@ func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error { return err } } - gui.refreshMergePanel(g) + gui.refreshMergePanel() return nil } @@ -182,12 +182,12 @@ func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error { if err != nil { panic(err) } - return gui.refreshMergePanel(g) + return gui.refreshMergePanel() } -func (gui *Gui) refreshMergePanel(g *gocui.Gui) error { +func (gui *Gui) refreshMergePanel() error { panelState := gui.State.Panels.Merging - cat, err := gui.catSelectedFile(g) + cat, err := gui.catSelectedFile(gui.g) if err != nil { return err } @@ -207,18 +207,21 @@ func (gui *Gui) refreshMergePanel(g *gocui.Gui) error { panelState.ConflictIndex = len(panelState.Conflicts) - 1 } - gui.g.SetViewOnTop("merging") - hasFocus := gui.currentViewName(g) == "merging" + hasFocus := gui.currentViewName(gui.g) == "main" content, err := gui.coloredConflictFile(cat, panelState.Conflicts, panelState.ConflictIndex, panelState.ConflictTop, hasFocus) if err != nil { return err } - if err := gui.renderString(g, "merging", content); err != nil { + if err := gui.renderString(gui.g, "main", content); err != nil { return err } - if err := gui.scrollToConflict(g); err != nil { + if err := gui.scrollToConflict(gui.g); err != nil { return err } + + mainView := gui.getMainView() + mainView.Wrap = false + return nil } @@ -227,7 +230,7 @@ func (gui *Gui) scrollToConflict(g *gocui.Gui) error { if len(panelState.Conflicts) == 0 { return nil } - mergingView := gui.getMergingView() + mergingView := gui.getMainView() conflict := panelState.Conflicts[panelState.ConflictIndex] gui.Log.Info(utils.AsJson(conflict)) ox, _ := mergingView.Origin() @@ -242,14 +245,6 @@ func (gui *Gui) scrollToConflict(g *gocui.Gui) error { return nil } -func (gui *Gui) switchToMerging(g *gocui.Gui) error { - _, err := g.SetCurrentView("merging") - if err != nil { - return err - } - return gui.refreshMergePanel(g) -} - func (gui *Gui) renderMergeOptions() error { return gui.renderOptionsMap(map[string]string{ "↑ ↓": gui.Tr.SLocalize("selectHunk"), @@ -262,11 +257,10 @@ func (gui *Gui) renderMergeOptions() error { func (gui *Gui) handleEscapeMerge(g *gocui.Gui, v *gocui.View) error { gui.State.Panels.Merging.EditHistory = stack.New() - gui.g.SetViewOnBottom("merging") gui.refreshFiles() // it's possible this method won't be called from the merging view so we need to // ensure we only 'return' focus if we already have it - if gui.g.CurrentView() == gui.getMergingView() { + if gui.g.CurrentView() == gui.getMainView() { return gui.switchFocus(g, v, gui.getFilesView()) } return nil @@ -279,7 +273,7 @@ func (gui *Gui) handleCompleteMerge() error { // if there are no more files with merge conflicts, we should ask whether the user wants to continue if !gui.anyFilesWithMergeConflicts() { // ask if user wants to continue - if err := gui.createConfirmationPanel(gui.g, filesView, "continue", "all merge conflicts, resolved. Continue?", func(g *gocui.Gui, v *gocui.View) error { + if err := gui.createConfirmationPanel(gui.g, filesView, "continue", gui.Tr.SLocalize("ConflictsResolved"), func(g *gocui.Gui, v *gocui.View) error { if err := gui.genericRebaseCommand("continue"); err != nil { if err == gui.Errors.ErrSubProcess { return err @@ -292,6 +286,7 @@ func (gui *Gui) handleCompleteMerge() error { gui.createErrorPanel(gui.g, err.Error()) } } else { + // HERE is the place for this special error panel gui.createErrorPanel(gui.g, err.Error()) } } @@ -300,5 +295,5 @@ func (gui *Gui) handleCompleteMerge() error { return err } } - return gui.handleEscapeMerge(gui.g, gui.getMergingView()) + return gui.handleEscapeMerge(gui.g, gui.getMainView()) } diff --git a/pkg/gui/options_menu_panel.go b/pkg/gui/options_menu_panel.go index 71c3c9665..d217fb8f2 100644 --- a/pkg/gui/options_menu_panel.go +++ b/pkg/gui/options_menu_panel.go @@ -13,7 +13,7 @@ func (gui *Gui) getBindings(v *gocui.View) []*Binding { bindingsGlobal, bindingsPanel []*Binding ) - bindings := gui.GetKeybindings() + bindings := gui.GetCurrentKeybindings() for _, binding := range bindings { if binding.GetKey() != "" && binding.Description != "" { diff --git a/pkg/gui/staging_panel.go b/pkg/gui/staging_panel.go index 099dd5da8..5d52cf081 100644 --- a/pkg/gui/staging_panel.go +++ b/pkg/gui/staging_panel.go @@ -66,14 +66,19 @@ func (gui *Gui) refreshStagingPanel() error { if err := gui.focusLineAndHunk(); err != nil { return err } - return gui.renderString(gui.g, "staging", colorDiff) + + mainView := gui.getMainView() + mainView.Highlight = true + mainView.Wrap = false + + gui.g.Update(func(*gocui.Gui) error { + return gui.setViewContent(gui.g, gui.getMainView(), colorDiff) + }) + + return nil } func (gui *Gui) handleStagingEscape(g *gocui.Gui, v *gocui.View) error { - if _, err := gui.g.SetViewOnBottom("staging"); err != nil { - return err - } - gui.State.Panels.Staging = nil return gui.switchFocus(gui.g, nil, gui.getFilesView()) @@ -138,7 +143,7 @@ func (gui *Gui) handleCycleLine(prev bool) error { // focusLineAndHunk works out the best focus for the staging panel given the // selected line and size of the hunk func (gui *Gui) focusLineAndHunk() error { - stagingView := gui.getStagingView() + stagingView := gui.getMainView() state := gui.State.Panels.Staging lineNumber := state.StageableLines[state.SelectedLine] diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 7d343c9a4..b7b23f16a 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -104,15 +104,11 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error { case "credentials": return gui.handleCredentialsViewFocused(g, v) case "main": - // TODO: pull this out into a 'view focused' function - gui.refreshMergePanel(g) + if gui.State.Contexts["main"] == "merging" { + return gui.refreshMergePanel() + } v.Highlight = false return nil - case "merging": - return nil - case "staging": - return nil - // return gui.handleStagingSelect(g, v) default: panic(gui.Tr.SLocalize("NoViewMachingNewLineFocusedSwitchStatement")) } @@ -130,20 +126,6 @@ func (gui *Gui) returnFocus(g *gocui.Gui, v *gocui.View) error { return gui.switchFocus(g, v, previousView) } -// in lieu of a proper window system, we've got three panels that overlap, -// the main panel, the staging panel, and the merging panel. We will call this -// function whenever we might need to hide one of these panels -// this function introduces some unwanted technical debt but is necessary for this rebasing feature -func (gui *Gui) showCorrectMainPanel() error { - // if the files view is not focused or the current file is not in a merging state we hide the merging panel - if gui.g.CurrentView().Name() != "merging" && gui.g.CurrentView().Name() != "confirmation" { - if _, err := gui.g.SetViewOnBottom("merging"); err != nil { - return err - } - } - return nil -} - // pass in oldView = nil if you don't want to be able to return to your old view func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error { // we assume we'll never want to return focus to a confirmation panel i.e. @@ -187,10 +169,6 @@ func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error { return err } - if err := gui.showCorrectMainPanel(); err != nil { - return err - } - return gui.newLineFocused(g, newView) } @@ -303,11 +281,6 @@ func (gui *Gui) getBranchesView() *gocui.View { return v } -func (gui *Gui) getStagingView() *gocui.View { - v, _ := gui.g.View("staging") - return v -} - func (gui *Gui) getMainView() *gocui.View { v, _ := gui.g.View("main") return v @@ -318,11 +291,6 @@ func (gui *Gui) getStashView() *gocui.View { return v } -func (gui *Gui) getMergingView() *gocui.View { - v, _ := gui.g.View("merging") - return v -} - func (gui *Gui) trimmedContent(v *gocui.View) string { return strings.TrimSpace(v.Buffer()) } @@ -413,8 +381,9 @@ func (gui *Gui) renderPanelOptions() error { case "menu": return gui.renderMenuOptions() case "main": - return gui.renderMergeOptions() - default: - return gui.renderGlobalOptions() + if gui.State.Contexts["main"] == "merging" { + return gui.renderMergeOptions() + } } + return gui.renderGlobalOptions() } diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 7ee1c147d..331feee38 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -498,6 +498,9 @@ func addEnglish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "RebaseOptionsTitle", Other: "Rebase Options", + }, &i18n.Message{ + ID: "ConflictsResolved", + Other: "all merge conflicts resolved. Continue?", }, ) } diff --git a/scripts/generate_cheatsheet.go b/scripts/generate_cheatsheet.go index f427c29fa..d42088d6b 100644 --- a/scripts/generate_cheatsheet.go +++ b/scripts/generate_cheatsheet.go @@ -10,11 +10,12 @@ package main import ( "fmt" - "github.com/jesseduffield/lazygit/pkg/app" - "github.com/jesseduffield/lazygit/pkg/config" "log" "os" "strings" + + "github.com/jesseduffield/lazygit/pkg/app" + "github.com/jesseduffield/lazygit/pkg/config" ) func writeString(file *os.File, str string) { @@ -43,6 +44,7 @@ func main() { writeString(file, "
\n")
 
+	// TODO: add context-based keybindings
 	for _, binding := range mApp.Gui.GetKeybindings() {
 		if binding.Description == "" {
 			continue