1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-27 12:32:37 +02:00

clean up interface for popup panels

This commit is contained in:
Jesse Duffield 2020-08-15 16:36:39 +10:00
parent c44ee71ad4
commit d9fa02c53b
34 changed files with 674 additions and 396 deletions

View File

@ -66,7 +66,7 @@ func (gui *Gui) WithWaitingStatus(name string, f func() error) error {
if appStatus == "" {
return
}
gui.renderString(gui.g, "appStatus", appStatus)
gui.renderString("appStatus", appStatus)
}
}()

View File

@ -125,7 +125,7 @@ func (gui *Gui) handleCreatePullRequestPress(g *gocui.Gui, v *gocui.View) error
}
func (gui *Gui) handleGitFetch(g *gocui.Gui, v *gocui.View) error {
if err := gui.createLoaderPanel(gui.g, v, gui.Tr.SLocalize("FetchWait")); err != nil {
if err := gui.createLoaderPanel(v, gui.Tr.SLocalize("FetchWait")); err != nil {
return err
}
go func() {
@ -140,12 +140,19 @@ func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error {
branch := gui.getSelectedBranch()
message := gui.Tr.SLocalize("SureForceCheckout")
title := gui.Tr.SLocalize("ForceCheckoutBranch")
return gui.createConfirmationPanel(g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: title,
prompt: message,
handleConfirm: func() error {
if err := gui.GitCommand.Checkout(branch.Name, commands.CheckoutOptions{Force: true}); err != nil {
_ = gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}, nil)
},
})
}
type handleCheckoutRefOptions struct {
@ -179,8 +186,12 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions)
if strings.Contains(err.Error(), "Please commit your changes or stash them before you switch branch") {
// offer to autostash changes
return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("AutoStashTitle"), gui.Tr.SLocalize("AutoStashPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getBranchesView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("AutoStashTitle"),
prompt: gui.Tr.SLocalize("AutoStashPrompt"),
handleConfirm: func() error {
if err := gui.GitCommand.StashSave(gui.Tr.SLocalize("StashPrefix") + ref); err != nil {
return gui.surfaceError(err)
}
@ -196,7 +207,8 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions)
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI})
}, nil)
},
})
}
if err := gui.surfaceError(err); err != nil {
@ -210,12 +222,19 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions)
}
func (gui *Gui) handleCheckoutByName(g *gocui.Gui, v *gocui.View) error {
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("BranchName")+":", "", func(g *gocui.Gui, v *gocui.View) error {
return gui.handleCheckoutRef(gui.trimmedContent(v), handleCheckoutRefOptions{
return gui.createPromptPanel(v, gui.Tr.SLocalize("BranchName")+":", "", func(response string) error {
return gui.handleCheckoutRef(response, handleCheckoutRefOptions{
onRefNotFound: func(ref string) error {
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("BranchNotFoundTitle"), fmt.Sprintf("%s %s%s", gui.Tr.SLocalize("BranchNotFoundPrompt"), ref, "?"), func(_g *gocui.Gui, _v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("BranchNotFoundTitle"),
prompt: fmt.Sprintf("%s %s%s", gui.Tr.SLocalize("BranchNotFoundPrompt"), ref, "?"),
handleConfirm: func() error {
return gui.createNewBranchWithName(ref)
}, nil)
},
})
},
})
})
@ -240,8 +259,8 @@ func (gui *Gui) handleNewBranch(g *gocui.Gui, v *gocui.View) error {
"branchName": branch.Name,
},
)
return gui.createPromptPanel(g, v, message, "", func(g *gocui.Gui, v *gocui.View) error {
return gui.createNewBranchWithName(gui.trimmedContent(v))
return gui.createPromptPanel(v, message, "", func(response string) error {
return gui.createNewBranchWithName(response)
})
}
@ -288,7 +307,13 @@ func (gui *Gui) deleteNamedBranch(g *gocui.Gui, v *gocui.View, selectedBranch *c
"selectedBranchName": selectedBranch.Name,
},
)
return gui.createConfirmationPanel(g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: title,
prompt: message,
handleConfirm: func() error {
if err := gui.GitCommand.DeleteBranch(selectedBranch.Name, force); err != nil {
errMessage := err.Error()
if !force && strings.Contains(errMessage, "is not fully merged") {
@ -297,7 +322,8 @@ func (gui *Gui) deleteNamedBranch(g *gocui.Gui, v *gocui.View, selectedBranch *c
return gui.createErrorPanel(errMessage)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{BRANCHES}})
}, nil)
},
})
}
func (gui *Gui) mergeBranchIntoCheckedOutBranch(branchName string) error {
@ -319,12 +345,17 @@ func (gui *Gui) mergeBranchIntoCheckedOutBranch(branchName string) error {
"selectedBranch": branchName,
},
)
return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("MergingTitle"), prompt,
func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getBranchesView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("MergingTitle"),
prompt: prompt,
handleConfirm: func() error {
err := gui.GitCommand.Merge(branchName, commands.MergeOpts{})
return gui.handleGenericMergeCommandResult(err)
}, nil)
},
})
}
func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error {
@ -357,11 +388,17 @@ func (gui *Gui) handleRebaseOntoBranch(selectedBranchName string) error {
"selectedBranch": selectedBranchName,
},
)
return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("RebasingTitle"), prompt,
func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getBranchesView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("RebasingTitle"),
prompt: prompt,
handleConfirm: func() error {
err := gui.GitCommand.RebaseBranch(selectedBranchName)
return gui.handleGenericMergeCommandResult(err)
}, nil)
},
})
}
func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error {
@ -396,7 +433,7 @@ func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error {
},
)
go func() {
_ = gui.createLoaderPanel(gui.g, v, message)
_ = gui.createLoaderPanel(v, message)
if gui.State.Panels.Branches.SelectedLine == 0 {
_ = gui.pullWithMode("ff-only", PullFilesOptions{})
@ -500,14 +537,13 @@ func (gui *Gui) handleRenameBranch(g *gocui.Gui, v *gocui.View) error {
// way to get it to show up in the reflog)
promptForNewName := func() error {
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("NewBranchNamePrompt")+" "+branch.Name+":", "", func(g *gocui.Gui, v *gocui.View) error {
newName := gui.trimmedContent(v)
if err := gui.GitCommand.RenameBranch(branch.Name, newName); err != nil {
return gui.createPromptPanel(v, gui.Tr.SLocalize("NewBranchNamePrompt")+" "+branch.Name+":", "", func(newBranchName string) error {
if err := gui.GitCommand.RenameBranch(branch.Name, newBranchName); err != nil {
return gui.surfaceError(err)
}
// need to checkout so that the branch shows up in our reflog and therefore
// doesn't get lost among all the other branches when we switch to something else
if err := gui.GitCommand.Checkout(newName, commands.CheckoutOptions{Force: false}); err != nil {
if err := gui.GitCommand.Checkout(newBranchName, commands.CheckoutOptions{Force: false}); err != nil {
return gui.surfaceError(err)
}
@ -522,9 +558,14 @@ func (gui *Gui) handleRenameBranch(g *gocui.Gui, v *gocui.View) error {
if notTrackingRemote {
return promptForNewName()
}
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("renameBranch"), gui.Tr.SLocalize("RenameBranchWarning"), func(_g *gocui.Gui, _v *gocui.View) error {
return promptForNewName()
}, nil)
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("renameBranch"),
prompt: gui.Tr.SLocalize("RenameBranchWarning"),
handleConfirm: promptForNewName,
})
}
func (gui *Gui) currentBranch() *commands.Branch {

View File

@ -36,7 +36,7 @@ func (gui *Gui) handleCommitFileSelect(g *gocui.Gui, v *gocui.View) error {
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString(g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
@ -57,7 +57,7 @@ func (gui *Gui) handleCommitFileSelect(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleSwitchToCommitsPanel(g *gocui.Gui, v *gocui.View) error {
return gui.switchFocus(g, v, gui.getCommitsView())
return gui.switchFocus(v, gui.getCommitsView())
}
func (gui *Gui) handleCheckoutCommitFile(g *gocui.Gui, v *gocui.View) error {
@ -77,7 +77,12 @@ func (gui *Gui) handleDiscardOldFileChange(g *gocui.Gui, v *gocui.View) error {
fileName := gui.State.CommitFiles[gui.State.Panels.CommitFiles.SelectedLine].Name
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("DiscardFileChangesTitle"), gui.Tr.SLocalize("DiscardFileChangesPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DiscardFileChangesTitle"),
prompt: gui.Tr.SLocalize("DiscardFileChangesPrompt"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("RebasingStatus"), func() error {
if err := gui.GitCommand.DiscardOldFileChanges(gui.State.Commits, gui.State.Panels.Commits.SelectedLine, fileName); err != nil {
if err := gui.handleGenericMergeCommandResult(err); err != nil {
@ -87,7 +92,8 @@ func (gui *Gui) handleDiscardOldFileChange(g *gocui.Gui, v *gocui.View) error {
return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI})
})
}, nil)
},
})
}
func (gui *Gui) refreshCommitFilesView() error {
@ -144,7 +150,7 @@ func (gui *Gui) handleToggleFileForPatch(g *gocui.Gui, v *gocui.View) error {
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString(g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
@ -161,10 +167,16 @@ func (gui *Gui) handleToggleFileForPatch(g *gocui.Gui, v *gocui.View) error {
}
if gui.GitCommand.PatchManager.CommitSelected() && gui.GitCommand.PatchManager.CommitSha != commitFile.Sha {
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("DiscardPatch"), gui.Tr.SLocalize("DiscardPatchConfirm"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DiscardPatch"),
prompt: gui.Tr.SLocalize("DiscardPatchConfirm"),
handleConfirm: func() error {
gui.GitCommand.PatchManager.Reset()
return toggleTheFile()
}, nil)
},
})
}
return toggleTheFile()
@ -200,7 +212,7 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString(gui.g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
@ -212,18 +224,25 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
}
gui.changeMainViewsContext("patch-building")
if err := gui.switchFocus(gui.g, gui.getCommitFilesView(), gui.getMainView()); err != nil {
if err := gui.switchFocus(gui.getCommitFilesView(), gui.getMainView()); err != nil {
return err
}
return gui.refreshPatchBuildingPanel(selectedLineIdx)
}
if gui.GitCommand.PatchManager.CommitSelected() && gui.GitCommand.PatchManager.CommitSha != commitFile.Sha {
return gui.createConfirmationPanel(gui.g, gui.getCommitFilesView(), false, gui.Tr.SLocalize("DiscardPatch"), gui.Tr.SLocalize("DiscardPatchConfirm"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getCommitFilesView(),
returnFocusOnClose: false,
title: gui.Tr.SLocalize("DiscardPatch"),
prompt: gui.Tr.SLocalize("DiscardPatchConfirm"),
handleConfirm: func() error {
gui.GitCommand.PatchManager.Reset()
return enterTheFile(selectedLineIdx)
}, func(g *gocui.Gui, v *gocui.View) error {
return gui.switchFocus(gui.g, nil, gui.getCommitFilesView())
},
handleClose: func() error {
return gui.switchFocus(nil, gui.getCommitFilesView())
},
})
}

View File

@ -47,13 +47,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())
_ = gui.switchFocus(v, gui.getFilesView())
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}
func (gui *Gui) handleCommitClose(g *gocui.Gui, v *gocui.View) error {
_, _ = g.SetViewOnBottom("commitMessage")
return gui.switchFocus(g, v, gui.getFilesView())
return gui.switchFocus(v, gui.getFilesView())
}
func (gui *Gui) handleCommitFocused(g *gocui.Gui, v *gocui.View) error {
@ -69,7 +69,7 @@ func (gui *Gui) handleCommitFocused(g *gocui.Gui, v *gocui.View) error {
"keyBindNewLine": "tab",
},
)
gui.renderString(g, "options", message)
gui.renderString("options", message)
return nil
}

View File

@ -155,12 +155,18 @@ func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error {
return nil
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("Squash"), gui.Tr.SLocalize("SureSquashThisCommit"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("Squash"),
prompt: gui.Tr.SLocalize("SureSquashThisCommit"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("SquashingStatus"), func() error {
err := gui.GitCommand.InteractiveRebase(gui.State.Commits, gui.State.Panels.Commits.SelectedLine, "squash")
return gui.handleGenericMergeCommandResult(err)
})
}, nil)
},
})
}
func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error {
@ -180,12 +186,18 @@ func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error {
return nil
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("Fixup"), gui.Tr.SLocalize("SureFixupThisCommit"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("Fixup"),
prompt: gui.Tr.SLocalize("SureFixupThisCommit"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("FixingStatus"), func() error {
err := gui.GitCommand.InteractiveRebase(gui.State.Commits, gui.State.Panels.Commits.SelectedLine, "fixup")
return gui.handleGenericMergeCommandResult(err)
})
}, nil)
},
})
}
func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error {
@ -204,8 +216,8 @@ func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error {
if gui.State.Panels.Commits.SelectedLine != 0 {
return gui.createErrorPanel(gui.Tr.SLocalize("OnlyRenameTopCommit"))
}
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("renameCommit"), "", func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.RenameCommit(v.Buffer()); err != nil {
return gui.createPromptPanel(v, gui.Tr.SLocalize("renameCommit"), "", func(response string) error {
if err := gui.GitCommand.RenameCommit(response); err != nil {
return gui.surfaceError(err)
}
@ -276,12 +288,18 @@ func (gui *Gui) handleCommitDelete(g *gocui.Gui, v *gocui.View) error {
return nil
}
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("DeleteCommitTitle"), gui.Tr.SLocalize("DeleteCommitPrompt"), func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DeleteCommitTitle"),
prompt: gui.Tr.SLocalize("DeleteCommitPrompt"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("DeletingStatus"), func() error {
err := gui.GitCommand.InteractiveRebase(gui.State.Commits, gui.State.Panels.Commits.SelectedLine, "drop")
return gui.handleGenericMergeCommandResult(err)
})
}, nil)
},
})
}
func (gui *Gui) handleCommitMoveDown(g *gocui.Gui, v *gocui.View) error {
@ -362,12 +380,18 @@ func (gui *Gui) handleCommitAmendTo(g *gocui.Gui, v *gocui.View) error {
return err
}
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("AmendCommitTitle"), gui.Tr.SLocalize("AmendCommitPrompt"), func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("AmendCommitTitle"),
prompt: gui.Tr.SLocalize("AmendCommitPrompt"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("AmendingStatus"), func() error {
err := gui.GitCommand.AmendTo(gui.State.Commits[gui.State.Panels.Commits.SelectedLine].Sha)
return gui.handleGenericMergeCommandResult(err)
})
}, nil)
},
})
}
func (gui *Gui) handleCommitPick(g *gocui.Gui, v *gocui.View) error {
@ -474,12 +498,18 @@ func (gui *Gui) HandlePasteCommits(g *gocui.Gui, v *gocui.View) error {
return err
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("CherryPick"), gui.Tr.SLocalize("SureCherryPick"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("CherryPick"),
prompt: gui.Tr.SLocalize("SureCherryPick"),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("CherryPickingStatus"), func() error {
err := gui.GitCommand.CherryPickCommits(gui.State.CherryPickedCommits)
return gui.handleGenericMergeCommandResult(err)
})
}, nil)
},
})
}
func (gui *Gui) handleSwitchToCommitFilesPanel(g *gocui.Gui, v *gocui.View) error {
@ -487,7 +517,7 @@ func (gui *Gui) handleSwitchToCommitFilesPanel(g *gocui.Gui, v *gocui.View) erro
return err
}
return gui.switchFocus(g, gui.getCommitsView(), gui.getCommitFilesView())
return gui.switchFocus(gui.getCommitsView(), gui.getCommitFilesView())
}
func (gui *Gui) hasCommit(commits []*commands.Commit, target string) (int, bool) {
@ -513,18 +543,24 @@ func (gui *Gui) handleCreateFixupCommit(g *gocui.Gui, v *gocui.View) error {
return nil
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("CreateFixupCommit"), gui.Tr.TemplateLocalize(
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("CreateFixupCommit"),
prompt: gui.Tr.TemplateLocalize(
"SureCreateFixupCommit",
Teml{
"commit": commit.Sha,
},
), func(g *gocui.Gui, v *gocui.View) error {
),
handleConfirm: func() error {
if err := gui.GitCommand.CreateFixupCommit(commit.Sha); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}, nil)
},
})
}
func (gui *Gui) handleSquashAllAboveFixupCommits(g *gocui.Gui, v *gocui.View) error {
@ -537,17 +573,23 @@ func (gui *Gui) handleSquashAllAboveFixupCommits(g *gocui.Gui, v *gocui.View) er
return nil
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("SquashAboveCommits"), gui.Tr.TemplateLocalize(
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("SquashAboveCommits"),
prompt: gui.Tr.TemplateLocalize(
"SureSquashAboveCommits",
Teml{
"commit": commit.Sha,
},
), func(g *gocui.Gui, v *gocui.View) error {
),
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("SquashingStatus"), func() error {
err := gui.GitCommand.SquashAllAboveFixupCommits(commit.Sha)
return gui.handleGenericMergeCommandResult(err)
})
}, nil)
},
})
}
func (gui *Gui) handleTagCommit(g *gocui.Gui, v *gocui.View) error {
@ -563,8 +605,8 @@ func (gui *Gui) handleTagCommit(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleCreateLightweightTag(commitSha string) error {
return gui.createPromptPanel(gui.g, gui.getCommitsView(), gui.Tr.SLocalize("TagNameTitle"), "", func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.CreateLightweightTag(v.Buffer(), commitSha); err != nil {
return gui.createPromptPanel(gui.getCommitsView(), gui.Tr.SLocalize("TagNameTitle"), "", func(response string) error {
if err := gui.GitCommand.CreateLightweightTag(response, commitSha); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{COMMITS, TAGS}})
@ -577,9 +619,15 @@ func (gui *Gui) handleCheckoutCommit(g *gocui.Gui, v *gocui.View) error {
return nil
}
return gui.createConfirmationPanel(g, gui.getCommitsView(), true, gui.Tr.SLocalize("checkoutCommit"), gui.Tr.SLocalize("SureCheckoutThisCommit"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getCommitsView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("checkoutCommit"),
prompt: gui.Tr.SLocalize("SureCheckoutThisCommit"),
handleConfirm: func() error {
return gui.handleCheckoutRef(commit.Sha, handleCheckoutRefOptions{})
}, nil)
},
})
}
func (gui *Gui) renderBranchCommitsWithSelection() error {

View File

@ -15,11 +15,76 @@ import (
"github.com/jesseduffield/lazygit/pkg/theme"
)
func (gui *Gui) wrappedConfirmationFunction(function func(*gocui.Gui, *gocui.View) error, returnFocusOnClose bool) func(*gocui.Gui, *gocui.View) error {
type createPopupPanelOpts struct {
returnToView *gocui.View
hasLoader bool
returnFocusOnClose bool
editable bool
title string
prompt string
handleConfirm func() error
handleConfirmPrompt func(string) error
handleClose func() error
}
type createConfirmationPanelOpts struct {
returnToView *gocui.View
returnFocusOnClose bool
title string
prompt string
handleConfirm func() error
handleClose func() error
}
func (gui *Gui) createLoaderPanel(currentView *gocui.View, prompt string) error {
return gui.createPopupPanel(createPopupPanelOpts{
returnToView: currentView,
prompt: prompt,
hasLoader: true,
returnFocusOnClose: true,
})
}
func (gui *Gui) createConfirmationPanel(opts createConfirmationPanelOpts) error {
return gui.createPopupPanel(createPopupPanelOpts{
returnToView: opts.returnToView,
title: opts.title,
prompt: opts.prompt,
returnFocusOnClose: opts.returnFocusOnClose,
handleConfirm: opts.handleConfirm,
handleClose: opts.handleClose,
})
}
func (gui *Gui) createPromptPanel(currentView *gocui.View, title string, initialContent string, handleConfirm func(string) error) error {
return gui.createPopupPanel(createPopupPanelOpts{
returnToView: currentView,
title: title,
prompt: initialContent,
returnFocusOnClose: true,
editable: true,
handleConfirmPrompt: handleConfirm,
})
}
func (gui *Gui) wrappedConfirmationFunction(function func() error, returnFocusOnClose bool) func(*gocui.Gui, *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
if function != nil {
if err := function(g, v); err != nil {
if err := function(); err != nil {
return err
}
}
return gui.closeConfirmationPrompt(g, returnFocusOnClose)
}
}
func (gui *Gui) wrappedPromptConfirmationFunction(function func(string) error, returnFocusOnClose bool) func(*gocui.Gui, *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
if function != nil {
if err := function(v.Buffer()); err != nil {
return err
}
}
@ -96,7 +161,7 @@ func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt
confirmationView.FgColor = theme.GocuiDefaultTextColor
}
gui.g.Update(func(g *gocui.Gui) error {
return gui.switchFocus(gui.g, currentView, confirmationView)
return gui.switchFocus(currentView, confirmationView)
})
return confirmationView, nil
}
@ -110,21 +175,21 @@ func (gui *Gui) onNewPopupPanel() {
}
}
func (gui *Gui) createPopupPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, hasLoader bool, returnFocusOnClose bool, editable bool, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
func (gui *Gui) createPopupPanel(opts createPopupPanelOpts) error {
gui.onNewPopupPanel()
g.Update(func(g *gocui.Gui) error {
gui.g.Update(func(g *gocui.Gui) error {
// delete the existing confirmation panel if it exists
if view, _ := g.View("confirmation"); view != nil {
if err := gui.closeConfirmationPrompt(g, true); err != nil {
gui.Log.Error(err)
}
}
confirmationView, err := gui.prepareConfirmationPanel(currentView, title, prompt, hasLoader)
confirmationView, err := gui.prepareConfirmationPanel(opts.returnToView, opts.title, opts.prompt, opts.hasLoader)
if err != nil {
return err
}
confirmationView.Editable = editable
if editable {
confirmationView.Editable = opts.editable
if opts.editable {
go func() {
// TODO: remove this wait (right now if you remove it the EditGotoToEndOfLine method doesn't seem to work)
time.Sleep(time.Millisecond)
@ -135,26 +200,13 @@ func (gui *Gui) createPopupPanel(g *gocui.Gui, currentView *gocui.View, title, p
}()
}
gui.renderString(g, "confirmation", prompt)
return gui.setKeyBindings(g, handleConfirm, handleClose, returnFocusOnClose)
gui.renderString("confirmation", opts.prompt)
return gui.setKeyBindings(opts)
})
return nil
}
func (gui *Gui) createLoaderPanel(g *gocui.Gui, currentView *gocui.View, prompt string) error {
return gui.createPopupPanel(g, currentView, "", prompt, true, true, false, nil, nil)
}
// it is very important that within this function we never include the original prompt in any error messages, because it may contain e.g. a user password
func (gui *Gui) createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, returnFocusOnClose bool, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
return gui.createPopupPanel(g, currentView, title, prompt, false, returnFocusOnClose, false, handleConfirm, handleClose)
}
func (gui *Gui) createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, initialContent string, handleConfirm func(*gocui.Gui, *gocui.View) error) error {
return gui.createPopupPanel(gui.g, currentView, title, initialContent, false, true, true, handleConfirm, nil)
}
func (gui *Gui) setKeyBindings(g *gocui.Gui, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error, returnFocusOnClose bool) error {
func (gui *Gui) setKeyBindings(opts createPopupPanelOpts) error {
actions := gui.Tr.TemplateLocalize(
"CloseConfirm",
Teml{
@ -163,40 +215,33 @@ func (gui *Gui) setKeyBindings(g *gocui.Gui, handleConfirm, handleClose func(*go
},
)
gui.renderString(g, "options", actions)
if err := g.SetKeybinding("confirmation", nil, gocui.KeyEnter, gocui.ModNone, gui.wrappedConfirmationFunction(handleConfirm, returnFocusOnClose)); err != nil {
gui.renderString("options", actions)
if opts.handleConfirmPrompt != nil {
if err := gui.g.SetKeybinding("confirmation", nil, gocui.KeyEnter, gocui.ModNone, gui.wrappedPromptConfirmationFunction(opts.handleConfirmPrompt, opts.returnFocusOnClose)); err != nil {
return err
}
} else {
if err := gui.g.SetKeybinding("confirmation", nil, gocui.KeyEnter, gocui.ModNone, gui.wrappedConfirmationFunction(opts.handleConfirm, opts.returnFocusOnClose)); err != nil {
return err
}
return g.SetKeybinding("confirmation", nil, gocui.KeyEsc, gocui.ModNone, gui.wrappedConfirmationFunction(handleClose, returnFocusOnClose))
}
// createSpecificErrorPanel allows you to create an error popup, specifying the
// view to be focused when the user closes the popup, and a boolean specifying
// whether we will log the error. If the message may include a user password,
// this function is to be used over the more generic createErrorPanel, with
// willLog set to false
func (gui *Gui) createSpecificErrorPanel(message string, nextView *gocui.View, willLog bool) error {
if willLog {
go func() {
// when reporting is switched on this log call sometimes introduces
// a delay on the error panel popping up. Here I'm adding a second wait
// so that the error is logged while the user is reading the error message
time.Sleep(time.Second)
gui.Log.Error(message)
}()
}
return gui.g.SetKeybinding("confirmation", nil, gocui.KeyEsc, gocui.ModNone, gui.wrappedConfirmationFunction(opts.handleClose, opts.returnFocusOnClose))
}
func (gui *Gui) createErrorPanel(message string) error {
colorFunction := color.New(color.FgRed).SprintFunc()
coloredMessage := colorFunction(strings.TrimSpace(message))
if err := gui.refreshSidePanels(refreshOptions{mode: ASYNC}); err != nil {
return err
}
return gui.createConfirmationPanel(gui.g, nextView, true, gui.Tr.SLocalize("Error"), coloredMessage, nil, nil)
}
func (gui *Gui) createErrorPanel(message string) error {
return gui.createSpecificErrorPanel(message, gui.g.CurrentView(), true)
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.g.CurrentView(),
title: gui.Tr.SLocalize("Error"),
prompt: coloredMessage,
returnFocusOnClose: true,
})
}
func (gui *Gui) surfaceError(err error) error {

View File

@ -20,7 +20,7 @@ func (gui *Gui) promptUserForCredential(passOrUname string) string {
credentialsView.Title = gui.Tr.SLocalize("CredentialsPassword")
credentialsView.Mask = '*'
}
err := gui.switchFocus(g, gui.g.CurrentView(), credentialsView)
err := gui.switchFocus(gui.g.CurrentView(), credentialsView)
if err != nil {
return err
}
@ -43,7 +43,7 @@ func (gui *Gui) handleSubmitCredential(g *gocui.Gui, v *gocui.View) error {
if err != nil {
nextView = gui.getFilesView()
}
err = gui.switchFocus(g, nil, nextView)
err = gui.switchFocus(nil, nextView)
if err != nil {
return err
}
@ -57,7 +57,7 @@ func (gui *Gui) handleCloseCredentialsView(g *gocui.Gui, v *gocui.View) error {
}
gui.credentials <- ""
return gui.switchFocus(g, nil, gui.getFilesView())
return gui.switchFocus(nil, gui.getFilesView())
}
func (gui *Gui) handleCredentialsViewFocused(g *gocui.Gui, v *gocui.View) error {
@ -72,7 +72,7 @@ func (gui *Gui) handleCredentialsViewFocused(g *gocui.Gui, v *gocui.View) error
"keyBindConfirm": "enter",
},
)
gui.renderString(g, "options", message)
gui.renderString("options", message)
return nil
}
@ -85,7 +85,7 @@ func (gui *Gui) handleCredentialsPopup(cmdErr error) {
errMessage = gui.Tr.SLocalize("PassUnameWrong")
}
// we are not logging this error because it may contain a password
_ = gui.createSpecificErrorPanel(errMessage, gui.getFilesView(), false)
gui.createErrorPanel(errMessage)
} else {
_ = gui.closeConfirmationPrompt(gui.g, true)
}

View File

@ -150,8 +150,8 @@ func (gui *Gui) handleCreateDiffingMenuPanel(g *gocui.Gui, v *gocui.View) error
{
displayString: gui.Tr.SLocalize("enterRefToDiff"),
onPress: func() error {
return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("enteRefName"), "", func(g *gocui.Gui, promptView *gocui.View) error {
gui.State.Diff.Ref = strings.TrimSpace(promptView.Buffer())
return gui.createPromptPanel(v, gui.Tr.SLocalize("enteRefName"), "", func(response string) error {
gui.State.Diff.Ref = strings.TrimSpace(response)
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
})
},

View File

@ -172,7 +172,7 @@ func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error
return gui.createErrorPanel(gui.Tr.SLocalize("FileStagingRequirements"))
}
gui.changeMainViewsContext("staging")
if err := gui.switchFocus(gui.g, gui.getFilesView(), gui.getMainView()); err != nil {
if err := gui.switchFocus(gui.getFilesView(), gui.getMainView()); err != nil {
return err
}
return gui.refreshStagingPanel(forceSecondaryFocused, selectedLineIdx)
@ -249,9 +249,12 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
}
if file.Tracked {
return gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("IgnoreTracked"), gui.Tr.SLocalize("IgnoreTrackedPrompt"),
// On confirmation
func(_ *gocui.Gui, _ *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.g.CurrentView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("IgnoreTracked"),
prompt: gui.Tr.SLocalize("IgnoreTrackedPrompt"),
handleConfirm: func() error {
if err := gui.GitCommand.Ignore(file.Name); err != nil {
return err
}
@ -259,7 +262,8 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
return err
}
return gui.refreshSidePanels(refreshOptions{scope: []int{FILES}})
}, nil)
},
})
}
if err := gui.GitCommand.Ignore(file.Name); err != nil {
@ -275,7 +279,7 @@ func (gui *Gui) handleWIPCommitPress(g *gocui.Gui, filesView *gocui.View) error
return gui.createErrorPanel(gui.Tr.SLocalize("SkipHookPrefixNotConfigured"))
}
gui.renderString(g, "commitMessage", skipHookPreifx)
gui.renderString("commitMessage", skipHookPreifx)
if err := gui.getCommitMessageView().SetCursor(len(skipHookPreifx), 0); err != nil {
return err
}
@ -299,7 +303,7 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
return gui.createErrorPanel(fmt.Sprintf("%s: %s", gui.Tr.SLocalize("commitPrefixPatternError"), err.Error()))
}
prefix := rgx.ReplaceAllString(gui.getCheckedOutBranch().Name, prefixReplace)
gui.renderString(g, "commitMessage", prefix)
gui.renderString("commitMessage", prefix)
if err := commitMessageView.SetCursor(len(prefix), 0); err != nil {
return err
}
@ -310,7 +314,7 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
return err
}
if err := gui.switchFocus(g, filesView, commitMessageView); err != nil {
if err := gui.switchFocus(filesView, commitMessageView); err != nil {
return err
}
@ -321,9 +325,12 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
}
func (gui *Gui) promptToStageAllAndRetry(retry func() error) error {
return gui.createConfirmationPanel(
gui.g, gui.getFilesView(), true, gui.Tr.SLocalize("NoFilesStagedTitle"), gui.Tr.SLocalize("NoFilesStagedPrompt"),
func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getFilesView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("NoFilesStagedTitle"),
prompt: gui.Tr.SLocalize("NoFilesStagedPrompt"),
handleConfirm: func() error {
if err := gui.GitCommand.StageAll(); err != nil {
return gui.surfaceError(err)
}
@ -332,7 +339,8 @@ func (gui *Gui) promptToStageAllAndRetry(retry func() error) error {
}
return retry()
}, nil)
},
})
}
func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) error {
@ -346,10 +354,12 @@ func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) erro
return gui.createErrorPanel(gui.Tr.SLocalize("NoCommitToAmend"))
}
title := strings.Title(gui.Tr.SLocalize("AmendLastCommit"))
question := gui.Tr.SLocalize("SureToAmend")
return gui.createConfirmationPanel(g, filesView, true, title, question, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: filesView,
returnFocusOnClose: true,
title: strings.Title(gui.Tr.SLocalize("AmendLastCommit")),
prompt: gui.Tr.SLocalize("SureToAmend"),
handleConfirm: func() error {
ok, err := gui.runSyncOrAsyncCommand(gui.GitCommand.AmendHead())
if err != nil {
return err
@ -359,7 +369,8 @@ func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) erro
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}, nil)
},
})
}
// handleCommitEditorPress - handle when the user wants to commit changes via
@ -450,8 +461,7 @@ func (gui *Gui) handlePullFiles(g *gocui.Gui, v *gocui.View) error {
}
}
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("EnterUpstream"), "origin/"+currentBranch.Name, func(g *gocui.Gui, v *gocui.View) error {
upstream := gui.trimmedContent(v)
return gui.createPromptPanel(v, gui.Tr.SLocalize("EnterUpstream"), "origin/"+currentBranch.Name, func(upstream string) error {
if err := gui.GitCommand.SetUpstreamBranch(upstream); err != nil {
errorMessage := err.Error()
if strings.Contains(errorMessage, "does not exist") {
@ -472,7 +482,7 @@ type PullFilesOptions struct {
}
func (gui *Gui) pullFiles(opts PullFilesOptions) error {
if err := gui.createLoaderPanel(gui.g, gui.g.CurrentView(), gui.Tr.SLocalize("PullWait")); err != nil {
if err := gui.createLoaderPanel(gui.g.CurrentView(), gui.Tr.SLocalize("PullWait")); err != nil {
return err
}
@ -512,16 +522,22 @@ func (gui *Gui) pullWithMode(mode string, opts PullFilesOptions) error {
}
func (gui *Gui) pushWithForceFlag(g *gocui.Gui, v *gocui.View, force bool, upstream string, args string) error {
if err := gui.createLoaderPanel(gui.g, v, gui.Tr.SLocalize("PushWait")); err != nil {
if err := gui.createLoaderPanel(v, gui.Tr.SLocalize("PushWait")); err != nil {
return err
}
go func() {
branchName := gui.getCheckedOutBranch().Name
err := gui.GitCommand.Push(branchName, force, upstream, args, gui.promptUserForCredential)
if err != nil && !force && strings.Contains(err.Error(), "Updates were rejected") {
gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("ForcePush"), gui.Tr.SLocalize("ForcePushPrompt"), func(g *gocui.Gui, v *gocui.View) error {
gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("ForcePush"),
prompt: gui.Tr.SLocalize("ForcePushPrompt"),
handleConfirm: func() error {
return gui.pushWithForceFlag(gui.g, v, true, upstream, args)
}, nil)
},
})
return
}
@ -550,16 +566,23 @@ func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error {
if gui.GitCommand.PushToCurrent {
return gui.pushWithForceFlag(g, v, false, "", "--set-upstream")
} else {
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("EnterUpstream"), "origin "+currentBranch.Name, func(g *gocui.Gui, v *gocui.View) error {
return gui.pushWithForceFlag(g, v, false, gui.trimmedContent(v), "")
return gui.createPromptPanel(v, gui.Tr.SLocalize("EnterUpstream"), "origin "+currentBranch.Name, func(response string) error {
return gui.pushWithForceFlag(g, v, false, response, "")
})
}
} else if currentBranch.Pullables == "0" {
return gui.pushWithForceFlag(g, v, false, "", "")
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("ForcePush"), gui.Tr.SLocalize("ForcePushPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("ForcePush"),
prompt: gui.Tr.SLocalize("ForcePushPrompt"),
handleConfirm: func() error {
return gui.pushWithForceFlag(g, v, true, "", "")
}, nil)
},
})
}
func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error {
@ -574,7 +597,7 @@ func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error {
return gui.createErrorPanel(gui.Tr.SLocalize("FileNoMergeCons"))
}
gui.changeMainViewsContext("merging")
if err := gui.switchFocus(g, v, gui.getMainView()); err != nil {
if err := gui.switchFocus(v, gui.getMainView()); err != nil {
return err
}
return gui.refreshMergePanel()
@ -597,8 +620,7 @@ func (gui *Gui) anyFilesWithMergeConflicts() bool {
}
func (gui *Gui) handleCustomCommand(g *gocui.Gui, v *gocui.View) error {
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("CustomCommand"), "", func(g *gocui.Gui, v *gocui.View) error {
command := gui.trimmedContent(v)
return gui.createPromptPanel(v, gui.Tr.SLocalize("CustomCommand"), "", func(command string) error {
gui.SubProcess = gui.OSCommand.RunCustomCommand(command)
return gui.Errors.ErrSubProcess
})

View File

@ -1,16 +1,22 @@
package gui
import "github.com/jesseduffield/gocui"
func (gui *Gui) inFilterMode() bool {
return gui.State.FilterPath != ""
}
func (gui *Gui) validateNotInFilterMode() (bool, error) {
if gui.inFilterMode() {
return false, gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("MustExitFilterModeTitle"), gui.Tr.SLocalize("MustExitFilterModePrompt"), func(*gocui.Gui, *gocui.View) error {
err := gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.g.CurrentView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("MustExitFilterModeTitle"),
prompt: gui.Tr.SLocalize("MustExitFilterModePrompt"),
handleConfirm: func() error {
return gui.exitFilterMode()
}, nil)
},
})
return false, err
}
return true, nil
}

View File

@ -41,8 +41,8 @@ func (gui *Gui) handleCreateFilteringMenuPanel(g *gocui.Gui, v *gocui.View) erro
menuItems = append(menuItems, &menuItem{
displayString: gui.Tr.SLocalize("filterPathOption"),
onPress: func() error {
return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("enterFileName"), "", func(g *gocui.Gui, promptView *gocui.View) error {
gui.State.FilterPath = strings.TrimSpace(promptView.Buffer())
return gui.createPromptPanel(v, gui.Tr.SLocalize("enterFileName"), "", func(response string) error {
gui.State.FilterPath = strings.TrimSpace(response)
return gui.Errors.ErrRestart
})
},

View File

@ -51,8 +51,7 @@ func (gui *Gui) handleCreateGitFlowMenu(g *gocui.Gui, v *gocui.View) error {
startHandler := func(branchType string) func() error {
return func() error {
title := gui.Tr.TemplateLocalize("NewBranchNamePrompt", map[string]interface{}{"branchType": branchType})
return gui.createPromptPanel(gui.g, gui.getMenuView(), title, "", func(g *gocui.Gui, v *gocui.View) error {
name := gui.trimmedContent(v)
return gui.createPromptPanel(gui.getMenuView(), title, "", func(name string) error {
subProcess := gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "start", name)
gui.SubProcess = subProcess
return gui.Errors.ErrSubProcess

View File

@ -4,7 +4,6 @@ import (
"math"
"strings"
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
@ -176,12 +175,7 @@ func (gui *Gui) fetch(canPromptForCredentials bool) (err error) {
err = gui.GitCommand.Fetch(fetchOpts)
if canPromptForCredentials && err != nil && strings.Contains(err.Error(), "exit status 128") {
colorFunction := color.New(color.FgRed).SprintFunc()
coloredMessage := colorFunction(strings.TrimSpace(gui.Tr.SLocalize("PassUnameWrong")))
close := func(g *gocui.Gui, v *gocui.View) error {
return nil
}
_ = gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("Error"), coloredMessage, close, close)
gui.createErrorPanel(gui.Tr.SLocalize("PassUnameWrong"))
}
gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, COMMITS, REMOTES, TAGS}, mode: ASYNC})

View File

@ -463,21 +463,35 @@ func (gui *Gui) showInitialPopups(tasks []func(chan struct{}) error) {
}
func (gui *Gui) showShamelessSelfPromotionMessage(done chan struct{}) error {
onConfirm := func(g *gocui.Gui, v *gocui.View) error {
onConfirm := func() error {
done <- struct{}{}
return gui.Config.WriteToUserConfig("startupPopupVersion", StartupPopupVersion)
}
return gui.createConfirmationPanel(gui.g, nil, true, gui.Tr.SLocalize("ShamelessSelfPromotionTitle"), gui.Tr.SLocalize("ShamelessSelfPromotionMessage"), onConfirm, onConfirm)
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: nil,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("ShamelessSelfPromotionTitle"),
prompt: gui.Tr.SLocalize("ShamelessSelfPromotionMessage"),
handleConfirm: onConfirm,
handleClose: onConfirm,
})
}
func (gui *Gui) promptAnonymousReporting(done chan struct{}) error {
return gui.createConfirmationPanel(gui.g, nil, true, gui.Tr.SLocalize("AnonymousReportingTitle"), gui.Tr.SLocalize("AnonymousReportingPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: nil,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("AnonymousReportingTitle"),
prompt: gui.Tr.SLocalize("AnonymousReportingPrompt"),
handleConfirm: func() error {
done <- struct{}{}
return gui.Config.WriteToUserConfig("reporting", "on")
}, func(g *gocui.Gui, v *gocui.View) error {
},
handleClose: func() error {
done <- struct{}{}
return gui.Config.WriteToUserConfig("reporting", "off")
},
})
}
@ -504,7 +518,12 @@ func (gui *Gui) startBackgroundFetch() {
}
err := gui.fetch(false)
if err != nil && strings.Contains(err.Error(), "exit status 128") && isNew {
_ = gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("NoAutomaticGitFetchTitle"), gui.Tr.SLocalize("NoAutomaticGitFetchBody"), nil, nil)
_ = gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.g.CurrentView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("NoAutomaticGitFetchTitle"),
prompt: gui.Tr.SLocalize("NoAutomaticGitFetchBody"),
})
} else {
gui.goEvery(time.Second*60, gui.stopChan, func() error {
err := gui.fetch(false)

View File

@ -326,7 +326,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
informationView.BgColor = gocui.ColorDefault
informationView.FgColor = gocui.ColorGreen
informationView.Frame = false
gui.renderString(g, "information", INFO_SECTION_PADDING+informationStr)
gui.renderString("information", INFO_SECTION_PADDING+informationStr)
}
if gui.State.OldInformation != informationStr {
gui.setViewContent(informationView, informationStr)
@ -342,7 +342,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
return err
}
if err := gui.switchFocus(gui.g, nil, initialView); err != nil {
if err := gui.switchFocus(nil, initialView); err != nil {
return err
}
}

View File

@ -119,7 +119,7 @@ func (gui *Gui) createMenu(title string, items []*menuItem, createMenuOptions cr
}
}
currentView := gui.g.CurrentView()
return gui.switchFocus(gui.g, currentView, menuView)
return gui.switchFocus(currentView, menuView)
})
return nil
}

View File

@ -308,7 +308,7 @@ func (gui *Gui) handleEscapeMerge(g *gocui.Gui, v *gocui.View) error {
// it's possible this method won't be called from the merging view so we need to
// ensure we only 'return' focus if we already have it
if gui.g.CurrentView() == gui.getMainView() {
return gui.switchFocus(g, v, gui.getFilesView())
return gui.switchFocus(v, gui.getFilesView())
}
return nil
}
@ -336,9 +336,15 @@ func (gui *Gui) handleCompleteMerge() error {
func (gui *Gui) promptToContinue() error {
gui.takeOverScrolling()
return gui.createConfirmationPanel(gui.g, gui.getFilesView(), true, "continue", gui.Tr.SLocalize("ConflictsResolved"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getFilesView(),
returnFocusOnClose: true,
title: "continue",
prompt: gui.Tr.SLocalize("ConflictsResolved"),
handleConfirm: func() error {
return gui.genericMergeCommand("continue")
}, nil)
},
})
}
func (gui *Gui) canScrollMergePanel() bool {

View File

@ -18,7 +18,7 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error {
// get diff from commit file that's currently selected
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString(gui.g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
@ -58,7 +58,7 @@ func (gui *Gui) handleToggleSelectionForPatch(g *gocui.Gui, v *gocui.View) error
// add range of lines to those set for the file
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {
gui.renderString(gui.g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
gui.renderString("commitFiles", gui.Tr.SLocalize("NoCommiteFiles"))
return nil
}
@ -83,7 +83,7 @@ func (gui *Gui) handleEscapePatchBuildingPanel(g *gocui.Gui, v *gocui.View) erro
gui.State.SplitMainPanel = false
}
return gui.switchFocus(gui.g, nil, gui.getCommitFilesView())
return gui.switchFocus(nil, gui.getCommitFilesView())
}
func (gui *Gui) refreshSecondaryPatchPanel() error {

View File

@ -133,9 +133,15 @@ func (gui *Gui) handlePullPatchIntoWorkingTree() error {
}
if len(gui.trackedFiles()) > 0 {
return gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("MustStashTitle"), gui.Tr.SLocalize("MustStashWarning"), func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.g.CurrentView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("MustStashTitle"),
prompt: gui.Tr.SLocalize("MustStashWarning"),
handleConfirm: func() error {
return pull(true)
}, nil)
},
})
} else {
return pull(false)
}

View File

@ -55,9 +55,15 @@ func (gui *Gui) quit(v *gocui.View) error {
}
if gui.Config.GetUserConfig().GetBool("confirmOnQuit") {
return gui.createConfirmationPanel(gui.g, v, true, "", gui.Tr.SLocalize("ConfirmQuit"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: "",
prompt: gui.Tr.SLocalize("ConfirmQuit"),
handleConfirm: func() error {
return gocui.ErrQuit
}, nil)
},
})
}
return gocui.ErrQuit

View File

@ -78,13 +78,18 @@ func (gui *Gui) handleGenericMergeCommandResult(result error) error {
// assume in this case that we're already done
return nil
} else if strings.Contains(result.Error(), "When you have resolved this problem") || strings.Contains(result.Error(), "fix conflicts") || strings.Contains(result.Error(), "Resolve all conflicts manually") {
return gui.createConfirmationPanel(gui.g, gui.getFilesView(), true, gui.Tr.SLocalize("FoundConflictsTitle"), gui.Tr.SLocalize("FoundConflicts"),
func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getFilesView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("FoundConflictsTitle"),
prompt: gui.Tr.SLocalize("FoundConflicts"),
handleConfirm: func() error {
return nil
}, func(g *gocui.Gui, v *gocui.View) error {
},
handleClose: func() error {
return gui.genericMergeCommand("abort")
},
)
})
} else {
return gui.createErrorPanel(result.Error())
}

View File

@ -121,9 +121,15 @@ func (gui *Gui) handleCheckoutReflogCommit(g *gocui.Gui, v *gocui.View) error {
return nil
}
err := gui.createConfirmationPanel(g, gui.getCommitsView(), true, gui.Tr.SLocalize("checkoutCommit"), gui.Tr.SLocalize("SureCheckoutThisCommit"), func(g *gocui.Gui, v *gocui.View) error {
err := gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getCommitsView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("checkoutCommit"),
prompt: gui.Tr.SLocalize("SureCheckoutThisCommit"),
handleConfirm: func() error {
return gui.handleCheckoutRef(commit.Sha, handleCheckoutRefOptions{})
}, nil)
},
})
if err != nil {
return err
}

View File

@ -94,7 +94,13 @@ func (gui *Gui) handleDeleteRemoteBranch(g *gocui.Gui, v *gocui.View) error {
return nil
}
message := fmt.Sprintf("%s '%s'?", gui.Tr.SLocalize("DeleteRemoteBranchMessage"), remoteBranch.FullName())
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("DeleteRemoteBranch"), message, func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DeleteRemoteBranch"),
prompt: message,
handleConfirm: func() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("DeletingStatus"), func() error {
if err := gui.GitCommand.DeleteRemoteBranch(remoteBranch.RemoteName, remoteBranch.Name); err != nil {
return err
@ -102,7 +108,8 @@ func (gui *Gui) handleDeleteRemoteBranch(g *gocui.Gui, v *gocui.View) error {
return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, REMOTES}})
})
}, nil)
},
})
}
func (gui *Gui) handleRebaseOntoRemoteBranch(g *gocui.Gui, v *gocui.View) error {
@ -122,13 +129,19 @@ func (gui *Gui) handleSetBranchUpstream(g *gocui.Gui, v *gocui.View) error {
},
)
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("SetUpstreamTitle"), message, func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("SetUpstreamTitle"),
prompt: message,
handleConfirm: func() error {
if err := gui.GitCommand.SetBranchUpstream(selectedBranch.RemoteName, selectedBranch.Name, checkedOutBranch.Name); err != nil {
return err
}
return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, REMOTES}})
}, nil)
},
})
}
func (gui *Gui) handleCreateResetToRemoteBranchMenu(g *gocui.Gui, v *gocui.View) error {
@ -151,8 +164,8 @@ func (gui *Gui) handleNewBranchOffRemote(g *gocui.Gui, v *gocui.View) error {
"branchName": branch.FullName(),
},
)
return gui.createPromptPanel(g, v, message, branch.FullName(), func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.NewBranch(gui.trimmedContent(v), branch.FullName()); err != nil {
return gui.createPromptPanel(v, message, branch.FullName(), func(response string) error {
if err := gui.GitCommand.NewBranch(response, branch.FullName()); err != nil {
return gui.surfaceError(err)
}
gui.State.Panels.Branches.SelectedLine = 0

View File

@ -116,10 +116,8 @@ func (gui *Gui) handleRemoteEnter(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) handleAddRemote(g *gocui.Gui, v *gocui.View) error {
branchesView := gui.getBranchesView()
return gui.createPromptPanel(g, branchesView, gui.Tr.SLocalize("newRemoteName"), "", func(g *gocui.Gui, v *gocui.View) error {
remoteName := gui.trimmedContent(v)
return gui.createPromptPanel(g, branchesView, gui.Tr.SLocalize("newRemoteUrl"), "", func(g *gocui.Gui, v *gocui.View) error {
remoteUrl := gui.trimmedContent(v)
return gui.createPromptPanel(branchesView, gui.Tr.SLocalize("newRemoteName"), "", func(remoteName string) error {
return gui.createPromptPanel(branchesView, gui.Tr.SLocalize("newRemoteUrl"), "", func(remoteUrl string) error {
if err := gui.GitCommand.AddRemote(remoteName, remoteUrl); err != nil {
return err
}
@ -133,14 +131,20 @@ func (gui *Gui) handleRemoveRemote(g *gocui.Gui, v *gocui.View) error {
if remote == nil {
return nil
}
return gui.createConfirmationPanel(g, v, true, gui.Tr.SLocalize("removeRemote"), gui.Tr.SLocalize("removeRemotePrompt")+" '"+remote.Name+"'?", func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("removeRemote"),
prompt: gui.Tr.SLocalize("removeRemotePrompt") + " '" + remote.Name + "'?",
handleConfirm: func() error {
if err := gui.GitCommand.RemoveRemote(remote.Name); err != nil {
return err
}
return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, REMOTES}})
}, nil)
},
})
}
func (gui *Gui) handleEditRemote(g *gocui.Gui, v *gocui.View) error {
@ -157,9 +161,7 @@ func (gui *Gui) handleEditRemote(g *gocui.Gui, v *gocui.View) error {
},
)
return gui.createPromptPanel(g, branchesView, editNameMessage, "", func(g *gocui.Gui, v *gocui.View) error {
updatedRemoteName := gui.trimmedContent(v)
return gui.createPromptPanel(branchesView, editNameMessage, "", func(updatedRemoteName string) error {
if updatedRemoteName != remote.Name {
if err := gui.GitCommand.RenameRemote(remote.Name, updatedRemoteName); err != nil {
return gui.surfaceError(err)
@ -173,8 +175,7 @@ func (gui *Gui) handleEditRemote(g *gocui.Gui, v *gocui.View) error {
},
)
return gui.createPromptPanel(g, branchesView, editUrlMessage, "", func(g *gocui.Gui, v *gocui.View) error {
updatedRemoteUrl := gui.trimmedContent(v)
return gui.createPromptPanel(branchesView, editUrlMessage, "", func(updatedRemoteUrl string) error {
if err := gui.GitCommand.UpdateRemoteUrl(updatedRemoteName, updatedRemoteUrl); err != nil {
return gui.surfaceError(err)
}

View File

@ -11,8 +11,8 @@ import (
func (gui *Gui) handleOpenSearch(g *gocui.Gui, v *gocui.View) error {
gui.State.Searching.isSearching = true
gui.State.Searching.view = v
gui.renderString(gui.g, "search", "")
if err := gui.switchFocus(gui.g, v, gui.getSearchView()); err != nil {
gui.renderString("search", "")
if err := gui.switchFocus(v, gui.getSearchView()); err != nil {
return err
}
@ -21,7 +21,7 @@ func (gui *Gui) handleOpenSearch(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) handleSearch(g *gocui.Gui, v *gocui.View) error {
gui.State.Searching.searchString = gui.getSearchView().Buffer()
if err := gui.switchFocus(gui.g, nil, gui.State.Searching.view); err != nil {
if err := gui.switchFocus(nil, gui.State.Searching.view); err != nil {
return err
}
@ -36,7 +36,6 @@ func (gui *Gui) onSelectItemWrapper(innerFunc func(int) error) func(int, int, in
return func(y int, index int, total int) error {
if total == 0 {
gui.renderString(
gui.g,
"search",
fmt.Sprintf(
"no matches for '%s' %s",
@ -50,7 +49,6 @@ func (gui *Gui) onSelectItemWrapper(innerFunc func(int) error) func(int, int, in
return nil
}
gui.renderString(
gui.g,
"search",
fmt.Sprintf(
"matches for '%s' (%d of %d) %s",
@ -86,7 +84,7 @@ func (gui *Gui) onSearchEscape() error {
}
func (gui *Gui) handleSearchEscape(g *gocui.Gui, v *gocui.View) error {
if err := gui.switchFocus(gui.g, nil, gui.State.Searching.view); err != nil {
if err := gui.switchFocus(nil, gui.State.Searching.view); err != nil {
return err
}

View File

@ -15,7 +15,7 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
// We need to force focus here because the confirmation panel for safely staging lines does not return focus automatically.
// This is because if we tell it to return focus it will unconditionally return it to the main panel which may not be what we want
// e.g. in the event that there's nothing left to stage.
if err := gui.switchFocus(gui.g, nil, gui.getMainView()); err != nil {
if err := gui.switchFocus(nil, gui.getMainView()); err != nil {
return err
}
@ -96,7 +96,7 @@ func (gui *Gui) handleTogglePanel(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) handleStagingEscape(g *gocui.Gui, v *gocui.View) error {
gui.handleEscapeLineByLinePanel()
return gui.switchFocus(gui.g, nil, gui.getFilesView())
return gui.switchFocus(nil, gui.getFilesView())
}
func (gui *Gui) handleToggleStagedSelection(g *gocui.Gui, v *gocui.View) error {
@ -114,9 +114,15 @@ func (gui *Gui) handleResetSelection(g *gocui.Gui, v *gocui.View) error {
}
if !gui.Config.GetUserConfig().GetBool("gui.skipUnstageLineWarning") {
return gui.createConfirmationPanel(gui.g, gui.getMainView(), false, "unstage lines", "Are you sure you want to delete the selected lines (git reset)? It is irreversible.\nTo disable this dialogue set the config key of 'gui.skipUnstageLineWarning' to true", func(*gocui.Gui, *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getMainView(),
returnFocusOnClose: false,
title: gui.Tr.SLocalize("UnstageLinesTitle"),
prompt: gui.Tr.SLocalize("UnstageLinesPrompt"),
handleConfirm: func() error {
return gui.applySelection(true)
}, nil)
},
})
} else {
return gui.applySelection(true)
}

View File

@ -76,11 +76,15 @@ func (gui *Gui) handleStashApply(g *gocui.Gui, v *gocui.View) error {
return apply()
}
title := gui.Tr.SLocalize("StashApply")
message := gui.Tr.SLocalize("SureApplyStashEntry")
return gui.createConfirmationPanel(g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("StashApply"),
prompt: gui.Tr.SLocalize("SureApplyStashEntry"),
handleConfirm: func() error {
return apply()
}, nil)
},
})
}
func (gui *Gui) handleStashPop(g *gocui.Gui, v *gocui.View) error {
@ -94,19 +98,27 @@ func (gui *Gui) handleStashPop(g *gocui.Gui, v *gocui.View) error {
return pop()
}
title := gui.Tr.SLocalize("StashPop")
message := gui.Tr.SLocalize("SurePopStashEntry")
return gui.createConfirmationPanel(g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("StashPop"),
prompt: gui.Tr.SLocalize("SurePopStashEntry"),
handleConfirm: func() error {
return pop()
}, nil)
},
})
}
func (gui *Gui) handleStashDrop(g *gocui.Gui, v *gocui.View) error {
title := gui.Tr.SLocalize("StashDrop")
message := gui.Tr.SLocalize("SureDropStashEntry")
return gui.createConfirmationPanel(g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("StashDrop"),
prompt: gui.Tr.SLocalize("SureDropStashEntry"),
handleConfirm: func() error {
return gui.stashDo(g, v, "drop")
}, nil)
},
})
}
func (gui *Gui) stashDo(g *gocui.Gui, v *gocui.View, method string) error {
@ -130,8 +142,8 @@ func (gui *Gui) handleStashSave(stashFunc func(message string) error) error {
if len(gui.trackedFiles()) == 0 && len(gui.stagedFiles()) == 0 {
return gui.createErrorPanel(gui.Tr.SLocalize("NoTrackedStagedFilesStash"))
}
return gui.createPromptPanel(gui.g, gui.getFilesView(), gui.Tr.SLocalize("StashChanges"), "", func(g *gocui.Gui, v *gocui.View) error {
if err := stashFunc(gui.trimmedContent(v)); err != nil {
return gui.createPromptPanel(gui.getFilesView(), gui.Tr.SLocalize("StashChanges"), "", func(stashComment string) error {
if err := stashFunc(stashComment); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{scope: []int{STASH, FILES}})

View File

@ -57,7 +57,7 @@ func cursorInSubstring(cx int, prefix string, substring string) bool {
func (gui *Gui) handleCheckForUpdate(g *gocui.Gui, v *gocui.View) error {
gui.Updater.CheckForNewUpdate(gui.onUserUpdateCheckFinish, true)
return gui.createLoaderPanel(gui.g, v, gui.Tr.SLocalize("CheckingForUpdates"))
return gui.createLoaderPanel(v, gui.Tr.SLocalize("CheckingForUpdates"))
}
func (gui *Gui) handleStatusClick(g *gocui.Gui, v *gocui.View) error {

View File

@ -104,12 +104,18 @@ func (gui *Gui) handleDeleteTag(g *gocui.Gui, v *gocui.View) error {
},
)
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("DeleteTagTitle"), prompt, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: gui.Tr.SLocalize("DeleteTagTitle"),
prompt: prompt,
handleConfirm: func() error {
if err := gui.GitCommand.DeleteTag(tag.Name); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{COMMITS, TAGS}})
}, nil)
},
})
}
func (gui *Gui) handlePushTag(g *gocui.Gui, v *gocui.View) error {
@ -125,8 +131,8 @@ func (gui *Gui) handlePushTag(g *gocui.Gui, v *gocui.View) error {
},
)
return gui.createPromptPanel(gui.g, v, title, "origin", func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.PushTag(v.Buffer(), tag.Name); err != nil {
return gui.createPromptPanel(v, title, "origin", func(response string) error {
if err := gui.GitCommand.PushTag(response, tag.Name); err != nil {
return gui.surfaceError(err)
}
return nil
@ -134,9 +140,8 @@ func (gui *Gui) handlePushTag(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleCreateTag(g *gocui.Gui, v *gocui.View) error {
return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("CreateTagTitle"), "", func(g *gocui.Gui, v *gocui.View) error {
return gui.createPromptPanel(v, gui.Tr.SLocalize("CreateTagTitle"), "", func(tagName string) error {
// leaving commit SHA blank so that we're just creating the tag for the current commit
tagName := v.Buffer()
if err := gui.GitCommand.CreateLightweightTag(tagName, ""); err != nil {
return gui.surfaceError(err)
}

View File

@ -59,7 +59,7 @@ func (gui *Gui) newStringTask(viewName string, str string) error {
manager := gui.getManager(view)
f := func(stop chan struct{}) error {
gui.renderString(gui.g, viewName, str)
gui.renderString(viewName, str)
return nil
}

View File

@ -166,7 +166,12 @@ func (gui *Gui) handleHardResetWithAutoStash(commitSha string, options handleHar
dirtyWorkingTree := len(gui.trackedFiles()) > 0
if dirtyWorkingTree {
// offer to autostash changes
return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("AutoStashTitle"), gui.Tr.SLocalize("AutoStashPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: gui.getBranchesView(),
returnFocusOnClose: true,
title: gui.Tr.SLocalize("AutoStashTitle"),
prompt: gui.Tr.SLocalize("AutoStashPrompt"),
handleConfirm: func() error {
return gui.WithWaitingStatus(options.WaitingStatus, func() error {
if err := gui.GitCommand.StashSave(gui.Tr.SLocalize("StashPrefix") + commitSha); err != nil {
return gui.surfaceError(err)
@ -183,7 +188,8 @@ func (gui *Gui) handleHardResetWithAutoStash(commitSha string, options handleHar
}
return nil
})
}, nil)
},
})
}
return gui.WithWaitingStatus(options.WaitingStatus, func() error {

View File

@ -3,13 +3,18 @@ package gui
import "github.com/jesseduffield/gocui"
func (gui *Gui) showUpdatePrompt(newVersion string) error {
title := "New version available!"
message := "Download latest version? (enter/esc)"
currentView := gui.g.CurrentView()
return gui.createConfirmationPanel(gui.g, currentView, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: currentView,
returnFocusOnClose: true,
title: "New version available!",
prompt: "Download latest version? (enter/esc)",
handleConfirm: func() error {
gui.startUpdating(newVersion)
return nil
}, nil)
},
})
}
func (gui *Gui) onUserUpdateCheckFinish(newVersion string, err error) error {
@ -47,7 +52,7 @@ func (gui *Gui) startUpdating(newVersion string) {
func (gui *Gui) onUpdateFinish(err error) error {
gui.State.Updating = false
gui.statusManager.removeStatus("updating")
gui.renderString(gui.g, "appStatus", "")
gui.renderString("appStatus", "")
if err != nil {
return gui.createErrorPanel("Update failed: " + err.Error())
}
@ -55,9 +60,13 @@ func (gui *Gui) onUpdateFinish(err error) error {
}
func (gui *Gui) createUpdateQuitConfirmation(g *gocui.Gui, v *gocui.View) error {
title := "Currently Updating"
message := "An update is in progress. Are you sure you want to quit?"
return gui.createConfirmationPanel(gui.g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(createConfirmationPanelOpts{
returnToView: v,
returnFocusOnClose: true,
title: "Currently Updating",
prompt: "An update is in progress. Are you sure you want to quit?",
handleConfirm: func() error {
return gocui.ErrQuit
}, nil)
},
})
}

View File

@ -175,7 +175,7 @@ func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error {
if err := gui.resetOrigin(gui.getMainView()); err != nil {
return err
}
return gui.switchFocus(g, v, focusedView)
return gui.switchFocus(v, focusedView)
}
func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
@ -213,7 +213,7 @@ func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
if err := gui.resetOrigin(gui.getMainView()); err != nil {
return err
}
return gui.switchFocus(g, v, focusedView)
return gui.switchFocus(v, focusedView)
}
func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
@ -272,7 +272,7 @@ func (gui *Gui) returnFocus(g *gocui.Gui, v *gocui.View) error {
gui.Log.Error(err)
}
}
return gui.switchFocus(g, v, previousView)
return gui.switchFocus(v, previousView)
}
func (gui *Gui) goToSideView(sideViewName string) func(g *gocui.Gui, v *gocui.View) error {
@ -287,7 +287,7 @@ func (gui *Gui) goToSideView(sideViewName string) func(g *gocui.Gui, v *gocui.Vi
gui.Log.Error(err)
return nil
}
return gui.switchFocus(g, nil, view)
return gui.switchFocus(nil, view)
}
}
@ -303,7 +303,7 @@ func (gui *Gui) closePopupPanels() error {
// pass in oldView = nil if you don't want to be able to return to your old view
// TODO: move some of this logic into our onFocusLost and onFocus hooks
func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
func (gui *Gui) switchFocus(oldView, newView *gocui.View) error {
// we assume we'll never want to return focus to a popup panel i.e.
// we should never stack popup panels
if oldView != nil && !gui.isPopupPanel(oldView.Name()) {
@ -318,20 +318,20 @@ func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
},
)
gui.Log.Info(message)
if _, err := g.SetCurrentView(newView.Name()); err != nil {
if _, err := gui.g.SetCurrentView(newView.Name()); err != nil {
return err
}
if _, err := g.SetViewOnTop(newView.Name()); err != nil {
if _, err := gui.g.SetViewOnTop(newView.Name()); err != nil {
return err
}
g.Cursor = newView.Editable
gui.g.Cursor = newView.Editable
if err := gui.renderPanelOptions(); err != nil {
return err
}
return gui.newLineFocused(g, newView)
return gui.newLineFocused(gui.g, newView)
}
func (gui *Gui) resetOrigin(v *gocui.View) error {
@ -350,9 +350,9 @@ func (gui *Gui) setViewContent(v *gocui.View, s string) {
}
// renderString resets the origin of a view and sets its content
func (gui *Gui) renderString(g *gocui.Gui, viewName, s string) {
g.Update(func(*gocui.Gui) error {
v, err := g.View(viewName)
func (gui *Gui) renderString(viewName, s string) {
gui.g.Update(func(*gocui.Gui) error {
v, err := gui.g.View(viewName)
if err != nil {
return nil // return gracefully if view has been deleted
}
@ -377,7 +377,7 @@ func (gui *Gui) optionsMapToString(optionsMap map[string]string) string {
}
func (gui *Gui) renderOptionsMap(optionsMap map[string]string) error {
gui.renderString(gui.g, "options", gui.optionsMapToString(optionsMap))
gui.renderString("options", gui.optionsMapToString(optionsMap))
return nil
}

View File

@ -1165,6 +1165,12 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "BranchNotFoundPrompt",
Other: "Branch not found. Create a new branch named",
}, &i18n.Message{
ID: "UnstageLinesTitle",
Other: "Unstage lines",
}, &i18n.Message{
ID: "UnstageLinesPrompt",
Other: "Are you sure you want to delete the selected lines (git reset)? It is irreversible.\nTo disable this dialogue set the config key of 'gui.skipUnstageLineWarning' to true",
},
)
}