cbind/configuration.go

123 lines
2.6 KiB
Go
Raw Permalink Normal View History

2020-01-22 00:01:30 +00:00
package cbind
import (
"fmt"
"sync"
2020-02-07 01:37:48 +00:00
"unicode"
2020-01-22 00:01:30 +00:00
2020-08-26 21:45:15 +00:00
"github.com/gdamore/tcell/v2"
2020-01-22 00:01:30 +00:00
)
type eventHandler func(ev *tcell.EventKey) *tcell.EventKey
// Configuration maps keys to event handlers and processes key events.
2020-01-22 00:01:30 +00:00
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
}
2020-01-22 00:01:30 +00:00
// 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()
2020-02-08 14:08:29 +00:00
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 {
2020-02-07 01:37:48 +00:00
for _, ctrlKey := range ctrlKeys {
if key == ctrlKey {
mod |= tcell.ModCtrl
break
}
}
}
2020-01-22 00:01:30 +00:00
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
}
2020-02-07 01:37:48 +00:00
if mod&tcell.ModCtrl != 0 {
k, ok := ctrlKeys[unicode.ToLower(ch)]
if ok {
c.SetKey(mod, k, handler)
return
}
}
2020-01-22 00:01:30 +00:00
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
}
2020-05-15 16:21:27 +00:00
// Clear removes all handlers.
func (c *Configuration) Clear() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.handlers = make(map[string]eventHandler)
}