-
Notifications
You must be signed in to change notification settings - Fork 0
/
event_key.go
160 lines (136 loc) · 4 KB
/
event_key.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package gecore
import (
"fmt"
"github.com/gdamore/tcell/v2"
)
// Hold the *KeyPointer created with func KeyMapper()
var keyPointers = []*KeyPointer{}
// Only one ExtendedFunctionInterface can be executed
// The method Draw() of ExtendedFunctionInterface is
// Must be called at the end of main loop drawing
var currentExtendedFunction *ExtendedFunctionInterface
// KeyMapper provides an entry point for managing key mapping and command execution.
func KeyMapper() *KeyPointer {
kp := &KeyPointer{}
kp.root = &keyMap{}
kp.current = kp.root
keyPointers = append(keyPointers, kp)
return kp
}
type KeyPointer struct {
root *keyMap // ルートキーマップ
current *keyMap
extendedFunction *ExtendedFunctionInterface
}
type Key int64
// mod int16, Key int16, rune int32
func MakeKey(mod tcell.ModMask, key tcell.Key, ch rune) Key {
// verb.PP("MakeKey mod %#v, ch %#v, key %#v", mod, ch, int64(mod)<<(32+16)+int64(key)<<32+int64(ch))
return Key(int64(mod)<<(32+16) + int64(key)<<32 + int64(ch))
}
// keyMap is a map that associates keys with arbitrary actions.
type keyMap map[Key]any
// func KeyMapper() Release the KeyPointer created with
func (kp *KeyPointer) Release() {
for index, k := range keyPointers {
if k == kp {
keyPointers = append(keyPointers[:index], keyPointers[index+1:]...)
break
}
}
// kp = nil
*kp = KeyPointer{}
}
func (kp *KeyPointer) SetExtendedFunction(e *ExtendedFunctionInterface) {
currentExtendedFunction = e
}
func (kp *KeyPointer) IsExtendedFunctionValid() bool {
return currentExtendedFunction != nil
}
func (kp *KeyPointer) GetExtendedFunctionInterface() *ExtendedFunctionInterface {
return currentExtendedFunction
}
// Bind adds an action associated with the specified key.
func (kp *KeyPointer) Bind(keys []string, fn any) {
a := kp.root // Start from root *keyMap
for i := 0; i < len(keys); i++ {
s := keys[i]
// md, ky, ch, err := cbind.Decode(s)
md, ky, ch, err := Decode(s)
if err != nil {
// verb.PP("%#v", err)
continue
}
k := MakeKey(md, ky, ch)
if (*a) == nil {
(*a) = make(keyMap)
}
if i == len(keys)-1 {
(*a)[k] = fn
} else {
if (*a)[k] == nil {
(*a)[k] = make(keyMap)
}
// Set pointer to next keymap
nextKeyMap := (*a)[k].(keyMap)
a = &nextKeyMap
}
}
}
// Reset resets the current keymap to the root keymap.
// Exit from ExtendedFunction
func (kp *KeyPointer) Reset() {
kp.ResetKeyMapInAllInstance()
currentExtendedFunction = nil
}
// ResetKeyMapInAllInstance resets the current keymap of all KeyPointer instances created with func KeyMapper() to the root keymap.
func (kp *KeyPointer) ResetKeyMapInAllInstance() {
for _, k := range keyPointers {
k.current = k.root
}
}
// Reset resets the current keymap to the root keymap.
func (kp *KeyPointer) ResetKeyMap() {
kp.current = kp.root
}
// Execute executes the action associated with the specified key.
// SkipExtendedFunction should be set to true mainly in the following cases
// - Prioritize processing over ExtendedFunctions
// - when calling from inside ExtendedFunctions
func (kp *KeyPointer) Execute(tKey *tcell.EventKey, skipExtendedFunction bool) error {
k := MakeKey(tKey.Modifiers(), tKey.Key(), tKey.Rune())
if !skipExtendedFunction && currentExtendedFunction != nil {
(*currentExtendedFunction).Event(tKey)
kp.ResetKeyMapInAllInstance()
return ErrCodeExtendedFunction
}
if _, ok := (*kp.current)[k]; !ok {
kp.ResetKeyMap()
return ErrCodeKeyBindingNotFount
}
switch e := (*kp.current)[k].(type) {
case func():
e()
kp.ResetKeyMapInAllInstance()
return ErrCodeFunc
case func() error:
err := e()
kp.ResetKeyMap()
return err
case *ExtendedFunctionInterface:
currentExtendedFunction = e
(*currentExtendedFunction).Event(tKey)
kp.ResetKeyMapInAllInstance()
return ErrCodeExtendedFunction
case keyMap:
kp.current = &e
return ErrCodeKeyBound
default:
kp.Reset()
return fmt.Errorf("unknown key binding type %T", e)
}
}
type ExtendedFunctionInterface interface {
Draw()
Event(*tcell.EventKey) *tcell.EventKey
}