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:
parent
6c1a202329
commit
ef0d5420d4
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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") {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user