2

我如何在 Go 中进行“光标向上”?(清楚到行尾也很高兴知道)。(所有平台)。

为了详细说明和显示上下文,我正在用 Go 编写一个测试程序,它需要输入一些参数(通过控制台),这些参数存储在一个文本文件中并用作下一次使用的默认值。我想要一些非常基本的控制台“编辑”功能。

目前它相当原始,因为我不想深入控制台编辑,我只想要一些相当基本但又不太基本的东西。

在下面来自我的测试程序的示例中,字符串变量“sPrompt”包含输入提示,右侧显示默认值,然后有退格字符来定位光标,这样默认值就不会被覆盖——就像我说,很基础。

当操作员输入输入时,如果出现错误,我想显示一条错误消息,然后在任何一种情况下将光标向上移动到刚刚显示/输入的行,如果出现错误,则显示原始行,或者如果正确,只显示提示和新参数。

我确实在某处读到应该避免使用 ReadLine(),但它似乎可以完成这项工作。

例子:

func fInputString(sPrompt string, asValid []string, sDefault string)
    (sInput string, tEnd bool) {

    oBufReader := bufio.NewReader(os.Stdin)
    for {
        print("\n" + sPrompt)
        vLine, _, _ := oBufReader.ReadLine()
        sInput = strings.ToLower(string(vLine))
        if sInput == "end" {
            return "", true
        }
        if sInput == "" {
            sInput = sDefault
        }
        // check for valid input //
        for _, sVal := range asValid {
            if sInput == sVal {
                return sInput, false
            }
        }
    }
}

这就是 sPrompt 的构造方式(不是为了优化):

if sDefault != "" {
    for len(sPrompt) < 67 {
        sPrompt += " "
    }
    sPrompt += sDefault
    for iBack := 20 + len(sDefault); iBack > 0; iBack-- {
        sPrompt += "\b"
    }
}
4

2 回答 2

-1

使用tput字符串控制屏幕周围的光标:

  • tput sc保存光标位置
  • tput rc恢复光标位置

然后在 Go 函数中使用这些字符串:

package main

import (
    "fmt"
    "time"
)

const sc = "\u001B7"
const rc = "\u001B8"

func main() {
    fmt.Print(sc)
    for i := 1; i <= 10; i++ {
        fmt.Print(rc + sc)
        fmt.Println(i, "one")
        fmt.Println(i, "two")
        fmt.Println(i, "three")
        fmt.Println(i, "four")
        fmt.Println(i, "five")
        time.Sleep(time.Second)
    }
}

应该在大多数终端中工作。

于 2020-09-17T22:56:17.843 回答
-2

制作自己的小贝壳

您不应该重新发明轮子并使用完全符合您要求的库。一个流行的选项是readline 库,它显然也可用于 Windows。例如,bash 和 ZSH 使用它。有一些 Go 包装器:

  1. https://github.com/shavac/readline
  2. https://github.com/bobappleyard/readline

我个人会推荐bobappleyard/readline它,因为它有更好的文档并且有更好的 API(不像 C)。Windows 似乎没有特殊的构建标签,因此您可能必须自己编写它,但这应该不难。

@bgp已经指出的termbox及其(纯)Go 实现termbox-go似乎不适用于简单地阅读一行,因为它似乎更适用于全屏控制台应用程序。此外,您必须自己编写向上/向下匹配和历史记录。

.Readline()

该文档说您不应该使用它是正确的,因为它不会为您处理任何事情。例如,从发出部分数据的流中读取,您无法保证会从Readline. 为此使用ReadSlice('\n')

于 2013-11-06T14:41:43.317 回答