summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/gui/branches_panel.go173
-rw-r--r--pkg/gui/commit_message_panel.go4
-rw-r--r--pkg/gui/commits_panel.go102
-rw-r--r--pkg/gui/files_panel.go145
-rw-r--r--pkg/gui/gui.go21
-rw-r--r--pkg/gui/keybindings.go24
-rw-r--r--pkg/gui/menu_panel.go31
-rw-r--r--pkg/gui/stash_panel.go67
-rw-r--r--pkg/gui/view_helpers.go88
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":
return nil
// return gui.handleStagingSelect(g, v)
@@ -165,61 +163,6 @@ func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
return gui.newLineFocused(g, newView)
}
-func (gui *Gui) getItemPosition(v *gocui.View) int {
- gui.correctCursor(v)
- _, cy := v.Cursor()
- _, oy := v.Origin()
- return oy + cy
-}
-
-func (gui *Gui) cursorUp(g *gocui.Gui, v *gocui.View) error {
- // swallowing cursor movements in main
- if v == nil || v.Name() == "main" {
- return nil
- }
-
- ox, oy := v.Origin()
- cx, cy := v.Cursor()
- if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 {
- if err := v.SetOrigin(ox, oy-1); err != nil {
- return err
- }
- }
-
- gui.newLineFocused(g, v)
- return nil
-}
-
-func (gui *Gui) cursorDown(g *gocui.Gui, v *gocui.View) error {
- // swallowing cursor movements in main
- if v == nil || v.Name() == "main" {
- return nil
- }
- cx, cy := v.Cursor()
- ox, oy := v.Origin()
- ly := v.LinesHeight() - 1
- _, height := v.Size()
- maxY := height - 1
-
- // if we are at the end we just return
- if cy+oy == ly {
- return nil
- }
-
- var err error
- if cy < maxY {
- err = v.SetCursor(cx, cy+1)
- } else {
- err = v.SetOrigin(ox, oy+1)
- }
- if err != nil {
- return err
- }
-
- gui.newLineFocused(g, v)
- return nil
-}
-
func (gui *Gui) resetOrigin(v *gocui.View) error {
if err := v.SetCursor(0, 0); err != nil {
return err
@@ -228,12 +171,6 @@ func (gui *Gui) resetOrigin(v *gocui.View) error {
}
// if the cursor down past the last item, move it to the last line
-func (gui *Gui) correctCursor(v *gocui.View) error {
- cx, cy := v.Cursor()
- retur