2016-10-03 74 views
3

我正在寫一個交互式應用程序,它接受循環中的用戶輸入並在後臺輸出響應。我的代碼的讀取器部分是這樣的:如何在Go中等待用戶輸入時打印到控制檯?

scanner := bufio.NewReader(os.Stdin) 
for { 
    fmt.Print(":: ")    // prompt for user to enter stuff 
    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,以某種方式擦除它,打印自己的數據,並恢復原始文本。我不知道如何掃描未通過輸入鍵輸入的文本,或者如何清除一行。我該如何解決它?

+2

也許你可以用這些https://github.com/avelino/awesome-go#advanced-console-uis中的一個來做這樣的事情,特別是termbox或其上的一個包? – jcbwlkr

+0

@jcbwlkr謝謝。我最終使用鏈接中的'termbox-go'。我不得不寫我自己的打印功能和管理光標位置等,但最終我得到了我想要的效果。 – hazrmard

回答

1

要清除一條線,您可以使用\r將光標返回到行的開頭,然後用空白替換該行上的所有字符,然後發出另一個\r以再次返回行的開頭。例如(如果需要添加更多空間):

fmt.Printf("\r              \r") 

現在,您可以打印數據用戶的頂部後臺數據已經輸入。

那你怎麼重印數據用戶輸入的?您無法從終端本身讀取它,因此您必須在輸入時將其保存在某個位置。一種方法是在你的終端上禁用輸入緩衝,以便你立即輸入的每個字符都被刷新到標準輸入,你可以在其中讀取它。例如:

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) 
} 

所以,當你需要插入背景數據,首先要明確的線,然後打印後臺數據最後打印在下一行輸入變量的內容。

+0

謝謝。然而,這看起來像只能在linux上工作,而不是Windows,因爲'exec.Command'的參數。 – hazrmard