star/bed/key/key.go

92 lines
1.8 KiB
Go
Raw Permalink Normal View History

2025-04-26 19:33:14 +08:00
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}
}