diff options
| author | blasty <blasty@local> | 2026-07-23 22:52:54 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-23 22:52:54 +0200 |
| commit | 1540b3904dbf605a881121f9571a1b021168af00 (patch) | |
| tree | 038b40ec04978c7feaf3039a274226a5bd81d86f | |
| parent | fix: Tab back from a decomp jump returns to the listing cleanly (diff) | |
| download | ida-tui-1540b3904dbf605a881121f9571a1b021168af00.tar.gz ida-tui-1540b3904dbf605a881121f9571a1b021168af00.tar.xz ida-tui-1540b3904dbf605a881121f9571a1b021168af00.zip | |
fix: Tab decomp->listing reuses the nav entry so edits stay put
The previous fix reopened the listing via _goto_ea(push=False), which made _cur a
DETACHED entry (not _nav[-1]). Cursor moves update _nav[-1], so _cur.cursor went
stale: after moving to a label and renaming it, _reload_active_code ->
_open_entry(cur) restored the stale cursor and scrolled the just-renamed label
off-screen. The rename actually applied (model showed the new name) but the view
jumped away, so it looked like it "didn't propagate".
Now Tab from a jumped-to pseudocode view converts the CURRENT entry (which is
_nav[-1]) to a listing view in place (_toggle_to_listing): set view="listing",
position at the current line's address, and reopen. Cursor moves keep updating
the same entry, so a subsequent rename reloads at the cursor and the renamed
label stays on screen.
Verified: decomp jump -> Tab -> move to loc_ label -> rename: cursor stays on the
label, which now shows the new name (00002040 ZZLABEL:) in the viewport.
view_toggle/decomp_nav/decomp_follow_self/follow_xrefs/xref_labels/rename/
rename_history/disasm_nav/search/mouse/listing_view/continuous_view/func_banners/
scroll_restore 70/0.
| -rw-r--r-- | idatui/app.py | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/idatui/app.py b/idatui/app.py index e06d2c8..c4cae93 100644 --- a/idatui/app.py +++ b/idatui/app.py @@ -2611,18 +2611,38 @@ class IdaTui(App): self._active = "listing" self._open_entry(ret, push=False) elif self._cur is not None: - # No F5 snapshot (we arrived via a decomp navigation): open the - # listing at the current pseudocode line's address, as a real listing - # view — otherwise we'd show a stale widget with _cur.view still - # "decomp", and the next edit would bounce back to the decompiler. + # No F5 snapshot (we arrived via a decomp navigation): show THIS entry + # in the listing at the current pseudocode line's address. Reuse the + # entry (it is _nav[-1]) rather than spawning a detached one, so cursor + # moves keep updating it and a later edit reloads at the right spot. dec = self.query_one(DecompView) ea = dec._line_ea(dec.cursor) - self._goto_ea(ea if ea is not None else self._cur.ea, push=False) + self._toggle_to_listing(ea if ea is not None else self._cur.ea) else: self._active = "listing" self._show_active() @work(thread=True, group="nav") + def _toggle_to_listing(self, ea: int) -> None: + assert self.program is not None + lm = self.program.listing(ea) + idx = max(lm.ensure_ea(ea), 0) if lm is not None else 0 + self.app.call_from_thread(self._apply_toggle_listing, idx) + + def _apply_toggle_listing(self, idx: int) -> None: + cur = self._cur + if cur is None: + self._active = "listing" + self._show_active() + return + cur.view = "listing" + cur.cursor = idx + cur.cursor_x = 0 + cur.scroll_y = -1 # derive a viewport (keeps the target in context) + self._active = "listing" + self._open_entry(cur, push=False) + + @work(thread=True, group="nav") def _decomp_from_listing(self, ea: int) -> None: assert self.program is not None fn = self.program.function_of(ea) |
