如何在Go中启动Vim?

9

我有一个用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进程关闭),并显示“退出状态1”。 我还尝试捕获标准错误输出:
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)
}

但是在这种情况下,程序会无限期地被卡住。

你有什么想法是什么问题?

2个回答

24

将调用程序的标准输入和标准输出传递给Vim。如果调用程序是从终端(可能是命令行程序)运行的,它将为您启动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)
}

想要从Go中运行vimdiff。本以为需要处理pty,但实际上不需要。这很容易。感谢提供干净的示例。 - WeakPointer

7

VIM需要一个合适的终端并检测其是否存在。

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

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

执行过程中读取stderr的示例(在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()

为了让vim运行,可能需要模拟终端。

也许goat文档)可以帮助您:

tty := term.NewTTY(os.Stdin)

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

// ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接