92 lines
1.8 KiB
Go
92 lines
1.8 KiB
Go
|
package key
|
||
|
|
||
|
import (
|
||
|
"strconv"
|
||
|
|
||
|
"b612.me/apps/b612/bed/event"
|
||
|
)
|
||
|
|
||
|
// Key represents one keyboard stroke.
|
||
|
type Key string
|
||
|
|
||
|
type keyEvent struct {
|
||
|
keys []Key
|
||
|
event event.Type
|
||
|
bang bool
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
keysEq = iota
|
||
|
keysPending
|
||
|
keysNeq
|
||
|
)
|
||
|
|
||
|
func (ke keyEvent) cmp(ks []Key) int {
|
||
|
if len(ke.keys) < len(ks) {
|
||
|
return keysNeq
|
||
|
}
|
||
|
for i, k := range ke.keys {
|
||
|
if i >= len(ks) {
|
||
|
return keysPending
|
||
|
}
|
||
|
if k != ks[i] {
|
||
|
return keysNeq
|
||
|
}
|
||
|
}
|
||
|
return keysEq
|
||
|
}
|
||
|
|
||
|
// Manager holds the key mappings and current key sequence.
|
||
|
type Manager struct {
|
||
|
keys []Key
|
||
|
events []keyEvent
|
||
|
count bool
|
||
|
}
|
||
|
|
||
|
// NewManager creates a new Manager.
|
||
|
func NewManager(count bool) *Manager {
|
||
|
return &Manager{count: count}
|
||
|
}
|
||
|
|
||
|
// Register adds a new key mapping.
|
||
|
func (km *Manager) Register(eventType event.Type, keys ...Key) {
|
||
|
km.events = append(km.events, keyEvent{keys, eventType, false})
|
||
|
}
|
||
|
|
||
|
// RegisterBang adds a new key mapping with bang.
|
||
|
func (km *Manager) RegisterBang(eventType event.Type, keys ...Key) {
|
||
|
km.events = append(km.events, keyEvent{keys, eventType, true})
|
||
|
}
|
||
|
|
||
|
// Press checks the new key down event.
|
||
|
func (km *Manager) Press(k Key) event.Event {
|
||
|
km.keys = append(km.keys, k)
|
||
|
for i := range len(km.keys) {
|
||
|
keys := km.keys[i:]
|
||
|
var count int64
|
||
|
if km.count {
|
||
|
numStr := ""
|
||
|
for j, k := range keys {
|
||
|
if len(k) == 1 && ('1' <= k[0] && k[0] <= '9' || k[0] == '0' && j > 0) {
|
||
|
numStr += string(k)
|
||
|
} else {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
keys = keys[len(numStr):]
|
||
|
count, _ = strconv.ParseInt(numStr, 10, 64)
|
||
|
}
|
||
|
for _, ke := range km.events {
|
||
|
switch ke.cmp(keys) {
|
||
|
case keysPending:
|
||
|
return event.Event{Type: event.Nop}
|
||
|
case keysEq:
|
||
|
km.keys = nil
|
||
|
return event.Event{Type: ke.event, Count: count, Bang: ke.bang}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
km.keys = nil
|
||
|
return event.Event{Type: event.Nop}
|
||
|
}
|