I am trying to figure out how to launch an external editor from within a Go program, wait for the user to close the editor, and then continue execution of the program. Based on this SO answer, I currently have this code:
package main
import (
"log"
"os"
"os/exec"
)
func main() {
fpath := os.TempDir() + "/thetemporaryfile.txt"
f, err := os.Create(fpath)
if err != nil {
log.Printf("1")
log.Fatal(err)
}
f.Close()
cmd := exec.Command("vim", fpath)
err = cmd.Start()
if err != nil {
log.Printf("2")
log.Fatal(err)
}
err = cmd.Wait()
if err != nil {
log.Printf("Error while editing. Error: %v
", err)
} else {
log.Printf("Successfully edited.")
}
}
When I run the program, I get this:
chris@DPC3:~/code/go/src/launcheditor$ go run launcheditor.go
2012/08/23 10:50:37 Error while editing. Error: exit status 1
chris@DPC3:~/code/go/src/launcheditor$
I have also tried using exec.Run()
instead of exec.Start()
, but that doesn't seem to work either (though it doesn't fail at the same place).
I can get it to work if I use Gvim instead of Vim, but it refuses to work with both Vim and nano. I think it's related to Vim and nano running inside the terminal emulator instead of creating an external window.
Apparently, you have to set Stdin
, Stdout
and Stderr
on the Cmd
object to os.Std(in|out|err)
. Like this (assuming that the object is called cmd
):
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Credit for solving this goes to the guys on #go-nuts on freenode.
Here in cmd := exec.Command("vim", fpath)
, you're doing more or less:
$ PATH= vim foo.txt
bash: vim: No such file or directory
$
Shell uses the PATH environment variable, exec.Command
does not. You have to lookup the vim
binary and pass its full path to exec.Command
. exec.LookPath does that for you.
This works for me but it has the disadvantage of opening another terminal (which will automatically close after edition) :
cmd := exec.Command("/usr/bin/xterm", "-e", "vim "+fpath)