Support HVP cursor positioning - #34
Conversation
8a35571 to
a58cbf7
Compare
9baf1fb to
e984df3
Compare
| #[test] | ||
| fn horizontal_vertical_position() { | ||
| let mut vt = vt100::Parser::new(5, 10, 0); | ||
|
|
||
| vt.process(b"\x1b[3;7fX"); | ||
| assert_eq!(vt.screen().cell(2, 6).unwrap().contents(), "X"); | ||
| assert_eq!(vt.screen().cursor_position(), (2, 7)); | ||
|
|
||
| vt.process(b"\x1b[fY"); | ||
| assert_eq!(vt.screen().cell(0, 0).unwrap().contents(), "Y"); | ||
| } |
There was a problem hiding this comment.
Optional additions — zero parameters, clamping, and explicit CUP/HVP equivalence. Verified against the 5x10 grid.
| #[test] | |
| fn horizontal_vertical_position() { | |
| let mut vt = vt100::Parser::new(5, 10, 0); | |
| vt.process(b"\x1b[3;7fX"); | |
| assert_eq!(vt.screen().cell(2, 6).unwrap().contents(), "X"); | |
| assert_eq!(vt.screen().cursor_position(), (2, 7)); | |
| vt.process(b"\x1b[fY"); | |
| assert_eq!(vt.screen().cell(0, 0).unwrap().contents(), "Y"); | |
| } | |
| #[test] | |
| fn horizontal_vertical_position() { | |
| let mut vt = vt100::Parser::new(5, 10, 0); | |
| vt.process(b"\x1b[3;7fX"); | |
| assert_eq!(vt.screen().cell(2, 6).unwrap().contents(), "X"); | |
| assert_eq!(vt.screen().cursor_position(), (2, 7)); | |
| vt.process(b"\x1b[fY"); | |
| assert_eq!(vt.screen().cell(0, 0).unwrap().contents(), "Y"); | |
| vt.process(b"\x1b[0;0fZ"); | |
| assert_eq!(vt.screen().cell(0, 0).unwrap().contents(), "Z"); | |
| vt.process(b"\x1b[99;99f"); | |
| assert_eq!(vt.screen().cursor_position(), (4, 9)); | |
| let mut cup = vt100::Parser::new(5, 10, 0); | |
| cup.process(b"\x1b[3;7H"); | |
| let mut hvp = vt100::Parser::new(5, 10, 0); | |
| hvp.process(b"\x1b[3;7f"); | |
| assert_eq!( | |
| cup.screen().cursor_position(), | |
| hvp.screen().cursor_position() | |
| ); | |
| } |
Keeps their grid size, test name and existing four assertions untouched — it only appends. Extensions get accepted far more readily than rewrites.
Every assertion was verified empirically against the patched crate at 5x10:
ESC[3;7fX cell(2,6)="X" cursor=(2,7) ESC[fY cell(0,0)="Y" ESC[0;0fZ cell(0,0)="Z" ESC[99;99f cursor=(4,9) clamps equivalence cup=(2,6) hvp=(2,6)
|
Thanks for this. I hit the same bug from the other direction — btop's box layout collapsing into a single wrapped stream inside a terminal built on this crate — and independently arrived at the identical fix, so this looks right to me. Routing A few notes that might help it land: Related threads. #26 (the issue), this PR, and #36 (another HVP fix) don't currently reference each other, so none of them is discoverable from the others. Cross-linking would save the next person the rediscovery. CHANGELOG. The repo looks like it expects changes to carry their own entry — 7076e0f (the #13 fix) and 062f9de (from an outside contributor) both added one in the same commit as the code. Something like: ## [Unreleased]
### Fixed
* Handle HVP (`CSI f`), which is functionally identical to CUP (`CSI H`).
It was previously dispatched as an unhandled sequence, silently dropping
every cursor movement made by applications that emit it. (#26)Test coverage. Left a suggestion on the test adding zero-parameter handling, out-of-range clamping, and explicit CUP/HVP equivalence. All assertions verified against your 5x10 grid. Optional. The Assertions verified by running them against the patched crate rather than by inspection. |
Thanks! The thing is, we don't know when our PR will get merged 😆 (e.g. #11 ) |
…1240) The daemon's terminal model never applied CSI 'f' (HVP), the ECMA-48 alias of CUP that btop uses for all of its cursor positioning: vt100's dispatch has no 'f' arm, so the sequence fell to unhandled_csi and the output applied as one continuous append. The corrupted model surfaced both in the dash Preview snapshot and on session re-attach, while real terminals (which implement HVP) rendered btop fine. No vt100-lineage crate ships the fix: doy/vt100 is dormant (one commit since July 2025, two duplicate HVP PRs open since then) and the ChrisTitusTech packaging fork adds nothing we use while inheriting the same gap. Switch the dependency back to upstream vt100 0.16.2 and patch it against gominimal/vt100-rust's minimal-patches branch, which carries rezigned's fix from doy/vt100-rust#34 (cherry-picked with authorship, drive-by cleanup dropped). A regression test in session_host asserts both explicit and default-parameter HVP positioning. Refs: #1197
Support HVP cursor positioning
Summary
CSI Ps ; Ps f(HVP) as an alias ofCSI Ps ; Ps H(CUP).canonicalize_params_2.Problem
HVP is the ANSI horizontal and vertical position command. It has the same cursor-positioning behavior as CUP, but the parser only dispatched the
Hfinal byte. Applications that useffor absolute cursor movement therefore had their cursor commands ignored.This is visible with
btop, which uses HVP throughout its redraw output. Ignoring those commands causes drawing payloads to be written sequentially and wrap across rows instead of appearing at their requested coordinates.Fix
Dispatch both final bytes to the existing CUP implementation:
No new screen behavior or parser state is introduced.
Verification
Results: