mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-14 02:57:52 +08:00
127 lines
1.7 KiB
Go
127 lines
1.7 KiB
Go
package edit
|
|
|
|
import (
|
|
"time"
|
|
"../async"
|
|
)
|
|
|
|
var EscTimeout = time.Millisecond * 10
|
|
|
|
type Key struct {
|
|
rune
|
|
Ctrl bool
|
|
Alt bool
|
|
}
|
|
|
|
var ZeroKey = Key{}
|
|
|
|
func PlainKey(r rune) Key {
|
|
return Key{rune: r}
|
|
}
|
|
|
|
func CtrlKey(r rune) Key {
|
|
return Key{rune: r, Ctrl: true}
|
|
}
|
|
|
|
func AltKey(r rune) Key {
|
|
return Key{rune: r, Alt: true}
|
|
}
|
|
|
|
func (k Key) String() (s string) {
|
|
if k.Ctrl {
|
|
s += "Ctrl-"
|
|
}
|
|
if k.Alt {
|
|
s += "Alt-"
|
|
}
|
|
s += string(k.rune)
|
|
return
|
|
}
|
|
|
|
const (
|
|
F1 rune = -1-iota
|
|
F2
|
|
F3
|
|
F4
|
|
F5
|
|
F6
|
|
F7
|
|
F8
|
|
F9
|
|
F10
|
|
F11
|
|
F12
|
|
|
|
Escape // ^[
|
|
Backspace // ^?
|
|
|
|
Up // ^[OA
|
|
Down // ^[OB
|
|
Right // ^[OC
|
|
Left // ^[OD
|
|
|
|
Home // ^[[1~
|
|
Insert // ^[[2~
|
|
Delete // ^[[3~
|
|
End // ^[[4~
|
|
PageUp // ^[[5~
|
|
PageDown // ^[[6~
|
|
)
|
|
|
|
// reader is the part of an Editor responsible for reading and decoding
|
|
// terminal key sequences.
|
|
type reader struct {
|
|
runeReader *async.RuneReader
|
|
readAhead []Key
|
|
}
|
|
|
|
func newReader(rr *async.RuneReader) *reader {
|
|
return &reader{
|
|
rr,
|
|
make([]Key, 0),
|
|
}
|
|
}
|
|
|
|
// type readerState func(rune) (bool, readerState)
|
|
|
|
func (rd *reader) readKey() (k Key, err error) {
|
|
if n := len(rd.readAhead); n > 0 {
|
|
k = rd.readAhead[0]
|
|
rd.readAhead = rd.readAhead[1:]
|
|
return
|
|
}
|
|
|
|
r, _, err := rd.runeReader.ReadRune()
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
switch r {
|
|
case 0x0:
|
|
k = CtrlKey('`')
|
|
case 0x1d:
|
|
k = CtrlKey('6')
|
|
case 0x1f:
|
|
k = CtrlKey('/')
|
|
case 0x7f:
|
|
k = PlainKey(Backspace)
|
|
case 0x1b:
|
|
// ^[, or Escape
|
|
r, _, e := rd.runeReader.ReadRuneTimeout(EscTimeout)
|
|
if e == async.Timeout {
|
|
return CtrlKey('['), nil
|
|
} else if e != nil {
|
|
return ZeroKey, e
|
|
}
|
|
return AltKey(r), nil
|
|
default:
|
|
if 0x1 <= r && r <= 0x1d {
|
|
k = CtrlKey(r+0x40)
|
|
} else {
|
|
k = PlainKey(r)
|
|
}
|
|
}
|
|
return
|
|
}
|