123 lines
2.6 KiB
Go
123 lines
2.6 KiB
Go
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)
|
|
}
|