Skip to content

feat(terminal): add synchronized output (DEC mode ?2026)#70

Draft
roramirez wants to merge 1 commit into
mainfrom
feat/synchronized-output
Draft

feat(terminal): add synchronized output (DEC mode ?2026)#70
roramirez wants to merge 1 commit into
mainfrom
feat/synchronized-output

Conversation

@roramirez

Copy link
Copy Markdown
Owner

Summary

Implements synchronized output (DEC private mode ?2026). While a program holds ?2026h, mmterm skips presenting frames, so a complex update (vim redraw, lazygit, fullscreen TUIs) is never shown half-drawn — the window keeps the last complete frame until the program sends ?2026l, at which point the next frame renders normally. This eliminates tearing and is supported by WezTerm, Alacritty, and Ghostty.

Changes

  • src/terminal/grid.rs: add Grid.synchronized_output (pattern of bracketed_paste): declared, initialized false, and cleared by RIS.
  • src/terminal/parser.rs: handle_dec_private_modes sets/clears the flag on ?2026h/?2026l. Also collapse the DECSET/DECRST (h/l) arms into ('h' | 'l', …) patterns.
  • src/renderer/render_ops.rs: redraw() returns early (before acquiring the surface buffer) when the active pane's grid has synchronized_output set, via a new active_grid_synchronized() helper. The held frame is flushed by the redraw triggered when the ?2026l reset byte arrives from the PTY.
  • Tests: synchronized_output_mode in parser_test.rs.
  • CHANGELOG.md: entry under [Unreleased] / Added.

How to test

  • cargo test (see synchronized_output_mode).
  • In a running mmterm session: printf '\033[?2026h'; sleep 1; printf 'partial'; printf '\033[?2026l'partial does not appear until the reset; without the sequence it would appear immediately.

Checks

  • cargo fmt
  • cargo clippy --locked -- -D warnings
  • cargo test (1209 passed)
  • [~] km score --trend origin/main --fail-if-worse — grade B+ (passes .kimun.toml fail_below = B); trend -0.02 at the Cognitive rounding floor from the render-gate early-return, partially offset by simplifying the DEC private-mode setter.
  • CHANGELOG.md updated

Note / limitation

This implementation has no safety timeout: if a program sets ?2026h and never resets it, frames stay frozen until the next mode reset or RIS. Real applications reliably send ?2026l; a timeout (e.g. ~150 ms) could be added as a follow-up if needed.

Track ?2026 on the grid and skip presenting frames while it is set, so a
program writing a complex update (vim, lazygit) never shows a partial
screen — the window keeps the last frame until the program resets the
mode, eliminating tearing. Reset by RIS.

Collapse the DECSET/DECRST arms of handle_dec_private_modes into
`h | l` patterns while adding ?2026.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant