mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-04 10:34:55 +02:00
WIP
This commit is contained in:
parent
9ee7793782
commit
99707a527d
@ -23,6 +23,7 @@ type Context interface {
|
||||
GetKind() int
|
||||
GetViewName() string
|
||||
GetKey() string
|
||||
GetSelectedItemId() string
|
||||
}
|
||||
|
||||
type BasicContext struct {
|
||||
@ -34,6 +35,11 @@ type BasicContext struct {
|
||||
ViewName string
|
||||
}
|
||||
|
||||
// TODO: think about whether we need this on the Context interface or if it should just be on the ListContext struct
|
||||
func (c BasicContext) GetSelectedItemId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c BasicContext) HandleRender() error {
|
||||
if c.OnRender != nil {
|
||||
return c.OnRender()
|
||||
|
@ -222,7 +222,7 @@ type guiState struct {
|
||||
Remotes []*commands.Remote
|
||||
RemoteBranches []*commands.RemoteBranch
|
||||
Tags []*commands.Tag
|
||||
MenuItemCount int // can't store the actual list because it's of interface{} type
|
||||
MenuItems []*menuItem
|
||||
Updating bool
|
||||
Panels *panelStates
|
||||
MainContext string // used to keep the main and secondary views' contexts in sync
|
||||
|
@ -1383,6 +1383,24 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.scrollDownConfirmationPanel,
|
||||
},
|
||||
{
|
||||
ViewName: "menu",
|
||||
Key: gui.getKey("universal.select"),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.wrappedHandler(gui.onMenuPress),
|
||||
},
|
||||
{
|
||||
ViewName: "menu",
|
||||
Key: gui.getKey("universal.confirm"),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.wrappedHandler(gui.onMenuPress),
|
||||
},
|
||||
{
|
||||
ViewName: "menu",
|
||||
Key: gui.getKey("universal.confirm-alt1"),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.wrappedHandler(gui.onMenuPress),
|
||||
},
|
||||
}
|
||||
|
||||
for _, viewName := range []string{"status", "branches", "files", "commits", "commitFiles", "stash", "menu"} {
|
||||
|
@ -283,36 +283,33 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
||||
}
|
||||
|
||||
type listContextState struct {
|
||||
selectedLine int
|
||||
lineCount int
|
||||
view *gocui.View
|
||||
contextKey string
|
||||
listContext *ListContext
|
||||
view *gocui.View
|
||||
listContext *ListContext
|
||||
}
|
||||
|
||||
listContextStates := []listContextState{
|
||||
{view: filesView, contextKey: "files", selectedLine: gui.State.Panels.Files.SelectedLine, lineCount: len(gui.State.Files), listContext: gui.filesListContext()},
|
||||
{view: branchesView, contextKey: "local-branches", selectedLine: gui.State.Panels.Branches.SelectedLine, lineCount: len(gui.State.Branches), listContext: gui.branchesListContext()},
|
||||
{view: branchesView, contextKey: "remotes", selectedLine: gui.State.Panels.Remotes.SelectedLine, lineCount: len(gui.State.Remotes), listContext: gui.remotesListContext()},
|
||||
{view: branchesView, contextKey: "remote-branches", selectedLine: gui.State.Panels.RemoteBranches.SelectedLine, lineCount: len(gui.State.Remotes), listContext: gui.remoteBranchesListContext()},
|
||||
{view: branchesView, contextKey: "tags", selectedLine: gui.State.Panels.Tags.SelectedLine, lineCount: len(gui.State.Tags), listContext: gui.tagsListContext()},
|
||||
{view: commitsView, contextKey: "branch-commits", selectedLine: gui.State.Panels.Commits.SelectedLine, lineCount: len(gui.State.Commits), listContext: gui.branchCommitsListContext()},
|
||||
{view: commitsView, contextKey: "reflog-commits", selectedLine: gui.State.Panels.ReflogCommits.SelectedLine, lineCount: len(gui.State.FilteredReflogCommits), listContext: gui.reflogCommitsListContext()},
|
||||
{view: stashView, contextKey: "stash", selectedLine: gui.State.Panels.Stash.SelectedLine, lineCount: len(gui.State.StashEntries), listContext: gui.stashListContext()},
|
||||
{view: commitFilesView, contextKey: "commitFiles", selectedLine: gui.State.Panels.CommitFiles.SelectedLine, lineCount: len(gui.State.CommitFiles), listContext: gui.commitFilesListContext()},
|
||||
{view: filesView, listContext: gui.filesListContext()},
|
||||
{view: branchesView, listContext: gui.branchesListContext()},
|
||||
{view: branchesView, listContext: gui.remotesListContext()},
|
||||
{view: branchesView, listContext: gui.remoteBranchesListContext()},
|
||||
{view: branchesView, listContext: gui.tagsListContext()},
|
||||
{view: commitsView, listContext: gui.branchCommitsListContext()},
|
||||
{view: commitsView, listContext: gui.reflogCommitsListContext()},
|
||||
{view: stashView, listContext: gui.stashListContext()},
|
||||
{view: commitFilesView, listContext: gui.commitFilesListContext()},
|
||||
}
|
||||
|
||||
// menu view might not exist so we check to be safe
|
||||
if menuView, err := gui.g.View("menu"); err == nil {
|
||||
listContextStates = append(listContextStates, listContextState{view: menuView, contextKey: "menu", selectedLine: gui.State.Panels.Menu.SelectedLine, lineCount: gui.State.MenuItemCount, listContext: gui.menuListContext()})
|
||||
listContextStates = append(listContextStates, listContextState{view: menuView, listContext: gui.menuListContext()})
|
||||
}
|
||||
for _, listContextState := range listContextStates {
|
||||
// ignore contexts whose view is owned by another context right now
|
||||
if listContextState.view.Context != listContextState.contextKey {
|
||||
if listContextState.view.Context != listContextState.listContext.GetKey() {
|
||||
continue
|
||||
}
|
||||
// check if the selected line is now out of view and if so refocus it
|
||||
listContextState.view.FocusPoint(0, listContextState.selectedLine)
|
||||
listContextState.view.FocusPoint(0, *listContextState.listContext.GetSelectedLineIdxPtr())
|
||||
|
||||
listContextState.view.SelBgColor = theme.GocuiSelectedLineBgColor
|
||||
|
||||
|
@ -14,12 +14,46 @@ type ListContext struct {
|
||||
OnFocus func() error
|
||||
OnFocusLost func() error
|
||||
OnClickSelectedItem func() error
|
||||
GetItems func() []ListItem
|
||||
|
||||
Gui *Gui
|
||||
RendersToMainView bool
|
||||
Kind int
|
||||
}
|
||||
|
||||
type ListItem interface {
|
||||
ID() string
|
||||
}
|
||||
|
||||
func (lc *ListContext) GetSelectedItem() ListItem {
|
||||
items := lc.GetItems()
|
||||
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
selectedLineIdx := *lc.GetSelectedLineIdxPtr()
|
||||
|
||||
if selectedLineIdx > len(items)-1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
item := items[selectedLineIdx]
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func (lc *ListContext) GetSelectedItemId() string {
|
||||
|
||||
item := lc.GetSelectedItem()
|
||||
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
// 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)
|
||||
@ -64,6 +98,10 @@ func (lc *ListContext) HandleFocus() error {
|
||||
return lc.Gui.renderDiff()
|
||||
}
|
||||
|
||||
// every time you select an item we need to store that item's ID on the context (a string). After a state refresh, after we update the selected line, we need to check if the selected item is new, in which case we will reset the origin. In the case of the merge panel we set the origin in a custom way, so it can't be as simple as just resetting the origin. for files we need to know whether we're dealing with a file with merge conflicts, and if so, we need to scroll to the file in a custom way, after rendering to the main view.
|
||||
|
||||
// we can use this id to know what to do once we're actually in the merging context, so that we're not affected by outside state changes.
|
||||
|
||||
if lc.OnFocus != nil {
|
||||
return lc.OnFocus()
|
||||
}
|
||||
@ -186,6 +224,7 @@ func (gui *Gui) menuListContext() *ListContext {
|
||||
Gui: gui,
|
||||
RendersToMainView: false,
|
||||
Kind: PERSISTENT_POPUP,
|
||||
// GetItems:
|
||||
|
||||
// no GetDisplayStrings field because we do a custom render on menu creation
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||
@ -14,6 +15,15 @@ type menuItem struct {
|
||||
onPress func() error
|
||||
}
|
||||
|
||||
// every item in a list context needs an ID
|
||||
func (i *menuItem) ID() string {
|
||||
if i.displayString != "" {
|
||||
return i.displayString
|
||||
}
|
||||
|
||||
return strings.Join(i.displayStrings, "-")
|
||||
}
|
||||
|
||||
// list panel functions
|
||||
|
||||
func (gui *Gui) handleMenuSelect() error {
|
||||
@ -31,16 +41,7 @@ func (gui *Gui) renderMenuOptions() error {
|
||||
return gui.renderOptionsMap(optionsMap)
|
||||
}
|
||||
|
||||
func (gui *Gui) menuConfirmationKeys() []interface{} {
|
||||
return []interface{}{gui.getKey("universal.select"), gui.getKey("universal.confirm"), gui.getKey("universal.confirm-alt1")}
|
||||
}
|
||||
|
||||
func (gui *Gui) handleMenuClose(g *gocui.Gui, v *gocui.View) error {
|
||||
for _, key := range gui.menuConfirmationKeys() {
|
||||
if err := g.DeleteKeybinding("menu", key, gocui.ModNone); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err := g.DeleteView("menu")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -63,7 +64,7 @@ func (gui *Gui) createMenu(title string, items []*menuItem, createMenuOptions cr
|
||||
})
|
||||
}
|
||||
|
||||
gui.State.MenuItemCount = len(items)
|
||||
gui.State.MenuItems = items
|
||||
|
||||
stringArrays := make([][]string, len(items))
|
||||
for i, item := range items {
|
||||
@ -88,27 +89,17 @@ func (gui *Gui) createMenu(title string, items []*menuItem, createMenuOptions cr
|
||||
fmt.Fprint(menuView, list)
|
||||
gui.State.Panels.Menu.SelectedLine = 0
|
||||
|
||||
wrappedHandlePress := func(g *gocui.Gui, v *gocui.View) error {
|
||||
selectedLine := gui.State.Panels.Menu.SelectedLine
|
||||
if err := items[selectedLine].onPress(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gui.returnFromContext()
|
||||
}
|
||||
|
||||
gui.State.Panels.Menu.OnPress = wrappedHandlePress
|
||||
|
||||
for _, key := range gui.menuConfirmationKeys() {
|
||||
_ = gui.g.DeleteKeybinding("menu", key, gocui.ModNone)
|
||||
|
||||
if err := gui.g.SetKeybinding("menu", nil, key, gocui.ModNone, wrappedHandlePress); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
gui.g.Update(func(g *gocui.Gui) error {
|
||||
return gui.switchContext(gui.Contexts.Menu.Context)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) onMenuPress() error {
|
||||
selectedLine := gui.State.Panels.Menu.SelectedLine
|
||||
if err := gui.State.MenuItems[selectedLine].onPress(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gui.returnFromContext()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user