Skip to content

fix(painter): keep the cursor position query off the tty in tests - #1156

Open
kronberger-droid wants to merge 1 commit into
nushell:mainfrom
kronberger-droid:fix/painter-cursor-query-in-tests
Open

fix(painter): keep the cursor position query off the tty in tests#1156
kronberger-droid wants to merge 1 commit into
nushell:mainfrom
kronberger-droid:fix/painter-cursor-query-in-tests

Conversation

@kronberger-droid

Copy link
Copy Markdown
Collaborator

Summary

Painter already routes all writes through W so tests don't hit the terminal, since crossterm bypasses libtest's capture.
The read side slipped through: four cursor::position() calls went straight to crossterm.
Any test that painted with a stale anchor (every deferred-completion test does, via invalidate_anchor_if_host_completer_runs) sent ESC[6n to the real tty and waited on crossterm's timeout, serialized behind its global reader lock.
Locally that shows as a_lone_late_suggestion_is_accepted_rather_than_spliced has been running for over 60 seconds until a keypress completes the cooked-mode line; on CI without a tty the read loop never returns.

W gets a cursor_position() that delegates for Terminal and returns an error for the test writers, which is the branch those paints already took after the timeout, thus no test semantics moved.
The one-off #[cfg(not(test))] around the resize query is gone with it.

No public API change, no behavior change on the terminal.

Additional notes

Full cargo test --lib with stdin closed: 1487 passed in 0.02s, no keypress needed.
Follow-up: (column, row) and the other painter tuples could use a small CursorPos-style type.

crossterm queries the file descriptor directly, bypassing libtest's
capture, so every test that painted with a stale anchor sent `ESC[6n`
to the real terminal and blocked on crossterm's timeout, serialized
behind its global reader lock. A full run could stall for a minute
until a keypress completed the cooked-mode line; on CI without a tty
the read loop never returns.

`cursor::position()` now goes through the painter's writer. The test
writers answer with an error, which is the branch those paints already
took after the timeout. The one-off `cfg(not(test))` around the resize
query goes away with it.
@fdncred

fdncred commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Is this the cause to the ESC[6n we see sometimes? We have people report these not knowing what it is because the terminal/nushell is reporting the cursor position.

@kronberger-droid

Copy link
Copy Markdown
Collaborator Author

Well I don't know, my starting point was a blocking test which was using the sink, waiting for a cursor position.

Do we have an issue on the ESC[6n then i check it out.

@fdncred

fdncred commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

We probably do in nushell but I doubt it contains the string ESC[6n. I think this is one of them https://github.com/nushell/nushell/issues/15312
another maybe https://github.com/nushell/nushell/issues/17473
another https://github.com/nushell/nushell/issues/11950
https://github.com/nushell/nushell/issues/13570

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.

2 participants