1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-03-19 21:28:28 +02:00

use suspense rather than close the gui when switching to a subprocess

This commit is contained in:
Jesse Duffield 2021-04-02 21:30:39 +11:00
parent 6c1a202329
commit ef0d5420d4
9 changed files with 49 additions and 65 deletions

View File

@ -239,7 +239,7 @@ func (app *App) Run() error {
os.Exit(0) os.Exit(0)
} }
err := app.Gui.RunWithSubprocesses() err := app.Gui.RunWithRestarts()
return err return err
} }

View File

@ -11,17 +11,13 @@ import (
// runSyncOrAsyncCommand takes the output of a command that may have returned // runSyncOrAsyncCommand takes the output of a command that may have returned
// either no error, an error, or a subprocess to execute, and if a subprocess // either no error, an error, or a subprocess to execute, and if a subprocess
// needs to be set on the gui object, it does so, and then returns the error // needs to be run, it runs it
// the bool returned tells us whether the calling code should continue
func (gui *Gui) runSyncOrAsyncCommand(sub *exec.Cmd, err error) (bool, error) { func (gui *Gui) runSyncOrAsyncCommand(sub *exec.Cmd, err error) (bool, error) {
if err != nil { if err != nil {
if err != gui.Errors.ErrSubProcess { return false, gui.surfaceError(err)
return false, gui.surfaceError(err)
}
} }
if sub != nil { if sub != nil {
gui.SubProcess = sub return false, gui.runSubprocessWithSuspense(sub)
return false, gui.Errors.ErrSubProcess
} }
return true, nil return true, nil
} }

View File

@ -263,8 +263,7 @@ func (gui *Gui) handleRenameCommitEditor() error {
return gui.surfaceError(err) return gui.surfaceError(err)
} }
if subProcess != nil { if subProcess != nil {
gui.SubProcess = subProcess return gui.runSubprocessWithSuspense(subProcess)
return gui.Errors.ErrSubProcess
} }
return nil return nil

View File

@ -60,8 +60,7 @@ func (gui *Gui) handleCustomCommandKeybinding(customCommand config.CustomCommand
} }
if customCommand.Subprocess { if customCommand.Subprocess {
gui.PrepareShellSubProcess(cmdStr) return gui.runSubprocessWithSuspense(gui.OSCommand.PrepareShellSubProcess(cmdStr))
return nil
} }
loadingText := customCommand.LoadingText loadingText := customCommand.LoadingText

View File

@ -5,7 +5,6 @@ import "github.com/go-errors/errors"
// SentinelErrors are the errors that have special meaning and need to be checked // SentinelErrors are the errors that have special meaning and need to be checked
// by calling functions. The less of these, the better // by calling functions. The less of these, the better
type SentinelErrors struct { type SentinelErrors struct {
ErrSubProcess error
ErrNoFiles error ErrNoFiles error
ErrSwitchRepo error ErrSwitchRepo error
ErrRestart error ErrRestart error
@ -25,7 +24,6 @@ const UNKNOWN_VIEW_ERROR_MSG = "unknown view"
// localising things in the code. // localising things in the code.
func (gui *Gui) GenerateSentinelErrors() { func (gui *Gui) GenerateSentinelErrors() {
gui.Errors = SentinelErrors{ gui.Errors = SentinelErrors{
ErrSubProcess: errors.New(gui.Tr.RunningSubprocess),
ErrNoFiles: errors.New(gui.Tr.NoChangedFiles), ErrNoFiles: errors.New(gui.Tr.NoChangedFiles),
ErrSwitchRepo: errors.New("switching repo"), ErrSwitchRepo: errors.New("switching repo"),
ErrRestart: errors.New("restarting"), ErrRestart: errors.New("restarting"),
@ -34,7 +32,6 @@ func (gui *Gui) GenerateSentinelErrors() {
func (gui *Gui) sentinelErrorsArr() []error { func (gui *Gui) sentinelErrorsArr() []error {
return []error{ return []error{
gui.Errors.ErrSubProcess,
gui.Errors.ErrNoFiles, gui.Errors.ErrNoFiles,
gui.Errors.ErrSwitchRepo, gui.Errors.ErrSwitchRepo,
gui.Errors.ErrRestart, gui.Errors.ErrRestart,

View File

@ -17,7 +17,6 @@ import (
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/mgutz/str"
) )
// list panel functions // list panel functions
@ -475,24 +474,9 @@ func (gui *Gui) handleCommitEditorPress() error {
return gui.promptToStageAllAndRetry(gui.handleCommitEditorPress) return gui.promptToStageAllAndRetry(gui.handleCommitEditorPress)
} }
gui.PrepareSubProcess("git commit") return gui.runSubprocessWithSuspense(
return nil gui.OSCommand.PrepareSubProcess("git", "commit"),
} )
// PrepareSubProcess - prepare a subprocess for execution and tell the gui to switch to it
func (gui *Gui) PrepareSubProcess(command string) {
splitCmd := str.ToArgv(command)
gui.SubProcess = gui.OSCommand.PrepareSubProcess(splitCmd[0], splitCmd[1:]...)
gui.g.Update(func(g *gocui.Gui) error {
return gui.Errors.ErrSubProcess
})
}
func (gui *Gui) PrepareShellSubProcess(command string) {
gui.SubProcess = gui.OSCommand.PrepareShellSubProcess(command)
gui.g.Update(func(g *gocui.Gui) error {
return gui.Errors.ErrSubProcess
})
} }
func (gui *Gui) editFile(filename string) error { func (gui *Gui) editFile(filename string) error {
@ -816,8 +800,9 @@ func (gui *Gui) handleCustomCommand() error {
return gui.prompt(promptOpts{ return gui.prompt(promptOpts{
title: gui.Tr.CustomCommand, title: gui.Tr.CustomCommand,
handleConfirm: func(command string) error { handleConfirm: func(command string) error {
gui.SubProcess = gui.OSCommand.PrepareShellSubProcess(command) return gui.runSubprocessWithSuspense(
return gui.Errors.ErrSubProcess gui.OSCommand.PrepareShellSubProcess(command),
)
}, },
}) })
} }

View File

@ -31,9 +31,9 @@ func (gui *Gui) gitFlowFinishBranch(gitFlowConfig string, branchName string) err
return gui.createErrorPanel(gui.Tr.NotAGitFlowBranch) return gui.createErrorPanel(gui.Tr.NotAGitFlowBranch)
} }
subProcess := gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "finish", suffix) return gui.runSubprocessWithSuspense(
gui.SubProcess = subProcess gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "finish", suffix),
return gui.Errors.ErrSubProcess )
} }
func (gui *Gui) handleCreateGitFlowMenu() error { func (gui *Gui) handleCreateGitFlowMenu() error {
@ -55,9 +55,9 @@ func (gui *Gui) handleCreateGitFlowMenu() error {
return gui.prompt(promptOpts{ return gui.prompt(promptOpts{
title: title, title: title,
handleConfirm: func(name string) error { handleConfirm: func(name string) error {
subProcess := gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "start", name) return gui.runSubprocessWithSuspense(
gui.SubProcess = subProcess gui.OSCommand.PrepareSubProcess("git", "flow", branchType, "start", name),
return gui.Errors.ErrSubProcess )
}, },
}) })
} }

View File

@ -476,10 +476,9 @@ func (gui *Gui) Run() error {
return err return err
} }
// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration // RunWithRestarts loops, instantiating a new gocui.Gui with each iteration
// if the error returned from a run is a ErrSubProcess, it runs the subprocess // (i.e. when switching repos or restarting). If it's a random error, we quit
// otherwise it handles the error, possibly by quitting the application func (gui *Gui) RunWithRestarts() error {
func (gui *Gui) RunWithSubprocesses() error {
gui.StartTime = time.Now() gui.StartTime = time.Now()
go utils.Safe(gui.replayRecordedEvents) go utils.Safe(gui.replayRecordedEvents)
@ -512,11 +511,6 @@ func (gui *Gui) RunWithSubprocesses() error {
return nil return nil
case gui.Errors.ErrSwitchRepo, gui.Errors.ErrRestart: case gui.Errors.ErrSwitchRepo, gui.Errors.ErrRestart:
continue continue
case gui.Errors.ErrSubProcess:
if err := gui.runCommand(); err != nil {
return err
}
default: default:
return err return err
} }
@ -524,23 +518,40 @@ func (gui *Gui) RunWithSubprocesses() error {
} }
} }
func (gui *Gui) runCommand() error { func (gui *Gui) runSubprocessWithSuspense(subprocess *exec.Cmd) error {
gui.SubProcess.Stdout = os.Stdout if err := gocui.Screen.Suspend(); err != nil {
gui.SubProcess.Stderr = os.Stdout return gui.surfaceError(err)
gui.SubProcess.Stdin = os.Stdin }
fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(gui.SubProcess.Args, " "), color.FgBlue)) cmdErr := gui.runSubprocess(subprocess)
if err := gui.SubProcess.Run(); err != nil { if err := gocui.Screen.Resume(); err != nil {
return gui.surfaceError(err)
}
if err := gui.refreshSidePanels(refreshOptions{mode: ASYNC}); err != nil {
return err
}
return gui.surfaceError(cmdErr)
}
func (gui *Gui) runSubprocess(subprocess *exec.Cmd) error {
subprocess.Stdout = os.Stdout
subprocess.Stderr = os.Stdout
subprocess.Stdin = os.Stdin
fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(subprocess.Args, " "), color.FgBlue))
if err := subprocess.Run(); err != nil {
// not handling the error explicitly because usually we're going to see it // not handling the error explicitly because usually we're going to see it
// in the output anyway // in the output anyway
gui.Log.Error(err) gui.Log.Error(err)
} }
gui.SubProcess.Stdout = ioutil.Discard subprocess.Stdout = ioutil.Discard
gui.SubProcess.Stderr = ioutil.Discard subprocess.Stderr = ioutil.Discard
gui.SubProcess.Stdin = nil subprocess.Stdin = nil
gui.SubProcess = nil
fmt.Fprintf(os.Stdout, "\n%s", utils.ColoredString(gui.Tr.PressEnterToReturn, color.FgGreen)) fmt.Fprintf(os.Stdout, "\n%s", utils.ColoredString(gui.Tr.PressEnterToReturn, color.FgGreen))
fmt.Scanln() // wait for enter press fmt.Scanln() // wait for enter press

View File

@ -50,8 +50,7 @@ func (gui *Gui) genericMergeCommand(command string) error {
if status == commands.REBASE_MODE_MERGING && command != "abort" && gui.Config.GetUserConfig().Git.Merging.ManualCommit { if status == commands.REBASE_MODE_MERGING && command != "abort" && gui.Config.GetUserConfig().Git.Merging.ManualCommit {
sub := gui.OSCommand.PrepareSubProcess("git", commandType, fmt.Sprintf("--%s", command)) sub := gui.OSCommand.PrepareSubProcess("git", commandType, fmt.Sprintf("--%s", command))
if sub != nil { if sub != nil {
gui.SubProcess = sub return gui.runSubprocessWithSuspense(sub)
return gui.Errors.ErrSubProcess
} }
return nil return nil
} }
@ -68,8 +67,6 @@ func (gui *Gui) handleGenericMergeCommandResult(result error) error {
} }
if result == nil { if result == nil {
return nil return nil
} else if result == gui.Errors.ErrSubProcess {
return result
} else if strings.Contains(result.Error(), "No changes - did you forget to use") { } else if strings.Contains(result.Error(), "No changes - did you forget to use") {
return gui.genericMergeCommand("skip") return gui.genericMergeCommand("skip")
} else if strings.Contains(result.Error(), "The previous cherry-pick is now empty") { } else if strings.Contains(result.Error(), "The previous cherry-pick is now empty") {