How to print to console while waiting for user input in Go?

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

How to print to console while waiting for user input in Go?

问题

我正在编写一个交互式应用程序,它在循环中接受用户输入并在后台打印出响应。我的代码中的读取部分如下所示:

scanner := bufio.NewReader(os.Stdin)
for {
    fmt.Print(":: ")                // 提示用户输入内容
    in,_:=scanner.ReadString('\n')
}

然而,在等待用户输入时,我想要打印一些通过网络获取的异步数据,如下所示:

>> Some text
>> :: Hi I'm the user and I'm

现在一些后台数据到达:

>> Some text
>> This data was printed while user was inputting
>> :: Hi I'm the user and I'm

现在用户可以完成他们的输入:

>> Some text
>> This data was printed while user was inputting
>> :: Hi I'm the user and I'm entering some text
>> ::

我在考虑后台程序需要扫描stdin以获取文本,以某种方式擦除它,打印自己的数据,并恢复原始文本。我不知道如何扫描尚未通过回车键输入的文本,或者如何清除一行。我该如何处理这个问题?

英文:

I am writing an interactive application that accepts user inputs in a loop and prints out responses in the background. The reader part of my code looks like:

scanner := bufio.NewReader(os.Stdin)
for {
    fmt.Print(":: ")                // prompt for user to enter stuff
    in,_:=scanner.ReadString('\n')
}

However, while I am waiting for the user input, I want to print some asynchronous data I got over the network like so:

>> Some text
>> :: Hi I'm the user and I'm

Now some background data arrives:

>> Some text
>> This data was printed while user was inputting
>> :: Hi I'm the user and I'm

And now the user can finish their input:

>> Some text
>> This data was printed while user was inputting
>> :: Hi I'm the user and I'm entering some text
>> :: 

I'm thinking that the background routine would need to scan stdin for text, erase it somehow, print its own data, and restore the original text. I do not know how to scan text that has not been input via the enter key, or how to clear a line. How do I go about it?

答案1

得分: 1

清除一行可以使用\r将光标返回到行的开头,然后用空格替换该行上的所有字符,然后再次使用\r返回到行的开头。例如(如果需要,可以添加更多空格):

fmt.Printf("\r                                                        \r")

现在,您可以在用户输入的数据上打印您的背景数据。

那么如何重新打印用户输入的数据呢?您无法从终端本身读取它,因此在输入时必须将其保存在某个地方。一种方法是在终端上禁用输入缓冲,这样您键入的每个字符都会立即刷新到stdin,您可以从stdin中读取它。例如:

var input []byte
reader := bufio.NewReader(os.Stdin)
// 禁用输入缓冲
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
// 将键入的每个字符追加到input切片中
for {
        b, err := reader.ReadByte()
        if err != nil {
                panic(err)
        }
        input = append(input, b)
}

因此,当您需要插入背景数据时,首先清除该行,然后打印您的背景数据,最后在下一行打印输入变量的内容。

英文:

To clear a line you can use \r to return the cursor to the beginning of line and then replace all the characters on the line with whitespace and then issue another \r to return to the beginning of line again. For example (add more spaces if needed):

fmt.Printf("\r                                                        \r")

Now you can print your background data on top of the data user had inputted.

Then how do you reprint the data user had inputted? You can't read it from terminal itself so you have to save it somewhere while it's being input. One way to do this would be to disable input buffering on your terminal so each character you type immediately gets flushed to stdin where you can read it. For example:

var input []byte
reader := bufio.NewReader(os.Stdin)
// disables input buffering
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
// append each character that gets typed to input slice
for {
        b, err := reader.ReadByte()
        if err != nil {
                panic(err)
        }
        input = append(input, b)
}

So when you need to insert background data, first clear the line, then print your background data and finally print the contents of the input variable on the next line.

huangapple
  • 本文由 发表于 2016年10月4日 04:14:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/39839661.html
匿名

发表评论

匿名网友

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

确定