okami.mom/ultraviolet

git clone https://git.nkp.pet/okami.mom/ultraviolet

Ayman Bagabasfix: lint issuesf678006

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