@@ -117,2 +117,4 @@ interface INativeChildStats { | ||
| onDetach?(pty: IPty): void; | ||
| /** Optional: called after the PTY is resized, with the new dimensions. */ | ||
| onResize?(cols: number, rows: number): void; | ||
| } | ||
@@ -119,0 +121,0 @@ interface IPtyChildStats { |
@@ -35,2 +35,10 @@ import { a as IPtyConsumer, i as IPty } from "../_chunks/types.mjs"; | ||
| graceMs?: number; | ||
| /** | ||
| * Suppression window (ms) opened by {@link IdleDetector.suppress} — and | ||
| * automatically on PTY resize — during which significant bytes are | ||
| * silently absorbed. Filters out the full-screen repaint a TUI emits | ||
| * after a resize or an explicit redraw (`^L`), which would otherwise look | ||
| * like a fresh burst of agent output. Default `500`. | ||
| */ | ||
| redrawGraceMs?: number; | ||
| } | ||
@@ -51,2 +59,5 @@ /** | ||
| * threshold, so heavy color/escape output doesn't masquerade as text. | ||
| * - **Resize / redraw repaints**: bytes arriving within `redrawGraceMs` of a | ||
| * PTY resize (auto) or an explicit {@link suppress} call (e.g. before | ||
| * sending `^L`) are absorbed — a full-screen repaint isn't fresh output. | ||
| * | ||
@@ -69,2 +80,3 @@ * @example | ||
| private _escState; | ||
| private _suppressUntil; | ||
| private _listeners; | ||
@@ -74,2 +86,3 @@ private readonly _quietMs; | ||
| private readonly _graceMs; | ||
| private readonly _redrawGraceMs; | ||
| constructor(listener?: IdleListener, options?: IdleDetectorOptions); | ||
@@ -83,2 +96,16 @@ /** Subscribe to idle/active transitions. Returns a disposer. */ | ||
| onDetach(_pty: IPty): void; | ||
| /** | ||
| * Auto-called by `pty.attach()` wiring whenever the PTY is resized. Opens a | ||
| * suppression window so the TUI's full-screen repaint isn't counted as a | ||
| * fresh activity burst. | ||
| */ | ||
| onResize(_cols: number, _rows: number): void; | ||
| /** | ||
| * Open a suppression window of `durationMs` (default `redrawGraceMs`). | ||
| * Significant bytes arriving within it are absorbed silently — they never | ||
| * push the detector into `active`, nor keep an active burst alive. Call this | ||
| * right before sending an explicit redraw (e.g. `^L`) so the repaint that | ||
| * follows isn't mistaken for new output. Resize triggers it automatically. | ||
| */ | ||
| suppress(durationMs?: number): void; | ||
| /** Feed bytes into the detector. Accepts string (utf-8), Buffer, or Uint8Array. */ | ||
@@ -85,0 +112,0 @@ feed(data: string | Buffer | Uint8Array): void; |
+14
-0
@@ -15,2 +15,3 @@ import { Buffer } from "node:buffer"; | ||
| _escState = Ground; | ||
| _suppressUntil = 0; | ||
| _listeners = []; | ||
@@ -20,2 +21,3 @@ _quietMs; | ||
| _graceMs; | ||
| _redrawGraceMs; | ||
| constructor(listener, options = {}) { | ||
@@ -25,2 +27,3 @@ this._quietMs = options.quietMs ?? 750; | ||
| this._graceMs = options.graceMs ?? 1500; | ||
| this._redrawGraceMs = options.redrawGraceMs ?? 500; | ||
| const now = Date.now(); | ||
@@ -51,2 +54,8 @@ this._stateStart = now; | ||
| } | ||
| onResize(_cols, _rows) { | ||
| this.suppress(); | ||
| } | ||
| suppress(durationMs = this._redrawGraceMs) { | ||
| this._suppressUntil = Date.now() + durationMs; | ||
| } | ||
| feed(data) { | ||
@@ -57,2 +66,6 @@ const buf = typeof data === "string" ? Buffer.from(data, "utf8") : Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength); | ||
| const now = Date.now(); | ||
| if (now < this._suppressUntil) { | ||
| this._lastSigTime = now; | ||
| return; | ||
| } | ||
| if (this._state === "idle") { | ||
@@ -93,2 +106,3 @@ if (now - this._attachAt < this._graceMs) { | ||
| this._escState = Ground; | ||
| this._suppressUntil = 0; | ||
| } | ||
@@ -95,0 +109,0 @@ _scheduleIdle() { |
+3
-0
@@ -12,2 +12,3 @@ import { a as IPtyConsumer, c as IPtyStats, d as hasNative, i as IPty, l as Terminal, n as IEvent, o as IPtyOpenOptions, r as IOpenResult, s as IPtyOptions, t as IDisposable, u as TerminalOptions } from "./_chunks/types.mjs"; | ||
| }) => void>; | ||
| protected _resizeListeners: Array<(cols: number, rows: number) => void>; | ||
| protected _closed: boolean; | ||
@@ -32,2 +33,4 @@ protected _exitCode: number | null; | ||
| [Symbol.asyncDispose](): Promise<void>; | ||
| /** Notify attached consumers of a resize. Call from each platform's `resize`. */ | ||
| protected _notifyResize(cols: number, rows: number): void; | ||
| protected _handleExit(info: { | ||
@@ -34,0 +37,0 @@ exitCode: number; |
+21
-1
@@ -237,2 +237,3 @@ import { createRequire } from "node:module"; | ||
| _exitListeners = []; | ||
| _resizeListeners = []; | ||
| _closed = false; | ||
@@ -285,2 +286,7 @@ _exitCode = null; | ||
| }; | ||
| let resizeListener; | ||
| if (consumer.onResize) { | ||
| resizeListener = consumer.onResize.bind(consumer); | ||
| this._resizeListeners.push(resizeListener); | ||
| } | ||
| let dataSub; | ||
@@ -297,2 +303,6 @@ let terminalListener; | ||
| dataSub?.dispose(); | ||
| if (resizeListener) { | ||
| const idx = this._resizeListeners.indexOf(resizeListener); | ||
| if (idx >= 0) this._resizeListeners.splice(idx, 1); | ||
| } | ||
| if (terminalListener) { | ||
@@ -359,2 +369,7 @@ const listeners = this._terminal?._dataListeners; | ||
| } | ||
| _notifyResize(cols, rows) { | ||
| for (const listener of this._resizeListeners) try { | ||
| listener(cols, rows); | ||
| } catch {} | ||
| } | ||
| _handleExit(info) { | ||
@@ -462,2 +477,3 @@ this._closed = true; | ||
| native.resize(this._fd, cols, rows, pixelSize?.width ?? 0, pixelSize?.height ?? 0); | ||
| this._notifyResize(cols, rows); | ||
| } | ||
@@ -562,3 +578,6 @@ clear() {} | ||
| this.rows = rows; | ||
| const doResize = () => this._native.resize(this._handle, cols, rows); | ||
| const doResize = () => { | ||
| this._native.resize(this._handle, cols, rows); | ||
| this._notifyResize(cols, rows); | ||
| }; | ||
| if (this._ready) doResize(); | ||
@@ -739,2 +758,3 @@ else this._deferredCalls.push(doResize); | ||
| } catch {} | ||
| this._notifyResize(cols, rows); | ||
| } | ||
@@ -741,0 +761,0 @@ clear() {} |
+1
-1
| { | ||
| "name": "zigpty", | ||
| "version": "0.2.0", | ||
| "version": "0.2.1", | ||
| "repository": "pithings/zigpty", | ||
@@ -5,0 +5,0 @@ "workspaces": [ |
421847
0.62%1704
2.04%