Skip to content

Conversation

@jesseduffield
Copy link
Owner

@jesseduffield jesseduffield commented Aug 5, 2018

Based on issue #12

We need to be able to run a subprocess, wait for it to return, then continue running without issues. For example, opening vim to edit a file, and running git add -p. This is proving challenging!

This PR makes a start in the context of editing files.

This opens the chosen editor via $VISUAL and $EDITOR env variables when you press 'e' on a file. There's some weird issues here that occur when you try and run a subprocess then wait for it to finish. The closest I've got is running the subprocess, then running another instance of Gui (yes this is a bad solution). If you just return to the same Gui instance, and start switching through panels, weird glitchy characters start showing up. Anybody with Go skills your help is much appreciated!

If you pull down this branch and press 'e' (edit) on a file, an editor should pop up and you should be able to exit it and return to the application. Ideally we want to have that happen without needing to close or reinitialize the Gui.

gitcommands.go Outdated
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Run()
run()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restarting the Gui here with run()

@jesseduffield jesseduffield force-pushed the feature/better-file-opening branch from f780df2 to 9067c3b Compare August 6, 2018 13:29
@jesseduffield jesseduffield changed the title WIP: Opening editors as a subprocess WIP: Opening a subprocess Aug 6, 2018
@char101
Copy link

char101 commented Aug 7, 2018

Closing and rerunning the CUI should be done outside of the main loop, for example:

diff --git a/.gitignore b/.gitignore
index 5210291..cd61867 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ extra/lgit.rb
 notes/go.notes
 TODO.notes
 TODO.md
+vendor/github.com/fatih/color/Gopkg.lock
+vendor/github.com/fatih/color/Gopkg.toml
diff --git a/gitcommands.go b/gitcommands.go
index 27b5677..7b96311 100644
--- a/gitcommands.go
+++ b/gitcommands.go
@@ -351,13 +351,14 @@ func getOpenCommand() (string, string) {
 func runSubProcess(g *gocui.Gui, cmdName string, commandArgs ...string) {
 	// TODO: find a way to wait for the subprocess without having to
 	// close and reinitialize the gui
-	// g.Close() // TODO: find a way to make close properly after uncommenting
-	cmd := exec.Command(cmdName, commandArgs...)
-	cmd.Stdin = os.Stdin
-	cmd.Stdout = os.Stdout
-	cmd.Stderr = os.Stderr
-	cmd.Run()
-	run() // start another Gui
+	subprocess = exec.Command(cmdName, commandArgs...)
+	subprocess.Stdin = os.Stdin
+	subprocess.Stdout = os.Stdout
+	subprocess.Stderr = os.Stderr
+
+	g.Update(func(g *gocui.Gui) error {
+		return ErrSubprocess
+	})
 }
 
 func getBranchDiff(branch string, baseBranch string) (string, error) {
diff --git a/gui.go b/gui.go
index b2bda8c..a3a92bd 100644
--- a/gui.go
+++ b/gui.go
@@ -5,7 +5,6 @@ import (
 	// "io"
 	// "io/ioutil"
 
-	"log"
 	"strings"
 	"time"
 
@@ -321,10 +320,10 @@ func updateLoader(g *gocui.Gui) {
 	}
 }
 
-func run() {
+func run() (err error) {
 	g, err := gocui.NewGui(gocui.OutputNormal, OverlappingEdges)
 	if err != nil {
-		log.Panicln(err)
+		return
 	}
 	defer g.Close()
 
@@ -343,13 +342,12 @@ func run() {
 
 	g.SetManagerFunc(layout)
 
-	if err := keybindings(g); err != nil {
-		log.Panicln(err)
+	if err = keybindings(g); err != nil {
+		return
 	}
 
-	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
-		log.Panicln(err)
-	}
+	err = g.MainLoop()
+	return
 }
 
 func quit(g *gocui.Gui, v *gocui.View) error {
diff --git a/main.go b/main.go
index b3586b0..da2454a 100644
--- a/main.go
+++ b/main.go
@@ -1,19 +1,24 @@
 package main
 
 import (
+	"errors"
 	"flag"
 	"fmt"
 	"log"
 	"os"
+	"os/exec"
 	"os/user"
 	"time"
 
 	"github.com/fatih/color"
+	"github.com/jesseduffield/gocui"
 )
 
 var (
-	startTime time.Time
-	debugging bool
+	startTime     time.Time
+	debugging     bool
+	ErrSubprocess = errors.New("running subprocess")
+	subprocess    *exec.Cmd
 )
 
 func homeDirectory() string {
@@ -65,5 +70,15 @@ func main() {
 	startTime = time.Now()
 	verifyInGitRepo()
 	navigateToRepoRootDirectory()
-	run()
+	for {
+		if err := run(); err != nil {
+			if err == gocui.ErrQuit {
+				break
+			} else if err == ErrSubprocess {
+				subprocess.Run()
+			} else {
+				log.Panicln(err)
+			}
+		}
+	}
 }

@jesseduffield
Copy link
Owner Author

Really good stuff, that'll do it! In debugging I did come across one crash scenario but couldn't replicate it so I'm confident moving forward with this

@ponsfrilus
Copy link
Contributor

Is there a way to use core.editor git variable if set ?

By default, Git uses whatever you’ve set as your default text editor via one of the shell environment variables VISUAL or EDITOR, or else falls back to the vi editor to create and edit your commit and tag messages. To change that default to something else, you can use the core.editor setting:

$ git config --global core.editor emacs

Now, no matter what is set as your default shell editor, Git will fire up Emacs to edit messages.

https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration

@jesseduffield jesseduffield merged commit 4281cc2 into master Aug 8, 2018
@Androbin
Copy link

Don't forget to update the "Spawning Subprocesses" milestone in the README.

@jesseduffield jesseduffield deleted the feature/better-file-opening branch July 7, 2019 11:46
LordHerdier pushed a commit to LordHerdier/lazygit that referenced this pull request Jun 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants