diff options
| author | blasty <blasty@local> | 2026-07-09 22:40:29 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-09 22:40:29 +0200 |
| commit | 08cd9409b1d30da6a0439144a295c47c2a021827 (patch) | |
| tree | 674f5296824e529e486a3e48f0c81f3536df42f3 /tests | |
| parent | xrefs: informative labels — function+offset, and section instead of '?' (diff) | |
| download | ida-tui-08cd9409b1d30da6a0439144a295c47c2a021827.tar.gz ida-tui-08cd9409b1d30da6a0439144a295c47c2a021827.tar.xz ida-tui-08cd9409b1d30da6a0439144a295c47c2a021827.zip | |
xrefs: pre-select the site the dialog was invoked from
Opening the xref dialog with 'x' now highlights the entry for the current site
(the instruction/pseudocode line under the cursor), so a long xref list can be
stepped through systematically without losing your place.
Capture the cursor's ea span when 'x' is pressed (disasm: the instruction .. the
next; decomp: the line's /*0xEA*/ anchor .. the next), and pre-select the xref
whose frm matches exactly, else the one within that span. Threaded through
_xrefs_{disasm,decomp} -> _xrefs_present -> XrefsScreen(preselect), which sets
OptionList.highlighted (also scrolls it into view).
Pilot check for the decomp path. full suite 68/68.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_tui.py | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/tests/test_tui.py b/tests/test_tui.py index 567c302..8874c54 100644 --- a/tests/test_tui.py +++ b/tests/test_tui.py @@ -493,6 +493,51 @@ async def run(db): all(x != "?" for x in locs), f"locs={locs[:8]}") await pilot.press("escape") await wait_until(pilot, lambda: not isinstance(app.screen, XrefsScreen), 25) + + # Pre-selection: invoking 'x' at a call SITE highlights that very + # site in the dialog, so a long list can be stepped without losing + # your place. Use the decompiler (the exact-match seam). + bycaller = defaultdict(list) + for x in app.program.xrefs_to(multi.addr): + if x.fn_name and x.type == "code": + bycaller[x.fn_addr].append(x) + csites = next((sorted(v, key=lambda x: x.frm) + for v in bycaller.values() if len(v) >= 2), None) + if csites: + site = csites[len(csites) // 2] + await pilot.press("g") + await pilot.pause(0.1) + for ch in hex(site.fn_addr): + await pilot.press(ch) + await pilot.press("enter") + await wait_until(pilot, lambda: app._cur and app._cur.ea == site.fn_addr, 20) + if app._active != "decomp": + await pilot.press("tab") + await wait_until(pilot, lambda: dec.loaded_ea == site.fn_addr, 25) + li = app._decomp_line_for(site.fn_addr, site.frm) + col = dec._texts[li].find(multi.name) if 0 <= li < len(dec._texts) else -1 + if col >= 0: + dec.focus() + dec.cursor, dec.cursor_x = li, col + 1 + dec.refresh() + await pilot.pause(0.05) + await pilot.press("x") + await wait_until(pilot, lambda: isinstance(app.screen, XrefsScreen), 25) + hl = app.screen.query_one(OptionList).highlighted + it = app.screen._items + check("xref dialog pre-selects the site it was invoked from", + hl is not None and it[hl][0] == site.frm, + f"hl={hl} frm={hex(it[hl][0]) if hl is not None else None} " + f"want={hex(site.frm)}") + await pilot.press("escape") + await wait_until(pilot, lambda: not isinstance(app.screen, XrefsScreen), 25) + else: + check("found the callee token for preselect", False) + if app._active != "disasm": # restore for the following mouse test + await pilot.press("tab") + await wait_until(pilot, lambda: app._active == "disasm", 10) + else: + check("found a caller with multiple sites for preselect", False) else: check("found a function with multiple same-caller xrefs", False) |
