ghostty-web 0.3.0 → 0.4.0-next.0.g9e4e126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -13,7 +13,9 @@ export declare class CanvasRenderer {
13
13
  private cursorBlinkInterval?;
14
14
  private lastCursorPosition;
15
15
  private lastViewportY;
16
+ private currentBuffer;
16
17
  private selectionManager?;
18
+ private currentSelectionCoords;
17
19
  private hoveredHyperlinkId;
18
20
  private previousHoveredHyperlinkId;
19
21
  private hoveredLinkRange;
@@ -34,13 +36,28 @@ export declare class CanvasRenderer {
34
36
  */
35
37
  render(buffer: IRenderable, forceAll?: boolean, viewportY?: number, scrollbackProvider?: IScrollbackProvider, scrollbarOpacity?: number): void;
36
38
  /**
37
- * Render a single line
39
+ * Render a single line using two-pass approach:
40
+ * 1. First pass: Draw all cell backgrounds
41
+ * 2. Second pass: Draw all cell text and decorations
42
+ *
43
+ * This two-pass approach is necessary for proper rendering of complex scripts
44
+ * like Devanagari where diacritics (like vowel sign ि) can extend LEFT of the
45
+ * base character into the previous cell's visual area. If we draw backgrounds
46
+ * and text in a single pass (cell by cell), the background of cell N would
47
+ * cover any left-extending portions of graphemes from cell N-1.
38
48
  */
39
49
  private renderLine;
40
50
  /**
41
- * Render a single cell
51
+ * Render a cell's background only (Pass 1 of two-pass rendering)
52
+ * Selection highlighting is integrated here to avoid z-order issues with
53
+ * complex glyphs (like Devanagari) that extend outside their cell bounds.
54
+ */
55
+ private renderCellBackground;
56
+ /**
57
+ * Render a cell's text and decorations (Pass 2 of two-pass rendering)
58
+ * Selection foreground color is applied here to match the selection background.
42
59
  */
43
- private renderCell;
60
+ private renderCellText;
44
61
  /**
45
62
  * Render cursor
46
63
  */
@@ -82,9 +99,14 @@ export declare class CanvasRenderer {
82
99
  */
83
100
  getCanvas(): HTMLCanvasElement;
84
101
  /**
85
- * Set selection manager (for rendering selection overlay)
102
+ * Set selection manager (for rendering selection)
86
103
  */
87
104
  setSelectionManager(manager: SelectionManager): void;
105
+ /**
106
+ * Check if a cell at (x, y) is within the current selection.
107
+ * Uses cached selection coordinates for performance.
108
+ */
109
+ private isInSelection;
88
110
  /**
89
111
  * Set the currently hovered hyperlink ID for rendering underlines
90
112
  */
@@ -111,10 +133,6 @@ export declare class CanvasRenderer {
111
133
  * Clear entire canvas
112
134
  */
113
135
  clear(): void;
114
- /**
115
- * Render selection overlay
116
- */
117
- private renderSelection;
118
136
  /**
119
137
  * Cleanup resources
120
138
  */
@@ -144,6 +162,15 @@ export declare interface Cursor {
144
162
  visible: boolean;
145
163
  }
146
164
 
165
+ /**
166
+ * Dirty state from RenderState
167
+ */
168
+ declare enum DirtyState {
169
+ NONE = 0,
170
+ PARTIAL = 1,
171
+ FULL = 2
172
+ }
173
+
147
174
  export declare class EventEmitter<T> {
148
175
  private listeners;
149
176
  fire(arg: T): void;
@@ -212,23 +239,10 @@ export declare class Ghostty {
212
239
  private exports;
213
240
  private memory;
214
241
  constructor(wasmInstance: WebAssembly.Instance);
215
- /**
216
- * Get current memory buffer (may change when memory grows)
217
- */
218
- private getBuffer;
219
- /**
220
- * Create a key encoder instance
221
- */
222
242
  createKeyEncoder(): KeyEncoder;
223
- /**
224
- * Create a terminal emulator instance
225
- */
226
243
  createTerminal(cols?: number, rows?: number, config?: GhosttyTerminalConfig): GhosttyTerminal;
227
- /**
228
- * Load Ghostty WASM from URL or file path
229
- * If no path is provided, attempts to load from common default locations
230
- */
231
244
  static load(wasmPath?: string): Promise<Ghostty>;
245
+ private static loadFromPath;
232
246
  }
233
247
 
234
248
  /**
@@ -245,25 +259,16 @@ export declare interface GhosttyCell {
245
259
  flags: number;
246
260
  width: number;
247
261
  hyperlink_id: number;
262
+ grapheme_len: number;
248
263
  }
249
264
 
250
265
  /**
251
- * GhosttyTerminal - Wraps the WASM terminal emulator
266
+ * GhosttyTerminal - High-performance terminal emulator
252
267
  *
253
- * Provides a TypeScript-friendly interface to Ghostty's complete
254
- * terminal implementation via WASM.
255
- *
256
- * @example
257
- * ```typescript
258
- * const ghostty = await Ghostty.load('./ghostty-vt.wasm');
259
- * const term = ghostty.createTerminal(80, 24);
260
- *
261
- * term.write('Hello\x1b[31m Red\x1b[0m\n');
262
- * const cursor = term.getCursor();
263
- * const cells = term.getLine(0);
264
- *
265
- * term.free();
266
- * ```
268
+ * Uses Ghostty's native RenderState for optimal performance:
269
+ * - ONE call to update all state (renderStateUpdate)
270
+ * - ONE call to get all cells (getViewport)
271
+ * - No per-row WASM boundary crossings!
267
272
  */
268
273
  export declare class GhosttyTerminal {
269
274
  private exports;
@@ -271,186 +276,145 @@ export declare class GhosttyTerminal {
271
276
  private handle;
272
277
  private _cols;
273
278
  private _rows;
274
- /**
275
- * Size of ghostty_cell_t in bytes (16 bytes in WASM)
276
- * Structure: codepoint(u32) + fg_rgb(3xu8) + bg_rgb(3xu8) + flags(u8) + width(u8) + hyperlink_id(u16) + padding(u32)
277
- */
279
+ /** Size of GhosttyCell in WASM (16 bytes) */
278
280
  private static readonly CELL_SIZE;
279
- /**
280
- * Create a new terminal.
281
- *
282
- * @param exports WASM exports
283
- * @param memory WASM memory
284
- * @param cols Number of columns (default: 80)
285
- * @param rows Number of rows (default: 24)
286
- * @param config Optional terminal configuration (colors, scrollback)
287
- * @throws Error if allocation fails
288
- */
281
+ /** Reusable buffer for viewport operations */
282
+ private viewportBufferPtr;
283
+ private viewportBufferSize;
284
+ /** Cell pool for zero-allocation rendering */
285
+ private cellPool;
289
286
  constructor(exports: GhosttyWasmExports, memory: WebAssembly.Memory, cols?: number, rows?: number, config?: GhosttyTerminalConfig);
290
- /**
291
- * Free the terminal. Must be called to prevent memory leaks.
292
- */
287
+ get cols(): number;
288
+ get rows(): number;
289
+ write(data: string | Uint8Array): void;
290
+ resize(cols: number, rows: number): void;
293
291
  free(): void;
294
292
  /**
295
- * Write data to terminal (parses VT sequences and updates screen).
293
+ * Update render state from terminal.
296
294
  *
297
- * @param data UTF-8 string or Uint8Array
295
+ * This syncs the RenderState with the current Terminal state.
296
+ * The dirty state (full/partial/none) is stored in the WASM RenderState
297
+ * and can be queried via isRowDirty(). When dirty==full, isRowDirty()
298
+ * returns true for ALL rows.
298
299
  *
299
- * @example
300
- * ```typescript
301
- * term.write('Hello, World!\n');
302
- * term.write('\x1b[1;31mBold Red\x1b[0m\n');
303
- * term.write(new Uint8Array([0x1b, 0x5b, 0x41])); // Up arrow
304
- * ```
305
- */
306
- write(data: string | Uint8Array): void;
307
- /**
308
- * Resize the terminal.
300
+ * The WASM layer automatically detects screen switches (normal <-> alternate)
301
+ * and returns FULL dirty state when switching screens (e.g., vim exit).
309
302
  *
310
- * @param cols New column count
311
- * @param rows New row count
303
+ * Safe to call multiple times - dirty state persists until markClean().
312
304
  */
313
- resize(cols: number, rows: number): void;
305
+ update(): DirtyState;
314
306
  /**
315
- * Get terminal dimensions.
307
+ * Get cursor state from render state.
308
+ * Ensures render state is fresh by calling update().
316
309
  */
317
- get cols(): number;
318
- get rows(): number;
310
+ getCursor(): RenderStateCursor;
319
311
  /**
320
- * Get terminal dimensions (for IRenderable compatibility)
312
+ * Get default colors from render state
321
313
  */
322
- getDimensions(): {
323
- cols: number;
324
- rows: number;
325
- };
314
+ getColors(): RenderStateColors;
326
315
  /**
327
- * Get cursor position and visibility.
316
+ * Check if a specific row is dirty
328
317
  */
329
- getCursor(): Cursor;
318
+ isRowDirty(y: number): boolean;
330
319
  /**
331
- * Get scrollback length (number of lines in history).
320
+ * Mark render state as clean (call after rendering)
332
321
  */
333
- getScrollbackLength(): number;
322
+ markClean(): void;
334
323
  /**
335
- * Check if terminal is in alternate screen buffer mode.
336
- *
337
- * The alternate screen is used by vim, less, htop, etc.
338
- * When active, normal buffer is preserved and restored when the app exits.
339
- *
340
- * @returns true if in alternate screen, false if in normal screen
341
- *
342
- * @example
343
- * ```typescript
344
- * // Detect if vim is running
345
- * if (term.isAlternateScreen()) {
346
- * console.log('Full-screen app is active');
347
- * }
348
- * ```
324
+ * Get ALL viewport cells in ONE WASM call - the key performance optimization!
325
+ * Returns a reusable cell array (zero allocation after warmup).
349
326
  */
350
- isAlternateScreen(): boolean;
327
+ getViewport(): GhosttyCell[];
351
328
  /**
352
- * Check if a row is wrapped from the previous row.
353
- *
354
- * Wrapped rows are continuations of long lines that exceeded terminal width.
355
- * Used for text selection to treat wrapped lines as single logical lines.
356
- *
357
- * @param row Row index (0 = top visible line)
358
- * @returns true if row continues from previous line, false otherwise
359
- *
360
- * @example
361
- * ```typescript
362
- * // Get full logical line including wraps
363
- * let text = '';
364
- * for (let row = 0; row < term.rows; row++) {
365
- * const line = term.getLine(row);
366
- * text += lineToString(line);
367
- *
368
- * // Only add newline if NOT wrapped
369
- * if (!term.isRowWrapped(row + 1)) {
370
- * text += '\n';
371
- * }
372
- * }
373
- * ```
374
- */
375
- isRowWrapped(row: number): boolean;
376
- /**
377
- * Get a line of cells from the visible screen.
378
- *
379
- * @param y Line number (0 = top visible line)
380
- * @returns Array of cells, or null if y is out of bounds
381
- *
382
- * @example
383
- * ```typescript
384
- * const cells = term.getLine(0);
385
- * if (cells) {
386
- * for (const cell of cells) {
387
- * const char = String.fromCodePoint(cell.codepoint);
388
- * const isBold = (cell.flags & CellFlags.BOLD) !== 0;
389
- * console.log(`"${char}" ${isBold ? 'bold' : 'normal'}`);
390
- * }
391
- * }
392
- * ```
329
+ * Get line - for compatibility, extracts from viewport.
330
+ * Ensures render state is fresh by calling update().
331
+ * Returns a COPY of the cells to avoid pool reference issues.
393
332
  */
394
333
  getLine(y: number): GhosttyCell[] | null;
395
- /**
396
- * Get a line from scrollback history.
397
- *
398
- * @param offset Line offset from top of scrollback (0 = oldest line)
399
- * @returns Array of cells, or null if not available
400
- */
401
- getScrollbackLine(offset: number): GhosttyCell[] | null;
402
- /**
403
- * Check if any part of the screen is dirty.
404
- */
334
+ /** For compatibility with old API */
405
335
  isDirty(): boolean;
406
336
  /**
407
- * Check if a specific row is dirty.
408
- */
409
- isRowDirty(y: number): boolean;
410
- /**
411
- * Clear all dirty flags (call after rendering).
337
+ * Check if a full redraw is needed (screen change, resize, etc.)
338
+ * Note: This calls update() to ensure fresh state. Safe to call multiple times.
412
339
  */
340
+ needsFullRedraw(): boolean;
341
+ /** Mark render state as clean after rendering */
413
342
  clearDirty(): void;
343
+ isAlternateScreen(): boolean;
344
+ hasBracketedPaste(): boolean;
345
+ hasFocusEvents(): boolean;
346
+ hasMouseTracking(): boolean;
347
+ /** Get dimensions - for compatibility */
348
+ getDimensions(): {
349
+ cols: number;
350
+ rows: number;
351
+ };
352
+ /** Get number of scrollback lines (history, not including active screen) */
353
+ getScrollbackLength(): number;
414
354
  /**
415
- * Get all visible lines at once (convenience method).
416
- *
417
- * @returns Array of line arrays, or empty array on error
355
+ * Get a line from the scrollback buffer.
356
+ * Ensures render state is fresh by calling update().
357
+ * @param offset 0 = oldest line, (length-1) = most recent scrollback line
418
358
  */
419
- getAllLines(): GhosttyCell[][];
359
+ getScrollbackLine(offset: number): GhosttyCell[] | null;
360
+ /** Check if a row in the active screen is wrapped (soft-wrapped to next line) */
361
+ isRowWrapped(row: number): boolean;
362
+ /** Hyperlink URI not yet exposed in simplified API */
363
+ getHyperlinkUri(_id: number): string | null;
420
364
  /**
421
- * Get only the dirty lines (for optimized rendering).
422
- *
423
- * @returns Map of row number to cell array
365
+ * Check if there are pending responses from the terminal.
366
+ * Responses are generated by escape sequences like DSR (Device Status Report).
424
367
  */
425
- getDirtyLines(): Map<number, GhosttyCell[]>;
368
+ hasResponse(): boolean;
426
369
  /**
427
- * Get hyperlink URI by ID
370
+ * Read pending responses from the terminal.
371
+ * Returns the response string, or null if no responses pending.
428
372
  *
429
- * @param hyperlinkId Hyperlink ID from a GhosttyCell (0 = no link)
430
- * @returns URI string or null if ID is invalid/not found
373
+ * Responses are generated by escape sequences that require replies:
374
+ * - DSR 6 (cursor position): Returns \x1b[row;colR
375
+ * - DSR 5 (operating status): Returns \x1b[0n
431
376
  */
432
- getHyperlinkUri(hyperlinkId: number): string | null;
377
+ readResponse(): string | null;
433
378
  /**
434
- * Query terminal mode state
379
+ * Query arbitrary terminal mode by number
380
+ * @param mode Mode number (e.g., 25 for cursor visibility, 2004 for bracketed paste)
381
+ * @param isAnsi True for ANSI modes, false for DEC modes (default: false)
435
382
  */
436
383
  getMode(mode: number, isAnsi?: boolean): boolean;
384
+ private initCellPool;
385
+ private parseCellsIntoPool;
386
+ /** Small buffer for grapheme lookups (reused to avoid allocation) */
387
+ private graphemeBuffer;
388
+ private graphemeBufferPtr;
437
389
  /**
438
- * Check if bracketed paste mode is enabled
390
+ * Get all codepoints for a grapheme cluster at the given position.
391
+ * For most cells this returns a single codepoint, but for complex scripts
392
+ * (Hindi, emoji with ZWJ, etc.) it returns multiple codepoints.
393
+ * @returns Array of codepoints, or null on error
439
394
  */
440
- hasBracketedPaste(): boolean;
395
+ getGrapheme(row: number, col: number): number[] | null;
441
396
  /**
442
- * Check if focus event reporting is enabled
397
+ * Get a string representation of the grapheme at the given position.
398
+ * This properly handles complex scripts like Hindi, emoji with ZWJ, etc.
443
399
  */
444
- hasFocusEvents(): boolean;
400
+ getGraphemeString(row: number, col: number): string;
445
401
  /**
446
- * Check if mouse tracking is enabled
402
+ * Get all codepoints for a grapheme cluster in the scrollback buffer.
403
+ * @param offset Scrollback line offset (0 = oldest)
404
+ * @param col Column index
405
+ * @returns Array of codepoints, or null on error
447
406
  */
448
- hasMouseTracking(): boolean;
407
+ getScrollbackGrapheme(offset: number, col: number): number[] | null;
408
+ /**
409
+ * Get a string representation of a grapheme in the scrollback buffer.
410
+ */
411
+ getScrollbackGraphemeString(offset: number, col: number): string;
412
+ private invalidateBuffers;
449
413
  }
450
414
 
451
415
  /**
452
- * Terminal configuration for WASM.
453
- * All colors use 0xRRGGBB format. A value of 0 means "use default".
416
+ * Terminal configuration (passed to ghostty_terminal_new_with_config)
417
+ * All color values use 0xRRGGBB format. A value of 0 means "use default".
454
418
  */
455
419
  declare interface GhosttyTerminalConfig {
456
420
  scrollbackLimit?: number;
@@ -497,26 +461,29 @@ declare interface GhosttyWasmExports extends WebAssembly.Exports {
497
461
  ghostty_terminal_new(cols: number, rows: number): TerminalHandle;
498
462
  ghostty_terminal_new_with_config(cols: number, rows: number, configPtr: number): TerminalHandle;
499
463
  ghostty_terminal_free(terminal: TerminalHandle): void;
500
- ghostty_terminal_write(terminal: TerminalHandle, dataPtr: number, dataLen: number): void;
501
464
  ghostty_terminal_resize(terminal: TerminalHandle, cols: number, rows: number): void;
502
- ghostty_terminal_get_cols(terminal: TerminalHandle): number;
503
- ghostty_terminal_get_rows(terminal: TerminalHandle): number;
504
- ghostty_terminal_get_cursor_x(terminal: TerminalHandle): number;
505
- ghostty_terminal_get_cursor_y(terminal: TerminalHandle): number;
506
- ghostty_terminal_get_cursor_visible(terminal: TerminalHandle): boolean;
465
+ ghostty_terminal_write(terminal: TerminalHandle, dataPtr: number, dataLen: number): void;
466
+ ghostty_render_state_update(terminal: TerminalHandle): number;
467
+ ghostty_render_state_get_cols(terminal: TerminalHandle): number;
468
+ ghostty_render_state_get_rows(terminal: TerminalHandle): number;
469
+ ghostty_render_state_get_cursor_x(terminal: TerminalHandle): number;
470
+ ghostty_render_state_get_cursor_y(terminal: TerminalHandle): number;
471
+ ghostty_render_state_get_cursor_visible(terminal: TerminalHandle): boolean;
472
+ ghostty_render_state_get_bg_color(terminal: TerminalHandle): number;
473
+ ghostty_render_state_get_fg_color(terminal: TerminalHandle): number;
474
+ ghostty_render_state_is_row_dirty(terminal: TerminalHandle, row: number): boolean;
475
+ ghostty_render_state_mark_clean(terminal: TerminalHandle): void;
476
+ ghostty_render_state_get_viewport(terminal: TerminalHandle, bufPtr: number, bufLen: number): number;
477
+ ghostty_render_state_get_grapheme(terminal: TerminalHandle, row: number, col: number, bufPtr: number, bufLen: number): number;
507
478
  ghostty_terminal_is_alternate_screen(terminal: TerminalHandle): boolean;
508
- ghostty_terminal_is_row_wrapped(terminal: TerminalHandle, row: number): boolean;
509
- ghostty_terminal_is_dirty(terminal: TerminalHandle): boolean;
510
- ghostty_terminal_is_row_dirty(terminal: TerminalHandle, row: number): boolean;
511
- ghostty_terminal_clear_dirty(terminal: TerminalHandle): void;
512
- ghostty_terminal_get_hyperlink_uri(terminal: TerminalHandle, hyperlinkId: number, bufPtr: number, bufLen: number): number;
513
- ghostty_terminal_get_line(terminal: TerminalHandle, row: number, bufPtr: number, bufLen: number): number;
514
- ghostty_terminal_get_scrollback_line(terminal: TerminalHandle, offset: number, bufPtr: number, bufLen: number): number;
515
- ghostty_terminal_get_scrollback_length(terminal: TerminalHandle): number;
516
- ghostty_terminal_get_mode(terminal: TerminalHandle, mode: number, isAnsi: number): number;
517
- ghostty_terminal_has_bracketed_paste(terminal: TerminalHandle): number;
518
- ghostty_terminal_has_focus_events(terminal: TerminalHandle): number;
519
479
  ghostty_terminal_has_mouse_tracking(terminal: TerminalHandle): number;
480
+ ghostty_terminal_get_mode(terminal: TerminalHandle, mode: number, isAnsi: boolean): number;
481
+ ghostty_terminal_get_scrollback_length(terminal: TerminalHandle): number;
482
+ ghostty_terminal_get_scrollback_line(terminal: TerminalHandle, offset: number, bufPtr: number, bufLen: number): number;
483
+ ghostty_terminal_get_scrollback_grapheme(terminal: TerminalHandle, offset: number, col: number, bufPtr: number, bufLen: number): number;
484
+ ghostty_terminal_is_row_wrapped(terminal: TerminalHandle, row: number): number;
485
+ ghostty_terminal_has_response(terminal: TerminalHandle): boolean;
486
+ ghostty_terminal_read_response(terminal: TerminalHandle, bufPtr: number, bufLen: number): number;
520
487
  }
521
488
 
522
489
  /**
@@ -744,9 +711,14 @@ export declare class InputHandler {
744
711
  private onBellCallback;
745
712
  private onKeyCallback?;
746
713
  private customKeyEventHandler?;
714
+ private getModeCallback?;
747
715
  private keydownListener;
748
716
  private keypressListener;
749
717
  private pasteListener;
718
+ private compositionStartListener;
719
+ private compositionUpdateListener;
720
+ private compositionEndListener;
721
+ private isComposing;
750
722
  private isDisposed;
751
723
  /**
752
724
  * Create a new InputHandler
@@ -756,8 +728,9 @@ export declare class InputHandler {
756
728
  * @param onBell - Callback for bell/beep event
757
729
  * @param onKey - Optional callback for raw key events
758
730
  * @param customKeyEventHandler - Optional custom key event handler
731
+ * @param getMode - Optional callback to query terminal mode state (for application cursor mode)
759
732
  */
760
- constructor(ghostty: Ghostty, container: HTMLElement, onData: (data: string) => void, onBell: () => void, onKey?: (keyEvent: IKeyEvent) => void, customKeyEventHandler?: (event: KeyboardEvent) => boolean);
733
+ constructor(ghostty: Ghostty, container: HTMLElement, onData: (data: string) => void, onBell: () => void, onKey?: (keyEvent: IKeyEvent) => void, customKeyEventHandler?: (event: KeyboardEvent) => boolean, getMode?: (mode: number) => boolean);
761
734
  /**
762
735
  * Set custom key event handler (for runtime updates)
763
736
  */
@@ -794,6 +767,18 @@ export declare class InputHandler {
794
767
  * @param event - ClipboardEvent
795
768
  */
796
769
  private handlePaste;
770
+ /**
771
+ * Handle compositionstart event
772
+ */
773
+ private handleCompositionStart;
774
+ /**
775
+ * Handle compositionupdate event
776
+ */
777
+ private handleCompositionUpdate;
778
+ /**
779
+ * Handle compositionend event
780
+ */
781
+ private handleCompositionEnd;
797
782
  /**
798
783
  * Dispose the InputHandler and remove event listeners
799
784
  */
@@ -816,7 +801,15 @@ export declare interface IRenderable {
816
801
  rows: number;
817
802
  };
818
803
  isRowDirty(y: number): boolean;
804
+ /** Returns true if a full redraw is needed (e.g., screen change) */
805
+ needsFullRedraw?(): boolean;
819
806
  clearDirty(): void;
807
+ /**
808
+ * Get the full grapheme string for a cell at (row, col).
809
+ * For cells with grapheme_len > 0, this returns all codepoints combined.
810
+ * For simple cells, returns the single character.
811
+ */
812
+ getGraphemeString?(row: number, col: number): string;
820
813
  }
821
814
 
822
815
  declare interface IScrollbackProvider {
@@ -938,119 +931,186 @@ export declare interface IUnicodeVersionProvider {
938
931
  }
939
932
 
940
933
  /**
941
- * Physical key codes (based on USB HID Usage Tables - Keyboard/Keypad Page 0x07)
942
- * Reference: https://www.usb.org/sites/default/files/hut1_21.pdf
934
+ * Physical key codes matching Ghostty's internal Key enum.
935
+ * These values are used by Ghostty's key encoder to produce correct escape sequences.
936
+ * Reference: ghostty/src/input/key.zig
943
937
  */
944
938
  export declare enum Key {
945
- A = 4,
946
- B = 5,
947
- C = 6,
948
- D = 7,
949
- E = 8,
950
- F = 9,
951
- G = 10,
952
- H = 11,
953
- I = 12,
954
- J = 13,
955
- K = 14,
956
- L = 15,
957
- M = 16,
958
- N = 17,
959
- O = 18,
960
- P = 19,
961
- Q = 20,
962
- R = 21,
963
- S = 22,
964
- T = 23,
965
- U = 24,
966
- V = 25,
967
- W = 26,
968
- X = 27,
969
- Y = 28,
970
- Z = 29,
971
- ONE = 30,
972
- TWO = 31,
973
- THREE = 32,
974
- FOUR = 33,
975
- FIVE = 34,
976
- SIX = 35,
977
- SEVEN = 36,
978
- EIGHT = 37,
979
- NINE = 38,
980
- ZERO = 39,
981
- ENTER = 40,
982
- ESCAPE = 41,
983
- BACKSPACE = 42,
984
- TAB = 43,
985
- SPACE = 44,
986
- MINUS = 45,// - and _
987
- EQUAL = 46,// = and +
988
- BRACKET_LEFT = 47,// [ and {
989
- BRACKET_RIGHT = 48,// ] and }
990
- BACKSLASH = 49,// \ and |
991
- SEMICOLON = 51,// ; and :
992
- QUOTE = 52,// ' and "
993
- GRAVE = 53,// ` and ~
994
- COMMA = 54,// , and <
995
- PERIOD = 55,// . and >
996
- SLASH = 56,// / and ?
997
- CAPS_LOCK = 57,
998
- F1 = 58,
999
- F2 = 59,
1000
- F3 = 60,
1001
- F4 = 61,
1002
- F5 = 62,
1003
- F6 = 63,
1004
- F7 = 64,
1005
- F8 = 65,
1006
- F9 = 66,
1007
- F10 = 67,
1008
- F11 = 68,
1009
- F12 = 69,
1010
- PRINT_SCREEN = 70,
1011
- SCROLL_LOCK = 71,
1012
- PAUSE = 72,
1013
- INSERT = 73,
1014
- HOME = 74,
1015
- PAGE_UP = 75,
1016
- DELETE = 76,
1017
- END = 77,
1018
- PAGE_DOWN = 78,
1019
- RIGHT = 79,
1020
- LEFT = 80,
1021
- DOWN = 81,
1022
- UP = 82,
1023
- NUM_LOCK = 83,
1024
- KP_DIVIDE = 84,// Keypad /
1025
- KP_MULTIPLY = 85,// Keypad *
1026
- KP_MINUS = 86,// Keypad -
1027
- KP_PLUS = 87,// Keypad +
1028
- KP_ENTER = 88,// Keypad Enter
1029
- KP_1 = 89,
1030
- KP_2 = 90,
1031
- KP_3 = 91,
1032
- KP_4 = 92,
1033
- KP_5 = 93,
1034
- KP_6 = 94,
1035
- KP_7 = 95,
1036
- KP_8 = 96,
1037
- KP_9 = 97,
1038
- KP_0 = 98,
1039
- KP_PERIOD = 99,// Keypad .
1040
- NON_US_BACKSLASH = 100,// \ and | on non-US keyboards
1041
- APPLICATION = 101,// Context menu key
1042
- F13 = 104,
1043
- F14 = 105,
1044
- F15 = 106,
1045
- F16 = 107,
1046
- F17 = 108,
1047
- F18 = 109,
1048
- F19 = 110,
1049
- F20 = 111,
1050
- F21 = 112,
1051
- F22 = 113,
1052
- F23 = 114,
1053
- F24 = 115
939
+ UNIDENTIFIED = 0,
940
+ GRAVE = 1,// ` and ~
941
+ BACKSLASH = 2,// \ and |
942
+ BRACKET_LEFT = 3,// [ and {
943
+ BRACKET_RIGHT = 4,// ] and }
944
+ COMMA = 5,// , and <
945
+ ZERO = 6,
946
+ ONE = 7,
947
+ TWO = 8,
948
+ THREE = 9,
949
+ FOUR = 10,
950
+ FIVE = 11,
951
+ SIX = 12,
952
+ SEVEN = 13,
953
+ EIGHT = 14,
954
+ NINE = 15,
955
+ EQUAL = 16,// = and +
956
+ INTL_BACKSLASH = 17,
957
+ INTL_RO = 18,
958
+ INTL_YEN = 19,
959
+ A = 20,
960
+ B = 21,
961
+ C = 22,
962
+ D = 23,
963
+ E = 24,
964
+ F = 25,
965
+ G = 26,
966
+ H = 27,
967
+ I = 28,
968
+ J = 29,
969
+ K = 30,
970
+ L = 31,
971
+ M = 32,
972
+ N = 33,
973
+ O = 34,
974
+ P = 35,
975
+ Q = 36,
976
+ R = 37,
977
+ S = 38,
978
+ T = 39,
979
+ U = 40,
980
+ V = 41,
981
+ W = 42,
982
+ X = 43,
983
+ Y = 44,
984
+ Z = 45,
985
+ MINUS = 46,// - and _
986
+ PERIOD = 47,// . and >
987
+ QUOTE = 48,// ' and "
988
+ SEMICOLON = 49,// ; and :
989
+ SLASH = 50,// / and ?
990
+ ALT_LEFT = 51,
991
+ ALT_RIGHT = 52,
992
+ BACKSPACE = 53,
993
+ CAPS_LOCK = 54,
994
+ CONTEXT_MENU = 55,
995
+ CONTROL_LEFT = 56,
996
+ CONTROL_RIGHT = 57,
997
+ ENTER = 58,
998
+ META_LEFT = 59,
999
+ META_RIGHT = 60,
1000
+ SHIFT_LEFT = 61,
1001
+ SHIFT_RIGHT = 62,
1002
+ SPACE = 63,
1003
+ TAB = 64,
1004
+ CONVERT = 65,
1005
+ KANA_MODE = 66,
1006
+ NON_CONVERT = 67,
1007
+ DELETE = 68,
1008
+ END = 69,
1009
+ HELP = 70,
1010
+ HOME = 71,
1011
+ INSERT = 72,
1012
+ PAGE_DOWN = 73,
1013
+ PAGE_UP = 74,
1014
+ DOWN = 75,
1015
+ LEFT = 76,
1016
+ RIGHT = 77,
1017
+ UP = 78,
1018
+ NUM_LOCK = 79,
1019
+ KP_0 = 80,
1020
+ KP_1 = 81,
1021
+ KP_2 = 82,
1022
+ KP_3 = 83,
1023
+ KP_4 = 84,
1024
+ KP_5 = 85,
1025
+ KP_6 = 86,
1026
+ KP_7 = 87,
1027
+ KP_8 = 88,
1028
+ KP_9 = 89,
1029
+ KP_PLUS = 90,// Keypad +
1030
+ KP_BACKSPACE = 91,
1031
+ KP_CLEAR = 92,
1032
+ KP_CLEAR_ENTRY = 93,
1033
+ KP_COMMA = 94,
1034
+ KP_PERIOD = 95,// Keypad .
1035
+ KP_DIVIDE = 96,// Keypad /
1036
+ KP_ENTER = 97,// Keypad Enter
1037
+ KP_EQUAL = 98,
1038
+ KP_MEMORY_ADD = 99,
1039
+ KP_MEMORY_CLEAR = 100,
1040
+ KP_MEMORY_RECALL = 101,
1041
+ KP_MEMORY_STORE = 102,
1042
+ KP_MEMORY_SUBTRACT = 103,
1043
+ KP_MULTIPLY = 104,// Keypad *
1044
+ KP_PAREN_LEFT = 105,
1045
+ KP_PAREN_RIGHT = 106,
1046
+ KP_MINUS = 107,// Keypad -
1047
+ KP_SEPARATOR = 108,
1048
+ NUMPAD_UP = 109,
1049
+ NUMPAD_DOWN = 110,
1050
+ NUMPAD_RIGHT = 111,
1051
+ NUMPAD_LEFT = 112,
1052
+ NUMPAD_BEGIN = 113,
1053
+ NUMPAD_HOME = 114,
1054
+ NUMPAD_END = 115,
1055
+ NUMPAD_INSERT = 116,
1056
+ NUMPAD_DELETE = 117,
1057
+ NUMPAD_PAGE_UP = 118,
1058
+ NUMPAD_PAGE_DOWN = 119,
1059
+ ESCAPE = 120,
1060
+ F1 = 121,
1061
+ F2 = 122,
1062
+ F3 = 123,
1063
+ F4 = 124,
1064
+ F5 = 125,
1065
+ F6 = 126,
1066
+ F7 = 127,
1067
+ F8 = 128,
1068
+ F9 = 129,
1069
+ F10 = 130,
1070
+ F11 = 131,
1071
+ F12 = 132,
1072
+ F13 = 133,
1073
+ F14 = 134,
1074
+ F15 = 135,
1075
+ F16 = 136,
1076
+ F17 = 137,
1077
+ F18 = 138,
1078
+ F19 = 139,
1079
+ F20 = 140,
1080
+ F21 = 141,
1081
+ F22 = 142,
1082
+ F23 = 143,
1083
+ F24 = 144,
1084
+ F25 = 145,
1085
+ FN_LOCK = 146,
1086
+ PRINT_SCREEN = 147,
1087
+ SCROLL_LOCK = 148,
1088
+ PAUSE = 149,
1089
+ BROWSER_BACK = 150,
1090
+ BROWSER_FAVORITES = 151,
1091
+ BROWSER_FORWARD = 152,
1092
+ BROWSER_HOME = 153,
1093
+ BROWSER_REFRESH = 154,
1094
+ BROWSER_SEARCH = 155,
1095
+ BROWSER_STOP = 156,
1096
+ EJECT = 157,
1097
+ LAUNCH_APP_1 = 158,
1098
+ LAUNCH_APP_2 = 159,
1099
+ LAUNCH_MAIL = 160,
1100
+ MEDIA_PLAY_PAUSE = 161,
1101
+ MEDIA_SELECT = 162,
1102
+ MEDIA_STOP = 163,
1103
+ MEDIA_TRACK_NEXT = 164,
1104
+ MEDIA_TRACK_PREVIOUS = 165,
1105
+ POWER = 166,
1106
+ SLEEP = 167,
1107
+ AUDIO_VOLUME_DOWN = 168,
1108
+ AUDIO_VOLUME_MUTE = 169,
1109
+ AUDIO_VOLUME_UP = 170,
1110
+ WAKE_UP = 171,
1111
+ COPY = 172,
1112
+ CUT = 173,
1113
+ PASTE = 174
1054
1114
  }
1055
1115
 
1056
1116
  /**
@@ -1063,28 +1123,15 @@ export declare enum KeyAction {
1063
1123
  }
1064
1124
 
1065
1125
  /**
1066
- * Key Encoder
1067
- * Converts keyboard events into terminal escape sequences
1126
+ * Key Encoder - converts keyboard events into terminal escape sequences
1068
1127
  */
1069
1128
  export declare class KeyEncoder {
1070
1129
  private exports;
1071
1130
  private encoder;
1072
1131
  constructor(exports: GhosttyWasmExports);
1073
- /**
1074
- * Set an encoder option
1075
- */
1076
1132
  setOption(option: KeyEncoderOption, value: boolean | number): void;
1077
- /**
1078
- * Enable Kitty keyboard protocol with specified flags
1079
- */
1080
1133
  setKittyFlags(flags: KittyKeyFlags): void;
1081
- /**
1082
- * Encode a key event to escape sequence
1083
- */
1084
1134
  encode(event: KeyEvent): Uint8Array;
1085
- /**
1086
- * Free encoder resources
1087
- */
1088
1135
  dispose(): void;
1089
1136
  }
1090
1137
 
@@ -1220,6 +1267,29 @@ export declare interface RendererOptions {
1220
1267
  devicePixelRatio?: number;
1221
1268
  }
1222
1269
 
1270
+ /**
1271
+ * Colors from RenderState (12 bytes packed)
1272
+ */
1273
+ declare interface RenderStateColors {
1274
+ background: RGB;
1275
+ foreground: RGB;
1276
+ cursor: RGB | null;
1277
+ }
1278
+
1279
+ /**
1280
+ * Cursor state from RenderState (8 bytes packed)
1281
+ * Layout: x(u16) + y(u16) + viewport_x(i16) + viewport_y(i16) + visible(bool) + blinking(bool) + style(u8) + _pad(u8)
1282
+ */
1283
+ declare interface RenderStateCursor {
1284
+ x: number;
1285
+ y: number;
1286
+ viewportX: number;
1287
+ viewportY: number;
1288
+ visible: boolean;
1289
+ blinking: boolean;
1290
+ style: 'block' | 'underline' | 'bar';
1291
+ }
1292
+
1223
1293
  /**
1224
1294
  * RGB color
1225
1295
  */
@@ -1430,7 +1500,7 @@ export declare class Terminal implements ITerminalCore {
1430
1500
  private addons;
1431
1501
  private customKeyEventHandler?;
1432
1502
  private currentTitle;
1433
- private viewportY;
1503
+ viewportY: number;
1434
1504
  private targetViewportY;
1435
1505
  private scrollAnimationStartTime?;
1436
1506
  private scrollAnimationStartY?;
@@ -1446,6 +1516,16 @@ export declare class Terminal implements ITerminalCore {
1446
1516
  private readonly SCROLLBAR_HIDE_DELAY_MS;
1447
1517
  private readonly SCROLLBAR_FADE_DURATION_MS;
1448
1518
  constructor(options?: ITerminalOptions);
1519
+ /**
1520
+ * Handle runtime option changes (called when options are modified after terminal is open)
1521
+ * This enables xterm.js compatibility where options can be changed at runtime
1522
+ */
1523
+ private handleOptionChange;
1524
+ /**
1525
+ * Handle font changes (fontSize or fontFamily)
1526
+ * Updates canvas size to match new font metrics and forces a full re-render
1527
+ */
1528
+ private handleFontChange;
1449
1529
  /**
1450
1530
  * Parse a CSS color string to 0xRRGGBB format.
1451
1531
  * Returns 0 if the color is undefined or invalid.
@@ -1455,11 +1535,6 @@ export declare class Terminal implements ITerminalCore {
1455
1535
  * Convert terminal options to WASM terminal config.
1456
1536
  */
1457
1537
  private buildWasmConfig;
1458
- /**
1459
- * Handle runtime option changes (called when options are modified after terminal is open)
1460
- * This enables xterm.js compatibility where options can be changed at runtime
1461
- */
1462
- private handleOptionChange;
1463
1538
  /**
1464
1539
  * Open terminal in a parent element
1465
1540
  *
@@ -1682,6 +1757,18 @@ export declare class Terminal implements ITerminalCore {
1682
1757
  * Fade out scrollbar
1683
1758
  */
1684
1759
  private fadeOutScrollbar;
1760
+ /**
1761
+ * Process any pending terminal responses and emit them via onData.
1762
+ *
1763
+ * This handles escape sequences that require the terminal to send a response
1764
+ * back to the PTY, such as:
1765
+ * - DSR 6 (cursor position): Shell sends \x1b[6n, terminal responds with \x1b[row;colR
1766
+ * - DSR 5 (operating status): Shell sends \x1b[5n, terminal responds with \x1b[0n
1767
+ *
1768
+ * Without this, shells like nushell that rely on cursor position queries
1769
+ * will hang waiting for a response that never comes.
1770
+ */
1771
+ private processTerminalResponses;
1685
1772
  /**
1686
1773
  * Check for title changes in written data (OSC sequences)
1687
1774
  * Simplified implementation - looks for OSC 0, 1, 2