From 82f8d3d800d47c444b8b2f5a08918ede38954e46 Mon Sep 17 00:00:00 2001 From: blasty Date: Sat, 25 Jul 2026 10:47:41 +0200 Subject: split: keep the companion pane level with the driver's cursor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scrolling either pane left the other one wherever it happened to be: the companion only scrolled when the linked row went off-screen (reveal()), so the link could sit at the bottom edge while the driver's cursor was mid-viewport — visually incoherent, your eye had to hunt for it. Add ListingView/DecompView.align(row, screen_row): scroll so the linked row lands at the SAME viewport offset as the driver's cursor, and use it in _sync_split for both directions. The two panes now track each other line-for-line, so the eye reads straight across. Best-effort at the ends (can't scroll above line 0, nor past the end when the pseudocode is shorter than the viewport). Pilot split_view: deterministic alignment check — park the listing cursor at a known viewport offset deep in the function, sync, and assert the decomp's scroll top is exactly the aligned value (accounting for both clamps). 19/19; full suite 166/2-flake. --- tests/test_scenarios.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'tests') diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py index 2476b21..d5f710e 100644 --- a/tests/test_scenarios.py +++ b/tests/test_scenarios.py @@ -428,6 +428,25 @@ async def s_split_view(c: Ctx): dl is not None and lea is not None and dec._line_eas[dl] is not None and dec._line_eas[dl] <= lea, f"link_line={dl} lea={hex(lea) if lea else None}") + # the companion pane sits LEVEL with the driver's cursor (visual coherence): + # the linked row lands at the same viewport offset, not merely on-screen. + deep = [i for i, eas in enumerate(m) if eas][10:] + row = lst.model.ensure_ea(m[deep[0]][0]) if (deep and lst.model) else None + if row is not None and row > 12: + lst.scroll_to(y=row - 10, animate=False) + await c.pause(0.2) # let the deferred scroll land + lst.cursor = row # driver cursor now at viewport offset 10 + app._sync_split("listing") + await c.pause(0.2) # let the companion's scroll land + drv = lst.cursor - round(lst.scroll_offset.y) + link, top = dec._link_line, round(dec.scroll_offset.y) + # exact, modulo the unavoidable clamps (can't scroll above line 0, nor + # past the end when the pseudocode is shorter than the viewport) + want = min(max(0, (link or 0) - drv), + max(0, dec.total - dec._visible_height())) + c.check("the companion pane sits level with the driver's cursor", + link is not None and top == want, + f"driver_row={drv} link={link} dec_top={top} want={want}") await c.press("tab") await c.pause(0.1) c.check("Tab in split focuses the pseudocode pane", app._active == "decomp", -- cgit v1.3.1-sl0p