使用golang编写的libvterm

由于有空余时间,所以进行填补工作。

libvterm 是什么

libvterm是由知名的libtermkey作者Paul Evans先生开发的一个库,用于抽象化和模拟VT220/xterm/ECMA-48等终端仿真器的规范。根据该库的规范进行编程,可以在不依赖于平台和GUI/CUI的情况下操作终端仿真器。它被用作neovim和vim的:terminal功能。

libvterm不是一个shell,也不是一个用户界面。它是一个纯粹的虚拟终端模拟器的实现。因此,它不会读取键盘输入,也不会进行任何绘制操作。它只能写入终端单元格的转义序列等,并且只能获取由此控制的终端的输出结果。

所以,例如,在创建一个可以启动shell并与用户进行交互的终端模拟器时,程序将启动一个子进程(shell)并读取其pty输出流,然后将其传递给libvterm。同时,根据来自libvterm的回调事件,将读取终端的单元格信息并渲染到自定义用户界面上。

libvterm

我想从Go语言中使用libvterm。

我以前用Go语言写了一个用于处理libvterm的包。

我將使用這個套件,在80×25的終端機上寫一個程式,以紅色顯示「Hello」,綠色顯示「World」。

vt := vterm.New(25, 80)
defer vt.Close()

vt.SetUTF8(true)

screen := vt.ObtainScreen()
screen.Reset(true)

_, err := vt.Write([]byte("\033[31mHello \033[32mGolang\033[0m"))
if err != nil {
    log.Fatal(err)
}
screen.Flush()

即使执行这段代码,实际上也不会显示任何内容。也许你会想,“这有什么好的?” 接下来,让我们继续写以下的代码。

    rows, cols := vt.Size()
    img := image.NewRGBA(image.Rect(0, 0, cols*7, rows*13))
    draw.Draw(img, img.Bounds(), &image.Uniform{color.Black}, image.ZP, draw.Src)

    for row := 0; row < rows; row++ {
        for col := 0; col < cols; col++ {
            cell, err := screen.GetCellAt(row, col)
            if err != nil {
                log.Fatal(err)
            }
            chars := cell.Chars()
            if len(chars) > 0 && chars[0] != 0 {
                drawChar(img, (col+1)*7, (row+1)*13, cell.Fg(), string(chars))
            }
        }
    }
    f, err := os.Create("output.png")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    err = png.Encode(f, img)
    if err != nil {
        log.Fatal(err)
    }

通过这样的方法,可以拍摄到80×25的终端屏幕截图。

output.png

我将整个程序的代码复制粘贴到Gist上。

可以通过go-libvterm实现的功能。

由于可以在设备上嵌入不依赖于应用程序的终端画布,例如与Windows虚拟终端实现winpty结合使用,可以在命令提示符中创建类似于tmux的窗格,可以进一步在其中嵌入命令提示符。

terminal6.gif

如果您想在自己创建的窗口应用程序中加入Visual Studio Code的终端功能或Vim/neovim的:terminal功能,那么使用libvterm会很方便。而且如果该应用程序是用Go语言实现的,您可以使用go-libvterm。

如果您愿意,请使用我们的服务。

广告
将在 10 秒后关闭
bannerAds