diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2018-12-06 22:18:17 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2018-12-08 11:51:47 +1100 |
commit | ca3afa2a3905365ec79624e0c9b08865e9ab27ae (patch) | |
tree | 47add13ed3819ddc9ed89c16c12cb9aab22ad1cd /pkg | |
parent | 99a8b1ae8bb93565df8acbe168749278dc768979 (diff) |
standardising how list panels deal with cursor movement
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/gui/branches_panel.go | 173 | ||||
-rw-r--r-- | pkg/gui/commit_message_panel.go | 4 | ||||
-rw-r--r-- | pkg/gui/commits_panel.go | 102 | ||||
-rw-r--r-- | pkg/gui/files_panel.go | 145 | ||||
-rw-r--r-- | pkg/gui/gui.go | 21 | ||||
-rw-r--r-- | pkg/gui/keybindings.go | 24 | ||||
-rw-r--r-- | pkg/gui/menu_panel.go | 31 | ||||
-rw-r--r-- | pkg/gui/stash_panel.go | 67 | ||||
-rw-r--r-- | pkg/gui/view_helpers.go | 88 |
9 files changed, 333 insertions, 322 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index e1504bd69..809deaa7d 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -10,22 +10,103 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedBranch() *commands.Branch { + selectedLine := gui.State.Panels.Branches.SelectedLine + if selectedLine == -1 { + return nil + } + + return gui.State.Branches[selectedLine] +} + +// may want to standardise how these select methods work +func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error { + // This really shouldn't happen: there should always be a master branch + if len(gui.State.Branches) == 0 { + return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo")) + } + branch := gui.getSelectedBranch() + if err := gui.focusPoint(0, gui.State.Panels.Branches.SelectedLine, v); err != nil { + return err + } + go func() { + graph, err := gui.GitCommand.GetBranchGraph(branch.Name) + if err != nil && strings.HasPrefix(graph, "fatal: ambiguous argument") { + graph = gui.Tr.SLocalize("NoTrackingThisBranch") + } + _ = gui.renderString(g, "main", graph) + }() + return nil +} + +// gui.refreshStatus is called at the end of this because that's when we can +// be sure there is a state.Branches array to pick the current branch from +func (gui *Gui) refreshBranches(g *gocui.Gui) error { + g.Update(func(g *gocui.Gui) error { + v, err := g.View("branches") + if err != nil { + panic(err) + } + builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand) + if err != nil { + return err + } + gui.State.Branches = builder.Build() + + gui.refreshSelectedLine(&gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches)) + + v.Clear() + list, err := utils.RenderList(gui.State.Branches) + if err != nil { + return err + } + + fmt.Fprint(v, list) + + gui.resetOrigin(v) + return gui.refreshStatus(g) + }) + return nil +} + +func (gui *Gui) handleBranchesNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Branches + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), false) + + return gui.handleBranchSelect(gui.g, v) +} + +func (gui *Gui) handleBranchesPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Branches + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), true) + + return gui.handleBranchSelect(gui.g, v) +} + +// specific functions + func (gui *Gui) handleBranchPress(g *gocui.Gui, v *gocui.View) error { - index := gui.getItemPosition(gui.getBranchesView(g)) - if index == 0 { + if gui.State.Panels.Branches.SelectedLine == -1 { + return nil + } + if gui.State.Panels.Branches.SelectedLine == 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("AlreadyCheckedOutBranch")) } - branch := gui.getSelectedBranch(gui.getBranchesView(g)) + branch := gui.getSelectedBranch() if err := gui.GitCommand.Checkout(branch.Name, false); err != nil { - gui.createErrorPanel(g, err.Error()) + if err := gui.createErrorPanel(g, err.Error()); err != nil { + return err + } } return gui.refreshSidePanels(g) } func (gui *Gui) handleCreatePullRequestPress(g *gocui.Gui, v *gocui.View) error { - branch := gui.getSelectedBranch(gui.getBranchesView(g)) pullRequest := commands.NewPullRequest(gui.GitCommand) + branch := gui.getSelectedBranch() if err := pullRequest.Create(branch); err != nil { return gui.createErrorPanel(g, err.Error()) } @@ -34,7 +115,7 @@ func (gui *Gui) handleCreatePullRequestPress(g *gocui.Gui, v *gocui.View) error } func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error { - branch := gui.getSelectedBranch(v) + branch := gui.getSelectedBranch() message := gui.Tr.SLocalize("SureForceCheckout") title := gui.Tr.SLocalize("ForceCheckoutBranch") return gui.createConfirmationPanel(g, v, title, message, func(g *gocui.Gui, v *gocui.View) error { @@ -82,8 +163,11 @@ func (gui *Gui) handleForceDeleteBranch(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) deleteBranch(g *gocui.Gui, v *gocui.View, force bool) error { + selectedBranch := gui.getSelectedBranch() + if selectedBranch == nil { + return nil + } checkedOutBranch := gui.State.Branches[0] - selectedBranch := gui.getSelectedBranch(v) if checkedOutBranch.Name == selectedBranch.Name { return gui.createErrorPanel(g, gui.Tr.SLocalize("CantDeleteCheckOutBranch")) } @@ -119,7 +203,7 @@ func (gui *Gui) deleteNamedBranch(g *gocui.Gui, v *gocui.View, selectedBranch *c func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error { checkedOutBranch := gui.State.Branches[0] - selectedBranch := gui.getSelectedBranch(v) + selectedBranch := gui.getSelectedBranch() defer gui.refreshSidePanels(g) if checkedOutBranch.Name == selectedBranch.Name { return gui.createErrorPanel(g, gui.Tr.SLocalize("CantMergeBranchIntoItself")) @@ -129,76 +213,3 @@ func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error { } return nil } - -func (gui *Gui) getSelectedBranch(v *gocui.View) *commands.Branch { - selectedLine := gui.State.Panels.Branches.SelectedLine - if selectedLine == -1 { - return nil - } - - return gui.State.Branches[selectedLine] -} - -// may want to standardise how these select methods work -func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error { - // This really shouldn't happen: there should always be a master branch - if len(gui.State.Branches) == 0 { - return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo")) - } - branch := gui.getSelectedBranch(v) - if err := gui.focusPoint(0, gui.State.Panels.Branches.SelectedLine, v); err != nil { - return err - } - go func() { - graph, err := gui.GitCommand.GetBranchGraph(branch.Name) - if err != nil && strings.HasPrefix(graph, "fatal: ambiguous argument") { - graph = gui.Tr.SLocalize("NoTrackingThisBranch") - } - _ = gui.renderString(g, "main", graph) - }() - return nil -} - -// gui.refreshStatus is called at the end of this because that's when we can -// be sure there is a state.Branches array to pick the current branch from -func (gui *Gui) refreshBranches(g *gocui.Gui) error { - g.Update(func(g *gocui.Gui) error { - v, err := g.View("branches") - if err != nil { - panic(err) - } - builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand) - if err != nil { - return err - } - gui.State.Branches = builder.Build() - - gui.refreshSelectedLine(&gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches)) - - v.Clear() - list, err := utils.RenderList(gui.State.Branches) - if err != nil { - return err - } - - fmt.Fprint(v, list) - - gui.resetOrigin(v) - return gui.refreshStatus(g) - }) - return nil -} - -func (gui *Gui) handleBranchesNextLine(g *gocui.Gui, v *gocui.View) error { - panelState := gui.State.Panels.Branches - gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), false) - - return gui.handleBranchSelect(gui.g, v) -} - -func (gui *Gui) handleBranchesPrevLine(g *gocui.Gui, v *gocui.View) error { - panelState := gui.State.Panels.Branches - gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), true) - - return gui.handleBranchSelect(gui.g, v) -} diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go index 809442481..60058d48c 100644 --- a/pkg/gui/commit_message_panel.go +++ b/pkg/gui/commit_message_panel.go @@ -23,12 +23,12 @@ func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { gui.SubProcess = sub return gui.Errors.ErrSubProcess } - gui.refreshFiles(g) v.Clear() v.SetCursor(0, 0) + v.SetOrigin(0, 0) g.SetViewOnBottom("commitMessage") gui.switchFocus(g, v, gui.getFilesView(g)) - return gui.refreshCommits(g) + return gui.refreshSidePanels(g) } func (gui *Gui) handleCommitClose(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index be291091c..2591fa240 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -9,31 +9,54 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedCommit(g *gocui.Gui) *commands.Commit { + selectedLine := gui.State.Panels.Commits.SelectedLine + if selectedLine == -1 { + return nil + } + + return gui.State.Commits[selectedLine] +} + +func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { + commit := gui.getSelectedCommit(g) + if commit == nil { + return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) + } + + if err := gui.focusPoint(0, gui.State.Panels.Commits.SelectedLine, v); err != nil { + return err + } + commitText, err := gui.GitCommand.Show(commit.Sha) + if err != nil { + return err + } + return gui.renderString(g, "main", commitText) +} + func (gui *Gui) refreshCommits(g *gocui.Gui) error { g.Update(func(*gocui.Gui) error { commits, err := gui.GitCommand.GetCommits() if err != nil { return err } - gui.State.Commits = commits - v, err := g.View("commits") - if err != nil { - return err - } gui.refreshSelectedLine(&gui.State.Panels.Commits.SelectedLine, len(gui.State.Commits)) - v.Clear() - list, err := utils.RenderList(gui.State.Commits) if err != nil { return err } + + v := gui.getCommitsView(gui.g) + v.Clear() fmt.Fprint(v, list) gui.refreshStatus(g) - if g.CurrentView().Name() == "commits" { + if v == g.CurrentView() { gui.handleCommitSelect(g, v) } return nil @@ -41,6 +64,22 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error { return nil } +func (gui *Gui) handleCommitsNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Commits + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), false) + + return gui.handleCommitSelect(gui.g, v) +} + +func (gui *Gui) handleCommitsPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Commits + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), true) + + return gui.handleCommitSelect(gui.g, v) +} + +// specific functions + func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error { return gui.createConfirmationPanel(g, commitView, gui.Tr.SLocalize("ResetToCommit"), gui.Tr.SLocalize("SureResetThisCommit"), func(g *gocui.Gui, v *gocui.View) error { commit := gui.getSelectedCommit(g) @@ -61,24 +100,8 @@ func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error }, nil) } -func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { - commit := gui.getSelectedCommit(g) - if commit == nil { - return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) - } - - if err := gui.focusPoint(0, gui.State.Panels.Commits.SelectedLine, v); err != nil { - return err - } - commitText, err := gui.GitCommand.Show(commit.Sha) - if err != nil { - return err - } - return gui.renderString(g, "main", commitText) -} - func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error { - if gui.getItemPosition(v) != 0 { + if gui.State.Panels.Commits.SelectedLine != 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlySquashTopmostCommit")) } if len(gui.State.Commits) <= 1 { @@ -134,7 +157,7 @@ func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error { - if gui.getItemPosition(gui.getCommitsView(g)) != 0 { + if gui.State.Panels.Commits.SelectedLine != 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlyRenameTopCommit")) } return gui.createPromptPanel(g, v, gui.Tr.SLocalize("renameCommit"), func(g *gocui.Gui, v *gocui.View) error { @@ -149,7 +172,7 @@ func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error { - if gui.getItemPosition(gui.getCommitsView(g)) != 0 { + if gui.State.Panels.Commits.SelectedLine != 0 { return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlyRenameTopCommit")) } @@ -160,28 +183,3 @@ func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error { return nil } - -func (gui *Gui) getSelectedCommit(g *gocui.Gui) *commands.Commit { - selectedLine := gui.State.Panels.Commits.SelectedLine - if selectedLine == -1 { - return nil - } - - return gui.State.Commits[selectedLine] -} - -func (gui *Gui) handleCommitsNextLine(g *gocui.Gui, v *gocui.View) error { - gui.Log.Info(utils.AsJson(gui.State.Panels)) - panelState := gui.State.Panels.Commits - gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), false) - - return gui.handleCommitSelect(gui.g, v) -} - -func (gui *Gui) handleCommitsPrevLine(g *gocui.Gui, v *gocui.View) error { - gui.Log.Info(utils.AsJson(gui.State.Panels)) - panelState := gui.State.Panels.Commits - gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), true) - - return gui.handleCommitSelect(gui.g, v) -} diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 13ce48d10..231e5d488 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -15,6 +15,79 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { + selectedLine := gui.State.Panels.Files.SelectedLine + if selectedLine == -1 { + return &commands.File{}, gui.Errors.ErrNoFiles + } + + return gui.State.Files[selectedLine], nil +} + +func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error { + file, err := gui.getSelectedFile(g) + if err != nil { + if err != gui.Errors.ErrNoFiles { + return err + } + return gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedFiles")) + } + + if file.HasMergeConflicts { + return gui.refreshMergePanel(g) + } + + if err := gui.focusPoint(0, gui.State.Panels.Files.SelectedLine, v); err != nil { + return err + } + + content := gui.GitCommand.Diff(file, false) + return gui.renderString(g, "main", content) +} + +func (gui *Gui) refreshFiles(g *gocui.Gui) error { + filesView, err := g.View("files") + if err != nil { + return err + } + gui.refreshStateFiles() + + gui.g.Update(func(g *gocui.Gui) error { + + filesView.Clear() + list, err := utils.RenderList(gui.State.Files) + if err != nil { + return err + } + fmt.Fprint(filesView, list) + + if filesView == g.CurrentView() { + gui.handleFileSelect(g, filesView) + } + return nil + }) + + return nil +} + +func (gui *Gui) handleFilesNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Files + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), false) + + return gui.handleFileSelect(gui.g, v) +} + +func (gui *Gui) handleFilesPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Files + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), true) + + return gui.handleFileSelect(gui.g, v) +} + +// specific functions + func (gui *Gui) stagedFiles() []*commands.File { files := gui.State.Files result := make([]*commands.File, 0) @@ -139,15 +212,6 @@ func (gui *Gui) handleAddPatch(g *gocui.Gui, v *gocui.View) error { return gui.Errors.ErrSubProcess } -func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { - selectedLine := gui.State.Panels.Files.SelectedLine - if selectedLine == -1 { - return &commands.File{}, gui.Errors.ErrNoFiles - } - - return gui.State.Files[selectedLine], nil -} - func (gui *Gui) handleFileRemove(g *gocui.Gui, v *gocui.View) error { file, err := gui.getSelectedFile(g) if err != nil { @@ -191,27 +255,6 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { return gui.refreshFiles(g) } -func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) - if err != nil { - if err != gui.Errors.ErrNoFiles { - return err - } - return gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedFiles")) - } - - if file.HasMergeConflicts { - return gui.refreshMergePanel(g) - } - - if err := gui.focusPoint(0, gui.State.Panels.Files.SelectedLine, v); err != nil { - return err - } - - content := gui.GitCommand.Diff(file, false) - return gui.renderString(g, "main", content) -} - func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { if len(gui.stagedFiles()) == 0 && !gui.State.HasMergeConflicts { return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit")) @@ -335,45 +378,6 @@ func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) { return cat, nil } -func (gui *Gui) handleFilesNextLine(g *gocui.Gui, v *gocui.View) error { - panelState := gui.State.Panels.Files - gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), false) - - return gui.handleFileSelect(gui.g, v) -} - -func (gui *Gui) handleFilesPrevLine(g *gocui.Gui, v *gocui.View) error { - panelState := gui.State.Panels.Files - gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), true) - - return gui.handleFileSelect(gui.g, v) -} - -func (gui *Gui) refreshFiles(g *gocui.Gui) error { - filesView, err := g.View("files") - if err != nil { - return err - } - gui.refreshStateFiles() - - gui.g.Update(func(g *gocui.Gui) error { - - filesView.Clear() - list, err := utils.RenderList(gui.State.Files) - if err != nil { - return err - } - fmt.Fprint(filesView, list) - - if filesView == g.CurrentView() { - gui.handleFileSelect(g, filesView) - } - return nil - }) - - return nil -} - func (gui *Gui) pullFiles(g *gocui.Gui, v *gocui.View) error { gui.createMessagePanel(g, v, "", gui.Tr.SLocalize("PullWait")) go func() { @@ -399,8 +403,7 @@ func (gui *Gui) pushWithForceFlag(currentView *gocui.View, force bool) error { _ = gui.createErrorPanel(gui.g, err.Error()) } else { _ = gui.closeConfirmationPrompt(gui.g) - _ = gui.refreshCommits(gui.g) - _ = gui.refreshStatus(gui.g) + _ = gui.refreshSidePanels(gui.g) } }() return nil diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 1af3a5e1f..6a7eaaf98 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -95,12 +95,17 @@ type stashPanelState struct { SelectedLine int } +type menuPanelState struct { + SelectedLine int +} + type panelStates struct { Files *filePanelState Staging *stagingPanelState Branches *branchPanelState Commits *commitPanelState Stash *stashPanelState + Menu *menuPanelState } type guiState struct { @@ -137,6 +142,7 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma Branches: &branchPanelState{SelectedLine: 0}, Commits: &commitPanelState{SelectedLine: -1}, Stash: &stashPanelState{SelectedLine: -1}, + Menu: &menuPanelState{SelectedLine: 0}, }, } @@ -359,12 +365,12 @@ func (gui *Gui) layout(g *gocui.Gui) error { } gui.g.SetCurrentView(filesView.Name()) - gui.refreshFiles(g) - gui.refreshBranches(g) - gui.refreshCommits(g) - gui.refreshStashEntries(g) - if err := gui.renderGlobalOptions(g); err != nil { - return err + + gui.refreshSidePanels(gui.g) + if gui.g.CurrentView().Name() != "menu" { + if err := gui.renderGlobalOptions(g); err != nil { + return err + } } if err := gui.switchFocus(g, nil, filesView); err != nil { return err @@ -388,6 +394,9 @@ func (gui *Gui) layout(g *gocui.Gui) error { } } + // TODO: comment-out + gui.Log.Info(utils.AsJson(gui.State)) + return gui.resizeCurrentPopupPanel(g) } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index c8c3d642f..c02074d6f 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -386,7 +386,12 @@ func (gui *Gui) GetKeybindings() []*Binding { Modifier: gocui.ModNone, Handler: gui.handleStashDrop, Description: gui.Tr.SLocalize("drop"), - }, { + }, + {ViewName: "stash", Key: 'k', Modifier: gocui.ModNone, Handler: gui.handleStashPrevLine}, + {ViewName: "stash", Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: gui.handleStashPrevLine}, + {ViewName: "stash", Key: 'j', Modifier: gocui.ModNone, Handler: gui.handleStashNextLine}, + {ViewName: "stash", Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: gui.handleStashNextLine}, + { ViewName: "commitMessage", Key: gocui.KeyEnter, Modifier: gocui.ModNone, @@ -406,7 +411,11 @@ func (gui *Gui) GetKeybindings() []*Binding { Key: 'q', Modifier: gocui.ModNone, Handler: gui.handleMenuClose, - }, { + }, + {ViewName: "menu", Key: 'k', Modifier: gocui.ModNone, Handler: gui.handleMenuPrevLine}, + {ViewName: "menu", Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: gui.handleMenuPrevLine}, + {ViewName: "menu", Key: 'j', Modifier: gocui.ModNone, Handler: gui.handleMenuNextLine}, + {ViewName: "menu", Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: gui.handleMenuNextLine}, { ViewName: "staging", Key: gocui.KeyEsc, Modifier: gocui.ModNone, @@ -468,17 +477,6 @@ func (gui *Gui) GetKeybindings() []*Binding { }, } - // Would make these keybindings global but that interferes with editing - // input in the confirmation panel - for _, viewName := range []string{"status", "commits", "stash", "menu"} { - bindings = append(bindings, []*Binding{ - {ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: gui.cursorUp}, - {ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: gui.cursorDown}, - {ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: gui.cursorUp}, - {ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: gui.cursorDown}, - }...) - } - for _, viewName := range []string{"status", "branches", "files", "commits", "stash", "menu"} { bindings = append(bindings, []*Binding{ {ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: gui.nextView}, diff --git a/pkg/gui/menu_panel.go b/pkg/gui/menu_panel.go index 753e8f84d..0d3d8cf2b 100644 --- a/pkg/gui/menu_panel.go +++ b/pkg/gui/menu_panel.go @@ -8,12 +8,32 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + func (gui *Gui) handleMenuSelect(g *gocui.Gui, v *gocui.View) error { - // doing nothing for now - // but it is needed for switch in newLineFocused - return nil + return gui.focusPoint(0, gui.State.Panels.Menu.SelectedLine, v) +} + +func (gui *Gui) handleMenuNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Menu + gui.changeSelectedLine(&panelState.SelectedLine, v.LinesHeight(), false) + + return gui.handleMenuSelect(g, v) +} + +func (gui *Gui) handleMenuPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Menu + gui.changeSelectedLine(&panelState.SelectedLine, v.LinesHeight(), true) + + if err := gui.focusPoint(0, gui.State.Panels.Commits.SelectedLine, v); err != nil { + return err + } + + return gui.handleMenuSelect(g, v) } +// specific functions + func (gui *Gui) renderMenuOptions(g *gocui.Gui) error { optionsMap := map[string]string{ "esc/q": gui.Tr.SLocalize("close"), @@ -46,14 +66,15 @@ func (gui *Gui) createMenu(items interface{}, handlePress func(int) error) error menuView.FgColor = gocui.ColorWhite menuView.Clear() fmt.Fprint(menuView, list) + gui.State.Panels.Menu.SelectedLine = 0 if err := gui.renderMenuOptions(gui.g); err != nil { return err } wrappedHandlePress := func(g *gocui.Gui, v *gocui.View) error { - lineNumber := gui.getItemPosition(v) - return handlePress(lineNumber) + selectedLine := gui.State.Panels.Menu.SelectedLine + return handlePress(selectedLine) } if err := gui.g.SetKeybinding("menu", gocui.KeySpace, gocui.ModNone, wrappedHandlePress); err != nil { diff --git a/pkg/gui/stash_panel.go b/pkg/gui/stash_panel.go index 196a33a08..ef54ef997 100644 --- a/pkg/gui/stash_panel.go +++ b/pkg/gui/stash_panel.go @@ -8,19 +8,46 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" ) +// list panel functions + +func (gui *Gui) getSelectedStashEntry(v *gocui.View) *commands.StashEntry { + selectedLine := gui.State.Panels.Stash.SelectedLine + if selectedLine == -1 { + return nil + } + + return gui.State.StashEntries[selectedLine] +} + +func (gui *Gui) handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error { + stashEntry := gui.getSelectedStashEntry(v) + if stashEntry == nil { + return gui.renderString(g, "main", gui.Tr.SLocalize("NoStashEntries")) + } + if err := gui.focusPoint(0, gui.State.Panels.Stash.SelectedLine, v); err != nil { + return err + } + go func() { + // doing this asynchronously cos it can take time + diff, _ := gui.GitCommand.GetStashEntryDiff(stashEntry.Index) + gui.renderString(g, "main", diff) + }() + return nil +} + func (gui *Gui) refreshStashEntries(g *gocui.Gui) error { g.Update(func(g *gocui.Gui) error { - v, err := g.View("stash") - if err != nil { - panic(err) - } gui.State.StashEntries = gui.GitCommand.GetStashEntries() - v.Clear() + gui.refreshSelectedLine(&gui.State.Panels.Stash.SelectedLine, len(gui.State.StashEntries)) + list, err := utils.RenderList(gui.State.StashEntries) if err != nil { return err } + + v := gui.getStashView(gui.g) + v.Clear() fmt.Fprint(v, list) return gui.resetOrigin(v) @@ -28,28 +55,22 @@ func (gui *Gui) refreshStashEntries(g *gocui.Gui) error { return nil } -func (gui *Gui) getSelectedStashEntry(v *gocui.View) *commands.StashEntry { - if len(gui.State.StashEntries) == 0 { - return nil - } - stashView, _ := gui.g.View("stash") - lineNumber := gui.getItemPosition(stashView) - return gui.State.StashEntries[lineNumber] +func (gui *Gui) handleStashNextLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Stash + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.StashEntries), false) + + return gui.handleStashEntrySelect(gui.g, v) } -func (gui *Gui) handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error { - go func() { - stashEntry := gui.getSelectedStashEntry(v) - if stashEntry == nil { - gui.renderString(g, "main", gui.Tr.SLocalize("NoStashEntries")) - return - } - diff, _ := gui.GitCommand.GetStashEntryDiff(stashEntry.Index) - gui.renderString(g, "main", diff) - }() - return nil +func (gui *Gui) handleStashPrevLine(g *gocui.Gui, v *gocui.View) error { + panelState := gui.State.Panels.Stash + gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.StashEntries), true) + + return gui.handleStashEntrySelect(gui.g, v) } +// specific functions + func (gui *Gui) handleStashApply(g *gocui.Gui, v *gocui.View) error { return gui.stashDo(g, v, "apply") } diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 4c5002efe..5b02b1ae9 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -16,6 +16,7 @@ func (gui *Gui) refreshSidePanels(g *gocui.Gui) error { gui.refreshBranches(g) gui.refreshFiles(g) gui.refreshCommits(g) + gui.refreshStashEntries(g) return nil } @@ -78,18 +79,19 @@ func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error { - mainView, _ := g.View("main") - mainView.SetOrigin(0, 0) - switch v.Name() { case "menu": - return gui.handleMenuSelect(g, v) + return nil case "status": return gui.handleStatusSelect(g, v) case "files": return gui.handleFileSelect(g, v) case "branches": return gui.handleBranchSelect(g, v) + case "commits": + return gui.handleCommitSelect(g, v) + case "stash": + return gui.handleStashEntrySelect(g, v) case "confirmation": return nil case "commitMessage": @@ -99,10 +101,6 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error { gui.refreshMergePanel(g) v.Highlight = false return nil - case "commits": - return gui.handleCommitSelect(g, v) - case "stash": - return gui.handleStashEntrySelect(g, v) case "staging": |