Key event handling library for tcell
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.6 KiB

package cbind
import (
"fmt"
"sync"
"unicode"
"github.com/gdamore/tcell/v2"
)
type eventHandler func(ev *tcell.EventKey) *tcell.EventKey
// Configuration maps keys to event handlers and processes key events.
type Configuration struct {
handlers map[string]eventHandler
mutex *sync.RWMutex
}
// NewConfiguration returns a new input configuration.
func NewConfiguration() *Configuration {
c := Configuration{
handlers: make(map[string]eventHandler),
mutex: new(sync.RWMutex),
}
return &c
}
// Set sets the handler for a key event string.
func (c *Configuration) Set(s string, handler func(ev *tcell.EventKey) *tcell.EventKey) error {
mod, key, ch, err := Decode(s)
if err != nil {
return err
}
if key == tcell.KeyRune {
c.SetRune(mod, ch, handler)
} else {
c.SetKey(mod, key, handler)
}
return nil
}
// SetKey sets the handler for a key.
func (c *Configuration) SetKey(mod tcell.ModMask, key tcell.Key, handler func(ev *tcell.EventKey) *tcell.EventKey) {
c.mutex.Lock()
defer c.mutex.Unlock()
if mod&tcell.ModShift != 0 && key == tcell.KeyTab {
mod ^= tcell.ModShift
key = tcell.KeyBacktab
}
if mod&tcell.ModCtrl == 0 && key != tcell.KeyBackspace && key != tcell.KeyTab && key != tcell.KeyEnter {
for _, ctrlKey := range ctrlKeys {
if key == ctrlKey {
mod |= tcell.ModCtrl
break
}
}
}
c.handlers[fmt.Sprintf("%d-%d", mod, key)] = handler
}
// SetRune sets the handler for a rune.
func (c *Configuration) SetRune(mod tcell.ModMask, ch rune, handler func(ev *tcell.EventKey) *tcell.EventKey) {
// Some runes are identical to named keys. Set the bind on the matching
// named key instead.
switch ch {
case '\t':
c.SetKey(mod, tcell.KeyTab, handler)
return
case '\n':
c.SetKey(mod, tcell.KeyEnter, handler)
return
}
if mod&tcell.ModCtrl != 0 {
k, ok := ctrlKeys[unicode.ToLower(ch)]
if ok {
c.SetKey(mod, k, handler)
return
}
}
c.mutex.Lock()
defer c.mutex.Unlock()
c.handlers[fmt.Sprintf("%d:%d", mod, ch)] = handler
}
// Capture handles key events.
func (c *Configuration) Capture(ev *tcell.EventKey) *tcell.EventKey {
c.mutex.RLock()
defer c.mutex.RUnlock()
if ev == nil {
return nil
}
var keyName string
if ev.Key() != tcell.KeyRune {
keyName = fmt.Sprintf("%d-%d", ev.Modifiers(), ev.Key())
} else {
keyName = fmt.Sprintf("%d:%d", ev.Modifiers(), ev.Rune())
}
handler := c.handlers[keyName]
if handler != nil {
return handler(ev)
}
return ev
}
// Clear removes all handlers.
func (c *Configuration) Clear() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.handlers = make(map[string]eventHandler)
}