@opentui/core 0.2.16 → 0.3.1

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.
@@ -12352,6 +12352,7 @@ var VisualCursorStruct = defineStruct([
12352
12352
  ["offset", "u32"]
12353
12353
  ]);
12354
12354
  var UnicodeMethodEnum = defineEnum({ wcwidth: 0, unicode: 1 }, "u8");
12355
+ var TerminalMultiplexerEnum = defineEnum({ none: 0, tmux: 1, zellij: 2, screen: 3, unknown: 4 }, "u8");
12355
12356
  var TerminalCapabilitiesStruct = defineStruct([
12356
12357
  ["kitty_keyboard", "bool_u8"],
12357
12358
  ["kitty_graphics", "bool_u8"],
@@ -12370,7 +12371,8 @@ var TerminalCapabilitiesStruct = defineStruct([
12370
12371
  ["osc52", "bool_u8"],
12371
12372
  ["notifications", "bool_u8"],
12372
12373
  ["explicit_cursor_positioning", "bool_u8"],
12373
- ["in_tmux", "bool_u8"],
12374
+ ["remote", "bool_u8"],
12375
+ ["multiplexer", TerminalMultiplexerEnum],
12374
12376
  ["term_name", "char*"],
12375
12377
  ["term_name_len", "u64", { lengthOf: "term_name" }],
12376
12378
  ["term_version", "char*"],
@@ -12598,7 +12600,7 @@ function getOpenTUILib(libPath) {
12598
12600
  returns: "void"
12599
12601
  },
12600
12602
  createRenderer: {
12601
- args: ["u32", "u32", "bool", "bool"],
12603
+ args: ["u32", "u32", "u8", "u8", "ptr"],
12602
12604
  returns: "ptr"
12603
12605
  },
12604
12606
  setTerminalEnvVar: {
@@ -12659,15 +12661,15 @@ function getOpenTUILib(libPath) {
12659
12661
  },
12660
12662
  render: {
12661
12663
  args: ["ptr", "bool"],
12662
- returns: "void"
12664
+ returns: "u8"
12663
12665
  },
12664
12666
  repaintSplitFooter: {
12665
12667
  args: ["ptr", "u32", "bool"],
12666
- returns: "u32"
12668
+ returns: "u64"
12667
12669
  },
12668
12670
  commitSplitFooterSnapshot: {
12669
12671
  args: ["ptr", "ptr", "u32", "bool", "bool", "u32", "bool", "bool", "bool"],
12670
- returns: "u32"
12672
+ returns: "u64"
12671
12673
  },
12672
12674
  getNextBuffer: {
12673
12675
  args: ["ptr"],
@@ -12929,7 +12931,7 @@ function getOpenTUILib(libPath) {
12929
12931
  args: ["ptr", "i64"],
12930
12932
  returns: "void"
12931
12933
  },
12932
- dumpStdoutBuffer: {
12934
+ dumpOutputBuffer: {
12933
12935
  args: ["ptr", "i64"],
12934
12936
  returns: "void"
12935
12937
  },
@@ -13970,9 +13972,10 @@ class FFIRenderLib {
13970
13972
  return callback;
13971
13973
  }
13972
13974
  createRenderer(width, height, options = {}) {
13973
- const testing = options.testing ?? false;
13974
- const remote = options.remote ?? false;
13975
- return this.opentui.symbols.createRenderer(width, height, ffiBool(testing), ffiBool(remote));
13975
+ const bufferedOutputKind = options.bufferedOutput === "memory" ? 1 : 0;
13976
+ const remoteMode = options.remote === undefined ? 0 : options.remote ? 2 : 1;
13977
+ const feedPtr = options.feedPtr ?? null;
13978
+ return this.opentui.symbols.createRenderer(width, height, bufferedOutputKind, remoteMode, feedPtr);
13976
13979
  }
13977
13980
  setTerminalEnvVar(renderer, key, value) {
13978
13981
  const keyBytes = this.encoder.encode(key);
@@ -14217,13 +14220,20 @@ class FFIRenderLib {
14217
14220
  this.opentui.symbols.setCursorStyleOptions(renderer, ptr(buffer));
14218
14221
  }
14219
14222
  render(renderer, force) {
14220
- this.opentui.symbols.render(renderer, ffiBool(force));
14223
+ return this.opentui.symbols.render(renderer, ffiBool(force));
14224
+ }
14225
+ unpackRenderOperationResult(value) {
14226
+ const packed = typeof value === "bigint" ? value : BigInt(value);
14227
+ return {
14228
+ renderOffset: Number(packed & 0xffffffffn),
14229
+ status: Number(packed >> 32n & 0xffn)
14230
+ };
14221
14231
  }
14222
14232
  repaintSplitFooter(renderer, pinnedRenderOffset, force) {
14223
- return this.opentui.symbols.repaintSplitFooter(renderer, pinnedRenderOffset, ffiBool(force));
14233
+ return this.unpackRenderOperationResult(this.opentui.symbols.repaintSplitFooter(renderer, pinnedRenderOffset, ffiBool(force)));
14224
14234
  }
14225
14235
  commitSplitFooterSnapshot(renderer, snapshot, rowColumns, startOnNewLine, trailingNewline, pinnedRenderOffset, force, beginFrame = true, finalizeFrame = true) {
14226
- return this.opentui.symbols.commitSplitFooterSnapshot(renderer, snapshot.ptr, rowColumns, ffiBool(startOnNewLine), ffiBool(trailingNewline), pinnedRenderOffset, ffiBool(force), ffiBool(beginFrame), ffiBool(finalizeFrame));
14236
+ return this.unpackRenderOperationResult(this.opentui.symbols.commitSplitFooterSnapshot(renderer, snapshot.ptr, rowColumns, ffiBool(startOnNewLine), ffiBool(trailingNewline), pinnedRenderOffset, ffiBool(force), ffiBool(beginFrame), ffiBool(finalizeFrame)));
14227
14237
  }
14228
14238
  createOptimizedBuffer(width, height, widthMethod, respectAlpha = false, id) {
14229
14239
  if (Number.isNaN(width) || Number.isNaN(height)) {
@@ -14300,9 +14310,9 @@ class FFIRenderLib {
14300
14310
  const ts = timestamp ?? Date.now();
14301
14311
  this.opentui.symbols.dumpBuffers(renderer, ts);
14302
14312
  }
14303
- dumpStdoutBuffer(renderer, timestamp) {
14313
+ dumpOutputBuffer(renderer, timestamp) {
14304
14314
  const ts = timestamp ?? Date.now();
14305
- this.opentui.symbols.dumpStdoutBuffer(renderer, ts);
14315
+ this.opentui.symbols.dumpOutputBuffer(renderer, ts);
14306
14316
  }
14307
14317
  restoreTerminalModes(renderer) {
14308
14318
  this.opentui.symbols.restoreTerminalModes(renderer);
@@ -15058,7 +15068,8 @@ class FFIRenderLib {
15058
15068
  osc52: caps.osc52,
15059
15069
  notifications: caps.notifications,
15060
15070
  explicit_cursor_positioning: caps.explicit_cursor_positioning,
15061
- in_tmux: caps.in_tmux,
15071
+ remote: caps.remote,
15072
+ multiplexer: caps.multiplexer,
15062
15073
  terminal: {
15063
15074
  name: caps.term_name ?? "",
15064
15075
  version: caps.term_version ?? "",
@@ -19186,6 +19197,292 @@ class TextRenderable extends TextBufferRenderable {
19186
19197
  }
19187
19198
  }
19188
19199
 
19200
+ // src/NativeSpanFeed.ts
19201
+ function toNumber2(value) {
19202
+ return typeof value === "bigint" ? Number(value) : value;
19203
+ }
19204
+
19205
+ class NativeSpanFeed {
19206
+ static create(options) {
19207
+ const lib = resolveRenderLib();
19208
+ const streamPtr = lib.createNativeSpanFeed(options);
19209
+ const stream = new NativeSpanFeed(streamPtr);
19210
+ lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
19211
+ const status = lib.attachNativeSpanFeed(streamPtr);
19212
+ if (status !== 0) {
19213
+ lib.unregisterNativeSpanFeedStream(streamPtr);
19214
+ lib.destroyNativeSpanFeed(streamPtr);
19215
+ throw new Error(`Failed to attach stream: ${status}`);
19216
+ }
19217
+ return stream;
19218
+ }
19219
+ static attach(streamPtr, _options) {
19220
+ const lib = resolveRenderLib();
19221
+ const stream = new NativeSpanFeed(streamPtr);
19222
+ lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
19223
+ const status = lib.attachNativeSpanFeed(streamPtr);
19224
+ if (status !== 0) {
19225
+ lib.unregisterNativeSpanFeedStream(streamPtr);
19226
+ throw new Error(`Failed to attach stream: ${status}`);
19227
+ }
19228
+ return stream;
19229
+ }
19230
+ streamPtr;
19231
+ lib = resolveRenderLib();
19232
+ eventHandler;
19233
+ chunkMap = new Map;
19234
+ chunkSizes = new Map;
19235
+ dataHandlers = new Set;
19236
+ errorHandlers = new Set;
19237
+ drainBuffer = null;
19238
+ stateBuffer = null;
19239
+ closed = false;
19240
+ destroyed = false;
19241
+ draining = false;
19242
+ pendingDataAvailable = false;
19243
+ pendingClose = false;
19244
+ closing = false;
19245
+ pendingAsyncHandlers = 0;
19246
+ inCallback = false;
19247
+ closeQueued = false;
19248
+ idleResolvers = [];
19249
+ constructor(streamPtr) {
19250
+ this.streamPtr = streamPtr;
19251
+ this.eventHandler = (eventId, arg0, arg1) => {
19252
+ this.handleEvent(eventId, arg0, arg1);
19253
+ };
19254
+ this.ensureDrainBuffer();
19255
+ }
19256
+ ensureDrainBuffer() {
19257
+ if (this.drainBuffer)
19258
+ return;
19259
+ const capacity = 256;
19260
+ this.drainBuffer = new Uint8Array(capacity * SpanInfoStruct.size);
19261
+ }
19262
+ onData(handler) {
19263
+ this.dataHandlers.add(handler);
19264
+ if (this.pendingDataAvailable) {
19265
+ this.pendingDataAvailable = false;
19266
+ this.drainAll();
19267
+ }
19268
+ return () => this.dataHandlers.delete(handler);
19269
+ }
19270
+ onError(handler) {
19271
+ this.errorHandlers.add(handler);
19272
+ return () => this.errorHandlers.delete(handler);
19273
+ }
19274
+ hasPinnedChunks() {
19275
+ if (!this.stateBuffer)
19276
+ return false;
19277
+ for (const refcount of this.stateBuffer) {
19278
+ if (refcount > 0)
19279
+ return true;
19280
+ }
19281
+ return false;
19282
+ }
19283
+ isBackpressured() {
19284
+ return this.pendingAsyncHandlers > 0 || this.pendingDataAvailable || this.hasPinnedChunks();
19285
+ }
19286
+ close() {
19287
+ if (this.destroyed)
19288
+ return;
19289
+ if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0) {
19290
+ this.pendingClose = true;
19291
+ if (!this.closeQueued) {
19292
+ this.closeQueued = true;
19293
+ queueMicrotask(() => {
19294
+ this.closeQueued = false;
19295
+ this.processPendingClose();
19296
+ });
19297
+ }
19298
+ return;
19299
+ }
19300
+ this.performClose();
19301
+ }
19302
+ processPendingClose() {
19303
+ if (!this.pendingClose || this.destroyed)
19304
+ return;
19305
+ if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0)
19306
+ return;
19307
+ this.pendingClose = false;
19308
+ this.performClose();
19309
+ this.resolveIdleIfNeeded();
19310
+ }
19311
+ performClose() {
19312
+ if (this.closing)
19313
+ return;
19314
+ this.closing = true;
19315
+ if (!this.closed) {
19316
+ const status = this.lib.streamClose(this.streamPtr);
19317
+ if (status !== 0) {
19318
+ this.closing = false;
19319
+ return;
19320
+ }
19321
+ this.closed = true;
19322
+ }
19323
+ this.finalizeDestroy();
19324
+ }
19325
+ finalizeDestroy() {
19326
+ if (this.destroyed)
19327
+ return;
19328
+ this.lib.unregisterNativeSpanFeedStream(this.streamPtr);
19329
+ this.lib.destroyNativeSpanFeed(this.streamPtr);
19330
+ this.destroyed = true;
19331
+ this.chunkMap.clear();
19332
+ this.chunkSizes.clear();
19333
+ this.stateBuffer = null;
19334
+ this.drainBuffer = null;
19335
+ this.dataHandlers.clear();
19336
+ this.errorHandlers.clear();
19337
+ this.pendingDataAvailable = false;
19338
+ this.resolveIdleIfNeeded();
19339
+ }
19340
+ isIdle() {
19341
+ return !this.inCallback && !this.draining && this.pendingAsyncHandlers === 0 && !this.pendingDataAvailable && !this.hasPinnedChunks();
19342
+ }
19343
+ resolveIdleIfNeeded() {
19344
+ if (!this.isIdle())
19345
+ return;
19346
+ const resolvers = this.idleResolvers.splice(0);
19347
+ for (const resolve3 of resolvers) {
19348
+ resolve3();
19349
+ }
19350
+ }
19351
+ idle() {
19352
+ if (this.isIdle())
19353
+ return Promise.resolve();
19354
+ return new Promise((resolve3) => {
19355
+ this.idleResolvers.push(resolve3);
19356
+ });
19357
+ }
19358
+ handleEvent(eventId, arg0, arg1) {
19359
+ this.inCallback = true;
19360
+ try {
19361
+ switch (eventId) {
19362
+ case 8 /* StateBuffer */: {
19363
+ const len = toNumber2(arg1);
19364
+ if (len > 0 && arg0) {
19365
+ const buffer = toArrayBuffer(arg0, 0, len);
19366
+ this.stateBuffer = new Uint8Array(buffer);
19367
+ }
19368
+ break;
19369
+ }
19370
+ case 7 /* DataAvailable */: {
19371
+ if (this.closing)
19372
+ break;
19373
+ if (this.dataHandlers.size === 0) {
19374
+ this.pendingDataAvailable = true;
19375
+ break;
19376
+ }
19377
+ this.drainAll();
19378
+ break;
19379
+ }
19380
+ case 2 /* ChunkAdded */: {
19381
+ const chunkLen = toNumber2(arg1);
19382
+ if (chunkLen > 0 && arg0) {
19383
+ if (!this.chunkMap.has(arg0)) {
19384
+ const buffer = toArrayBuffer(arg0, 0, chunkLen);
19385
+ this.chunkMap.set(arg0, buffer);
19386
+ }
19387
+ this.chunkSizes.set(arg0, chunkLen);
19388
+ }
19389
+ break;
19390
+ }
19391
+ case 6 /* Error */: {
19392
+ const code = toNumber2(arg0);
19393
+ for (const handler of this.errorHandlers)
19394
+ handler(code);
19395
+ break;
19396
+ }
19397
+ case 5 /* Closed */: {
19398
+ this.closed = true;
19399
+ break;
19400
+ }
19401
+ default:
19402
+ break;
19403
+ }
19404
+ } finally {
19405
+ this.inCallback = false;
19406
+ this.resolveIdleIfNeeded();
19407
+ }
19408
+ }
19409
+ decrementRefcount(chunkIndex) {
19410
+ if (this.stateBuffer && chunkIndex < this.stateBuffer.length) {
19411
+ const prev = this.stateBuffer[chunkIndex];
19412
+ this.stateBuffer[chunkIndex] = prev > 0 ? prev - 1 : 0;
19413
+ }
19414
+ }
19415
+ drainOnce() {
19416
+ if (!this.drainBuffer || this.draining || this.pendingClose)
19417
+ return 0;
19418
+ const capacity = Math.floor(this.drainBuffer.byteLength / SpanInfoStruct.size);
19419
+ if (capacity === 0)
19420
+ return 0;
19421
+ const count = this.lib.streamDrainSpans(this.streamPtr, this.drainBuffer, capacity);
19422
+ if (count === 0)
19423
+ return 0;
19424
+ this.draining = true;
19425
+ const spans = SpanInfoStruct.unpackList(this.drainBuffer.buffer, count);
19426
+ let firstError = null;
19427
+ try {
19428
+ for (const span of spans) {
19429
+ if (span.len === 0)
19430
+ continue;
19431
+ let buffer = this.chunkMap.get(span.chunkPtr);
19432
+ if (!buffer) {
19433
+ const size = this.chunkSizes.get(span.chunkPtr);
19434
+ if (!size)
19435
+ continue;
19436
+ buffer = toArrayBuffer(span.chunkPtr, 0, size);
19437
+ this.chunkMap.set(span.chunkPtr, buffer);
19438
+ }
19439
+ if (span.offset + span.len > buffer.byteLength)
19440
+ continue;
19441
+ const slice = new Uint8Array(buffer, span.offset, span.len);
19442
+ let asyncResults = null;
19443
+ for (const handler of this.dataHandlers) {
19444
+ try {
19445
+ const result = handler(slice);
19446
+ if (result && typeof result.then === "function") {
19447
+ asyncResults ??= [];
19448
+ asyncResults.push(result);
19449
+ }
19450
+ } catch (e) {
19451
+ firstError ??= e;
19452
+ }
19453
+ }
19454
+ const shouldStopAfterThisSpan = this.pendingClose;
19455
+ if (asyncResults) {
19456
+ const chunkIndex = span.chunkIndex;
19457
+ this.pendingAsyncHandlers += 1;
19458
+ Promise.allSettled(asyncResults).then(() => {
19459
+ this.decrementRefcount(chunkIndex);
19460
+ this.pendingAsyncHandlers -= 1;
19461
+ this.processPendingClose();
19462
+ this.resolveIdleIfNeeded();
19463
+ });
19464
+ } else {
19465
+ this.decrementRefcount(span.chunkIndex);
19466
+ }
19467
+ if (shouldStopAfterThisSpan)
19468
+ break;
19469
+ }
19470
+ } finally {
19471
+ this.draining = false;
19472
+ this.resolveIdleIfNeeded();
19473
+ }
19474
+ if (firstError)
19475
+ throw firstError;
19476
+ return count;
19477
+ }
19478
+ drainAll() {
19479
+ let count = this.drainOnce();
19480
+ while (count > 0) {
19481
+ count = this.drainOnce();
19482
+ }
19483
+ }
19484
+ }
19485
+
19189
19486
  // src/console.ts
19190
19487
  import { EventEmitter as EventEmitter8 } from "events";
19191
19488
  import { Console } from "console";
@@ -21226,6 +21523,10 @@ var ANSI = {
21226
21523
  switchToAlternateScreen: "\x1B[?1049h",
21227
21524
  switchToMainScreen: "\x1B[?1049l",
21228
21525
  reset: "\x1B[0m",
21526
+ resetScrollRegion: "\x1B[r",
21527
+ home: "\x1B[H",
21528
+ clearScreen: "\x1B[2J",
21529
+ clearSavedLines: "\x1B[3J",
21229
21530
  scrollDown: (lines) => `\x1B[${lines}T`,
21230
21531
  scrollUp: (lines) => `\x1B[${lines}S`,
21231
21532
  moveCursor: (row, col) => `\x1B[${row};${col}H`,
@@ -21661,8 +21962,9 @@ class ExternalOutputQueue {
21661
21962
  writeSnapshot(commit) {
21662
21963
  this.commits.push(commit);
21663
21964
  }
21664
- peek() {
21665
- return this.commits;
21965
+ peek(limit = Number.POSITIVE_INFINITY) {
21966
+ const clampedLimit = Number.isFinite(limit) ? Math.max(1, Math.trunc(limit)) : this.commits.length;
21967
+ return this.commits.slice(0, clampedLimit);
21666
21968
  }
21667
21969
  claim(limit = Number.POSITIVE_INFINITY) {
21668
21970
  if (this.commits.length === 0) {
@@ -21678,11 +21980,13 @@ class ExternalOutputQueue {
21678
21980
  this.commits = this.commits.slice(clampedLimit);
21679
21981
  return output;
21680
21982
  }
21681
- clear() {
21682
- for (const commit of this.commits) {
21983
+ drop(count) {
21984
+ for (const commit of this.commits.splice(0, count)) {
21683
21985
  commit.snapshot.destroy();
21684
21986
  }
21685
- this.commits = [];
21987
+ }
21988
+ clear() {
21989
+ this.drop(this.commits.length);
21686
21990
  }
21687
21991
  }
21688
21992
  var CHAR_FLAG_CONTINUATION = 3221225472 >>> 0;
@@ -21752,6 +22056,9 @@ class ScrollbackSnapshotRenderContext extends EventEmitter9 {
21752
22056
  }
21753
22057
  var DEFAULT_FORWARDED_ENV_KEYS = [
21754
22058
  "TMUX",
22059
+ "ZELLIJ",
22060
+ "ZELLIJ_SESSION_NAME",
22061
+ "ZELLIJ_PANE_ID",
21755
22062
  "TERM",
21756
22063
  "OPENTUI_GRAPHICS",
21757
22064
  "TERM_PROGRAM",
@@ -21766,11 +22073,15 @@ var DEFAULT_FORWARDED_ENV_KEYS = [
21766
22073
  "OPENTUI_FORCE_UNICODE",
21767
22074
  "OPENTUI_FORCE_NOZWJ",
21768
22075
  "OPENTUI_FORCE_EXPLICIT_WIDTH",
22076
+ "OPENTUI_NOTIFICATION_PROTOCOL",
22077
+ "OPENTUI_NOTIFICATIONS",
21769
22078
  "WT_SESSION",
21770
22079
  "STY",
21771
22080
  "WSL_DISTRO_NAME",
21772
22081
  "WSL_INTEROP"
21773
22082
  ];
22083
+ var NATIVE_RENDER_STATUS_SKIPPED = 1;
22084
+ var NATIVE_RENDER_STATUS_FAILED = 2;
21774
22085
  var KITTY_FLAG_DISAMBIGUATE = 1;
21775
22086
  var KITTY_FLAG_EVENT_TYPES = 2;
21776
22087
  var KITTY_FLAG_ALTERNATE_KEYS = 4;
@@ -21845,57 +22156,30 @@ var MouseButton;
21845
22156
  MouseButton2[MouseButton2["WHEEL_UP"] = 4] = "WHEEL_UP";
21846
22157
  MouseButton2[MouseButton2["WHEEL_DOWN"] = 5] = "WHEEL_DOWN";
21847
22158
  })(MouseButton ||= {});
21848
- var rendererTracker = singleton("RendererTracker", () => {
21849
- const renderers = new Set;
21850
- return {
21851
- addRenderer: (renderer) => {
21852
- renderers.add(renderer);
21853
- },
21854
- removeRenderer: (renderer) => {
21855
- renderers.delete(renderer);
21856
- if (renderers.size === 0) {
21857
- process.stdin.pause();
21858
- if (hasSingleton("tree-sitter-client")) {
21859
- getTreeSitterClient().destroy();
21860
- destroySingleton("tree-sitter-client");
21861
- }
21862
- }
21863
- }
21864
- };
21865
- });
22159
+ var rendererTracker = singleton("RendererTracker", () => ({
22160
+ renderers: new Set,
22161
+ streamOwners: new WeakMap
22162
+ }));
21866
22163
  async function createCliRenderer(config = {}) {
21867
22164
  if (process.argv.includes("--delay-start")) {
21868
22165
  await new Promise((resolve3) => setTimeout(resolve3, 5000));
21869
22166
  }
21870
- const stdin = config.stdin || process.stdin;
21871
- const stdout = config.stdout || process.stdout;
21872
- const { screenMode, footerHeight } = resolveModes(config);
21873
- const width = stdout.columns || 80;
21874
- const height = stdout.rows || 24;
21875
- const geometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
21876
- const ziglib = resolveRenderLib();
21877
- const rendererPtr = ziglib.createRenderer(geometry.renderWidth, geometry.renderHeight, {
21878
- remote: config.remote ?? false,
21879
- testing: config.testing ?? false
21880
- });
21881
- if (!rendererPtr) {
21882
- throw new Error("Failed to create renderer");
21883
- }
21884
- if (config.useThread === undefined) {
21885
- config.useThread = true;
21886
- }
21887
- if (process.platform === "linux") {
21888
- config.useThread = false;
21889
- }
21890
- ziglib.setUseThread(rendererPtr, config.useThread);
21891
- const kittyConfig = config.useKittyKeyboard ?? {};
21892
- const kittyFlags = buildKittyKeyboardFlags(kittyConfig);
21893
- ziglib.setKittyKeyboardFlags(rendererPtr, kittyFlags);
21894
- const renderer = new CliRenderer(ziglib, rendererPtr, stdin, stdout, width, height, config);
21895
- if (!config.testing) {
22167
+ const stdin = config.stdin ?? process.stdin;
22168
+ const stdout = config.stdout ?? process.stdout;
22169
+ const width = stdout.columns || config.width || 80;
22170
+ const height = stdout.rows || config.height || 24;
22171
+ const renderer = new CliRenderer(stdin, stdout, width, height, config);
22172
+ try {
21896
22173
  await renderer.setupTerminal();
22174
+ return renderer;
22175
+ } catch (error) {
22176
+ try {
22177
+ renderer.destroy();
22178
+ } catch (destroyError) {
22179
+ console.error("Error destroying partially-set-up renderer:", destroyError);
22180
+ }
22181
+ throw error;
21897
22182
  }
21898
- return renderer;
21899
22183
  }
21900
22184
  var CliRenderEvents;
21901
22185
  ((CliRenderEvents2) => {
@@ -21937,6 +22221,7 @@ class CliRenderer extends EventEmitter9 {
21937
22221
  _destroyPending = false;
21938
22222
  _destroyFinalized = false;
21939
22223
  _destroyCleanupPrepared = false;
22224
+ _streamLeaseAcquired = false;
21940
22225
  nextRenderBuffer;
21941
22226
  currentRenderBuffer;
21942
22227
  _isRunning = false;
@@ -22116,22 +22401,79 @@ Captured external output:
22116
22401
  warningHandler = ((warning) => {
22117
22402
  console.warn(JSON.stringify(warning.message, null, 2));
22118
22403
  }).bind(this);
22404
+ _usesProcessStdout;
22405
+ _feed = null;
22406
+ _detachFeed = null;
22407
+ _detachFeedError = null;
22408
+ feedIdleRenderScheduled = false;
22119
22409
  get controlState() {
22120
22410
  return this._controlState;
22121
22411
  }
22122
- constructor(lib, rendererPtr, stdin, stdout, width, height, config = {}) {
22412
+ constructor(stdin, stdout, width, height, config = {}) {
22123
22413
  super();
22124
- rendererTracker.addRenderer(this);
22125
22414
  this.stdin = stdin;
22126
22415
  this.stdout = stdout;
22416
+ this._usesProcessStdout = stdout === process.stdout;
22127
22417
  this.realStdoutWrite = stdout.write;
22128
- this.lib = lib;
22129
- this._terminalWidth = stdout.columns ?? width;
22130
- this._terminalHeight = stdout.rows ?? height;
22131
- this._useThread = config.useThread === undefined ? false : config.useThread;
22418
+ const lib = resolveRenderLib();
22419
+ const useMemoryBufferedOutput = config.bufferedOutput === "memory";
22420
+ const useFeedOutput = !this._usesProcessStdout && !useMemoryBufferedOutput;
22132
22421
  const { screenMode, footerHeight, externalOutputMode } = resolveModes(config);
22422
+ const initialGeometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
22423
+ const remoteMode = config.remote ?? (useFeedOutput ? true : undefined);
22424
+ if (rendererTracker.streamOwners.get(stdin)) {
22425
+ throw new Error("Cannot create CliRenderer: stdin is already used by another CliRenderer");
22426
+ }
22427
+ if (rendererTracker.streamOwners.get(stdout)) {
22428
+ throw new Error("Cannot create CliRenderer: stdout is already used by another CliRenderer");
22429
+ }
22430
+ let feed = null;
22431
+ if (useFeedOutput) {
22432
+ try {
22433
+ feed = NativeSpanFeed.create();
22434
+ } catch (error) {
22435
+ throw new Error(`Failed to allocate NativeSpanFeed for custom stdout: ${error instanceof Error ? error.message : String(error)}`);
22436
+ }
22437
+ }
22438
+ let rendererPtr;
22439
+ try {
22440
+ rendererPtr = lib.createRenderer(initialGeometry.renderWidth, initialGeometry.renderHeight, {
22441
+ remote: remoteMode,
22442
+ feedPtr: feed?.streamPtr ?? null,
22443
+ bufferedOutput: config.bufferedOutput
22444
+ });
22445
+ } catch (error) {
22446
+ feed?.close();
22447
+ throw error;
22448
+ }
22449
+ if (!rendererPtr) {
22450
+ feed?.close();
22451
+ throw new Error("Failed to create renderer");
22452
+ }
22453
+ if (config.useThread === undefined)
22454
+ config.useThread = true;
22455
+ if (process.platform === "linux")
22456
+ config.useThread = false;
22457
+ lib.setUseThread(rendererPtr, config.useThread);
22458
+ const kittyConfig = config.useKittyKeyboard ?? {};
22459
+ const kittyFlags = buildKittyKeyboardFlags(kittyConfig);
22460
+ lib.setKittyKeyboardFlags(rendererPtr, kittyFlags);
22461
+ this._feed = feed;
22462
+ if (feed) {
22463
+ this._detachFeed = feed.onData((bytes) => {
22464
+ return new Promise((resolve3) => {
22465
+ this.realStdoutWrite.call(this.stdout, bytes, () => resolve3());
22466
+ });
22467
+ });
22468
+ this._detachFeedError = feed.onError((code) => {
22469
+ console.error(`[CliRenderer] NativeSpanFeed error: code=${code}`);
22470
+ });
22471
+ }
22472
+ this.lib = lib;
22473
+ this._terminalWidth = width;
22474
+ this._terminalHeight = height;
22475
+ this._useThread = config.useThread;
22133
22476
  this._externalOutputMode = externalOutputMode;
22134
- const initialGeometry = calculateRenderGeometry(screenMode, this._terminalWidth, this._terminalHeight, footerHeight);
22135
22477
  this.width = initialGeometry.renderWidth;
22136
22478
  this.height = initialGeometry.renderHeight;
22137
22479
  this._splitHeight = initialGeometry.effectiveFooterHeight;
@@ -22140,7 +22482,7 @@ Captured external output:
22140
22482
  this.rendererPtr = rendererPtr;
22141
22483
  this.clearOnShutdown = config.clearOnShutdown ?? true;
22142
22484
  this.lib.setClearOnShutdown(this.rendererPtr, this.clearOnShutdown);
22143
- const forwardEnvKeys = config.forwardEnvKeys ?? (config.remote ? [] : [...DEFAULT_FORWARDED_ENV_KEYS]);
22485
+ const forwardEnvKeys = config.forwardEnvKeys ?? (config.remote === false ? [...DEFAULT_FORWARDED_ENV_KEYS] : []);
22144
22486
  for (const key of forwardEnvKeys) {
22145
22487
  const value = process.env[key];
22146
22488
  if (value === undefined)
@@ -22193,12 +22535,13 @@ Captured external output:
22193
22535
  if (this.memorySnapshotInterval > 0) {
22194
22536
  this.startMemorySnapshotTimer();
22195
22537
  }
22196
- process.on("SIGWINCH", this.sigwinchHandler);
22538
+ if (this._usesProcessStdout) {
22539
+ process.on("SIGWINCH", this.sigwinchHandler);
22540
+ }
22197
22541
  process.on("warning", this.warningHandler);
22198
22542
  process.on("uncaughtException", this.handleError);
22199
22543
  process.on("unhandledRejection", this.handleError);
22200
22544
  process.on("beforeExit", this.exitHandler);
22201
- const kittyConfig = config.useKittyKeyboard ?? {};
22202
22545
  const useKittyForParsing = kittyConfig !== null;
22203
22546
  this._keyHandler = new InternalKeyHandler;
22204
22547
  this._keyHandler.on("keypress", (event) => {
@@ -22234,6 +22577,10 @@ Captured external output:
22234
22577
  });
22235
22578
  this.consoleMode = config.consoleMode ?? "console-overlay";
22236
22579
  this.applyScreenMode(screenMode, false, false);
22580
+ rendererTracker.streamOwners.set(stdin, this);
22581
+ rendererTracker.streamOwners.set(stdout, this);
22582
+ this._streamLeaseAcquired = true;
22583
+ rendererTracker.renderers.add(this);
22237
22584
  this.stdout.write = externalOutputMode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
22238
22585
  this._openConsoleOnError = config.openConsoleOnError ?? true;
22239
22586
  this._onDestroy = config.onDestroy;
@@ -22256,9 +22603,19 @@ Captured external output:
22256
22603
  if (this._splitHeight > 0) {
22257
22604
  this.flushStdoutCache(this._splitHeight);
22258
22605
  }
22606
+ return "rendered";
22259
22607
  };
22260
22608
  }
22261
- this.setupInput();
22609
+ try {
22610
+ this.setupInput();
22611
+ } catch (error) {
22612
+ try {
22613
+ this.destroy();
22614
+ } catch (destroyError) {
22615
+ console.error("Error destroying renderer after input setup failure:", destroyError);
22616
+ }
22617
+ throw error;
22618
+ }
22262
22619
  }
22263
22620
  addExitListeners() {
22264
22621
  if (this._exitListenersAdded || this.exitSignals.length === 0)
@@ -22363,7 +22720,7 @@ Captured external output:
22363
22720
  return this._frameId;
22364
22721
  }
22365
22722
  writeOut(chunk, encoding, callback) {
22366
- if (this.rendererPtr && this._useThread) {
22723
+ if (this.rendererPtr && (this._useThread || this._feed !== null)) {
22367
22724
  const data = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
22368
22725
  this.lib.writeOut(this.rendererPtr, data);
22369
22726
  if (typeof callback === "function") {
@@ -22373,6 +22730,30 @@ Captured external output:
22373
22730
  }
22374
22731
  return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
22375
22732
  }
22733
+ scheduleRenderAfterFeedIdle() {
22734
+ const feed = this._feed;
22735
+ if (!feed || this.feedIdleRenderScheduled || this._isDestroyed)
22736
+ return;
22737
+ this.feedIdleRenderScheduled = true;
22738
+ feed.idle().then(() => {
22739
+ this.feedIdleRenderScheduled = false;
22740
+ if (this._isDestroyed) {
22741
+ this.resolveIdleIfNeeded();
22742
+ return;
22743
+ }
22744
+ if (this._isRunning) {
22745
+ if (!this.renderTimeout && !this.rendering) {
22746
+ this.renderTimeout = this.clock.setTimeout(() => {
22747
+ this.renderTimeout = null;
22748
+ this.loop();
22749
+ }, 0);
22750
+ }
22751
+ return;
22752
+ }
22753
+ this.requestRender();
22754
+ this.resolveIdleIfNeeded();
22755
+ });
22756
+ }
22376
22757
  requestRender() {
22377
22758
  if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
22378
22759
  return;
@@ -22423,7 +22804,9 @@ Captured external output:
22423
22804
  return this._isRunning;
22424
22805
  }
22425
22806
  isIdleNow() {
22426
- return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.immediateRerenderRequested;
22807
+ if (this._isDestroyed)
22808
+ return true;
22809
+ return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.feedIdleRenderScheduled && !this.immediateRerenderRequested;
22427
22810
  }
22428
22811
  resolveIdleIfNeeded() {
22429
22812
  if (!this.isIdleNow())
@@ -22960,6 +23343,26 @@ Captured external output:
22960
23343
  }
22961
23344
  }
22962
23345
  }
23346
+ resetSplitFooterForReplay(options = {}) {
23347
+ if (this._isDestroyed)
23348
+ return;
23349
+ if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
23350
+ throw new Error('resetSplitFooterForReplay requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
23351
+ }
23352
+ if (!this._terminalIsSetup || this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
23353
+ throw new Error("resetSplitFooterForReplay requires an active terminal");
23354
+ }
23355
+ this.flushPendingSplitOutputBeforeTransition(true);
23356
+ this.externalOutputQueue.clear();
23357
+ this.abortSplitStartupCursorSeed();
23358
+ this.clearPendingSplitFooterTransition();
23359
+ this.resetSplitScrollback();
23360
+ this.currentRenderBuffer.clear(this.backgroundColor);
23361
+ this.nextRenderBuffer.clear(this.backgroundColor);
23362
+ this.forceFullRepaintRequested = true;
23363
+ this.writeOut(ANSI.resetScrollRegion + ANSI.reset + ANSI.home + ANSI.clearScreen + (options.clearSavedLines ? ANSI.clearSavedLines : "") + ANSI.home);
23364
+ this.requestRender();
23365
+ }
22963
23366
  getSnapshotWidth(value, fallback) {
22964
23367
  const rawValue = value ?? fallback;
22965
23368
  if (!Number.isFinite(rawValue)) {
@@ -23134,23 +23537,43 @@ Captured external output:
23134
23537
  return commits;
23135
23538
  }
23136
23539
  flushPendingSplitCommits(forceFooterRepaint = false, drainAll = false) {
23137
- const commits = this.externalOutputQueue.claim(drainAll ? Number.POSITIVE_INFINITY : this.maxSplitCommitsPerFrame);
23540
+ const commits = this.externalOutputQueue.peek(drainAll ? Number.POSITIVE_INFINITY : this.maxSplitCommitsPerFrame);
23138
23541
  let hasCommittedOutput = false;
23139
23542
  const lastCommitIndex = commits.length - 1;
23543
+ let acceptedCommits = 0;
23544
+ let nativeBackpressured = false;
23140
23545
  for (const [index, commit] of commits.entries()) {
23141
23546
  const forceCommit = forceFooterRepaint && index === lastCommitIndex;
23142
23547
  const beginFrame = index === 0;
23143
23548
  const finalizeFrame = index === lastCommitIndex;
23144
- try {
23145
- this.renderOffset = this.lib.commitSplitFooterSnapshot(this.rendererPtr, commit.snapshot, commit.rowColumns, commit.startOnNewLine, commit.trailingNewline, this.getSplitPinnedRenderOffset(), forceCommit, beginFrame, finalizeFrame);
23146
- this.recordSplitCommit(commit);
23147
- hasCommittedOutput = true;
23148
- } finally {
23149
- commit.snapshot.destroy();
23549
+ const nativeResult = this.lib.commitSplitFooterSnapshot(this.rendererPtr, commit.snapshot, commit.rowColumns, commit.startOnNewLine, commit.trailingNewline, this.getSplitPinnedRenderOffset(), forceCommit, beginFrame, finalizeFrame);
23550
+ if (nativeResult.status === NATIVE_RENDER_STATUS_SKIPPED) {
23551
+ nativeBackpressured = true;
23552
+ break;
23553
+ }
23554
+ if (nativeResult.status === NATIVE_RENDER_STATUS_FAILED) {
23555
+ nativeBackpressured = true;
23556
+ break;
23150
23557
  }
23558
+ this.renderOffset = nativeResult.renderOffset;
23559
+ this.recordSplitCommit(commit);
23560
+ hasCommittedOutput = true;
23561
+ acceptedCommits++;
23562
+ }
23563
+ if (acceptedCommits > 0) {
23564
+ this.externalOutputQueue.drop(acceptedCommits);
23565
+ }
23566
+ if (nativeBackpressured) {
23567
+ this.scheduleRenderAfterFeedIdle();
23568
+ return "backpressured";
23151
23569
  }
23152
23570
  if (!hasCommittedOutput) {
23153
- this.renderOffset = this.lib.repaintSplitFooter(this.rendererPtr, this.getSplitPinnedRenderOffset(), forceFooterRepaint);
23571
+ const nativeResult = this.lib.repaintSplitFooter(this.rendererPtr, this.getSplitPinnedRenderOffset(), forceFooterRepaint);
23572
+ if (nativeResult.status === NATIVE_RENDER_STATUS_SKIPPED || nativeResult.status === NATIVE_RENDER_STATUS_FAILED) {
23573
+ this.scheduleRenderAfterFeedIdle();
23574
+ return "backpressured";
23575
+ }
23576
+ this.renderOffset = nativeResult.renderOffset;
23154
23577
  }
23155
23578
  this.pendingSplitFooterTransition = null;
23156
23579
  if (this.externalOutputQueue.size > 0) {
@@ -23158,6 +23581,7 @@ Captured external output:
23158
23581
  } else {
23159
23582
  this.applyPendingExternalOutputModeIfReady();
23160
23583
  }
23584
+ return "rendered";
23161
23585
  }
23162
23586
  interceptStdoutWrite = (chunk, encoding, callback) => {
23163
23587
  const resolvedCallback = typeof encoding === "function" ? encoding : callback;
@@ -23188,8 +23612,8 @@ Captured external output:
23188
23612
  isSplitCursorSeedFrameBlocked() {
23189
23613
  return this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout" && this._splitHeight > 0 && this.pendingSplitStartupCursorSeed && this.splitStartupSeedTimeoutId !== null;
23190
23614
  }
23191
- canFlushSplitOutputBeforeTransition(allowSuspended = false) {
23192
- return this._terminalIsSetup && (allowSuspended || this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) && !this.isSplitCursorSeedFrameBlocked();
23615
+ canFlushSplitOutputBeforeTransition(allowSuspended = false, allowUnsetup = false) {
23616
+ return (this._terminalIsSetup || allowUnsetup) && (allowSuspended || this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) && !this.isSplitCursorSeedFrameBlocked();
23193
23617
  }
23194
23618
  clearSplitStartupCursorSeed() {
23195
23619
  this.pendingSplitStartupCursorSeed = false;
@@ -23208,7 +23632,7 @@ Captured external output:
23208
23632
  if (this._screenMode !== "split-footer" || this._splitHeight <= 0 || this._externalOutputMode !== "capture-stdout" && !(options.allowPassthrough && hasDeferredCapturedOutput)) {
23209
23633
  return;
23210
23634
  }
23211
- if (!this.canFlushSplitOutputBeforeTransition(options.allowSuspended ?? false)) {
23635
+ if (!this.canFlushSplitOutputBeforeTransition(options.allowSuspended ?? false, options.allowUnsetup ?? false)) {
23212
23636
  return;
23213
23637
  }
23214
23638
  if (this.externalOutputQueue.size === 0 && !forceFooterRepaint) {
@@ -23503,6 +23927,7 @@ Captured external output:
23503
23927
  if (this.shouldSyncNativePaletteState()) {
23504
23928
  this.refreshPalette();
23505
23929
  }
23930
+ await this._feed?.idle();
23506
23931
  }
23507
23932
  stdinListener = ((chunk) => {
23508
23933
  const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
@@ -23971,6 +24396,11 @@ Captured external output:
23971
24396
  this.emit("resize" /* RESIZE */, this.width, this.height);
23972
24397
  this.requestRender();
23973
24398
  }
24399
+ resize(width, height) {
24400
+ if (this._isDestroyed)
24401
+ return;
24402
+ this.processResize(width, height);
24403
+ }
23974
24404
  setBackgroundColor(color) {
23975
24405
  const parsedColor = parseColor(color);
23976
24406
  this.lib.setBackgroundColor(this.rendererPtr, parsedColor);
@@ -24004,7 +24434,7 @@ Captured external output:
24004
24434
  this.lib.setTerminalTitle(this.rendererPtr, title);
24005
24435
  }
24006
24436
  resetTerminalBgColor() {
24007
- process.stdout.write("\x1B]111\x07");
24437
+ this.writeOut("\x1B]111\x07");
24008
24438
  }
24009
24439
  copyToClipboardOSC52(text, target) {
24010
24440
  return this.clipboard.copyToClipboardOSC52(text, target);
@@ -24021,8 +24451,8 @@ Captured external output:
24021
24451
  dumpBuffers(timestamp) {
24022
24452
  this.lib.dumpBuffers(this.rendererPtr, timestamp);
24023
24453
  }
24024
- dumpStdoutBuffer(timestamp) {
24025
- this.lib.dumpStdoutBuffer(this.rendererPtr, timestamp);
24454
+ dumpOutputBuffer(timestamp) {
24455
+ this.lib.dumpOutputBuffer(this.rendererPtr, timestamp);
24026
24456
  }
24027
24457
  static setCursorPosition(renderer, x, y, visible = true) {
24028
24458
  const lib = resolveRenderLib();
@@ -24110,6 +24540,7 @@ Captured external output:
24110
24540
  suspend() {
24111
24541
  this._previousControlState = this._controlState;
24112
24542
  this._controlState = "explicit_suspended" /* EXPLICIT_SUSPENDED */;
24543
+ this.updateScheduled = false;
24113
24544
  this.internalPause();
24114
24545
  if (this._terminalIsSetup) {
24115
24546
  this.clearSplitStartupCursorSeed();
@@ -24218,7 +24649,9 @@ Captured external output:
24218
24649
  if (this._destroyCleanupPrepared)
24219
24650
  return;
24220
24651
  this._destroyCleanupPrepared = true;
24221
- process.removeListener("SIGWINCH", this.sigwinchHandler);
24652
+ if (this._usesProcessStdout) {
24653
+ process.removeListener("SIGWINCH", this.sigwinchHandler);
24654
+ }
24222
24655
  process.removeListener("uncaughtException", this.handleError);
24223
24656
  process.removeListener("unhandledRejection", this.handleError);
24224
24657
  process.removeListener("warning", this.warningHandler);
@@ -24254,7 +24687,19 @@ Captured external output:
24254
24687
  this.setCapturedRenderable(undefined);
24255
24688
  this.stdin.removeListener("data", this.stdinListener);
24256
24689
  if (this.stdin.setRawMode) {
24257
- this.stdin.setRawMode(false);
24690
+ try {
24691
+ this.stdin.setRawMode(false);
24692
+ } catch (e) {
24693
+ console.error("Error disabling raw mode during destroy:", e);
24694
+ }
24695
+ }
24696
+ try {
24697
+ this.stdin.pause();
24698
+ } catch (e) {
24699
+ console.error("Error pausing stdin during destroy:", e);
24700
+ }
24701
+ if (this._feed !== null && this._splitHeight > 0 && !this._terminalIsSetup) {
24702
+ this.flushPendingSplitOutputBeforeTransition(false, { allowSuspended: true, allowUnsetup: true });
24258
24703
  }
24259
24704
  this.externalOutputMode = "passthrough";
24260
24705
  if (this._splitHeight > 0) {
@@ -24304,8 +24749,43 @@ Captured external output:
24304
24749
  this.pendingExternalOutputMode = null;
24305
24750
  this.stdout.write = this.realStdoutWrite;
24306
24751
  this.externalOutputQueue.clear();
24307
- this.lib.destroyRenderer(this.rendererPtr);
24308
- rendererTracker.removeRenderer(this);
24752
+ if (this._feed) {
24753
+ try {
24754
+ this._feed.drainAll();
24755
+ } catch (e) {
24756
+ console.error("Error draining NativeSpanFeed during destroy:", e);
24757
+ }
24758
+ }
24759
+ try {
24760
+ this.lib.destroyRenderer(this.rendererPtr);
24761
+ } catch (e) {
24762
+ console.error("Error in lib.destroyRenderer during destroy:", e);
24763
+ }
24764
+ rendererTracker.renderers.delete(this);
24765
+ if (rendererTracker.renderers.size === 0 && hasSingleton("tree-sitter-client")) {
24766
+ getTreeSitterClient().destroy();
24767
+ destroySingleton("tree-sitter-client");
24768
+ }
24769
+ if (this._feed) {
24770
+ try {
24771
+ this._feed.drainAll();
24772
+ } catch (e) {
24773
+ console.error("Error draining NativeSpanFeed shutdown frames:", e);
24774
+ }
24775
+ this._detachFeed?.();
24776
+ this._detachFeed = null;
24777
+ this._detachFeedError?.();
24778
+ this._detachFeedError = null;
24779
+ this._feed.close();
24780
+ this._feed = null;
24781
+ }
24782
+ if (this._streamLeaseAcquired) {
24783
+ if (rendererTracker.streamOwners.get(this.stdin) === this)
24784
+ rendererTracker.streamOwners.delete(this.stdin);
24785
+ if (rendererTracker.streamOwners.get(this.stdout) === this)
24786
+ rendererTracker.streamOwners.delete(this.stdout);
24787
+ this._streamLeaseAcquired = false;
24788
+ }
24309
24789
  if (this._onDestroy) {
24310
24790
  try {
24311
24791
  this._onDestroy();
@@ -24373,30 +24853,49 @@ Captured external output:
24373
24853
  }
24374
24854
  this._console.renderToBuffer(this.nextRenderBuffer);
24375
24855
  if (!this._isDestroyed) {
24376
- this.renderNative();
24377
- if (this._useMouse && this.lib.getHitGridDirty(this.rendererPtr)) {
24378
- this.recheckHoverState();
24379
- }
24380
- const overallFrameTime = performance.now() - overallStart;
24381
- this.lib.updateStats(this.rendererPtr, overallFrameTime, this.renderStats.fps, this.renderStats.frameCallbackTime);
24382
- if (this.listenerCount("frame" /* FRAME */) > 0) {
24383
- this.emit("frame" /* FRAME */, {
24384
- frameId: this.frameId
24385
- });
24386
- }
24387
- if (this.gatherStats) {
24388
- this.collectStatSample(overallFrameTime);
24389
- }
24390
- if (this._isRunning || this.immediateRerenderRequested) {
24391
- const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
24392
- const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
24393
- this.immediateRerenderRequested = false;
24394
- this.renderTimeout = this.clock.setTimeout(() => {
24856
+ const nativeStatus = this.renderNative() ?? "rendered";
24857
+ if (nativeStatus === "rendered") {
24858
+ if (this._useMouse && this.lib.getHitGridDirty(this.rendererPtr)) {
24859
+ this.recheckHoverState();
24860
+ }
24861
+ const overallFrameTime = performance.now() - overallStart;
24862
+ this.lib.updateStats(this.rendererPtr, overallFrameTime, this.renderStats.fps, this.renderStats.frameCallbackTime);
24863
+ if (this.listenerCount("frame" /* FRAME */) > 0) {
24864
+ this.emit("frame" /* FRAME */, {
24865
+ frameId: this.frameId
24866
+ });
24867
+ }
24868
+ if (this.gatherStats) {
24869
+ this.collectStatSample(overallFrameTime);
24870
+ }
24871
+ if (this._isRunning || this.immediateRerenderRequested) {
24872
+ const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
24873
+ const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
24874
+ this.immediateRerenderRequested = false;
24875
+ this.renderTimeout = this.clock.setTimeout(() => {
24876
+ this.renderTimeout = null;
24877
+ this.loop();
24878
+ }, delay);
24879
+ } else {
24880
+ this.clock.clearTimeout(this.renderTimeout);
24395
24881
  this.renderTimeout = null;
24396
- this.loop();
24397
- }, delay);
24882
+ }
24883
+ } else if (nativeStatus === "skipped") {
24884
+ const overallFrameTime = performance.now() - overallStart;
24885
+ if (this._isRunning || this.immediateRerenderRequested) {
24886
+ const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
24887
+ const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
24888
+ this.immediateRerenderRequested = false;
24889
+ this.renderTimeout = this.clock.setTimeout(() => {
24890
+ this.renderTimeout = null;
24891
+ this.loop();
24892
+ }, delay);
24893
+ } else {
24894
+ this.clock.clearTimeout(this.renderTimeout);
24895
+ this.renderTimeout = null;
24896
+ }
24398
24897
  } else {
24399
- this.clock.clearTimeout(this.renderTimeout);
24898
+ this.immediateRerenderRequested = false;
24400
24899
  this.renderTimeout = null;
24401
24900
  }
24402
24901
  }
@@ -24418,22 +24917,32 @@ Captured external output:
24418
24917
  throw new Error("Rendering called concurrently");
24419
24918
  }
24420
24919
  this.renderingNative = true;
24421
- if (this.isSplitCursorSeedFrameBlocked()) {
24422
- this.renderingNative = false;
24423
- return;
24424
- }
24425
- if (this._splitHeight > 0 && this._externalOutputMode === "capture-stdout") {
24426
- const forceSplitRepaint = this.forceFullRepaintRequested;
24427
- this.forceFullRepaintRequested = false;
24428
- this.flushPendingSplitCommits(forceSplitRepaint, this.pendingExternalOutputMode === "passthrough");
24429
- this.pendingSplitFooterTransition = null;
24430
- } else {
24920
+ try {
24921
+ if (this.isSplitCursorSeedFrameBlocked()) {
24922
+ return "skipped";
24923
+ }
24924
+ if (this._splitHeight > 0 && this._externalOutputMode === "capture-stdout") {
24925
+ const forceSplitRepaint = this.forceFullRepaintRequested;
24926
+ const status = this.flushPendingSplitCommits(forceSplitRepaint, this.pendingExternalOutputMode === "passthrough");
24927
+ if (status === "backpressured") {
24928
+ return "backpressured";
24929
+ }
24930
+ this.forceFullRepaintRequested = false;
24931
+ this.pendingSplitFooterTransition = null;
24932
+ return "rendered";
24933
+ }
24431
24934
  const force = this.forceFullRepaintRequested;
24935
+ const nativeStatus = this.lib.render(this.rendererPtr, force);
24936
+ if (nativeStatus === NATIVE_RENDER_STATUS_SKIPPED || nativeStatus === NATIVE_RENDER_STATUS_FAILED) {
24937
+ this.scheduleRenderAfterFeedIdle();
24938
+ return "backpressured";
24939
+ }
24432
24940
  this.forceFullRepaintRequested = false;
24433
24941
  this.pendingSplitFooterTransition = null;
24434
- this.lib.render(this.rendererPtr, force);
24942
+ return "rendered";
24943
+ } finally {
24944
+ this.renderingNative = false;
24435
24945
  }
24436
- this.renderingNative = false;
24437
24946
  }
24438
24947
  collectStatSample(frameTime) {
24439
24948
  this.frameTimes.push(frameTime);
@@ -24610,7 +25119,7 @@ Captured external output:
24610
25119
  }
24611
25120
  ensurePaletteDetector() {
24612
25121
  if (!this._paletteDetector) {
24613
- const isTmux = Boolean(this.capabilities?.in_tmux || this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux"));
25122
+ const isTmux = Boolean(this.capabilities?.multiplexer === "tmux" || this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux"));
24614
25123
  const isLegacyTmux = this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux") && this.capabilities?.terminal?.version?.localeCompare("3.6") < 0;
24615
25124
  this._paletteDetector = createTerminalPalette({
24616
25125
  stdin: this.stdin,
@@ -24689,7 +25198,7 @@ Captured external output:
24689
25198
  }
24690
25199
  const terminal = this._capabilities?.terminal;
24691
25200
  const hasTmuxVersion = terminal?.name?.toLowerCase() === "tmux" && Boolean(terminal.version);
24692
- if (this._capabilities?.in_tmux && !hasTmuxVersion) {
25201
+ if (this._capabilities?.multiplexer === "tmux" && !hasTmuxVersion) {
24693
25202
  await this.waitForXtVersion();
24694
25203
  const afterCapabilityWait = this.getCachedPaletteBySize(requestedSize);
24695
25204
  if (afterCapabilityWait) {
@@ -24744,7 +25253,7 @@ Captured external output:
24744
25253
  }
24745
25254
  }
24746
25255
 
24747
- export { __export, __require, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, DEFAULT_FOREGROUND_RGB, DEFAULT_BACKGROUND_RGB, normalizeIndexedColorIndex, ansi256IndexToRgb, RGBA, normalizeColorValue, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, terminalNamedSingleStrokeKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, stringWidth2 as stringWidth, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, normalizeTerminalPalette, buildTerminalPaletteSignature, decodePasteBytes, stripAnsiSequences, detectLinks, toArrayBuffer, TextBuffer, SpanInfoStruct, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, TextBufferView, EditBuffer, EditorView, convertThemeToStyles, SyntaxStyle, ANSI, BoxRenderable, TextBufferRenderable, CodeRenderable, isTextNodeRenderable, TextNodeRenderable, RootTextNodeRenderable, TextRenderable, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingAction, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, calculateRenderGeometry, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
25256
+ export { __export, __require, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, DEFAULT_FOREGROUND_RGB, DEFAULT_BACKGROUND_RGB, normalizeIndexedColorIndex, ansi256IndexToRgb, RGBA, normalizeColorValue, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, terminalNamedSingleStrokeKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, stringWidth2 as stringWidth, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, normalizeTerminalPalette, buildTerminalPaletteSignature, decodePasteBytes, stripAnsiSequences, detectLinks, TextBuffer, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, TextBufferView, EditBuffer, EditorView, convertThemeToStyles, SyntaxStyle, ANSI, BoxRenderable, TextBufferRenderable, CodeRenderable, isTextNodeRenderable, TextNodeRenderable, RootTextNodeRenderable, TextRenderable, NativeSpanFeed, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingAction, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
24748
25257
 
24749
- //# debugId=E84D4FE4C755B03764756E2164756E21
24750
- //# sourceMappingURL=index-qfwqv8y3.js.map
25258
+ //# debugId=98141239160B854E64756E2164756E21
25259
+ //# sourceMappingURL=index-jx0p1c2f.js.map