event.go

  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// Key returns the underlying key event. This is a syntactic sugar for casting
135// the key event to a [Key].
136func (k KeyPressEvent) Key() Key {
137	return Key(k)
138}
139
140// KeyReleaseEvent represents a key release event.
141type KeyReleaseEvent Key
142
143// MatchString returns true if the [Key] matches the given string. The string
144// can be a key name like "enter", "tab", "a", or a printable character like
145// "1" or " ". It can also have combinations of modifiers like "ctrl+a",
146// "shift+enter", "alt+tab", "ctrl+shift+enter", etc.
147func (k KeyReleaseEvent) MatchString(s string) bool {
148	return Key(k).MatchString(s)
149}
150
151// MatchStrings returns true if the [Key] matches any of the given strings. The
152// strings can be key names like "enter", "tab", "a", or a printable character
153// like "1" or " ". It can also have combinations of modifiers like "ctrl+a",
154// "shift+enter", "alt+tab", "ctrl+shift+enter", etc.
155// See [Key.MatchString] for more details.
156func (k KeyReleaseEvent) MatchStrings(ss ...string) bool {
157	return Key(k).MatchStrings(ss...)
158}
159
160// String implements [fmt.Stringer] and is quite useful for matching key
161// events. For details, on what this returns see [Key.String].
162func (k KeyReleaseEvent) String() string {
163	return Key(k).String()
164}
165
166// Key returns the underlying key event. This is a convenience method and
167// syntactic sugar to satisfy the [KeyEvent] interface, and cast the key event to
168// [Key].
169func (k KeyReleaseEvent) Key() Key {
170	return Key(k)
171}
172
173// KeyEvent represents a key event. This can be either a key press or a key
174// release event.
175type KeyEvent interface {
176	fmt.Stringer
177
178	// Text returns the text representation of the key event. This is useful
179	// for matching key events along with [Key.String].
180	// TODO: Use this instead of storing Text in the [Key] struct.
181	// Text() string
182
183	// Key returns the underlying key event.
184	Key() Key
185}
186
187// MouseEvent represents a mouse message. This is a generic mouse message that
188// can represent any kind of mouse event.
189type MouseEvent interface {
190	fmt.Stringer
191
192	// Mouse returns the underlying mouse event.
193	Mouse() Mouse
194}
195
196// MouseClickEvent represents a mouse button click event.
197type MouseClickEvent Mouse
198
199// String returns a string representation of the mouse click event.
200func (e MouseClickEvent) String() string {
201	return Mouse(e).String()
202}
203
204// Mouse returns the underlying mouse event. This is a convenience method and
205// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
206// event to [Mouse].
207func (e MouseClickEvent) Mouse() Mouse {
208	return Mouse(e)
209}
210
211// MouseReleaseEvent represents a mouse button release event.
212type MouseReleaseEvent Mouse
213
214// String returns a string representation of the mouse release event.
215func (e MouseReleaseEvent) String() string {
216	return Mouse(e).String()
217}
218
219// Mouse returns the underlying mouse event. This is a convenience method and
220// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
221// event to [Mouse].
222func (e MouseReleaseEvent) Mouse() Mouse {
223	return Mouse(e)
224}
225
226// MouseWheelEvent represents a mouse wheel message event.
227type MouseWheelEvent Mouse
228
229// String returns a string representation of the mouse wheel event.
230func (e MouseWheelEvent) String() string {
231	return Mouse(e).String()
232}
233
234// Mouse returns the underlying mouse event. This is a convenience method and
235// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
236// event to [Mouse].
237func (e MouseWheelEvent) Mouse() Mouse {
238	return Mouse(e)
239}
240
241// MouseMotionEvent represents a mouse motion event.
242type MouseMotionEvent Mouse
243
244// String returns a string representation of the mouse motion event.
245func (e MouseMotionEvent) String() string {
246	m := Mouse(e)
247	if m.Button != 0 {
248		return m.String() + "+motion"
249	}
250	return m.String() + "motion"
251}
252
253// Mouse returns the underlying mouse event. This is a convenience method and
254// syntactic sugar to satisfy the [MouseEvent] interface, and cast the mouse
255// event to [Mouse].
256func (e MouseMotionEvent) Mouse() Mouse {
257	return Mouse(e)
258}
259
260// CursorPositionEvent represents a cursor position event. Where X is the
261// zero-based column and Y is the zero-based row.
262type CursorPositionEvent image.Point
263
264// FocusEvent represents a terminal focus event.
265// This occurs when the terminal gains focus.
266type FocusEvent struct{}
267
268// BlurEvent represents a terminal blur event.
269// This occurs when the terminal loses focus.
270type BlurEvent struct{}
271
272// DarkColorSchemeEvent is sent when the operating system is using a dark color
273// scheme. This is typically used to notify applications of the current or new
274// system color scheme.
275type DarkColorSchemeEvent struct{}
276
277// LightColorSchemeEvent is sent when the operating system is using a light color
278// scheme. This is typically used to notify applications of the current or new
279// system color scheme.
280type LightColorSchemeEvent struct{}
281
282// PasteEvent is an message that is emitted when a terminal receives pasted text
283// using bracketed-paste.
284type PasteEvent string
285
286// PasteStartEvent is an message that is emitted when the terminal starts the
287// bracketed-paste text.
288type PasteStartEvent struct{}
289
290// PasteEndEvent is an message that is emitted when the terminal ends the
291// bracketed-paste text.
292type PasteEndEvent struct{}
293
294// TerminalVersionEvent is a message that represents the terminal version.
295type TerminalVersionEvent string
296
297// ModifyOtherKeysEvent represents a modifyOtherKeys event.
298//
299//	0: disable
300//	1: enable mode 1
301//	2: enable mode 2
302//
303// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
304// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys
305type ModifyOtherKeysEvent uint8
306
307// KittyGraphicsEvent represents a Kitty Graphics response event.
308//
309// See https://sw.kovidgoyal.net/kitty/graphics-protocol/
310type KittyGraphicsEvent struct {
311	Options kitty.Options
312	Payload []byte
313}
314
315// KittyEnhancementsEvent represents a Kitty enhancements event.
316type KittyEnhancementsEvent int
317
318// Contains reports whether m contains the given enhancements.
319func (e KittyEnhancementsEvent) Contains(enhancements int) bool {
320	return int(e)&enhancements == enhancements
321}
322
323// PrimaryDeviceAttributesEvent is an event that represents the terminal
324// primary device attributes.
325//
326// Common attributes include:
327//   - 1	132 columns
328//   - 2	Printer port
329//   - 4	Sixel
330//   - 6	Selective erase
331//   - 7	Soft character set (DRCS)
332//   - 8	User-defined keys (UDKs)
333//   - 9	National replacement character sets (NRCS) (International terminal only)
334//   - 12	Yugoslavian (SCS)
335//   - 15	Technical character set
336//   - 18	Windowing capability
337//   - 21	Horizontal scrolling
338//   - 23	Greek
339//   - 24	Turkish
340//   - 42	ISO Latin-2 character set
341//   - 44	PCTerm
342//   - 45	Soft key map
343//   - 46	ASCII emulation
344//
345// See [ansi.PrimaryDeviceAttributes] for more details.
346type PrimaryDeviceAttributesEvent []int
347
348// ModeReportEvent is a message that represents a mode report event (DECRPM).
349//
350// See: https://vt100.net/docs/vt510-rm/DECRPM.html
351type ModeReportEvent struct {
352	// Mode is the mode number.
353	Mode ansi.Mode
354
355	// Value is the mode value.
356	Value ansi.ModeSetting
357}
358
359// ForegroundColorEvent represents a foreground color event. This event is
360// emitted when the terminal requests the terminal foreground color using
361// [ansi.RequestForegroundColor].
362type ForegroundColorEvent struct{ color.Color }
363
364// String returns the hex representation of the color.
365func (e ForegroundColorEvent) String() string {
366	return colorToHex(e.Color)
367}
368
369// IsDark returns whether the color is dark.
370func (e ForegroundColorEvent) IsDark() bool {
371	return isDarkColor(e.Color)
372}
373
374// BackgroundColorEvent represents a background color event. This event is
375// emitted when the terminal requests the terminal background color using
376// [ansi.RequestBackgroundColor].
377type BackgroundColorEvent struct{ color.Color }
378
379// String returns the hex representation of the color.
380func (e BackgroundColorEvent) String() string {
381	return colorToHex(e)
382}
383
384// IsDark returns whether the color is dark.
385func (e BackgroundColorEvent) IsDark() bool {
386	return isDarkColor(e.Color)
387}
388
389// CursorColorEvent represents a cursor color change event. This event is
390// emitted when the program requests the terminal cursor color using
391// [ansi.RequestCursorColor].
392type CursorColorEvent struct{ color.Color }
393
394// String returns the hex representation of the color.
395func (e CursorColorEvent) String() string {
396	return colorToHex(e)
397}
398
399// IsDark returns whether the color is dark.
400func (e CursorColorEvent) IsDark() bool {
401	return isDarkColor(e)
402}
403
404// WindowOpEvent is a window operation (XTWINOPS) report event. This is used to
405// report various window operations such as reporting the window size or cell
406// size.
407type WindowOpEvent struct {
408	Op   int
409	Args []int
410}
411
412// CapabilityEvent represents a Termcap/Terminfo response event. Termcap
413// responses are generated by the terminal in response to RequestTermcap
414// (XTGETTCAP) requests.
415//
416// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
417type CapabilityEvent string
418
419// ClipboardSelection represents a clipboard selection. The most common
420// clipboard selections are "system" and "primary" and selections.
421type ClipboardSelection = byte
422
423// Clipboard selections.
424const (
425	SystemClipboard  ClipboardSelection = ansi.SystemClipboard
426	PrimaryClipboard ClipboardSelection = ansi.PrimaryClipboard
427)
428
429// ClipboardEvent is a clipboard read message event. This message is emitted when
430// a terminal receives an OSC52 clipboard read message event.
431type ClipboardEvent struct {
432	Content   string
433	Selection ClipboardSelection
434}
435
436// String returns the string representation of the clipboard message.
437func (e ClipboardEvent) String() string {
438	return e.Content
439}
440
441// ignoredEvent represents a sequence event that is ignored by the terminal
442// reader. This is used to ignore certain sequences that can be canceled.
443type ignoredEvent string