restty 0.1.32 → 0.1.34

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.
@@ -13522,6 +13522,118 @@ function observeOscPromptState(state2, seq) {
13522
13522
  }
13523
13523
 
13524
13524
  // src/input/output/index.ts
13525
+ function normalizeCursorPosition(value) {
13526
+ if (!value)
13527
+ return null;
13528
+ const row = Number(value.row);
13529
+ const col = Number(value.col);
13530
+ if (!Number.isFinite(row) || !Number.isFinite(col))
13531
+ return null;
13532
+ return {
13533
+ row: Math.max(1, Math.floor(row)),
13534
+ col: Math.max(1, Math.floor(col))
13535
+ };
13536
+ }
13537
+ function resolveCursorStepParam(raw) {
13538
+ if (!raw)
13539
+ return 1;
13540
+ const parsed = Number(raw);
13541
+ if (!Number.isFinite(parsed) || parsed <= 0)
13542
+ return 1;
13543
+ return Math.floor(parsed);
13544
+ }
13545
+ function resolveCursorSetParam(raw) {
13546
+ if (!raw)
13547
+ return 1;
13548
+ const parsed = Number(raw);
13549
+ if (!Number.isFinite(parsed))
13550
+ return 1;
13551
+ return Math.max(1, Math.floor(parsed));
13552
+ }
13553
+ function applyTextToCursorHint(cursor, text, cols) {
13554
+ for (const ch of text) {
13555
+ const code = ch.charCodeAt(0);
13556
+ if (code === 13) {
13557
+ cursor.col = 1;
13558
+ continue;
13559
+ }
13560
+ if (code === 10) {
13561
+ cursor.row += 1;
13562
+ continue;
13563
+ }
13564
+ if (code === 8) {
13565
+ cursor.col = Math.max(1, cursor.col - 1);
13566
+ continue;
13567
+ }
13568
+ if (code === 9) {
13569
+ const nextTabCol = Math.floor((cursor.col - 1) / 8) * 8 + 9;
13570
+ cursor.col = cols > 0 ? Math.min(cols, nextTabCol) : nextTabCol;
13571
+ continue;
13572
+ }
13573
+ if (code < 32 || code === 127)
13574
+ continue;
13575
+ cursor.col += 1;
13576
+ if (cols > 0 && cursor.col > cols) {
13577
+ cursor.col = 1;
13578
+ cursor.row += 1;
13579
+ }
13580
+ }
13581
+ }
13582
+ function applyCsiToCursorHint(cursor, seq, cols) {
13583
+ if (!seq.startsWith("\x1B[") || seq.length < 3)
13584
+ return;
13585
+ const final = seq[seq.length - 1];
13586
+ const body = seq.slice(2, -1);
13587
+ if (!/^[0-9;]*$/.test(body))
13588
+ return;
13589
+ const parts = body.length ? body.split(";") : [];
13590
+ switch (final) {
13591
+ case "A": {
13592
+ cursor.row = Math.max(1, cursor.row - resolveCursorStepParam(parts[0]));
13593
+ return;
13594
+ }
13595
+ case "B": {
13596
+ cursor.row += resolveCursorStepParam(parts[0]);
13597
+ return;
13598
+ }
13599
+ case "C": {
13600
+ const next = cursor.col + resolveCursorStepParam(parts[0]);
13601
+ cursor.col = cols > 0 ? Math.min(cols, next) : next;
13602
+ return;
13603
+ }
13604
+ case "D": {
13605
+ cursor.col = Math.max(1, cursor.col - resolveCursorStepParam(parts[0]));
13606
+ return;
13607
+ }
13608
+ case "E": {
13609
+ cursor.row += resolveCursorStepParam(parts[0]);
13610
+ cursor.col = 1;
13611
+ return;
13612
+ }
13613
+ case "F": {
13614
+ cursor.row = Math.max(1, cursor.row - resolveCursorStepParam(parts[0]));
13615
+ cursor.col = 1;
13616
+ return;
13617
+ }
13618
+ case "G": {
13619
+ const next = resolveCursorSetParam(parts[0]);
13620
+ cursor.col = cols > 0 ? Math.min(cols, next) : next;
13621
+ return;
13622
+ }
13623
+ case "H":
13624
+ case "f": {
13625
+ cursor.row = resolveCursorSetParam(parts[0]);
13626
+ const next = resolveCursorSetParam(parts[1]);
13627
+ cursor.col = cols > 0 ? Math.min(cols, next) : next;
13628
+ return;
13629
+ }
13630
+ case "d": {
13631
+ cursor.row = resolveCursorSetParam(parts[0]);
13632
+ return;
13633
+ }
13634
+ }
13635
+ }
13636
+
13525
13637
  class OutputFilter {
13526
13638
  remainder = "";
13527
13639
  getCursorPosition;
@@ -13538,6 +13650,7 @@ class OutputFilter {
13538
13650
  getDefaultColors;
13539
13651
  desktopNotificationHandler;
13540
13652
  promptState = createPromptState();
13653
+ cursorHint = null;
13541
13654
  constructor(options) {
13542
13655
  this.getCursorPosition = options.getCursorPosition;
13543
13656
  this.sendReply = options.sendReply;
@@ -13551,6 +13664,7 @@ class OutputFilter {
13551
13664
  }
13552
13665
  setCursorProvider(fn) {
13553
13666
  this.getCursorPosition = fn;
13667
+ this.cursorHint = null;
13554
13668
  }
13555
13669
  setReplySink(fn) {
13556
13670
  this.sendReply = fn;
@@ -13616,12 +13730,17 @@ class OutputFilter {
13616
13730
  return output;
13617
13731
  let data = this.remainder + output;
13618
13732
  this.remainder = "";
13733
+ const metricCols = this.getWindowMetrics?.()?.cols;
13734
+ const colsHint = Number.isFinite(metricCols) && Number(metricCols) > 1 ? Math.floor(Number(metricCols)) : 0;
13735
+ let trackedCursor = this.cursorHint ?? normalizeCursorPosition(this.getCursorPosition()) ?? { row: 1, col: 1 };
13736
+ const getReplyCursor = () => trackedCursor;
13619
13737
  let result = "";
13620
13738
  let i = 0;
13621
13739
  while (i < data.length) {
13622
13740
  const ch = data[i];
13623
13741
  if (ch !== "\x1B") {
13624
13742
  result += ch;
13743
+ applyTextToCursorHint(trackedCursor, ch, colsHint);
13625
13744
  i += 1;
13626
13745
  continue;
13627
13746
  }
@@ -13686,12 +13805,14 @@ class OutputFilter {
13686
13805
  }
13687
13806
  if (!handleCoreCsiSequence(seq, {
13688
13807
  sendReply: this.sendReply,
13689
- getCursorPosition: this.getCursorPosition
13808
+ getCursorPosition: getReplyCursor
13690
13809
  })) {
13691
13810
  result += seq;
13811
+ applyCsiToCursorHint(trackedCursor, seq, colsHint);
13692
13812
  }
13693
13813
  i = j + 1;
13694
13814
  }
13815
+ this.cursorHint = { ...trackedCursor };
13695
13816
  return result;
13696
13817
  }
13697
13818
  }
@@ -19513,11 +19634,18 @@ function normalizeSelectionCell(cell, rows, cols, wideFlags) {
19513
19634
  }
19514
19635
  return { row, col };
19515
19636
  }
19516
- function positionToCell(clientX, clientY, canvasRect, dpr, cellW, cellH, cols, rows) {
19517
- const x = (clientX - canvasRect.left) * dpr;
19518
- const y = (clientY - canvasRect.top) * dpr;
19519
- const col = clamp(Math.floor(x / (cellW || 1)), 0, (cols || 1) - 1);
19520
- const row = clamp(Math.floor(y / (cellH || 1)), 0, (rows || 1) - 1);
19637
+ function positionToCell(clientX, clientY, canvasRect, dpr, cellW, cellH, cols, rows, canvasWidth, canvasHeight) {
19638
+ const safeDpr = dpr || 1;
19639
+ const safeCols = cols || 1;
19640
+ const safeRows = rows || 1;
19641
+ const safeCellW = cellW || 1;
19642
+ const safeCellH = cellH || 1;
19643
+ const scaleX = canvasRect.width > 0 ? (canvasWidth && canvasWidth > 0 ? canvasWidth : safeDpr) / canvasRect.width : safeDpr;
19644
+ const scaleY = canvasRect.height > 0 ? (canvasHeight && canvasHeight > 0 ? canvasHeight : safeDpr) / canvasRect.height : safeDpr;
19645
+ const x = (clientX - canvasRect.left) * scaleX;
19646
+ const y = (clientY - canvasRect.top) * scaleY;
19647
+ const col = clamp(Math.floor(x / safeCellW), 0, safeCols - 1);
19648
+ const row = clamp(Math.floor(y / safeCellH), 0, safeRows - 1);
19521
19649
  return { row, col };
19522
19650
  }
19523
19651
 
@@ -59385,13 +59513,16 @@ function createRuntimeInteraction(options) {
59385
59513
  const canvas = getCanvas();
59386
59514
  const rect2 = canvas.getBoundingClientRect();
59387
59515
  const { cellW, cellH, cols, rows } = getGridState();
59388
- return positionToCell(event.clientX, event.clientY, rect2, getCurrentDpr(), cellW || 1, cellH || 1, cols || 1, rows || 1);
59516
+ return positionToCell(event.clientX, event.clientY, rect2, getCurrentDpr(), cellW || 1, cellH || 1, cols || 1, rows || 1, canvas.width, canvas.height);
59389
59517
  };
59390
59518
  const positionToPixel = (event) => {
59391
59519
  const canvas = getCanvas();
59392
59520
  const rect2 = canvas.getBoundingClientRect();
59393
- const x3 = (event.clientX - rect2.left) * getCurrentDpr();
59394
- const y = (event.clientY - rect2.top) * getCurrentDpr();
59521
+ const fallbackScale = getCurrentDpr() || 1;
59522
+ const scaleX = rect2.width > 0 ? canvas.width / rect2.width : fallbackScale;
59523
+ const scaleY = rect2.height > 0 ? canvas.height / rect2.height : fallbackScale;
59524
+ const x3 = (event.clientX - rect2.left) * scaleX;
59525
+ const y = (event.clientY - rect2.top) * scaleY;
59395
59526
  return {
59396
59527
  x: Math.max(1, Math.round(x3 + 1)),
59397
59528
  y: Math.max(1, Math.round(y + 1))
@@ -63669,7 +63800,7 @@ function createRuntimeReporting(options) {
63669
63800
  function resolveCursorPosition(cursor) {
63670
63801
  if (!cursor)
63671
63802
  return lastResolvedCursor;
63672
- if (cursor.visible === 0) {
63803
+ if (cursor.visible === 0 && lastResolvedCursor) {
63673
63804
  return lastResolvedCursor;
63674
63805
  }
63675
63806
  let col = Number(cursor.col);
@@ -63690,14 +63821,32 @@ function createRuntimeReporting(options) {
63690
63821
  };
63691
63822
  const wasmExports = options.getWasmExports();
63692
63823
  const wasmHandle = options.getWasmHandle();
63693
- if (!inBounds(col, row) && wasmExports?.restty_active_cursor_x && wasmExports?.restty_active_cursor_y && wasmHandle) {
63824
+ const getActiveCursor = () => {
63825
+ if (!wasmExports?.restty_active_cursor_x || !wasmExports?.restty_active_cursor_y || !wasmHandle) {
63826
+ return null;
63827
+ }
63694
63828
  const activeCol = wasmExports.restty_active_cursor_x(wasmHandle);
63695
63829
  const activeRow = wasmExports.restty_active_cursor_y(wasmHandle);
63696
- if (inBounds(activeCol, activeRow)) {
63697
- col = activeCol;
63698
- row = activeRow;
63830
+ if (!inBounds(activeCol, activeRow))
63831
+ return null;
63832
+ return { col: activeCol, row: activeRow };
63833
+ };
63834
+ if (cursor.visible === 0 && !lastResolvedCursor) {
63835
+ const active = getActiveCursor();
63836
+ if (active) {
63837
+ lastResolvedCursor = {
63838
+ col: active.col,
63839
+ row: active.row,
63840
+ wideTail: cursor.wideTail === 1
63841
+ };
63842
+ return lastResolvedCursor;
63699
63843
  }
63700
63844
  }
63845
+ const activeFallback = !inBounds(col, row) ? getActiveCursor() : null;
63846
+ if (activeFallback) {
63847
+ col = activeFallback.col;
63848
+ row = activeFallback.row;
63849
+ }
63701
63850
  if (cols > 0 && rows > 0) {
63702
63851
  col = Math.max(0, Math.min(cols - 1, Math.floor(col)));
63703
63852
  row = Math.max(0, Math.min(rows - 1, Math.floor(row)));
@@ -64451,6 +64600,22 @@ function createResttyApp(options) {
64451
64600
  onFlush: (output) => sendInput(output, "pty")
64452
64601
  });
64453
64602
  let lastCursorForCpr = { row: 1, col: 1 };
64603
+ function resolveCursorForCpr() {
64604
+ if (wasmHandle && wasmExports?.restty_active_cursor_x && wasmExports?.restty_active_cursor_y) {
64605
+ const activeCol = wasmExports.restty_active_cursor_x(wasmHandle);
64606
+ const activeRow = wasmExports.restty_active_cursor_y(wasmHandle);
64607
+ const cols = lastRenderState?.cols ?? 0;
64608
+ const rows = lastRenderState?.rows ?? 0;
64609
+ const inBounds = cols > 0 && rows > 0 && Number.isFinite(activeCol) && Number.isFinite(activeRow) && activeCol >= 0 && activeRow >= 0 && activeCol < cols && activeRow < rows;
64610
+ if (inBounds) {
64611
+ lastCursorForCpr = {
64612
+ row: Math.floor(activeRow) + 1,
64613
+ col: Math.floor(activeCol) + 1
64614
+ };
64615
+ }
64616
+ }
64617
+ return lastCursorForCpr;
64618
+ }
64454
64619
  let inputHandler = null;
64455
64620
  let activeTheme = null;
64456
64621
  const webgpuUniforms = new Float32Array(8);
@@ -64588,7 +64753,7 @@ function createResttyApp(options) {
64588
64753
  }
64589
64754
  });
64590
64755
  inputHandler = createInputHandler({
64591
- getCursorPosition: () => lastCursorForCpr,
64756
+ getCursorPosition: resolveCursorForCpr,
64592
64757
  sendReply: (data) => {
64593
64758
  ptyTransport.sendInput(data);
64594
64759
  },
@@ -64649,7 +64814,7 @@ function createResttyApp(options) {
64649
64814
  cellH: gridState.cellH
64650
64815
  };
64651
64816
  },
64652
- getCursorForCpr: () => lastCursorForCpr,
64817
+ getCursorForCpr: resolveCursorForCpr,
64653
64818
  sendInput,
64654
64819
  runBeforeInputHook,
64655
64820
  shouldClearSelection: () => selectionState.active || selectionState.dragging,
@@ -54,6 +54,7 @@ export declare class OutputFilter {
54
54
  private getDefaultColors?;
55
55
  private desktopNotificationHandler?;
56
56
  private promptState;
57
+ private cursorHint;
57
58
  constructor(options: OutputFilterOptions);
58
59
  setCursorProvider(fn: () => CursorPosition): void;
59
60
  setReplySink(fn: (data: string) => void): void;
package/dist/internal.js CHANGED
@@ -100,7 +100,7 @@ import {
100
100
  updateGridState,
101
101
  updateImePosition,
102
102
  updateSelection
103
- } from "./chunk-8bv82tek.js";
103
+ } from "./chunk-meqn8xtd.js";
104
104
  export {
105
105
  updateSelection,
106
106
  updateImePosition,
package/dist/restty.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  isBuiltinThemeName,
9
9
  listBuiltinThemeNames,
10
10
  parseGhosttyTheme
11
- } from "./chunk-8bv82tek.js";
11
+ } from "./chunk-meqn8xtd.js";
12
12
  export {
13
13
  parseGhosttyTheme,
14
14
  listBuiltinThemeNames,
@@ -23,4 +23,4 @@ export declare function selectionForRow(state: SelectionState, row: number, cols
23
23
  */
24
24
  export declare function normalizeSelectionCell(cell: CellPosition | null, rows: number, cols: number, wideFlags?: Uint8Array | null): CellPosition | null;
25
25
  /** Convert client pixel coordinates to a grid cell position. */
26
- export declare function positionToCell(clientX: number, clientY: number, canvasRect: DOMRect, dpr: number, cellW: number, cellH: number, cols: number, rows: number): CellPosition;
26
+ export declare function positionToCell(clientX: number, clientY: number, canvasRect: DOMRect, dpr: number, cellW: number, cellH: number, cols: number, rows: number, canvasWidth?: number, canvasHeight?: number): CellPosition;
package/dist/xterm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createRestty
3
- } from "./chunk-8bv82tek.js";
3
+ } from "./chunk-meqn8xtd.js";
4
4
 
5
5
  // src/xterm/app-options.ts
6
6
  function createCompatAppOptions(userAppOptions, emitData) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "restty",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "description": "Browser terminal rendering library powered by WASM, WebGPU/WebGL2, and TypeScript text shaping.",
5
5
  "keywords": [
6
6
  "terminal",