3 type KeyAction func(Pane) bool
4 type MouseAction func(Pane, *MouseEvent) bool
6 type KeyAnyAction func(Pane, []KeyEvent) bool
8 // A KeyTreeNode stores a single node in the KeyTree (trie). The
9 // children are stored as a map, and any node may store a list of
10 // actions (the list will be nil if no actions correspond to a certain
12 type KeyTreeNode struct {
13 children map[Event]*KeyTreeNode
15 // Only one of these actions may be active in the current
16 // mode, and only one will be returned. If multiple actions
17 // are active, it is undefined which one will be the one
22 func NewKeyTreeNode() *KeyTreeNode {
24 n.children = make(map[Event]*KeyTreeNode)
25 n.actions = []TreeAction{}
29 // A TreeAction stores an action, and a set of mode constraints for
30 // the action to be active.
31 type TreeAction struct {
32 // only one of these can be non-nil
37 modes []ModeConstraint
40 // A KeyTree is a data structure for storing keybindings. It maps
41 // key events to actions, and maintains a set of currently enabled
42 // modes, which affects the action that is returned for a key event.
43 // The tree acts like a Trie for Events to handle sequence events.
51 // A KeyTreeCursor keeps track of the current location within the
52 // tree, and stores any information from previous events that may
53 // be needed to execute the action (values of wildcard events or
55 type KeyTreeCursor struct {
62 // MakeClosure uses the information stored in a key tree cursor to construct
63 // a KeyAction from a TreeAction (which may have a KeyAction, MouseAction,
65 func (k *KeyTreeCursor) MakeClosure(a TreeAction) KeyAction {
68 } else if a.any != nil {
69 return func(p Pane) bool {
70 return a.any(p, k.wildcards)
72 } else if a.mouse != nil {
73 return func(p Pane) bool {
74 return a.mouse(p, k.mouseInfo)
81 // NewKeyTree allocates and returns an empty key tree
82 func NewKeyTree() *KeyTree {
83 root := new(KeyTreeNode)
87 tree.modes = make(map[string]bool)
88 tree.cursor = KeyTreeCursor{
90 wildcards: []KeyEvent{},
97 // A ModeConstraint specifies that an action can only be executed
98 // while a certain mode is enabled or disabled.
99 type ModeConstraint struct {
104 // RegisterKeyBinding registers a KeyAction with an Event.
105 func (k *KeyTree) RegisterKeyBinding(e Event, a KeyAction) {
106 k.registerBinding(e, TreeAction{
114 // RegisterKeyAnyBinding registers a KeyAnyAction with an Event.
115 // The event should contain an "any" event.
116 func (k *KeyTree) RegisterKeyAnyBinding(e Event, a KeyAnyAction) {
117 k.registerBinding(e, TreeAction{
125 // RegisterMouseBinding registers a MouseAction with an Event.
126 // The event should contain a mouse event.
127 func (k *KeyTree) RegisterMouseBinding(e Event, a MouseAction) {
128 k.registerBinding(e, TreeAction{
136 func (k *KeyTree) registerBinding(e Event, a TreeAction) {
137 switch ev := e.(type) {
138 case *KeyEvent, *MouseEvent:
139 n, ok := k.root.children[e]
141 newNode := NewKeyTreeNode()
142 k.root.children[e] = newNode
144 n.actions = append(n.actions, a)
145 case *KeySequenceEvent:
147 for _, key := range ev.keys {
148 newNode, ok := n.children[key]
150 newNode := NewKeyTreeNode()
151 n.children[key] = newNode
156 n.actions = append(n.actions, a)
160 // NextEvent returns the action for the current sequence where e is the next
161 // event. Even if the action was registered as a KeyAnyAction or MouseAction,
162 // it will be returned as a KeyAction closure where the appropriate arguments
163 // have been provided.
164 // If no action is associated with the given Event, or mode constraints are not
165 // met for that action, nil is returned.
166 // A boolean is returned to indicate if there is a conflict with this action. A
167 // conflict occurs when there is an active action for this event but there are
168 // bindings associated with further sequences starting with this event. The
169 // calling function can decide what to do about the conflict (e.g. use a
171 func (k *KeyTree) NextEvent(e Event) (KeyAction, bool) {
173 c, ok := n.children[e]
178 more := len(c.children) > 0
180 if len(c.actions) > 0 {
181 // check if actions are active
182 for _, a := range c.actions {
184 for _, mc := range a.modes {
185 // if any mode constraint is not met, the action is not active
186 hasMode := k.modes[mc.mode]
187 if hasMode != mc.disabled {
193 // the first active action to be found is returned
194 return k.cursor.MakeClosure(a), more
202 // Reset sets the current sequence back to the initial value.
203 func (k *KeyTree) Reset() {
204 k.cursor.node = k.root
205 k.cursor.wildcards = []KeyEvent{}
206 k.cursor.mouseInfo = nil
209 // DeleteBinding removes any currently active actions associated with the
211 func (k *KeyTree) DeleteBinding(e Event) {
215 // DeleteAllBindings removes all actions associated with the given event,
216 // regardless of whether they are active or not.
217 func (k *KeyTree) DeleteAllBindings(e Event) {
221 // SetMode enables or disabled a given mode
222 func (k *KeyTree) SetMode(mode string, en bool) {
226 // HasMode returns if the given mode is currently active
227 func (k *KeyTree) HasMode(mode string) bool {