Skip to content

Add Printer::try_on_window to avoid panicking on a stale window size - #886

Open
akashchamp wants to merge 1 commit into
gyscos:mainfrom
akashchamp:fix-on-window-panic-885
Open

akashchamp wants to merge 1 commit into
gyscos:mainfrom
akashchamp:fix-on-window-panic-885

Conversation

@akashchamp

@akashchamp akashchamp commented Sep 24, 2026 •

Copy link
Copy Markdown

Fixes #885.

Printer::on_window .expect()s that the output window fits the backend buffer, so a printer whose output window exceeds the buffer panics with "printer size exceeds backend size".

This adds Printer::try_on_window<F, R>(&self, f: F) -> Option<R>, which skips the closure and returns None when the window doesn't fit. on_window is now built on top of it and keeps its panicking behavior (now documented with a # Panics section). GradientView, the only in-tree caller of on_window, uses try_on_window so the cosmetic gradient overlay is skipped for a frame instead of crashing. A CHANGELOG entry is included.

As the maintainer pointed out, a terminal resize cannot cause this mismatch, since layout and draw always use the same size. The root cause (printer output windows exceeding the buffer) is addressed separately upstream in 9250e09; this PR only adds a non-panicking alternative for callers that prefer one.

Testing, after rebasing onto current main:

  • cargo test -p cursive_core --lib: 93 passed, 0 failed. This includes new unit tests for on_window panicking on an undersized buffer and for try_on_window returning None or Some(result).

@gyscos

gyscos commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Hi, and thanks for the PR!

PrintBuffer::window() already documents and returns None for exactly
this mismatch (e.g. a terminal resize between the layout pass and the draw
pass)

This is not currently true: a terminal resize can never cause a panic in this case. The terminal resize event does not directly cause a buffer resize, it's only done at the start of the next cycle. Layout and draw always get the same size.

The problem comes from a printer with an output window that exceeds what the buffer provides, and that's what should be fixed, rather than a fallible API that should never fail in practice. I thought we were already enforcing it, but it looks like some parts were missed (no check in offset() currently), will be fixing that. EDIT: Done in 9250e09.

@akashchamp
akashchamp force-pushed the fix-on-window-panic-885 branch from 5525092 to 6cdce00 Compare September 25, 2026 17:47
Printer::on_window unconditionally .expect()s that the output window
fits the backend buffer, even though PrintBuffer::window() already
documents and returns None for exactly that mismatch (e.g. a terminal
resize between the layout pass and the draw pass). Hitting that
documented None case aborts the whole application instead of
degrading gracefully, unlike print_at/print_with_width, which already
clip to the printable area instead of panicking.

Add Printer::try_on_window<F, R>(&self, f: F) -> Option<R>, following
the try_* convention already used elsewhere in this crate (e.g.
ListView::try_remove, SelectView::try_iter_mut). It skips the closure
and returns None when the window doesn't fit, instead of panicking.
on_window is now implemented in terms of try_on_window and keeps its
existing panicking behavior/documentation for callers who want it.

Switch GradientView's internal use of on_window to try_on_window, so
the one built-in caller of this API degrades gracefully (skips the
gradient overlay for one frame) instead of crashing on a stale-size
race, as described in the issue.

Fixes gyscos#885
@akashchamp
akashchamp force-pushed the fix-on-window-panic-885 branch from 6cdce00 to 5be1d56 Compare October 7, 2026 15:29
@akashchamp

Copy link
Copy Markdown
Author

Thanks for the explanation, and for fixing the root cause in 9250e09. I've corrected the PR description: it no longer claims a resize race, and it now lists the test I ran after rebasing on current main (cargo test -p cursive_core --lib, 93 passed). try_on_window is now only an optional non-panicking alternative to on_window. If you'd rather not add a fallible API, I'm happy to close this.

This branch has not been deployed

No deployments
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.

[BUG] Printer::on_window panics when printer exceeds backend size instead of degrading gracefully

2 participants