如何从Go中启动vim?

huangapple go评论93阅读模式
英文:

How to start vim from go?

问题

我有一个用Golang编写的命令行工具,我需要从中启动vim。然而,它不起作用,也没有任何错误或其他可用的信息。我将代码简化为以下内容:

package main

import (
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("vim", "test.txt")
	err := cmd.Run()
	fmt.Println(err)
}

当我运行这段代码时,我可以看到vim进程持续运行2-3秒,但实际上应用程序并没有打开。然后程序简单地退出(vim进程关闭),并显示"exit status 1"。

我还尝试了以下代码来捕获stderr:

package main

import (
	"bytes"
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("vim", "test.txt")
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	err := cmd.Run()
	fmt.Println(err)
	fmt.Println(stderr)
}

但在这种情况下,程序会无限期地停滞。

有任何想法是什么问题呢?

英文:

I've got a command line tool written in Golang and I need to start vim from it. However it's not working, and there's not any error or much else to work with. I've reduced the code to just this:

package main

import (
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("vim", "test.txt")
	err := cmd.Run()
	fmt.Println(err)
}

When I run this, I can see the vim process for a 2-3 seconds but the application doesn't actually open. Then the program simply exits (and the vim process closes) with an "exit status 1".

I've also tried this to capture stderr:

package main

import (
	"bytes"
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("vim", "test.txt")
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	err := cmd.Run()
	fmt.Println(err)
	fmt.Println(stderr)
}

But in this case, the program gets stuck indefinitely.

Any idea what could be the issue?

答案1

得分: 24

stdinstdout从调用程序传递给它,如果调用程序是从终端运行的(通常是命令行程序),它将为您启动vim,并在用户完成编辑文件后返回控制。

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("vim", "test.txt")
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	err := cmd.Run()
	fmt.Println(err)
}
英文:

Pass on stdin and stdout from the calling program which, provided it was run from a terminal (likely for a command line program) will start vim for you and return control when the user has finished editing the file.

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("vim", "test.txt")
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	err := cmd.Run()
	fmt.Println(err)
}

答案2

得分: 7

VIM需要一个合适的终端,并会检测是否缺少终端。

如果你在vim运行时使用StderrPipe并读取它,你会看到以下内容:

2014/02/02 20:25:49 Vim: 警告: 输出不是终端
2014/02/02 20:25:49 Vim: 警告: 输入不是终端

以下是在执行过程中读取stderr的示例(在playground上):

func logger(pipe io.ReadCloser) {
	reader := bufio.NewReader(pipe)

	for {
		output, err := reader.ReadString('\n')

		if err != nil {
			log.Println(err)
			return
		}

		log.Print(string(output))
	}
}

pipe, err := cmd.StderrPipe()

go logger(pipe)
cmd.Run()

为了让vim正常运行,你可能需要模拟一个终端。

也许goat文档)可以帮到你:

tty := term.NewTTY(os.Stdin)

cmd := exec.Command("vim", "test.txt")
cmd.Stdin = t
cmd.Stdout = t

// ...
英文:

VIM needs a proper terminal and detects the absence of one.

If you use the StderrPipe and read it while vim is running you will see this:

2014/02/02 20:25:49 Vim: Warning: Output is not to a terminal
2014/02/02 20:25:49 Vim: Warning: Input is not from a terminal

Example for reading stderr while executing (on play):

func logger(pipe io.ReadCloser) {
	reader := bufio.NewReader(pipe)

	for {
		output, err := reader.ReadString('\n')

		if err != nil {
			log.Println(err)
			return
		}

		log.Print(string(output))
	}
}

pipe, err := cmd.StderrPipe()

go logger(pipe)
cmd.Run()

For vim to run you probably need to emulate a terminal.

Maybe goat (doc) can help you out:

tty := term.NewTTY(os.Stdin)

cmd := exec.Command("vim", "test.txt")
cmd.Stdin = t
cmd.Stdout = t

// ...

huangapple
  • 本文由 发表于 2014年2月3日 00:55:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/21513321.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定