问题
I have the following program that reads user input from stdin:
var input string = ""
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
exec.Command("stty", "-F", "/dev/tty", "-echo").Run()
var b []byte = make([]byte, 1)
for {
input += string(b)
}
I want to place some kind of condition inside the for loop so that i can "break" when the user presses "enter" (for example) or remove one char from a string when the user presses (backspace). However, i can't figure out what the byte array or string representation of those two keys are. How do i go about figuring this out ? enter just prints a \w and backspace prins an undefined character.
回答1:
Your use case is explained in this blog post. Just cross posting the necessary solution from the referenced blog:-
package main
import (
"fmt"
term "github.com/nsf/termbox-go"
)
func reset() {
term.Sync() // cosmestic purpose
}
func main() {
err := term.Init()
if err != nil {
panic(err)
}
defer term.Close()
fmt.Println("Enter any key to see their ASCII code or press ESC button to quit")
keyPressListenerLoop:
for {
switch ev := term.PollEvent(); ev.Type {
case term.EventKey:
switch ev.Key {
case term.KeyEsc:
break keyPressListenerLoop
case term.KeyF1:
reset()
fmt.Println("F1 pressed")
case term.KeyF2:
reset()
fmt.Println("F2 pressed")
case term.KeyF3:
reset()
fmt.Println("F3 pressed")
case term.KeyF4:
reset()
fmt.Println("F4 pressed")
case term.KeyF5:
reset()
fmt.Println("F5 pressed")
case term.KeyF6:
reset()
fmt.Println("F6 pressed")
case term.KeyF7:
reset()
fmt.Println("F7 pressed")
case term.KeyF8:
reset()
fmt.Println("F8 pressed")
case term.KeyF9:
reset()
fmt.Println("F9 pressed")
case term.KeyF10:
reset()
fmt.Println("F10 pressed")
case term.KeyF11:
reset()
fmt.Println("F11 pressed")
case term.KeyF12:
reset()
fmt.Println("F12 pressed")
case term.KeyInsert:
reset()
fmt.Println("Insert pressed")
case term.KeyDelete:
reset()
fmt.Println("Delete pressed")
case term.KeyHome:
reset()
fmt.Println("Home pressed")
case term.KeyEnd:
reset()
fmt.Println("End pressed")
case term.KeyPgup:
reset()
fmt.Println("Page Up pressed")
case term.KeyPgdn:
reset()
fmt.Println("Page Down pressed")
case term.KeyArrowUp:
reset()
fmt.Println("Arrow Up pressed")
case term.KeyArrowDown:
reset()
fmt.Println("Arrow Down pressed")
case term.KeyArrowLeft:
reset()
fmt.Println("Arrow Left pressed")
case term.KeyArrowRight:
reset()
fmt.Println("Arrow Right pressed")
case term.KeySpace:
reset()
fmt.Println("Space pressed")
case term.KeyBackspace:
reset()
fmt.Println("Backspace pressed")
case term.KeyEnter:
reset()
fmt.Println("Enter pressed")
case term.KeyTab:
reset()
fmt.Println("Tab pressed")
default:
// we only want to read a single character or one key pressed event
reset()
fmt.Println("ASCII : ", ev.Ch)
}
case term.EventError:
panic(ev.Err)
}
}
}
Sample Output
Enter any key to see their ASCII code or press ESC button to quit
Tab pressed
ASCII : 49
ASCII : 50
ASCII : 51
ASCII : 52
ASCII : 53
F1 pressed
Arrow Up pressed
Arrow Left pressed
Arrow Down pressed
Arrow Right pressed
Arrow Up pressed
If you don't mind hitting the Enter button then the above code looks like below:-
package main
import (
"fmt"
"os"
"bufio"
)
func main() {
fmt.Println("Press ESC button or Ctrl-C to exit this program")
fmt.Println("Press any key to see their ASCII code follow by Enter")
for {
// only read single characters, the rest will be ignored!!
consoleReader := bufio.NewReaderSize(os.Stdin, 1)
fmt.Print(">")
input, _ := consoleReader.ReadByte()
ascii := input
// ESC = 27 and Ctrl-C = 3
if ascii == 27 || ascii == 3 {
fmt.Println("Exiting...")
os.Exit(0)
}
fmt.Println("ASCII : ", ascii)
}
}
来源:https://stackoverflow.com/questions/40159137/golang-reading-from-stdin-how-to-detect-special-keys-enter-backspace-etc