Skip to content

Commit e2b0430

Browse files
committed
Stage 2b: prepare, commit and recover renderer frames
Upstream's renderer emits while it thinks, so the frame is recorded off-lock and replayed under one transaction only after its geometry, output, owner and terminal generations still match. A managed write, resize, owner change or handoff in between retires the batch without emitting a byte of it. Discarding the output is only half of discarding the frame. The renderer has already advanced: _last_screen became a baseline for a frame the terminal never received, and the mode flags latch beside their emission, so a full repaint never re-emits them. Recovery drops the baseline and re-establishes a small enumerated state contract physically, then tells the renderer what is true -- not a snapshot of upstream fields, and not upstream's reset(), which emits operations of its own and rewrites available-height bookkeeping. Cursor position replies are correlated by order, since the wire carries no generation, and a row inside the reserved band is rejected before it can set a height that upstream would have computed as zero or negative. The contract tests record why each of those choices is necessary against prompt_toolkit 3.0.53, so an upgrade that changes them fails loudly.
1 parent 1850173 commit e2b0430

6 files changed

Lines changed: 1158 additions & 3 deletions

‎cmd2/output_recorder.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ def capture(cls, output: Output) -> "PreflightFacts":
8989
rows_below = None
9090
try:
9191
descriptor: int | None = output.fileno()
92-
except (io.UnsupportedOperation, AttributeError, OSError):
92+
except (io.UnsupportedOperation, NotImplementedError, AttributeError, OSError):
93+
# Backends disagree on how to say "no descriptor": Vt100 lets StringIO raise
94+
# UnsupportedOperation, DummyOutput raises NotImplementedError outright.
9395
descriptor = None
9496
return cls(
9597
size=output.get_size(),

0 commit comments

Comments
 (0)