-
Notifications
You must be signed in to change notification settings - Fork 3
/
getkey.go
75 lines (67 loc) · 1.29 KB
/
getkey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package readline
import (
"strings"
"unicode/utf16"
)
// XTty is the interface of tty to use GetKey function.
type XTty interface {
Raw() (func() error, error)
ReadRune() (rune, error)
Buffered() bool
}
// GetKey reads one-key from *tty*.
// The *tty* object must have Raw(),ReadRune(), and Buffered() method.
func GetKey(tty XTty) (string, error) {
clean, err := tty.Raw()
if err != nil {
return "", err
}
defer clean()
return GetRawKey(tty)
}
func GetRawKey(tty XTty) (string, error) {
var buffer strings.Builder
escape := false
var surrogated rune = 0
for {
r, err := tty.ReadRune()
if err != nil {
return "", err
}
if r == 0 {
continue
}
if surrogated > 0 {
r = utf16.DecodeRune(surrogated, r)
surrogated = 0
} else if utf16.IsSurrogate(r) { // surrogate pair first word.
surrogated = r
continue
}
buffer.WriteRune(r)
if r == '\x1B' {
escape = true
}
if !(escape && tty.Buffered()) && buffer.Len() > 0 {
return buffer.String(), nil
}
}
}
func GetKeys(tty XTty) ([]string, error) {
clean, err := tty.Raw()
if err != nil {
return nil, err
}
defer clean()
keys := []string{}
for {
key1, err := GetRawKey(tty)
if err != nil {
return nil, err
}
keys = append(keys, key1)
if !tty.Buffered() {
return keys, nil
}
}
}