summaryrefslogtreecommitdiffstats
path: root/pkg/gui
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2018-12-08 16:54:54 +1100
committerJesse Duffield <jessedduffield@gmail.com>2018-12-11 22:02:12 +1100
commit9489a9447396b30bca86ea3df201cacfdffdb1a9 (patch)
treeae251c28096f2bde6b1647603852782c58329d4c /pkg/gui
parente0ff46fe53503d74fc63c90fc5ddc4d9468b60d5 (diff)
Make merge panel its own panel
Diffstat (limited to 'pkg/gui')
-rw-r--r--pkg/gui/branches_panel.go32
-rw-r--r--pkg/gui/commit_message_panel.go6
-rw-r--r--pkg/gui/commits_panel.go10
-rw-r--r--pkg/gui/confirmation_panel.go2
-rw-r--r--pkg/gui/files_panel.go90
-rw-r--r--pkg/gui/gui.go74
-rw-r--r--pkg/gui/keybindings.go58
-rw-r--r--pkg/gui/menu_panel.go13
-rw-r--r--pkg/gui/merge_panel.go137
-rw-r--r--pkg/gui/options_menu_panel.go3
-rw-r--r--pkg/gui/rebase_options_panel.go61
-rw-r--r--pkg/gui/recent_repos_panel.go2
-rw-r--r--pkg/gui/staging_panel.go6
-rw-r--r--pkg/gui/stash_panel.go17
-rw-r--r--pkg/gui/status_panel.go25
-rw-r--r--pkg/gui/view_helpers.go58
16 files changed, 381 insertions, 213 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index 165a75a4a..82a850e9d 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -53,7 +53,7 @@ func (gui *Gui) RenderSelectedBranchUpstreamDifferences() error {
branch := gui.getSelectedBranch()
branch.Pushables, branch.Pullables = gui.GitCommand.GetBranchUpstreamDifferenceCount(branch.Name)
- return gui.renderListPanel(gui.getBranchesView(gui.g), gui.State.Branches)
+ return gui.renderListPanel(gui.getBranchesView(), gui.State.Branches)
}
// gui.refreshStatus is called at the end of this because that's when we can
@@ -67,9 +67,6 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error {
gui.State.Branches = builder.Build()
gui.refreshSelectedLine(&gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches))
- if err := gui.resetOrigin(gui.getBranchesView(gui.g)); err != nil {
- return err
- }
if err := gui.RenderSelectedBranchUpstreamDifferences(); err != nil {
return err
}
@@ -82,6 +79,10 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error {
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)
+
+ if err := gui.resetOrigin(gui.getMainView()); err != nil {
+ return err
+ }
return gui.handleBranchSelect(gui.g, v)
}
@@ -89,6 +90,9 @@ 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)
+ if err := gui.resetOrigin(gui.getMainView()); err != nil {
+ return err
+ }
return gui.handleBranchSelect(gui.g, v)
}
@@ -108,8 +112,7 @@ func (gui *Gui) handleRebase(g *gocui.Gui, v *gocui.View) error {
}
if err := gui.GitCommand.RebaseBranch(selectedBranch); err != nil {
- gui.Log.Errorln(err)
- if err := gui.createConfirmationPanel(g, v, "Rebase failed", "Damn, conflicts! To abort press 'esc', otherwise press 'enter'",
+ return gui.createConfirmationPanel(g, v, "Auto-rebase failed", gui.Tr.SLocalize("FoundConflicts"),
func(g *gocui.Gui, v *gocui.View) error {
return nil
}, func(g *gocui.Gui, v *gocui.View) error {
@@ -117,9 +120,8 @@ func (gui *Gui) handleRebase(g *gocui.Gui, v *gocui.View) error {
return err
}
return gui.refreshSidePanels(g)
- }); err != nil {
- gui.Log.Errorln(err)
- }
+ },
+ )
}
return gui.refreshSidePanels(g)
@@ -251,6 +253,18 @@ func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantMergeBranchIntoItself"))
}
if err := gui.GitCommand.Merge(selectedBranch.Name); err != nil {
+ if strings.Contains(err.Error(), "fix conflicts") {
+ return gui.createConfirmationPanel(g, v, "Auto-merge failed", gui.Tr.SLocalize("FoundConflicts"),
+ func(g *gocui.Gui, v *gocui.View) error {
+ return nil
+ }, func(g *gocui.Gui, v *gocui.View) error {
+ if err := gui.GitCommand.AbortMergeBranch(); err != nil {
+ return err
+ }
+ return gui.refreshSidePanels(g)
+ },
+ )
+ }
return gui.createErrorPanel(g, err.Error())
}
return nil
diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go
index 33eb5b218..130ec3401 100644
--- a/pkg/gui/commit_message_panel.go
+++ b/pkg/gui/commit_message_panel.go
@@ -27,13 +27,13 @@ func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error {
_ = v.SetCursor(0, 0)
_ = v.SetOrigin(0, 0)
_, _ = g.SetViewOnBottom("commitMessage")
- _ = gui.switchFocus(g, v, gui.getFilesView(g))
+ _ = gui.switchFocus(g, v, gui.getFilesView())
return gui.refreshSidePanels(g)
}
func (gui *Gui) handleCommitClose(g *gocui.Gui, v *gocui.View) error {
g.SetViewOnBottom("commitMessage")
- return gui.switchFocus(g, v, gui.getFilesView(g))
+ return gui.switchFocus(g, v, gui.getFilesView())
}
func (gui *Gui) handleCommitFocused(g *gocui.Gui, v *gocui.View) error {
@@ -87,6 +87,6 @@ func (gui *Gui) RenderCommitLength() {
if !gui.Config.GetUserConfig().GetBool("gui.commitLength.show") {
return
}
- v := gui.getCommitMessageView(gui.g)
+ v := gui.getCommitMessageView()
v.Subtitle = gui.getBufferLength(v)
}
diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go
index 4ff79960d..53e979ac4 100644
--- a/pkg/gui/commits_panel.go
+++ b/pkg/gui/commits_panel.go
@@ -51,7 +51,7 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error {
return err
}
- v := gui.getCommitsView(gui.g)
+ v := gui.getCommitsView()
v.Clear()
fmt.Fprint(v, list)
@@ -68,6 +68,9 @@ 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)
+ if err := gui.resetOrigin(gui.getMainView()); err != nil {
+ return err
+ }
return gui.handleCommitSelect(gui.g, v)
}
@@ -75,6 +78,9 @@ 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)
+ if err := gui.resetOrigin(gui.getMainView()); err != nil {
+ return err
+ }
return gui.handleCommitSelect(gui.g, v)
}
@@ -92,7 +98,7 @@ func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error
if err := gui.refreshCommits(g); err != nil {
panic(err)
}
- if err := gui.refreshFiles(g); err != nil {
+ if err := gui.refreshFiles(); err != nil {
panic(err)
}
gui.resetOrigin(commitView)
diff --git a/pkg/gui/confirmation_panel.go b/pkg/gui/confirmation_panel.go
index 30d5e0661..66e859be3 100644
--- a/pkg/gui/confirmation_panel.go
+++ b/pkg/gui/confirmation_panel.go
@@ -78,7 +78,6 @@ func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt
confirmationView.FgColor = gocui.ColorWhite
}
gui.g.Update(func(g *gocui.Gui) error {
- confirmationView.Clear()
return gui.switchFocus(gui.g, currentView, confirmationView)
})
return confirmationView, nil
@@ -86,6 +85,7 @@ func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt
func (gui *Gui) onNewPopupPanel() {
gui.g.SetViewOnBottom("commitMessage")
+ gui.g.SetViewOnBottom("menu")
}
func (gui *Gui) createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 2059ac97f..3c8e6c7e7 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -35,23 +35,24 @@ func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error {
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
}
+ if file.HasMergeConflicts {
+ return gui.refreshMergePanel(g)
+ } else {
+ if _, err := gui.g.SetViewOnBottom("merging"); 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
- }
+func (gui *Gui) refreshFiles() error {
+ filesView := gui.getFilesView()
gui.refreshStateFiles()
gui.g.Update(func(g *gocui.Gui) error {
@@ -63,8 +64,8 @@ func (gui *Gui) refreshFiles(g *gocui.Gui) error {
}
fmt.Fprint(filesView, list)
- if filesView == g.CurrentView() {
- return gui.handleFileSelect(g, filesView)
+ if filesView == gui.g.CurrentView() {
+ return gui.handleFileSelect(gui.g, filesView)
}
return nil
})
@@ -76,6 +77,9 @@ 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)
+ if err := gui.resetOrigin(gui.getMainView()); err != nil {
+ return err
+ }
return gui.handleFileSelect(gui.g, v)
}
@@ -83,6 +87,9 @@ 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)
+ if err := gui.resetOrigin(gui.getMainView()); err != nil {
+ return err
+ }
return gui.handleFileSelect(gui.g, v)
}
@@ -130,13 +137,9 @@ func (gui *Gui) handleEnterFile(g *gocui.Gui, v *gocui.View) error {
return gui.handleSwitchToMerge(g, v)
}
if !file.HasUnstagedChanges {
- gui.Log.WithField("staging", "staging").Info("making error panel")
return gui.createErrorPanel(g, gui.Tr.SLocalize("FileStagingRequirements"))
}
- stagingView, err := g.View("staging")
- if err != nil {
- return err
- }
+ stagingView := gui.getStagingView()
if err := gui.switchFocus(g, v, stagingView); err != nil {
return err
}
@@ -162,7 +165,7 @@ func (gui *Gui) handleFilePress(g *gocui.Gui, v *gocui.View) error {
gui.GitCommand.UnStageFile(file.Name, file.Tracked)
}
- if err := gui.refreshFiles(g); err != nil {
+ if err := gui.refreshFiles(); err != nil {
return err
}
@@ -189,7 +192,7 @@ func (gui *Gui) handleStageAll(g *gocui.Gui, v *gocui.View) error {
_ = gui.createErrorPanel(g, err.Error())
}
- if err := gui.refreshFiles(g); err != nil {
+ if err := gui.refreshFiles(); err != nil {
return err
}
@@ -240,7 +243,7 @@ func (gui *Gui) handleFileRemove(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.RemoveFile(file); err != nil {
return err
}
- return gui.refreshFiles(g)
+ return gui.refreshFiles()
}, nil)
}
@@ -255,14 +258,14 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.Ignore(file.Name); err != nil {
return gui.createErrorPanel(g, err.Error())
}
- return gui.refreshFiles(g)
+ return gui.refreshFiles()
}
func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" {
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
}
- commitMessageView := gui.getCommitMessageView(g)
+ commitMessageView := gui.getCommitMessageView()
g.Update(func(g *gocui.Gui) error {
g.SetViewOnTop("commitMessage")
gui.switchFocus(g, filesView, commitMessageView)
@@ -342,7 +345,7 @@ func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error {
- return gui.refreshFiles(g)
+ return gui.refreshFiles()
}
func (gui *Gui) refreshStateFiles() {
@@ -353,27 +356,6 @@ func (gui *Gui) refreshStateFiles() {
gui.updateWorkTreeState()
}
-func (gui *Gui) updateWorkTreeState() error {
- merging, err := gui.GitCommand.IsInMergeState()
- if err != nil {
- return err
- }
- if merging {
- gui.State.WorkingTreeState = "merging"
- return nil
- }
- rebasing, err := gui.GitCommand.IsInRebaseState()
- if err != nil {
- return err
- }
- if rebasing {
- gui.State.WorkingTreeState = "rebasing"
- return nil
- }
- gui.State.WorkingTreeState = "normal"
- return nil
-}
-
func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) {
item, err := gui.getSelectedFile(g)
if err != nil {
@@ -403,7 +385,7 @@ func (gui *Gui) pullFiles(g *gocui.Gui, v *gocui.View) error {
gui.refreshCommits(g)
gui.refreshStatus(g)
}
- gui.refreshFiles(g)
+ gui.refreshFiles()
}()
return nil
}
@@ -437,10 +419,6 @@ func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error {
- mergeView, err := g.View("main")
- if err != nil {
- return err
- }
file, err := gui.getSelectedFile(g)
if err != nil {
if err != gui.Errors.ErrNoFiles {
@@ -451,8 +429,7 @@ func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error {
if !file.HasMergeConflicts {
return gui.createErrorPanel(g, gui.Tr.SLocalize("FileNoMergeCons"))
}
- gui.switchFocus(g, v, mergeView)
- return gui.refreshMergePanel(g)
+ return gui.switchFocus(g, v, gui.getMergingView())
}
func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error {
@@ -461,7 +438,7 @@ func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error {
}
gui.createMessagePanel(g, v, "", gui.Tr.SLocalize("MergeAborted"))
gui.refreshStatus(g)
- return gui.refreshFiles(g)
+ return gui.refreshFiles()
}
func (gui *Gui) handleResetAndClean(g *gocui.Gui, v *gocui.View) error {
@@ -469,7 +446,7 @@ func (gui *Gui) handleResetAndClean(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.ResetAndClean(); err != nil {
gui.createErrorPanel(g, err.Error())
}
- return gui.refreshFiles(g)
+ return gui.refreshFiles()
}, nil)
}
@@ -479,3 +456,12 @@ func (gui *Gui) openFile(filename string) error {
}
return nil
}
+
+func (gui *Gui) anyFilesWithMergeConflicts() bool {
+ for _, file := range gui.State.Files {
+ if file.HasMergeConflicts {
+ return true
+ }
+ }
+ return false
+}
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index ef41482c9..2b6eccb5d 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -82,6 +82,13 @@ type stagingPanelState struct {
Diff string
}
+type mergingPanelState struct {
+ ConflictIndex int
+ ConflictTop bool
+ Conflicts []commands.Conflict
+ EditHistory *stack.Stack
+}
+
type filePanelState struct {
SelectedLine int
}
@@ -104,11 +111,12 @@ type menuPanelState struct {
type panelStates struct {
Files *filePanelState
- Staging *stagingPanelState
Branches *branchPanelState
Commits *commitPanelState
Stash *stashPanelState
Menu *menuPanelState
+ Staging *stagingPanelState
+ Merging *mergingPanelState
}
type guiState struct {
@@ -118,10 +126,6 @@ type guiState struct {
StashEntries []*commands.StashEntry
PreviousView string
HasMergeConflicts bool
- ConflictIndex int
- ConflictTop bool
- Conflicts []commands.Conflict
- EditHistory *stack.Stack
Platform commands.Platform
Updating bool
Panels *panelStates
@@ -132,21 +136,23 @@ type guiState struct {
func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *commands.OSCommand, tr *i18n.Localizer, config config.AppConfigurer, updater *updates.Updater) (*Gui, error) {
initialState := guiState{
- Files: make([]*commands.File, 0),
- PreviousView: "files",
- Commits: make([]*commands.Commit, 0),
- StashEntries: make([]*commands.StashEntry, 0),
- ConflictIndex: 0,
- ConflictTop: true,
- Conflicts: make([]commands.Conflict, 0),
- EditHistory: stack.New(),
- Platform: *oSCommand.Platform,
+ Files: make([]*commands.File, 0),
+ PreviousView: "files",
+ Commits: make([]*commands.Commit, 0),
+ StashEntries: make([]*commands.StashEntry, 0),
+ Platform: *oSCommand.Platform,
Panels: &panelStates{
Files: &filePanelState{SelectedLine: -1},
Branches: &branchPanelState{SelectedLine: 0},
Commits: &commitPanelState{SelectedLine: -1},
Stash: &stashPanelState{SelectedLine: -1},
Menu: &menuPanelState{SelectedLine: 0},
+ Merging: &mergingPanelState{
+ ConflictIndex: 0,
+ ConflictTop: true,
+ Conflicts: []commands.Conflict{},
+ EditHistory: stack.New(),
+ },
},
}
@@ -271,6 +277,18 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
}
+ 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
+ }
+ }
+
if v, err := g.SetView("status", 0, 0, leftSideWidth, statusFilesBoundary, gocui.BOTTOM|gocui.RIGHT); err != nil {
if err != gocui.ErrUnknownView {
return err
@@ -324,7 +342,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
}
}
- if gui.getCommitMessageView(g) == nil {
+ if gui.getCommitMessageView() == nil {
// doesn't matter where this view starts because it will be hidden
if commitMessageView, err := g.SetView("commitMessage", 0, 0, width/2, height/2, 0); err != nil {
if err != gocui.ErrUnknownView {
@@ -401,7 +419,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
// here is a good place log some stuff
// if you download humanlog and do tail -f development.log | humanlog
// this will let you see these branches as prettified json
- // gui.Log.Info(utils.AsJson(gui.State.Branches[0:4]))
+ // gui.Log.Info(utils.AsJson(gui.State.Files))
return gui.resizeCurrentPopupPanel(g)
}
@@ -414,18 +432,18 @@ func (gui *Gui) promptAnonymousReporting() error {
})
}
-func (gui *Gui) fetch(g *gocui.Gui) error {
+func (gui *Gui) fetch() error {
gui.GitCommand.Fetch()
- gui.refreshStatus(g)
+ gui.refreshStatus(gui.g)
return nil
}
-func (gui *Gui) updateLoader(g *gocui.Gui) error {
- if view, _ := g.View("confirmation"); view != nil {
+func (gui *Gui) updateLoader() error {
+ if view, _ := gui.g.View("confirmation"); view != nil {
content := gui.trimmedContent(view)
if strings.Contains(content, "...") {
staticContent := strings.Split(content, "...")[0] + "..."
- if err := gui.renderString(g, "confirmation", staticContent+" "+utils.Loader()); err != nil {
+ if err := gui.renderString(gui.g, "confirmation", staticContent+" "+utils.Loader()); err != nil {
return err
}
}
@@ -433,7 +451,7 @@ func (gui *Gui) updateLoader(g *gocui.Gui) error {
return nil
}
-func (gui *Gui) renderAppStatus(g *gocui.Gui) error {
+func (gui *Gui) renderAppStatus() error {
appStatus := gui.statusManager.getStatusString()
if appStatus != "" {
return gui.renderString(gui.g, "appStatus", appStatus)
@@ -450,10 +468,10 @@ func (gui *Gui) renderGlobalOptions() error {
})
}
-func (gui *Gui) goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) error) {
+func (gui *Gui) goEvery(interval time.Duration, function func() error) {
go func() {
for range time.Tick(interval) {
- function(g)
+ function()
}
}()
}
@@ -472,10 +490,10 @@ func (gui *Gui) Run() error {
return err
}
- gui.goEvery(g, time.Second*60, gui.fetch)
- gui.goEvery(g, time.Second*2, gui.refreshFiles)
- gui.goEvery(g, time.Millisecond*50, gui.updateLoader)
- gui.goEvery(g, time.Millisecond*50, gui.renderAppStatus)
+ gui.goEvery(time.Second*60, gui.fetch)
+ gui.goEvery(time.Second*2, gui.refreshFiles)
+ gui.goEvery(time.Millisecond*50, gui.updateLoader)
+ gui.goEvery(time.Millisecond*50, gui.renderAppStatus)
g.SetManagerFunc(gui.layout)
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 745e2fa7f..410d4545c 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -153,11 +153,11 @@ func (gui *Gui) GetKeybindings() []*Binding {
Handler: gui.handleFileRemove,
Description: gui.Tr.SLocalize("removeFile"),
}, {
- ViewName: "files",
+ ViewName: "files", // TODO: might make this for more views as well
Key: 'm',
Modifier: gocui.ModNone,
- Handler: gui.handleSwitchToMerge,
- Description: gui.Tr.SLocalize("resolveMergeConflicts"),
+ Handler: gui.handleCreateRebaseOptionsMenu,
+ Description: gui.Tr.SLocalize("ViewMergeRebaseOptions"),
}, {
ViewName: "files",
Key: 'e',
@@ -190,12 +190,6 @@ func (gui *Gui) GetKeybindings() []*Binding {
Description: gui.Tr.SLocalize("stashFiles"),
}, {
ViewName: "files",
- Key: 'M',
- Modifier: gocui.ModNone,
- Handler: gui.handleAbortMerge,
- Description: gui.Tr.SLocalize("abortMerge"),
- }, {
- ViewName: "files",
Key: 'a',
Modifier: gocui.ModNone,
Handler: gui.handleStageAll,
@@ -220,65 +214,69 @@ func (gui *Gui) GetKeybindings() []*Binding {
Description: gui.Tr.SLocalize("StageLines"),
KeyReadable: "enter",
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: gocui.KeyEsc,
Modifier: gocui.ModNone,
Handler: gui.handleEscapeMerge,
}, {
- ViewName: "main",
- Key: gocui.KeySpace,
- Modifier: gocui.ModNone,
- Handler: gui.handlePickHunk,
+ ViewName: "merging",
+ Key: gocui.KeySpace,
+ Modifier: gocui.ModNone,
+ Handler: gui.handlePickHunk,
+ Description: gui.Tr.SLocalize("PickHunk"),
+ KeyReadable: "space",
}, {
- ViewName: "main",
- Key: 'b',
- Modifier: gocui.ModNone,
- Handler: gui.handlePickBothHunks,
+ ViewName: "merging",
+ Key: 'b',
+ Modifier: gocui.ModNone,
+ Handler: gui.handlePickBothHunks,
+ Description: gui.Tr.SLocalize("PickBothHunks"),
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: gocui.KeyArrowLeft,
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevConflict,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: gocui.KeyArrowRight,
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextConflict,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: gocui.KeyArrowUp,
Modifier: gocui.ModNone,
Handler: gui.handleSelectTop,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: gocui.KeyArrowDown,
Modifier: gocui.ModNone,
Handler: gui.handleSelectBottom,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: 'h',
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevConflict,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: 'l',
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextConflict,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: 'k',
Modifier: gocui.ModNone,
Handler: gui.handleSelectTop,
}, {
- ViewName: "main",
+ ViewName: "merging",
Key: 'j',
Modifier: gocui.ModNone,
Handler: gui.handleSelectBottom,
}, {
- ViewName: "main",
- Key: 'z',
- Modifier: gocui.ModNone,
- Handler: gui.handlePopFileSnapshot,
+ ViewName: "merging",
+ Key: 'z',
+ Modifier: gocui.ModNone,
+ Handler: gui.handlePopFileSnapshot,
+ Description: gui.Tr.SLocalize("Undo"),
}, {
ViewName: "branches",
Key: gocui.KeySpace,
diff --git a/pkg/gui/menu_panel.go b/pkg/gui/menu_panel.go
index 8ce60f6be..6dca1ad35 100644
--- a/pkg/gui/menu_panel.go
+++ b/pkg/gui/menu_panel.go
@@ -2,7 +2,6 @@ package gui
import (
"fmt"
- "strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -50,7 +49,7 @@ func (gui *Gui) handleMenuClose(g *gocui.Gui, v *gocui.View) error {
return gui.returnFocus(g, v)
}
-func (gui *Gui) createMenu(items interface{}, handlePress func(int) error) error {
+func (gui *Gui) createMenu(title string, items interface{}, handlePress func(int) error) error {
list, err := utils.RenderList(items)
if err != nil {
return err
@@ -58,7 +57,7 @@ func (gui *Gui) createMenu(items interface{}, handlePress func(int) error) error
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(gui.g, list)
menuView, _ := gui.g.SetView("menu", x0, y0, x1, y1, 0)
- menuView.Title = strings.Title(gui.Tr.SLocalize("menu"))
+ menuView.Title = title
menuView.FgColor = gocui.ColorWhite
menuView.Clear()
fmt.Fprint(menuView, list)
@@ -66,7 +65,13 @@ func (gui *Gui) createMenu(items interface{}, handlePress func(int) error) error
wrappedHandlePress := func(g *gocui.Gui, v *gocui.View) error {
selectedLine := gui.State.Panels.Menu.SelectedLine
- return handlePress(selectedLine)
+ if err := handlePress(selectedLine); err != nil {
+ return err
+ }
+ if _, err := gui.g.SetViewOnBottom("menu"); err != nil {
+ return err
+ }
+ return gui.returnFocus(gui.g, menuView)
}
if err := gui.g.SetKeybinding("menu", gocui.KeySpace, gocui.ModNone, wrappedHandlePress); err != nil {
diff --git a/pkg/gui/merge_panel.go b/pkg/gui/merge_panel.go
index 404266d29..07ba55894 100644
--- a/pkg/gui/merge_panel.go
+++ b/pkg/gui/merge_panel.go
@@ -11,6 +11,7 @@ import (
"strings"
"github.com/fatih/color"
+ "github.com/golang-collections/collections/stack"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
@@ -21,6 +22,7 @@ func (gui *Gui) findConflicts(content string) ([]commands.Conflict, error) {
var newConflict commands.Conflict
for i, line := range utils.SplitLines(content) {
trimmedLine := strings.TrimPrefix(line, "++")
+ gui.Log.Info(trimmedLine)
if trimmedLine == "<<<<<<< HEAD" || trimmedLine == "<<<<<<< MERGE_HEAD" || trimmedLine == "<<<<<<< Updated upstream" {
newConflict = commands.Conflict{Start: i}
} else if trimmedLine == "=======" {
@@ -65,28 +67,28 @@ func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflic
}
func (gui *Gui) handleSelectTop(g *gocui.Gui, v *gocui.View) error {
- gui.State.ConflictTop = true
+ gui.State.Panels.Merging.ConflictTop = true
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleSelectBottom(g *gocui.Gui, v *gocui.View) error {
- gui.State.ConflictTop = false
+ gui.State.Panels.Merging.ConflictTop = false
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error {
- if gui.State.ConflictIndex >= len(gui.State.Conflicts)-1 {
+ if gui.State.Panels.Merging.ConflictIndex >= len(gui.State.Panels.Merging.Conflicts)-1 {
return nil
}
- gui.State.ConflictIndex++
+ gui.State.Panels.Merging.ConflictIndex++
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error {
- if gui.State.ConflictIndex <= 0 {
+ if gui.State.Panels.Merging.ConflictIndex <= 0 {
return nil
}
- gui.State.ConflictIndex--
+ gui.State.Panels.Merging.ConflictIndex--
return gui.refreshMergePanel(g)
}
@@ -134,15 +136,15 @@ func (gui *Gui) pushFileSnapshot(g *gocui.Gui) error {
if err != nil {
return err
}
- gui.State.EditHistory.Push(content)
+ gui.State.Panels.Merging.EditHistory.Push(content)
return nil
}
func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error {
- if gui.State.EditHistory.Len() == 0 {
+ if gui.State.Panels.Merging.EditHistory.Len() == 0 {
return nil
}
- prevContent := gui.State.EditHistory.Pop().(string)
+ prevContent := gui.State.Panels.Merging.EditHistory.Pop().(string)
gitFile, err := gui.getSelectedFile(g)
if err != nil {
return err
@@ -152,22 +154,29 @@ func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error {
- conflict := gui.State.Conflicts[gui.State.ConflictIndex]
+ conflict := gui.State.Panels.Merging.Conflicts[gui.State.Panels.Merging.ConflictIndex]
gui.pushFileSnapshot(g)
pick := "bottom"
- if gui.State.ConflictTop {
+ if gui.State.Panels.Merging.ConflictTop {
pick = "top"
}
err := gui.resolveConflict(g, conflict, pick)
if err != nil {
panic(err)
}
+
+ // if that was the last conflict, finish the merge for this file
+ if len(gui.State.Panels.Merging.Conflicts) == 1 {
+ if err := gui.handleCompleteMerge(); err != nil {
+ return err
+ }
+ }
gui.refreshMergePanel(g)
return nil
}
func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error {
- conflict := gui.State.Conflicts[gui.State.ConflictIndex]
+ conflict := gui.State.Panels.Merging.Conflicts[gui.State.Panels.Merging.ConflictIndex]
gui.pushFileSnapshot(g)
err := gui.resolveConflict(g, conflict, "both")
if err != nil {
@@ -177,6 +186,7 @@ func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) refreshMergePanel(g *gocui.Gui) error {
+ panelState := gu