Skip to content

Commit d459bce

Browse files
committed
preserve offset
1 parent 08a3f47 commit d459bce

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

packages/core/src/renderer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ export class CliRenderer extends EventEmitter implements RenderContext {
12421242
}
12431243

12441244
if (previousMode === "capture-stdout" && mode === "passthrough" && this._splitHeight > 0) {
1245-
this.flushPendingSplitOutputBeforeTransition(true)
1245+
this.flushPendingSplitOutputBeforeTransition()
12461246
}
12471247

12481248
this._externalOutputMode = mode
@@ -1253,6 +1253,10 @@ export class CliRenderer extends EventEmitter implements RenderContext {
12531253
return
12541254
}
12551255

1256+
if (this._screenMode === "split-footer" && this._splitHeight > 0 && previousMode === "capture-stdout" && mode === "passthrough") {
1257+
return
1258+
}
1259+
12561260
this.syncSplitFooterState()
12571261
}
12581262

packages/core/src/tests/renderer.console-startup.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,50 @@ test("CliRenderer flushes captured output before switching to passthrough in spl
381381
splitCommitSpy.mockRestore()
382382
})
383383

384+
test("CliRenderer preserves split render offset when switching to passthrough", async () => {
385+
const result = await createTestRenderer({
386+
width: 40,
387+
height: 10,
388+
screenMode: "split-footer",
389+
footerHeight: 4,
390+
externalOutputMode: "capture-stdout",
391+
consoleMode: "disabled",
392+
})
393+
394+
renderer = result.renderer
395+
;(renderer as any).stdout.write("seed\n")
396+
await result.renderOnce()
397+
398+
const before = (renderer as any).renderOffset
399+
const pinned = (renderer as any)._terminalHeight - (renderer as any)._splitHeight
400+
401+
renderer.externalOutputMode = "passthrough"
402+
403+
expect(before).toBeGreaterThan(0)
404+
expect(before).toBeLessThanOrEqual(pinned)
405+
expect((renderer as any).renderOffset).toBe(before)
406+
})
407+
408+
test("CliRenderer does not force split repaint when switching to passthrough with no pending output", async () => {
409+
const result = await createTestRenderer({
410+
screenMode: "split-footer",
411+
footerHeight: 6,
412+
externalOutputMode: "capture-stdout",
413+
consoleMode: "disabled",
414+
})
415+
416+
renderer = result.renderer
417+
const lib = (renderer as any).lib
418+
const repaintSpy = spyOn(lib, "repaintSplitFooter")
419+
420+
expect((renderer as any).externalOutputQueue.size).toBe(0)
421+
422+
renderer.externalOutputMode = "passthrough"
423+
424+
expect(repaintSpy).toHaveBeenCalledTimes(0)
425+
repaintSpy.mockRestore()
426+
})
427+
384428
test("CliRenderer flushes pending split output before resize applies new geometry", async () => {
385429
const result = await createTestRenderer({
386430
width: 40,

0 commit comments

Comments
 (0)