gitstack

grindlemire/go-tui code browser

2.2 KB Go 50 lines 2026-06-03 · d15bb9f raw
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
package tui

// KeyMap is a list of key bindings returned by KeyListener.KeyMap().
// It is a value, not a registration — the framework collects and manages it.
type KeyMap []KeyBinding

// KeyBinding associates a key pattern with a handler.
type KeyBinding struct {
	Pattern KeyPattern
	Handler func(KeyEvent)
	Stop    bool // If true, prevent later handlers from firing for this key
	Preempt bool // If true, fires before normal handlers (used by modal to block parent keys)
}

// KeyPattern identifies which key events match a binding.
type KeyPattern struct {
	Key           Key      // Specific key (KeyEscape, KeyBackspace, etc.), or 0
	Rune          rune     // Specific rune, or 0
	AnyRune       bool     // Match any printable character
	AnyKey        bool     // Match any key event (rune or special key)
	Mod           Modifier // Required modifiers (when non-zero, event must have exactly these mods)
	ExcludeMods   Modifier // Reject event if any of these modifiers are present
	FocusRequired bool     // When true, only dispatch when owning component is focused
}

// On creates a broadcast binding. Other handlers for the same key will also fire.
func On(m KeyMatcher, handler func(KeyEvent)) KeyBinding {
	return KeyBinding{Pattern: m.keyPattern(), Handler: handler}
}

// OnStop creates a stop-propagation binding.
// No handlers registered after this one (in tree order) will fire for this event.
func OnStop(m KeyMatcher, handler func(KeyEvent)) KeyBinding {
	return KeyBinding{Pattern: m.keyPattern(), Handler: handler, Stop: true}
}

// OnPreemptStop creates a preemptive stop-propagation binding.
// Fires before all normal handlers, preventing them from seeing the event.
// Used by modal overlays to block parent component key handlers.
func OnPreemptStop(m KeyMatcher, handler func(KeyEvent)) KeyBinding {
	return KeyBinding{Pattern: m.keyPattern(), Handler: handler, Stop: true, Preempt: true}
}

// OnFocused creates a focus-gated stop-propagation binding.
// Only fires when the owning component's element is focused.
func OnFocused(m KeyMatcher, handler func(KeyEvent)) KeyBinding {
	p := m.keyPattern()
	p.FocusRequired = true
	return KeyBinding{Pattern: p, Handler: handler, Stop: true}
}