@opentui/core 0.2.16 → 0.3.0

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";
@@ -21661,8 +21958,9 @@ class ExternalOutputQueue {
21661
21958
  writeSnapshot(commit) {
21662
21959
  this.commits.push(commit);
21663
21960
  }
21664
- peek() {
21665
- return this.commits;
21961
+ peek(limit = Number.POSITIVE_INFINITY) {
21962
+ const clampedLimit = Number.isFinite(limit) ? Math.max(1, Math.trunc(limit)) : this.commits.length;
21963
+ return this.commits.slice(0, clampedLimit);
21666
21964
  }
21667
21965
  claim(limit = Number.POSITIVE_INFINITY) {
21668
21966
  if (this.commits.length === 0) {
@@ -21678,11 +21976,13 @@ class ExternalOutputQueue {
21678
21976
  this.commits = this.commits.slice(clampedLimit);
21679
21977
  return output;
21680
21978
  }
21681
- clear() {
21682
- for (const commit of this.commits) {
21979
+ drop(count) {
21980
+ for (const commit of this.commits.splice(0, count)) {
21683
21981
  commit.snapshot.destroy();
21684
21982
  }
21685
- this.commits = [];
21983
+ }
21984
+ clear() {
21985
+ this.drop(this.commits.length);
21686
21986
  }
21687
21987
  }
21688
21988
  var CHAR_FLAG_CONTINUATION = 3221225472 >>> 0;
@@ -21752,6 +22052,9 @@ class ScrollbackSnapshotRenderContext extends EventEmitter9 {
21752
22052
  }
21753
22053
  var DEFAULT_FORWARDED_ENV_KEYS = [
21754
22054
  "TMUX",
22055
+ "ZELLIJ",
22056
+ "ZELLIJ_SESSION_NAME",
22057
+ "ZELLIJ_PANE_ID",
21755
22058
  "TERM",
21756
22059
  "OPENTUI_GRAPHICS",
21757
22060
  "TERM_PROGRAM",
@@ -21766,11 +22069,15 @@ var DEFAULT_FORWARDED_ENV_KEYS = [
21766
22069
  "OPENTUI_FORCE_UNICODE",
21767
22070
  "OPENTUI_FORCE_NOZWJ",
21768
22071
  "OPENTUI_FORCE_EXPLICIT_WIDTH",
22072
+ "OPENTUI_NOTIFICATION_PROTOCOL",
22073
+ "OPENTUI_NOTIFICATIONS",
21769
22074
  "WT_SESSION",
21770
22075
  "STY",
21771
22076
  "WSL_DISTRO_NAME",
21772
22077
  "WSL_INTEROP"
21773
22078
  ];
22079
+ var NATIVE_RENDER_STATUS_SKIPPED = 1;
22080
+ var NATIVE_RENDER_STATUS_FAILED = 2;
21774
22081
  var KITTY_FLAG_DISAMBIGUATE = 1;
21775
22082
  var KITTY_FLAG_EVENT_TYPES = 2;
21776
22083
  var KITTY_FLAG_ALTERNATE_KEYS = 4;
@@ -21845,57 +22152,30 @@ var MouseButton;
21845
22152
  MouseButton2[MouseButton2["WHEEL_UP"] = 4] = "WHEEL_UP";
21846
22153
  MouseButton2[MouseButton2["WHEEL_DOWN"] = 5] = "WHEEL_DOWN";
21847
22154
  })(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
- });
22155
+ var rendererTracker = singleton("RendererTracker", () => ({
22156
+ renderers: new Set,
22157
+ streamOwners: new WeakMap
22158
+ }));
21866
22159
  async function createCliRenderer(config = {}) {
21867
22160
  if (process.argv.includes("--delay-start")) {
21868
22161
  await new Promise((resolve3) => setTimeout(resolve3, 5000));
21869
22162
  }
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) {
22163
+ const stdin = config.stdin ?? process.stdin;
22164
+ const stdout = config.stdout ?? process.stdout;
22165
+ const width = stdout.columns || config.width || 80;
22166
+ const height = stdout.rows || config.height || 24;
22167
+ const renderer = new CliRenderer(stdin, stdout, width, height, config);
22168
+ try {
21896
22169
  await renderer.setupTerminal();
22170
+ return renderer;
22171
+ } catch (error) {
22172
+ try {
22173
+ renderer.destroy();
22174
+ } catch (destroyError) {
22175
+ console.error("Error destroying partially-set-up renderer:", destroyError);
22176
+ }
22177
+ throw error;
21897
22178
  }
21898
- return renderer;
21899
22179
  }
21900
22180
  var CliRenderEvents;
21901
22181
  ((CliRenderEvents2) => {
@@ -21937,6 +22217,7 @@ class CliRenderer extends EventEmitter9 {
21937
22217
  _destroyPending = false;
21938
22218
  _destroyFinalized = false;
21939
22219
  _destroyCleanupPrepared = false;
22220
+ _streamLeaseAcquired = false;
21940
22221
  nextRenderBuffer;
21941
22222
  currentRenderBuffer;
21942
22223
  _isRunning = false;
@@ -22116,22 +22397,79 @@ Captured external output:
22116
22397
  warningHandler = ((warning) => {
22117
22398
  console.warn(JSON.stringify(warning.message, null, 2));
22118
22399
  }).bind(this);
22400
+ _usesProcessStdout;
22401
+ _feed = null;
22402
+ _detachFeed = null;
22403
+ _detachFeedError = null;
22404
+ feedIdleRenderScheduled = false;
22119
22405
  get controlState() {
22120
22406
  return this._controlState;
22121
22407
  }
22122
- constructor(lib, rendererPtr, stdin, stdout, width, height, config = {}) {
22408
+ constructor(stdin, stdout, width, height, config = {}) {
22123
22409
  super();
22124
- rendererTracker.addRenderer(this);
22125
22410
  this.stdin = stdin;
22126
22411
  this.stdout = stdout;
22412
+ this._usesProcessStdout = stdout === process.stdout;
22127
22413
  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;
22414
+ const lib = resolveRenderLib();
22415
+ const useMemoryBufferedOutput = config.bufferedOutput === "memory";
22416
+ const useFeedOutput = !this._usesProcessStdout && !useMemoryBufferedOutput;
22132
22417
  const { screenMode, footerHeight, externalOutputMode } = resolveModes(config);
22418
+ const initialGeometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
22419
+ const remoteMode = config.remote ?? (useFeedOutput ? true : undefined);
22420
+ if (rendererTracker.streamOwners.get(stdin)) {
22421
+ throw new Error("Cannot create CliRenderer: stdin is already used by another CliRenderer");
22422
+ }
22423
+ if (rendererTracker.streamOwners.get(stdout)) {
22424
+ throw new Error("Cannot create CliRenderer: stdout is already used by another CliRenderer");
22425
+ }
22426
+ let feed = null;
22427
+ if (useFeedOutput) {
22428
+ try {
22429
+ feed = NativeSpanFeed.create();
22430
+ } catch (error) {
22431
+ throw new Error(`Failed to allocate NativeSpanFeed for custom stdout: ${error instanceof Error ? error.message : String(error)}`);
22432
+ }
22433
+ }
22434
+ let rendererPtr;
22435
+ try {
22436
+ rendererPtr = lib.createRenderer(initialGeometry.renderWidth, initialGeometry.renderHeight, {
22437
+ remote: remoteMode,
22438
+ feedPtr: feed?.streamPtr ?? null,
22439
+ bufferedOutput: config.bufferedOutput
22440
+ });
22441
+ } catch (error) {
22442
+ feed?.close();
22443
+ throw error;
22444
+ }
22445
+ if (!rendererPtr) {
22446
+ feed?.close();
22447
+ throw new Error("Failed to create renderer");
22448
+ }
22449
+ if (config.useThread === undefined)
22450
+ config.useThread = true;
22451
+ if (process.platform === "linux")
22452
+ config.useThread = false;
22453
+ lib.setUseThread(rendererPtr, config.useThread);
22454
+ const kittyConfig = config.useKittyKeyboard ?? {};
22455
+ const kittyFlags = buildKittyKeyboardFlags(kittyConfig);
22456
+ lib.setKittyKeyboardFlags(rendererPtr, kittyFlags);
22457
+ this._feed = feed;
22458
+ if (feed) {
22459
+ this._detachFeed = feed.onData((bytes) => {
22460
+ return new Promise((resolve3) => {
22461
+ this.realStdoutWrite.call(this.stdout, bytes, () => resolve3());
22462
+ });
22463
+ });
22464
+ this._detachFeedError = feed.onError((code) => {
22465
+ console.error(`[CliRenderer] NativeSpanFeed error: code=${code}`);
22466
+ });
22467
+ }
22468
+ this.lib = lib;
22469
+ this._terminalWidth = width;
22470
+ this._terminalHeight = height;
22471
+ this._useThread = config.useThread;
22133
22472
  this._externalOutputMode = externalOutputMode;
22134
- const initialGeometry = calculateRenderGeometry(screenMode, this._terminalWidth, this._terminalHeight, footerHeight);
22135
22473
  this.width = initialGeometry.renderWidth;
22136
22474
  this.height = initialGeometry.renderHeight;
22137
22475
  this._splitHeight = initialGeometry.effectiveFooterHeight;
@@ -22140,7 +22478,7 @@ Captured external output:
22140
22478
  this.rendererPtr = rendererPtr;
22141
22479
  this.clearOnShutdown = config.clearOnShutdown ?? true;
22142
22480
  this.lib.setClearOnShutdown(this.rendererPtr, this.clearOnShutdown);
22143
- const forwardEnvKeys = config.forwardEnvKeys ?? (config.remote ? [] : [...DEFAULT_FORWARDED_ENV_KEYS]);
22481
+ const forwardEnvKeys = config.forwardEnvKeys ?? (config.remote === false ? [...DEFAULT_FORWARDED_ENV_KEYS] : []);
22144
22482
  for (const key of forwardEnvKeys) {
22145
22483
  const value = process.env[key];
22146
22484
  if (value === undefined)
@@ -22193,12 +22531,13 @@ Captured external output:
22193
22531
  if (this.memorySnapshotInterval > 0) {
22194
22532
  this.startMemorySnapshotTimer();
22195
22533
  }
22196
- process.on("SIGWINCH", this.sigwinchHandler);
22534
+ if (this._usesProcessStdout) {
22535
+ process.on("SIGWINCH", this.sigwinchHandler);
22536
+ }
22197
22537
  process.on("warning", this.warningHandler);
22198
22538
  process.on("uncaughtException", this.handleError);
22199
22539
  process.on("unhandledRejection", this.handleError);
22200
22540
  process.on("beforeExit", this.exitHandler);
22201
- const kittyConfig = config.useKittyKeyboard ?? {};
22202
22541
  const useKittyForParsing = kittyConfig !== null;
22203
22542
  this._keyHandler = new InternalKeyHandler;
22204
22543
  this._keyHandler.on("keypress", (event) => {
@@ -22234,6 +22573,10 @@ Captured external output:
22234
22573
  });
22235
22574
  this.consoleMode = config.consoleMode ?? "console-overlay";
22236
22575
  this.applyScreenMode(screenMode, false, false);
22576
+ rendererTracker.streamOwners.set(stdin, this);
22577
+ rendererTracker.streamOwners.set(stdout, this);
22578
+ this._streamLeaseAcquired = true;
22579
+ rendererTracker.renderers.add(this);
22237
22580
  this.stdout.write = externalOutputMode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
22238
22581
  this._openConsoleOnError = config.openConsoleOnError ?? true;
22239
22582
  this._onDestroy = config.onDestroy;
@@ -22256,9 +22599,19 @@ Captured external output:
22256
22599
  if (this._splitHeight > 0) {
22257
22600
  this.flushStdoutCache(this._splitHeight);
22258
22601
  }
22602
+ return "rendered";
22259
22603
  };
22260
22604
  }
22261
- this.setupInput();
22605
+ try {
22606
+ this.setupInput();
22607
+ } catch (error) {
22608
+ try {
22609
+ this.destroy();
22610
+ } catch (destroyError) {
22611
+ console.error("Error destroying renderer after input setup failure:", destroyError);
22612
+ }
22613
+ throw error;
22614
+ }
22262
22615
  }
22263
22616
  addExitListeners() {
22264
22617
  if (this._exitListenersAdded || this.exitSignals.length === 0)
@@ -22363,7 +22716,7 @@ Captured external output:
22363
22716
  return this._frameId;
22364
22717
  }
22365
22718
  writeOut(chunk, encoding, callback) {
22366
- if (this.rendererPtr && this._useThread) {
22719
+ if (this.rendererPtr && (this._useThread || this._feed !== null)) {
22367
22720
  const data = typeof chunk === "string" ? chunk : chunk?.toString() ?? "";
22368
22721
  this.lib.writeOut(this.rendererPtr, data);
22369
22722
  if (typeof callback === "function") {
@@ -22373,6 +22726,30 @@ Captured external output:
22373
22726
  }
22374
22727
  return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
22375
22728
  }
22729
+ scheduleRenderAfterFeedIdle() {
22730
+ const feed = this._feed;
22731
+ if (!feed || this.feedIdleRenderScheduled || this._isDestroyed)
22732
+ return;
22733
+ this.feedIdleRenderScheduled = true;
22734
+ feed.idle().then(() => {
22735
+ this.feedIdleRenderScheduled = false;
22736
+ if (this._isDestroyed) {
22737
+ this.resolveIdleIfNeeded();
22738
+ return;
22739
+ }
22740
+ if (this._isRunning) {
22741
+ if (!this.renderTimeout && !this.rendering) {
22742
+ this.renderTimeout = this.clock.setTimeout(() => {
22743
+ this.renderTimeout = null;
22744
+ this.loop();
22745
+ }, 0);
22746
+ }
22747
+ return;
22748
+ }
22749
+ this.requestRender();
22750
+ this.resolveIdleIfNeeded();
22751
+ });
22752
+ }
22376
22753
  requestRender() {
22377
22754
  if (this._controlState === "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
22378
22755
  return;
@@ -22423,7 +22800,9 @@ Captured external output:
22423
22800
  return this._isRunning;
22424
22801
  }
22425
22802
  isIdleNow() {
22426
- return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.immediateRerenderRequested;
22803
+ if (this._isDestroyed)
22804
+ return true;
22805
+ return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.feedIdleRenderScheduled && !this.immediateRerenderRequested;
22427
22806
  }
22428
22807
  resolveIdleIfNeeded() {
22429
22808
  if (!this.isIdleNow())
@@ -23134,23 +23513,43 @@ Captured external output:
23134
23513
  return commits;
23135
23514
  }
23136
23515
  flushPendingSplitCommits(forceFooterRepaint = false, drainAll = false) {
23137
- const commits = this.externalOutputQueue.claim(drainAll ? Number.POSITIVE_INFINITY : this.maxSplitCommitsPerFrame);
23516
+ const commits = this.externalOutputQueue.peek(drainAll ? Number.POSITIVE_INFINITY : this.maxSplitCommitsPerFrame);
23138
23517
  let hasCommittedOutput = false;
23139
23518
  const lastCommitIndex = commits.length - 1;
23519
+ let acceptedCommits = 0;
23520
+ let nativeBackpressured = false;
23140
23521
  for (const [index, commit] of commits.entries()) {
23141
23522
  const forceCommit = forceFooterRepaint && index === lastCommitIndex;
23142
23523
  const beginFrame = index === 0;
23143
23524
  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();
23525
+ const nativeResult = this.lib.commitSplitFooterSnapshot(this.rendererPtr, commit.snapshot, commit.rowColumns, commit.startOnNewLine, commit.trailingNewline, this.getSplitPinnedRenderOffset(), forceCommit, beginFrame, finalizeFrame);
23526
+ if (nativeResult.status === NATIVE_RENDER_STATUS_SKIPPED) {
23527
+ nativeBackpressured = true;
23528
+ break;
23150
23529
  }
23530
+ if (nativeResult.status === NATIVE_RENDER_STATUS_FAILED) {
23531
+ nativeBackpressured = true;
23532
+ break;
23533
+ }
23534
+ this.renderOffset = nativeResult.renderOffset;
23535
+ this.recordSplitCommit(commit);
23536
+ hasCommittedOutput = true;
23537
+ acceptedCommits++;
23538
+ }
23539
+ if (acceptedCommits > 0) {
23540
+ this.externalOutputQueue.drop(acceptedCommits);
23541
+ }
23542
+ if (nativeBackpressured) {
23543
+ this.scheduleRenderAfterFeedIdle();
23544
+ return "backpressured";
23151
23545
  }
23152
23546
  if (!hasCommittedOutput) {
23153
- this.renderOffset = this.lib.repaintSplitFooter(this.rendererPtr, this.getSplitPinnedRenderOffset(), forceFooterRepaint);
23547
+ const nativeResult = this.lib.repaintSplitFooter(this.rendererPtr, this.getSplitPinnedRenderOffset(), forceFooterRepaint);
23548
+ if (nativeResult.status === NATIVE_RENDER_STATUS_SKIPPED || nativeResult.status === NATIVE_RENDER_STATUS_FAILED) {
23549
+ this.scheduleRenderAfterFeedIdle();
23550
+ return "backpressured";
23551
+ }
23552
+ this.renderOffset = nativeResult.renderOffset;
23154
23553
  }
23155
23554
  this.pendingSplitFooterTransition = null;
23156
23555
  if (this.externalOutputQueue.size > 0) {
@@ -23158,6 +23557,7 @@ Captured external output:
23158
23557
  } else {
23159
23558
  this.applyPendingExternalOutputModeIfReady();
23160
23559
  }
23560
+ return "rendered";
23161
23561
  }
23162
23562
  interceptStdoutWrite = (chunk, encoding, callback) => {
23163
23563
  const resolvedCallback = typeof encoding === "function" ? encoding : callback;
@@ -23188,8 +23588,8 @@ Captured external output:
23188
23588
  isSplitCursorSeedFrameBlocked() {
23189
23589
  return this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout" && this._splitHeight > 0 && this.pendingSplitStartupCursorSeed && this.splitStartupSeedTimeoutId !== null;
23190
23590
  }
23191
- canFlushSplitOutputBeforeTransition(allowSuspended = false) {
23192
- return this._terminalIsSetup && (allowSuspended || this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) && !this.isSplitCursorSeedFrameBlocked();
23591
+ canFlushSplitOutputBeforeTransition(allowSuspended = false, allowUnsetup = false) {
23592
+ return (this._terminalIsSetup || allowUnsetup) && (allowSuspended || this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) && !this.isSplitCursorSeedFrameBlocked();
23193
23593
  }
23194
23594
  clearSplitStartupCursorSeed() {
23195
23595
  this.pendingSplitStartupCursorSeed = false;
@@ -23208,7 +23608,7 @@ Captured external output:
23208
23608
  if (this._screenMode !== "split-footer" || this._splitHeight <= 0 || this._externalOutputMode !== "capture-stdout" && !(options.allowPassthrough && hasDeferredCapturedOutput)) {
23209
23609
  return;
23210
23610
  }
23211
- if (!this.canFlushSplitOutputBeforeTransition(options.allowSuspended ?? false)) {
23611
+ if (!this.canFlushSplitOutputBeforeTransition(options.allowSuspended ?? false, options.allowUnsetup ?? false)) {
23212
23612
  return;
23213
23613
  }
23214
23614
  if (this.externalOutputQueue.size === 0 && !forceFooterRepaint) {
@@ -23503,6 +23903,7 @@ Captured external output:
23503
23903
  if (this.shouldSyncNativePaletteState()) {
23504
23904
  this.refreshPalette();
23505
23905
  }
23906
+ await this._feed?.idle();
23506
23907
  }
23507
23908
  stdinListener = ((chunk) => {
23508
23909
  const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
@@ -23971,6 +24372,11 @@ Captured external output:
23971
24372
  this.emit("resize" /* RESIZE */, this.width, this.height);
23972
24373
  this.requestRender();
23973
24374
  }
24375
+ resize(width, height) {
24376
+ if (this._isDestroyed)
24377
+ return;
24378
+ this.processResize(width, height);
24379
+ }
23974
24380
  setBackgroundColor(color) {
23975
24381
  const parsedColor = parseColor(color);
23976
24382
  this.lib.setBackgroundColor(this.rendererPtr, parsedColor);
@@ -24004,7 +24410,7 @@ Captured external output:
24004
24410
  this.lib.setTerminalTitle(this.rendererPtr, title);
24005
24411
  }
24006
24412
  resetTerminalBgColor() {
24007
- process.stdout.write("\x1B]111\x07");
24413
+ this.writeOut("\x1B]111\x07");
24008
24414
  }
24009
24415
  copyToClipboardOSC52(text, target) {
24010
24416
  return this.clipboard.copyToClipboardOSC52(text, target);
@@ -24021,8 +24427,8 @@ Captured external output:
24021
24427
  dumpBuffers(timestamp) {
24022
24428
  this.lib.dumpBuffers(this.rendererPtr, timestamp);
24023
24429
  }
24024
- dumpStdoutBuffer(timestamp) {
24025
- this.lib.dumpStdoutBuffer(this.rendererPtr, timestamp);
24430
+ dumpOutputBuffer(timestamp) {
24431
+ this.lib.dumpOutputBuffer(this.rendererPtr, timestamp);
24026
24432
  }
24027
24433
  static setCursorPosition(renderer, x, y, visible = true) {
24028
24434
  const lib = resolveRenderLib();
@@ -24110,6 +24516,7 @@ Captured external output:
24110
24516
  suspend() {
24111
24517
  this._previousControlState = this._controlState;
24112
24518
  this._controlState = "explicit_suspended" /* EXPLICIT_SUSPENDED */;
24519
+ this.updateScheduled = false;
24113
24520
  this.internalPause();
24114
24521
  if (this._terminalIsSetup) {
24115
24522
  this.clearSplitStartupCursorSeed();
@@ -24218,7 +24625,9 @@ Captured external output:
24218
24625
  if (this._destroyCleanupPrepared)
24219
24626
  return;
24220
24627
  this._destroyCleanupPrepared = true;
24221
- process.removeListener("SIGWINCH", this.sigwinchHandler);
24628
+ if (this._usesProcessStdout) {
24629
+ process.removeListener("SIGWINCH", this.sigwinchHandler);
24630
+ }
24222
24631
  process.removeListener("uncaughtException", this.handleError);
24223
24632
  process.removeListener("unhandledRejection", this.handleError);
24224
24633
  process.removeListener("warning", this.warningHandler);
@@ -24254,7 +24663,19 @@ Captured external output:
24254
24663
  this.setCapturedRenderable(undefined);
24255
24664
  this.stdin.removeListener("data", this.stdinListener);
24256
24665
  if (this.stdin.setRawMode) {
24257
- this.stdin.setRawMode(false);
24666
+ try {
24667
+ this.stdin.setRawMode(false);
24668
+ } catch (e) {
24669
+ console.error("Error disabling raw mode during destroy:", e);
24670
+ }
24671
+ }
24672
+ try {
24673
+ this.stdin.pause();
24674
+ } catch (e) {
24675
+ console.error("Error pausing stdin during destroy:", e);
24676
+ }
24677
+ if (this._feed !== null && this._splitHeight > 0 && !this._terminalIsSetup) {
24678
+ this.flushPendingSplitOutputBeforeTransition(false, { allowSuspended: true, allowUnsetup: true });
24258
24679
  }
24259
24680
  this.externalOutputMode = "passthrough";
24260
24681
  if (this._splitHeight > 0) {
@@ -24304,8 +24725,43 @@ Captured external output:
24304
24725
  this.pendingExternalOutputMode = null;
24305
24726
  this.stdout.write = this.realStdoutWrite;
24306
24727
  this.externalOutputQueue.clear();
24307
- this.lib.destroyRenderer(this.rendererPtr);
24308
- rendererTracker.removeRenderer(this);
24728
+ if (this._feed) {
24729
+ try {
24730
+ this._feed.drainAll();
24731
+ } catch (e) {
24732
+ console.error("Error draining NativeSpanFeed during destroy:", e);
24733
+ }
24734
+ }
24735
+ try {
24736
+ this.lib.destroyRenderer(this.rendererPtr);
24737
+ } catch (e) {
24738
+ console.error("Error in lib.destroyRenderer during destroy:", e);
24739
+ }
24740
+ rendererTracker.renderers.delete(this);
24741
+ if (rendererTracker.renderers.size === 0 && hasSingleton("tree-sitter-client")) {
24742
+ getTreeSitterClient().destroy();
24743
+ destroySingleton("tree-sitter-client");
24744
+ }
24745
+ if (this._feed) {
24746
+ try {
24747
+ this._feed.drainAll();
24748
+ } catch (e) {
24749
+ console.error("Error draining NativeSpanFeed shutdown frames:", e);
24750
+ }
24751
+ this._detachFeed?.();
24752
+ this._detachFeed = null;
24753
+ this._detachFeedError?.();
24754
+ this._detachFeedError = null;
24755
+ this._feed.close();
24756
+ this._feed = null;
24757
+ }
24758
+ if (this._streamLeaseAcquired) {
24759
+ if (rendererTracker.streamOwners.get(this.stdin) === this)
24760
+ rendererTracker.streamOwners.delete(this.stdin);
24761
+ if (rendererTracker.streamOwners.get(this.stdout) === this)
24762
+ rendererTracker.streamOwners.delete(this.stdout);
24763
+ this._streamLeaseAcquired = false;
24764
+ }
24309
24765
  if (this._onDestroy) {
24310
24766
  try {
24311
24767
  this._onDestroy();
@@ -24373,30 +24829,49 @@ Captured external output:
24373
24829
  }
24374
24830
  this._console.renderToBuffer(this.nextRenderBuffer);
24375
24831
  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(() => {
24832
+ const nativeStatus = this.renderNative() ?? "rendered";
24833
+ if (nativeStatus === "rendered") {
24834
+ if (this._useMouse && this.lib.getHitGridDirty(this.rendererPtr)) {
24835
+ this.recheckHoverState();
24836
+ }
24837
+ const overallFrameTime = performance.now() - overallStart;
24838
+ this.lib.updateStats(this.rendererPtr, overallFrameTime, this.renderStats.fps, this.renderStats.frameCallbackTime);
24839
+ if (this.listenerCount("frame" /* FRAME */) > 0) {
24840
+ this.emit("frame" /* FRAME */, {
24841
+ frameId: this.frameId
24842
+ });
24843
+ }
24844
+ if (this.gatherStats) {
24845
+ this.collectStatSample(overallFrameTime);
24846
+ }
24847
+ if (this._isRunning || this.immediateRerenderRequested) {
24848
+ const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
24849
+ const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
24850
+ this.immediateRerenderRequested = false;
24851
+ this.renderTimeout = this.clock.setTimeout(() => {
24852
+ this.renderTimeout = null;
24853
+ this.loop();
24854
+ }, delay);
24855
+ } else {
24856
+ this.clock.clearTimeout(this.renderTimeout);
24395
24857
  this.renderTimeout = null;
24396
- this.loop();
24397
- }, delay);
24858
+ }
24859
+ } else if (nativeStatus === "skipped") {
24860
+ const overallFrameTime = performance.now() - overallStart;
24861
+ if (this._isRunning || this.immediateRerenderRequested) {
24862
+ const targetFrameTime = this.immediateRerenderRequested ? this.minTargetFrameTime : this.targetFrameTime;
24863
+ const delay = Math.max(1, targetFrameTime - Math.floor(overallFrameTime));
24864
+ this.immediateRerenderRequested = false;
24865
+ this.renderTimeout = this.clock.setTimeout(() => {
24866
+ this.renderTimeout = null;
24867
+ this.loop();
24868
+ }, delay);
24869
+ } else {
24870
+ this.clock.clearTimeout(this.renderTimeout);
24871
+ this.renderTimeout = null;
24872
+ }
24398
24873
  } else {
24399
- this.clock.clearTimeout(this.renderTimeout);
24874
+ this.immediateRerenderRequested = false;
24400
24875
  this.renderTimeout = null;
24401
24876
  }
24402
24877
  }
@@ -24418,22 +24893,32 @@ Captured external output:
24418
24893
  throw new Error("Rendering called concurrently");
24419
24894
  }
24420
24895
  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 {
24896
+ try {
24897
+ if (this.isSplitCursorSeedFrameBlocked()) {
24898
+ return "skipped";
24899
+ }
24900
+ if (this._splitHeight > 0 && this._externalOutputMode === "capture-stdout") {
24901
+ const forceSplitRepaint = this.forceFullRepaintRequested;
24902
+ const status = this.flushPendingSplitCommits(forceSplitRepaint, this.pendingExternalOutputMode === "passthrough");
24903
+ if (status === "backpressured") {
24904
+ return "backpressured";
24905
+ }
24906
+ this.forceFullRepaintRequested = false;
24907
+ this.pendingSplitFooterTransition = null;
24908
+ return "rendered";
24909
+ }
24431
24910
  const force = this.forceFullRepaintRequested;
24911
+ const nativeStatus = this.lib.render(this.rendererPtr, force);
24912
+ if (nativeStatus === NATIVE_RENDER_STATUS_SKIPPED || nativeStatus === NATIVE_RENDER_STATUS_FAILED) {
24913
+ this.scheduleRenderAfterFeedIdle();
24914
+ return "backpressured";
24915
+ }
24432
24916
  this.forceFullRepaintRequested = false;
24433
24917
  this.pendingSplitFooterTransition = null;
24434
- this.lib.render(this.rendererPtr, force);
24918
+ return "rendered";
24919
+ } finally {
24920
+ this.renderingNative = false;
24435
24921
  }
24436
- this.renderingNative = false;
24437
24922
  }
24438
24923
  collectStatSample(frameTime) {
24439
24924
  this.frameTimes.push(frameTime);
@@ -24610,7 +25095,7 @@ Captured external output:
24610
25095
  }
24611
25096
  ensurePaletteDetector() {
24612
25097
  if (!this._paletteDetector) {
24613
- const isTmux = Boolean(this.capabilities?.in_tmux || this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux"));
25098
+ const isTmux = Boolean(this.capabilities?.multiplexer === "tmux" || this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux"));
24614
25099
  const isLegacyTmux = this.capabilities?.terminal?.name?.toLowerCase()?.includes("tmux") && this.capabilities?.terminal?.version?.localeCompare("3.6") < 0;
24615
25100
  this._paletteDetector = createTerminalPalette({
24616
25101
  stdin: this.stdin,
@@ -24689,7 +25174,7 @@ Captured external output:
24689
25174
  }
24690
25175
  const terminal = this._capabilities?.terminal;
24691
25176
  const hasTmuxVersion = terminal?.name?.toLowerCase() === "tmux" && Boolean(terminal.version);
24692
- if (this._capabilities?.in_tmux && !hasTmuxVersion) {
25177
+ if (this._capabilities?.multiplexer === "tmux" && !hasTmuxVersion) {
24693
25178
  await this.waitForXtVersion();
24694
25179
  const afterCapabilityWait = this.getCachedPaletteBySize(requestedSize);
24695
25180
  if (afterCapabilityWait) {
@@ -24744,7 +25229,7 @@ Captured external output:
24744
25229
  }
24745
25230
  }
24746
25231
 
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 };
25232
+ 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
25233
 
24749
- //# debugId=E84D4FE4C755B03764756E2164756E21
24750
- //# sourceMappingURL=index-qfwqv8y3.js.map
25234
+ //# debugId=F97AFCBE61BE955464756E2164756E21
25235
+ //# sourceMappingURL=index-081xws23.js.map