Skip to content

fix(cli): collect the changed cells once before painting a coloured diff - #601

Merged
vyncint merged 3 commits into
vyncint:mainfrom
bercedev:fix/colored-diff-changed-set
Oct 22, 2026
Merged

vyncint merged 3 commits into
vyncint:mainfrom
bercedev:fix/colored-diff-changed-set

Conversation

@bercedev

Copy link
Copy Markdown
Contributor

What & why

Closes #595

colored() in crates/termlens-cli/src/main.rs checked every cell it painted with diff.cells().any(...), which walks the whole changed list each time. A full-screen change was therefore quadratic. The changed (row, col) pairs now go into a HashSet once, before the rows are painted, and the paint closure looks each cell up there. The output is byte-for-byte the same.

A new CLI test, diff_color_always_paints_a_full_screen_change_quickly, diffs two 1000x1000 screens that differ in every cell with --color always. It sends stdout to a file, because the output is tens of megabytes and a pipe nobody drains would stall the child. It also has a 60 s deadline, so a regression fails the test instead of hanging the suite. It checks for exit 1 and that both sides are painted (\x1b[31ma\x1b[0m, \x1b[32mb\x1b[0m). In a debug build it finishes in about 2.6 s with the change. With the old main.rs it hits the 60 s deadline.

Checklist

  • Linked an issue (or explained above why none exists)
  • Tests added/updated for the change
  • cargo fmt --all and cargo clippy --workspace --all-targets --all-features are clean
  • All commits are signed off (git commit -s) — see CONTRIBUTING.md §5
  • No AI attribution trailers (no AI co-authors, "Generated with" footers, or bot identities) — see CONTRIBUTING.md §6
  • CHANGELOG.md updated under [Unreleased] (user-facing changes only)
  • Snapshot changes (if any) were reviewed with cargo insta review, not blind-accepted (no snapshot changes)

Checked with Rust 1.99.1, offline: cargo test -p termlens-cli (44 passed), cargo clippy with all features and with default features, cargo fmt --all --check, .github/scripts/check-dco.sh main..HEAD, check-no-ai-attribution.sh main..HEAD and check-readme-links.sh.

colored() asked the diff about every painted cell, which scanned the whole changed list each time: a full-screen change on a large terminal took seconds (vyncint#595). The changed cells now go into a HashSet first. A CLI test diffs two 1000x1000 screens that differ everywhere.

Signed-off-by: berce <75228263+bercedev@users.noreply.github.com>
…t a sleep

The new test was inserted between the vyncint#452 doc comment and the test it
documents, so `diff_names_a_missing_or_unknown_color_value` lost its doc
and the new test inherited it. It now sits above that comment.

Its deadline was a try_wait loop with a 50 ms sleep, and CONTRIBUTING §3
allows only two sleeps in tests. A thread now waits on the exit and the
test bounds that with recv_timeout. Checked against the old main.rs: the
test still fails at the 60 s deadline.

Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>

# Conflicts:
#	CHANGELOG.md

@vyncint vyncint left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — the HashSet fix is exactly right. I pushed two small changes to the test: it had been inserted between the #452 doc comment and its test (so that test lost its doc), and its deadline used a try_wait + sleep loop, which CONTRIBUTING §3 doesn't allow; it now waits on the exit with recv_timeout. Checked against the old main.rs: the test still fails at the 60 s deadline. I also merged main to resolve the CHANGELOG conflict with #602.

@vyncint
vyncint merged commit 06cd15d into vyncint:main Oct 22, 2026
16 checks passed
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.

Coloured termlens diff is quadratic in the number of changed cells

2 participants