diff options
| author | blasty <blasty@local> | 2026-07-24 21:48:20 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-24 21:48:20 +0200 |
| commit | 41b42e4e7ebb9303e7a861ee8c6d948d8cd813fa (patch) | |
| tree | de39ed2d30e47441839bf7d1911a37e1de025f6e /tests | |
| parent | decomp: fix stuck 'decompiling' spinner when re-opening a loaded function (diff) | |
| download | ida-tui-41b42e4e7ebb9303e7a861ee8c6d948d8cd813fa.tar.gz ida-tui-41b42e4e7ebb9303e7a861ee8c6d948d8cd813fa.tar.xz ida-tui-41b42e4e7ebb9303e7a861ee8c6d948d8cd813fa.zip | |
split-view phase 1: side-by-side listing <-> pseudocode layout
The Ghidra-style dual view, layout + toggle (no cursor sync yet — that's phase 2).
's' (and a "Split view" palette command) toggles a _split mode where the listing
(left) and pseudocode (right) show together, divided by a keyline, one focused.
Entering split loads the listing + decompiles the current function into both
panes; Tab/F5 switches the focused pane; any single-view target (hex, etc.) or 's'
again collapses back to the focused pane.
* app: _split flag; _show_active gains a split branch (both panes, load decomp,
focus active, #panes.split class); action_toggle_split + _enter_split worker;
action_toggle_view switches panes when split; 's' binding + palette entry;
#panes.split ListingView divider CSS.
* docs/SPLIT_VIEW.md: the full design + phased roadmap (the hard part — line<->EA
set mapping via a sweep of cfunc.get_line_item — is scoped for phase 3).
* tests: split_view scenario (enter/load/tab-focus/exit, 5 checks). Also fix
disasm_nav's stale goto-bottom (press ctrl+end; plain 'end' is end-of-line now).
Verified live over RPC (both panes render, Tab flips focus, 's' exits) and pilot
split_view 5/5.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_scenarios.py | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py index 39f8d86..aa0ecbf 100644 --- a/tests/test_scenarios.py +++ b/tests/test_scenarios.py @@ -338,6 +338,32 @@ async def s_command_palette(c: Ctx): await c.wait(lambda: app._active != "hex", 5) +@scenario("split_view") +async def s_split_view(c: Ctx): + app, lst, dec = c.app, c.lst, c.dec + await c.open_biggest("listing") + await c.press("s") + shown = await c.wait(lambda: app._split and lst.display and dec.display, 20) + c.check("'s' enters split view (both panes shown)", shown, + f"split={app._split} lst={lst.display} dec={dec.display}") + loaded = await c.wait(lambda: dec.loaded_ea == app._cur.ea, 25) + c.check("split loads the pseudocode alongside the listing", loaded, + f"loaded={dec.loaded_ea} cur={app._cur.ea if app._cur else None}") + await c.press("tab") + await c.pause(0.1) + c.check("Tab in split focuses the pseudocode pane", app._active == "decomp", + f"active={app._active}") + await c.press("tab") + await c.pause(0.1) + c.check("Tab again focuses the listing pane", app._active == "listing", + f"active={app._active}") + await c.press("s") + gone = await c.wait(lambda: not app._split and lst.display + and not dec.display, 10) + c.check("'s' exits split back to a single view", gone, + f"split={app._split} lst={lst.display} dec={dec.display}") + + @scenario("decomp_fallback") async def s_fallback(c: Ctx): app = c.app @@ -485,8 +511,9 @@ async def s_disasm_nav(c: Ctx): await c.wait(lambda: app._clipboard == cur_line, 10) c.check("Ctrl+Y copies the current code line to the clipboard", bool(cur_line) and app._clipboard == cur_line, f"clip={app._clipboard!r}") - # goto-bottom must not hang on a huge function. - await c.press("end") + # goto-bottom must not hang on a huge function (ctrl+end; plain 'end' now + # moves the cursor to end-of-line). + await c.press("ctrl+end") await c.pause(0.05) c.check("goto-bottom lands near end", view.cursor >= view.total - 1, f"cursor={view.cursor}/{view.total}") |
