如何在Go中进行游标?

时间:2013-10-06 04:42:30

标签: go

如何在Go中“向上移动”? (清除到终点也很有用)。 (所有平台)。

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

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

在我的测试程序的下面的例子中,String变量“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"
    }
}

2 个答案:

答案 0 :(得分:-1)

制作自己的小贝壳

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

  1. https://github.com/shavac/readline
  2. https://github.com/bobappleyard/readline
  3. 我个人会推荐bobappleyard/readline,因为它有更好的记录 并且具有更好的API(更少C类)。似乎没有特殊的构建标记 Windows,所以你可能不得不为自己编写,但这应该不那么难。

    @ pgp已经指出的

    termbox及其(纯)Go实现termbox-go 似乎对于简单地阅读一行似乎很好更有意思 用于全屏控制台应用程序。此外,您还必须编写上/下匹配代码 和自己的历史。

    .Readline()

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

答案 1 :(得分:-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)
    }
}

应该可以在大多数终端上使用。