aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-24 15:21:44 +0200
committerblasty <blasty@local>2026-07-24 15:21:44 +0200
commited60e9ba5d7b3d8dfb81911ba8623e6b5f6cda39 (patch)
tree37dc972e2681ac2aff4a34c496d3f137f8c2473c
parentlisting: <home> jumps the cursor to start-of-line (pairs with <end>) (diff)
downloadida-tui-ed60e9ba5d7b3d8dfb81911ba8623e6b5f6cda39.tar.gz
ida-tui-ed60e9ba5d7b3d8dfb81911ba8623e6b5f6cda39.tar.xz
ida-tui-ed60e9ba5d7b3d8dfb81911ba8623e6b5f6cda39.zip
listing: shift+home jumps to the start of the instruction text
<home> goes to the true start of line (the address); shift+home now lands on the mnemonic, skipping the address + opcode-bytes gutter. _insn_col() mirrors _line_plain()'s prefix (address + indent + opcode field + member indent + name prefix) so the column matches what's rendered; funchdr/label land after the address, sep after the indent. Verified live over RPC: on a code line, <home> -> col 0 (word '0000249A', the address), shift+home -> col 40 (word 'push', the mnemonic).
-rw-r--r--idatui/app.py24
1 files changed, 24 insertions, 0 deletions
diff --git a/idatui/app.py b/idatui/app.py
index 8944966..ce07cd0 100644
--- a/idatui/app.py
+++ b/idatui/app.py
@@ -956,6 +956,7 @@ class ListingView(SearchMixin, NavMixin, ColumnCursor, ScrollView, can_focus=Tru
Binding("pagedown", "page(1)", "PgDn", show=False),
Binding("pageup", "page(-1)", "PgUp", show=False),
Binding("home", "col_home", "bol", show=False),
+ Binding("shift+home", "col_insn_home", "insn start", show=False),
Binding("end", "col_end", "eol", show=False),
Binding("G,ctrl+end", "goto_bottom", "Bottom", show=False),
Binding("ctrl+home", "goto_top", "Top", show=False),
@@ -1033,6 +1034,29 @@ class ListingView(SearchMixin, NavMixin, ColumnCursor, ScrollView, can_focus=Tru
extra = _LST_INDENT if h.kind == "member" else ""
return base + self._op_field(h) + extra + self._name_prefix(h) + h.text
+ def _insn_col(self, idx: int) -> int:
+ """Column where the instruction/content text begins, past the address +
+ opcode-bytes gutter — the shift+home target. Mirrors ``_line_plain``'s
+ prefix so the column lines up with what's rendered."""
+ h = self._head(idx)
+ if h is None:
+ return 0
+ if h.kind in ("funchdr", "label"):
+ return len(f"{h.ea:08X} ")
+ base = f"{h.ea:08X} " + _LST_INDENT
+ if h.kind == "sep":
+ return len(base)
+ extra = _LST_INDENT if h.kind == "member" else ""
+ return len(base + self._op_field(h) + extra + self._name_prefix(h))
+
+ def action_col_insn_home(self) -> None:
+ """shift+home: jump to the start of the instruction text, skipping the
+ address + opcode-bytes gutter (home/0 still go to the true line start)."""
+ self.cursor_x = self._insn_col(self.cursor)
+ self._hscroll()
+ _refresh_lines(self, self.cursor)
+ self._refresh_hl()
+
# -- public API -------------------------------------------------------- #
def load(self, model: ListingModel, name: str, cursor: int = 0,
cursor_x: int = 0, scroll_y: int | None = None,