hybridgroup.gobot/platforms/keyboard/keyboard.go

162 lines
2.0 KiB
Go

package keyboard
import (
"os"
"os/exec"
)
type bytes [3]byte
// KeyEvent contains data about a keyboard event
type KeyEvent struct {
Bytes bytes
Key int
Char string
}
const (
Tilde = iota + 96
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
)
const (
Escape = 27
Spacebar = 32
)
const (
Zero = iota + 48
One
Two
Three
Four
Five
Six
Seven
Eight
Nine
)
const (
ArrowUp = iota + 65
ArrowDown
ArrowRight
ArrowLeft
)
// used to hold the original stty state
var originalState string
func Parse(input bytes) KeyEvent {
var event = KeyEvent{Bytes: input, Char: string(input[:])}
var code byte
// basic input codes
if input[1] == 0 && input[2] == 0 {
code = input[0]
// space bar
if code == Spacebar {
event.Key = Spacebar
}
// vanilla escape
if code == Escape {
event.Key = Escape
}
// number keys
if code >= 48 && code <= 57 {
event.Key = int(code)
}
// alphabet
if code >= 97 && code <= 122 {
event.Key = int(code)
}
return event
}
// arrow keys
if input[0] == Escape && input[1] == 91 {
code = input[2]
if code >= 65 && code <= 68 {
event.Key = int(code)
return event
}
}
return event
}
// fetches original state, sets up TTY for raw (unbuffered) input
func configure() (err error) {
state, err := stty("-g")
if err != nil {
return err
}
originalState = state
// -echo: terminal doesn't echo typed characters back to the terminal
// -icanon: terminal doesn't interpret special characters (like backspace)
if _, err := stty("-echo", "-icanon"); err != nil {
return err
}
return
}
// restores the TTY to the original state
func restore() (err error) {
if _, err = stty("echo"); err != nil {
return
}
if _, err = stty(originalState); err != nil {
return
}
return
}
func stty(args ...string) (string, error) {
cmd := exec.Command("stty", args...)
cmd.Stdin = os.Stdin
out, err := cmd.Output()
if err != nil {
return "", err
}
return string(out), nil
}