gitstack

grindlemire/go-tui code browser

3.3 KB Go 128 lines 2026-03-18 · 3a85fce 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
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
package tui

// Event is the base interface for all terminal events.
// Use type switch to handle specific event types.
type Event interface {
	// isEvent is a marker method to prevent external implementations.
	isEvent()
}

// KeyEvent represents a keyboard input event.
type KeyEvent struct {
	// Key is the key pressed. For printable characters, this is KeyRune.
	// For special keys (arrows, function keys), this is the specific constant.
	Key Key

	// Rune is the character for KeyRune events. Zero for special keys.
	Rune rune

	// Mod contains modifier flags (Ctrl, Alt, Shift).
	Mod Modifier

	// app is the App that dispatched this event. Set by the event loop.
	app *App
}

// App returns the App that dispatched this event.
// Use this in key handlers to call app methods like Stop(), PrintAbove(), etc.
func (e KeyEvent) App() *App { return e.app }

func (KeyEvent) isEvent() {}

// IsRune returns true if this is a printable character event.
func (e KeyEvent) IsRune() bool {
	return e.Key == KeyRune
}

// Is checks if the event matches a specific key with optional modifiers.
// Example: event.Is(KeyEnter) or event.Is(KeyRune, ModCtrl)
func (e KeyEvent) Is(key Key, mods ...Modifier) bool {
	if e.Key != key {
		return false
	}
	if len(mods) == 0 {
		return true
	}
	// Combine all provided modifiers and check if they all match
	var combined Modifier
	for _, m := range mods {
		combined |= m
	}
	return e.Mod == combined
}

// Char returns the rune if this is a KeyRune event, or 0 otherwise.
func (e KeyEvent) Char() rune {
	if e.Key == KeyRune {
		return e.Rune
	}
	return 0
}

// ResizeEvent is emitted when the terminal is resized.
type ResizeEvent struct {
	Width  int
	Height int
}

func (ResizeEvent) isEvent() {}

// MouseButton represents which mouse button was involved in an event.
type MouseButton int

const (
	// MouseLeft is the left (primary) mouse button.
	MouseLeft MouseButton = iota
	// MouseMiddle is the middle mouse button (scroll wheel click).
	MouseMiddle
	// MouseRight is the right (secondary) mouse button.
	MouseRight
	// MouseWheelUp is a scroll wheel up event.
	MouseWheelUp
	// MouseWheelDown is a scroll wheel down event.
	MouseWheelDown
	// MouseNone indicates no button (used for motion events).
	MouseNone
)

// MouseAction represents the type of mouse action.
type MouseAction int

const (
	// MousePress indicates a button was pressed.
	MousePress MouseAction = iota
	// MouseRelease indicates a button was released.
	MouseRelease
	// MouseDrag indicates motion while a button is held.
	MouseDrag
)

// MouseEvent represents a mouse input event.
type MouseEvent struct {
	// Button is which mouse button was involved.
	Button MouseButton
	// Action is the type of mouse action (press, release, drag).
	Action MouseAction
	// X is the column position (0-indexed).
	X int
	// Y is the row position (0-indexed).
	Y int
	// Mod contains modifier flags (Ctrl, Alt, Shift).
	Mod Modifier

	// app is the App that dispatched this event. Set by the event loop.
	app *App
}

// App returns the App that dispatched this event.
func (e MouseEvent) App() *App { return e.app }

func (MouseEvent) isEvent() {}

// UpdateEvent wraps a closure queued via QueueUpdate. Dispatch() executes
// the closure on the caller's goroutine.
type UpdateEvent struct {
	fn func()
}

func (UpdateEvent) isEvent() {}