1package uv
2
3import (
4 "fmt"
5 "image"
6 "image/color"
7 "strings"
8
9 "github.com/charmbracelet/x/ansi"
10 "github.com/charmbracelet/x/ansi/kitty"
11)
12
13// Event represents an input event that can be received from an input source.
14type Event interface{}
15
16// UnknownEvent represents an unknown event.
17type UnknownEvent string
18
19// String returns a string representation of the unknown event.
20func (e UnknownEvent) String() string {
21 return fmt.Sprintf("%q", string(e))
22}
23
24// UnknownCsiEvent represents an unknown CSI (Control Sequence Introducer) event.
25type UnknownCsiEvent string
26
27// String returns a string representation of the unknown CSI event.
28func (e UnknownCsiEvent) String() string {
29 return fmt.Sprintf("%q", string(e))
30}
31
32// UnknownSs3Event represents an unknown SS3 (Single Shift 3) event.
33type UnknownSs3Event string
34
35// String returns a string representation of the unknown SS3 event.
36func (e UnknownSs3Event) String() string {
37 return fmt.Sprintf("%q", string(e))
38}
39
40// UnknownOscEvent represents an unknown OSC (Operating System Command) event.
41type UnknownOscEvent string
42
43// String returns a string representation of the unknown OSC event.
44func (e UnknownOscEvent) String() string {
45 return fmt.Sprintf("%q", string(e))
46}
47
48// UnknownDcsEvent represents an unknown DCS (Device Control String) event.
49type UnknownDcsEvent string
50
51// String returns a string representation of the unknown DCS event.
52func (e UnknownDcsEvent) String() string {
53 return fmt.Sprintf("%q", string(e))
54}
55
56// UnknownSosEvent represents an unknown SOS (Start of String) event.
57type UnknownSosEvent string
58
59// String returns a string representation of the unknown SOS event.
60func (e UnknownSosEvent) String() string {
61 return fmt.Sprintf("%q", string(e))
62}
63
64// UnknownPmEvent represents an unknown PM (Privacy Message) event.
65type UnknownPmEvent string
66
67// String returns a string representation of the unknown PM event.
68func (e UnknownPmEvent) String() string {
69 return fmt.Sprintf("%q", string(e))
70}
71
72// UnknownApcEvent represents an unknown APC (Application Program Command) event.
73type UnknownApcEvent string
74
75// String returns a string representation of the unknown APC event.
76func (e UnknownApcEvent) String() string {
77 return fmt.Sprintf("%q", string(e))
78}
79
80// MultiEvent represents multiple messages event.
81type MultiEvent []Event
82
83// String returns a string representation of the multiple messages event.
84func (e MultiEvent) String() string {
85 var sb strings.Builder
86 for _, ev := range e {
87 sb.WriteString(fmt.Sprintf("%v\n", ev))
88 }
89 return sb.String()
90}
91
92// WindowSizeEvent represents the window size in cells.
93type WindowSizeEvent Size
94
95// Bounds returns the bounds corresponding to the size.
96func (s WindowSizeEvent) Bounds() Rectangle {
97 return Size(s).Bounds()
98}
99
100// WindowPixelSizeEvent represents the window size in pixels.
101type WindowPixelSizeEvent Size
102
103// Bounds returns the bounds corresponding to the size.
104func (s WindowPixelSizeEvent) Bounds() Rectangle {
105 return Size(s).Bounds()
106}
107
108// KeyPressEvent represents a key press event.
109type KeyPressEvent Key
110
111// MatchString returns true if the [Key] matches the given string. The string
112// can be a key name like "enter", "tab", "a", or a printable character like
113// "1" or " ". It can also have combinations of modifiers like "ctrl+a",
114// "shift+enter", "alt+tab", "ctrl+shift+enter", etc.
115func (k KeyPressEvent) MatchString(s string) bool {
116 return Key(k).MatchString(s)
117}
118
119// MatchStrings returns true if the [Key] matches any of the given strings. The
120// strings can be key names like "enter", "tab", "a", or a printable character
121// like "1" or " ". It can also have combinations of modifiers like "ctrl+a",
122// "shift+enter", "alt+tab", "ctrl+shift+enter", etc.
123// See [Key.MatchString] for more details.
124func (k KeyPressEvent) MatchStrings(ss ...string) bool {
125 return Key(k).MatchStrings(ss...)
126}
127
128// String implements [fmt.Stringer] and is quite useful for matching key
129// events. For details, on what this returns see [Key.String].
130func (k KeyPressEvent) String() string {
131 return Key(k).String()
132}
133
134// Keystroke returns the keystroke representation of the [Key]. While less type
135// safe than looking at the individual fields, it will usually be more
136// convenient and readable to use this method when matching against keys.
137//
138// Note that modifier keys are always printed in the following order:
139// - ctrl
140// - alt
141// - shift
142// - meta
143// - hyper
144// - super
145//
146// For example, you'll always see "ctrl+shift+alt+a" and never
147// "shift+ctrl+alt+a".
148func (k KeyPressEvent) Keystroke() string {
149 return Key(k).Keystroke()
150}
151
152// Key returns the underlying key event. This is a syntactic sugar for casting
153// the key event to a [Key].
154func (k KeyPressEvent) Key() Key {
155 return Key(k)
156}
157
158// KeyReleaseEvent represents a key release event.
159type KeyReleaseEvent Key
160
161// MatchString returns true if the [Key] matches the given string. The string
162// can be a key name like "enter", "tab", "a", or a printable character like
163// "1" or " ". It can also have combinations of modifiers like "ctrl+a",
164// "shift+enter", "alt+tab", "ctrl+shift+enter", etc.
165func (k KeyReleaseEvent) MatchString(s string) bool {
166 return Key(k).MatchString(s)
167}
168
169// MatchStrings returns true if the [Key] matches any of the given strings. The
170// strings can be key names like "enter", "tab", "a", or a printable character
171// like "1" or " ". It can also have combinations of modifiers like "ctrl+a",
172// "shift+enter", "alt+tab", "ctrl+shift+enter", etc.
173// See [Key.MatchString] for more details.
174func (k KeyReleaseEvent) MatchStrings(ss ...string) bool {
175 return Key(k).MatchStrings(ss...)
176}
177
178// String implements [fmt.Stringer] and is quite useful for matching key
179// events. For details, on what this returns see [Key.String].
180func (k KeyReleaseEvent) String() string {
181 return Key(k).String()
182}
183
184// Keystroke returns the keystroke representation of the [Key]. While less type
185// safe than looking at the individual fields, it will usually be more
186// convenient and readable to use this method when matching against keys.
187//
188// Note that modifier keys are always printed in the following order:
189// - ctrl
190// - alt
191// - shift
192// - meta
193// - hyper
194// - super
195//
196// For example, you'll always see "ctrl+shift+alt+a" and never
197// "shift+ctrl+alt+a".
198func (k KeyReleaseEvent) Keystroke() string {
199 return Key(k).Keystroke()
200}
201
202// Key returns the underlying key event. This is a convenience method and
203// syntactic sugar to satisfy the [KeyEvent] interface, and cast the key event to
204// [Key].
205func (k KeyReleaseEvent) Key() Key {
206 return Key(k)
207}
208
209// KeyEvent represents a key event. This can be either a key press or a key
210// release event.
211type KeyEvent interface {
212 fmt.Stringer
213
214 // Text returns the text representation of the key event. This is useful
215 // for matching key events along with [Key.String].
216 // TODO: Use this instead of storing Text in the [Key] struct.
217 // Text() string
218
219 // Key returns the underlying key event.
220 Key() Key
221}
222
223// MouseEvent represents a mouse message. This is a generic mouse message that
224// can represent any kind of mouse event.
225type MouseEvent interface {
226 fmt.Stringer
227
228 // Mouse returns the underlying mouse event.
229 Mouse() Mouse
230}
231
232// MouseClickEvent represents a mouse button click event.
233type MouseClickEvent Mouse
234
235// String returns a string representation of the mouse click event.
236func (e MouseClickEvent) String() string {
237 return Mouse(e).String()
238}
239
240// Mouse returns the underlying mouse event. This is a convenience method and
241// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
242// event to [Mouse].
243func (e MouseClickEvent) Mouse() Mouse {
244 return Mouse(e)
245}
246
247// MouseReleaseEvent represents a mouse button release event.
248type MouseReleaseEvent Mouse
249
250// String returns a string representation of the mouse release event.
251func (e MouseReleaseEvent) String() string {
252 return Mouse(e).String()
253}
254
255// Mouse returns the underlying mouse event. This is a convenience method and
256// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
257// event to [Mouse].
258func (e MouseReleaseEvent) Mouse() Mouse {
259 return Mouse(e)
260}
261
262// MouseWheelEvent represents a mouse wheel message event.
263type MouseWheelEvent Mouse
264
265// String returns a string representation of the mouse wheel event.
266func (e MouseWheelEvent) String() string {
267 return Mouse(e).String()
268}
269
270// Mouse returns the underlying mouse event. This is a convenience method and
271// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
272// event to [Mouse].
273func (e MouseWheelEvent) Mouse() Mouse {
274 return Mouse(e)
275}
276
277// MouseMotionEvent represents a mouse motion event.
278type MouseMotionEvent Mouse
279
280// String returns a string representation of the mouse motion event.
281func (e MouseMotionEvent) String() string {
282 m := Mouse(e)
283 if m.Button != 0 {
284 return m.String() + "+motion"
285 }
286 return m.String() + "motion"
287}
288
289// Mouse returns the underlying mouse event. This is a convenience method and
290// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
291// event to [Mouse].
292func (e MouseMotionEvent) Mouse() Mouse {
293 return Mouse(e)
294}
295
296// CursorPositionEvent represents a cursor position event. Where X is the
297// zero-based column and Y is the zero-based row.
298type CursorPositionEvent image.Point
299
300// FocusEvent represents a terminal focus event.
301// This occurs when the terminal gains focus.
302type FocusEvent struct{}
303
304// BlurEvent represents a terminal blur event.
305// This occurs when the terminal loses focus.
306type BlurEvent struct{}
307
308// DarkColorSchemeEvent is sent when the operating system is using a dark color
309// scheme. This is typically used to notify applications of the current or new
310// system color scheme.
311type DarkColorSchemeEvent struct{}
312
313// LightColorSchemeEvent is sent when the operating system is using a light color
314// scheme. This is typically used to notify applications of the current or new
315// system color scheme.
316type LightColorSchemeEvent struct{}
317
318// PasteEvent is an message that is emitted when a terminal receives pasted text
319// using bracketed-paste.
320type PasteEvent string
321
322// PasteStartEvent is an message that is emitted when the terminal starts the
323// bracketed-paste text.
324type PasteStartEvent struct{}
325
326// PasteEndEvent is an message that is emitted when the terminal ends the
327// bracketed-paste text.
328type PasteEndEvent struct{}
329
330// TerminalVersionEvent is a message that represents the terminal version.
331type TerminalVersionEvent string
332
333// ModifyOtherKeysEvent represents a modifyOtherKeys event.
334//
335// 0: disable
336// 1: enable mode 1
337// 2: enable mode 2
338//
339// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
340// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys
341type ModifyOtherKeysEvent uint8
342
343// KittyGraphicsEvent represents a Kitty Graphics response event.
344//
345// See https://sw.kovidgoyal.net/kitty/graphics-protocol/
346type KittyGraphicsEvent struct {
347 Options kitty.Options
348 Payload []byte
349}
350
351// KittyEnhancementsEvent represents a Kitty enhancements event.
352type KittyEnhancementsEvent int
353
354// Contains reports whether m contains the given enhancements.
355func (e KittyEnhancementsEvent) Contains(enhancements int) bool {
356 return int(e)&enhancements == enhancements
357}
358
359// PrimaryDeviceAttributesEvent is an event that represents the terminal
360// primary device attributes.
361//
362// Common attributes include:
363// - 1 132 columns
364// - 2 Printer port
365// - 4 Sixel
366// - 6 Selective erase
367// - 7 Soft character set (DRCS)
368// - 8 User-defined keys (UDKs)
369// - 9 National replacement character sets (NRCS) (International terminal only)
370// - 12 Yugoslavian (SCS)
371// - 15 Technical character set
372// - 18 Windowing capability
373// - 21 Horizontal scrolling
374// - 23 Greek
375// - 24 Turkish
376// - 42 ISO Latin-2 character set
377// - 44 PCTerm
378// - 45 Soft key map
379// - 46 ASCII emulation
380//
381// See [ansi.PrimaryDeviceAttributes] for more details.
382type PrimaryDeviceAttributesEvent []int
383
384// ModeReportEvent is a message that represents a mode report event (DECRPM).
385//
386// See: https://vt100.net/docs/vt510-rm/DECRPM.html
387type ModeReportEvent struct {
388 // Mode is the mode number.
389 Mode ansi.Mode
390
391 // Value is the mode value.
392 Value ansi.ModeSetting
393}
394
395// ForegroundColorEvent represents a foreground color event. This event is
396// emitted when the terminal requests the terminal foreground color using
397// [ansi.RequestForegroundColor].
398type ForegroundColorEvent struct{ color.Color }
399
400// String returns the hex representation of the color.
401func (e ForegroundColorEvent) String() string {
402 return colorToHex(e.Color)
403}
404
405// IsDark returns whether the color is dark.
406func (e ForegroundColorEvent) IsDark() bool {
407 return isDarkColor(e.Color)
408}
409
410// BackgroundColorEvent represents a background color event. This event is
411// emitted when the terminal requests the terminal background color using
412// [ansi.RequestBackgroundColor].
413type BackgroundColorEvent struct{ color.Color }
414
415// String returns the hex representation of the color.
416func (e BackgroundColorEvent) String() string {
417 return colorToHex(e)
418}
419
420// IsDark returns whether the color is dark.
421func (e BackgroundColorEvent) IsDark() bool {
422 return isDarkColor(e.Color)
423}
424
425// CursorColorEvent represents a cursor color change event. This event is
426// emitted when the program requests the terminal cursor color using
427// [ansi.RequestCursorColor].
428type CursorColorEvent struct{ color.Color }
429
430// String returns the hex representation of the color.
431func (e CursorColorEvent) String() string {
432 return colorToHex(e)
433}
434
435// IsDark returns whether the color is dark.
436func (e CursorColorEvent) IsDark() bool {
437 return isDarkColor(e)
438}
439
440// WindowOpEvent is a window operation (XTWINOPS) report event. This is used to
441// report various window operations such as reporting the window size or cell
442// size.
443type WindowOpEvent struct {
444 Op int
445 Args []int
446}
447
448// CapabilityEvent represents a Termcap/Terminfo response event. Termcap
449// responses are generated by the terminal in response to RequestTermcap
450// (XTGETTCAP) requests.
451//
452// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
453type CapabilityEvent string
454
455// ClipboardSelection represents a clipboard selection. The most common
456// clipboard selections are "system" and "primary" and selections.
457type ClipboardSelection = byte
458
459// Clipboard selections.
460const (
461 SystemClipboard ClipboardSelection = ansi.SystemClipboard
462 PrimaryClipboard ClipboardSelection = ansi.PrimaryClipboard
463)
464
465// ClipboardEvent is a clipboard read message event. This message is emitted when
466// a terminal receives an OSC52 clipboard read message event.
467type ClipboardEvent struct {
468 Content string
469 Selection ClipboardSelection
470}
471
472// String returns the string representation of the clipboard message.
473func (e ClipboardEvent) String() string {
474 return e.Content
475}
476
477// ignoredEvent represents a sequence event that is ignored by the terminal
478// reader. This is used to ignore certain sequences that can be canceled.
479type ignoredEvent string