...
1 package cbind
2
3 import (
4 "fmt"
5 "sync"
6
7 "github.com/gdamore/tcell/v3"
8 )
9
10 type eventHandler func(ev *tcell.EventKey) *tcell.EventKey
11
12
13 type Configuration struct {
14 handlers map[string]eventHandler
15 mutex *sync.RWMutex
16 }
17
18
19 func NewConfiguration() *Configuration {
20 c := Configuration{
21 handlers: make(map[string]eventHandler),
22 mutex: new(sync.RWMutex),
23 }
24
25 return &c
26 }
27
28
29 func (c *Configuration) Set(s string, handler func(ev *tcell.EventKey) *tcell.EventKey) error {
30 mod, key, str, err := Decode(s)
31 if err != nil {
32 return err
33 }
34
35 if key == tcell.KeyRune {
36 c.SetRune(mod, []rune(str)[0], handler)
37 } else {
38 c.SetKey(mod, key, handler)
39 }
40 return nil
41 }
42
43
44 func (c *Configuration) SetKey(mod tcell.ModMask, key tcell.Key, handler func(ev *tcell.EventKey) *tcell.EventKey) {
45 c.mutex.Lock()
46 defer c.mutex.Unlock()
47
48
49 if key >= tcell.KeyCtrlA && key <= tcell.KeyCtrlZ {
50 mod |= tcell.ModCtrl
51 r := 'a' + (key - tcell.KeyCtrlA)
52 c.handlers[fmt.Sprintf("%d:%d", mod, r)] = handler
53 return
54 }
55
56
57 if mod&tcell.ModShift != 0 && key == tcell.KeyTab {
58 mod ^= tcell.ModShift
59 key = tcell.KeyBacktab
60 }
61
62 c.handlers[fmt.Sprintf("%d-%d", mod, key)] = handler
63 }
64
65
66 func (c *Configuration) SetRune(mod tcell.ModMask, ch rune, handler func(ev *tcell.EventKey) *tcell.EventKey) {
67
68
69 switch ch {
70 case '\t':
71 c.SetKey(mod, tcell.KeyTab, handler)
72 return
73 case '\n':
74 c.SetKey(mod, tcell.KeyEnter, handler)
75 return
76 }
77
78 c.mutex.Lock()
79 defer c.mutex.Unlock()
80
81 c.handlers[fmt.Sprintf("%d:%d", mod, ch)] = handler
82 }
83
84
85 func (c *Configuration) Capture(ev *tcell.EventKey) *tcell.EventKey {
86 c.mutex.RLock()
87 defer c.mutex.RUnlock()
88
89 if ev == nil {
90 return nil
91 }
92
93 mod := ev.Modifiers()
94 key := ev.Key()
95 str := ev.Str()
96
97
98 if key >= tcell.KeyCtrlA && key <= tcell.KeyCtrlZ {
99 mod |= tcell.ModCtrl
100 str = string(rune('a' + (key - tcell.KeyCtrlA)))
101 key = tcell.KeyRune
102 }
103
104 var keyName string
105 if key != tcell.KeyRune {
106 keyName = fmt.Sprintf("%d-%d", mod, key)
107 } else {
108 keyName = fmt.Sprintf("%d:%d", mod, []rune(str)[0])
109 }
110
111 handler := c.handlers[keyName]
112 if handler != nil {
113 return handler(ev)
114 }
115 return ev
116 }
117
118
119 func (c *Configuration) Clear() {
120 c.mutex.Lock()
121 defer c.mutex.Unlock()
122
123 c.handlers = make(map[string]eventHandler)
124 }
125
View as plain text