<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ida-tui.git/docs/SPLIT_VIEW.md, branch main</title>
<subtitle>tui for headless ida</subtitle>
<id>https://git.sl0p.foo/ida-tui.git/atom/docs/SPLIT_VIEW.md?h=main</id>
<link rel='self' href='https://git.sl0p.foo/ida-tui.git/atom/docs/SPLIT_VIEW.md?h=main'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/'/>
<updated>2026-07-24T22:20:37Z</updated>
<entry>
<title>split: follow the decomp across functions as the listing cursor crosses bounds</title>
<updated>2026-07-24T22:20:37Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-07-24T22:20:37Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=b519051ce9ca3f8e0835221643211a8879fd6cd7'/>
<id>urn:sha1:b519051ce9ca3f8e0835221643211a8879fd6cd7</id>
<content type='text'>
The unified listing spans many functions, but the decomp pane was pinned to the
one function it was opened on — scrolling the listing cursor past that function's
bounds stopped syncing. Now _sync_split tracks the decompiled function's ea span
(_split_range, from decomp_map) and, when the listing cursor leaves it, re-points
the decomp pane to the function under the cursor: _resync_decomp (exclusive
worker) -&gt; function_of(ea) -&gt; _apply_resync re-decompiles + reloads the region
map, or just drops the band over data/undefined (keeping the last function).

Pilot split_view: moving the listing cursor into another function re-syncs the
decomp (18/18).
</content>
</entry>
<entry>
<title>split-view phase 4: split-aware status, min-width gate, verified nav</title>
<updated>2026-07-24T21:56:09Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-07-24T21:56:09Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=4cf09c7cebd59f2fcaebafb7d2abfee9b521c50f'/>
<id>urn:sha1:4cf09c7cebd59f2fcaebafb7d2abfee9b521c50f</id>
<content type='text'>
Polish for the split view:
* _split_status(): status line now reads "name @ ea [split · pseudocode line N
  ↔ K insn]" / "[split · listing]" from the focused pane, instead of the
  single-view [pseudocode]/[listing] labels clobbering it. Wired into both
  cursor-moved handlers and _apply_decomp.
* min-width gate: action_toggle_split refuses to enter split below
  _SPLIT_MIN_WIDTH (100 cols) so two usable code panes always have room.
* navigation keeps both panes on the same function: verified (not fixed —
  goto/follow in split already routes _open_entry -&gt; _show_active split branch,
  reloading the listing + decomp + region map for the new function).

Review turned two roadmap items into non-issues: split is a persistent mode
orthogonal to nav entries (back/forward just navigate within split), and search
is already per-focused-pane.

Pilot split_view gains: split-aware status, goto-in-split navigates, and both
panes reload on navigation (16/16). Full suite 157/2-flake. Split view is
feature-complete (phases 1-4).
</content>
</entry>
<entry>
<title>split-view phase 3: rich per-line instruction region highlight</title>
<updated>2026-07-24T21:38:30Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-07-24T21:38:30Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=de2fa194278bb132e23edddd65bdad84f32ec37d'/>
<id>urn:sha1:de2fa194278bb132e23edddd65bdad84f32ec37d</id>
<content type='text'>
The Ghidra "region band": moving the pseudocode cursor now lights up EVERY
instruction that C line owns, not just one.

* server/patch_server.py: new decomp_map tool — sweeps cfunc.get_line_item across
  each pseudocode line's columns and collects the ea from each item's dstr()
  ('EA: desc', matching the /*ea*/ marker source so it aligns with the display
  lines). Returns {addr, lines:[{ea, eas:[...]}]}. (First tried item.get_ea(),
  which reports a different ea and didn't align — dstr() is the right source.)
* domain: Program.decomp_map(ea) -&gt; per-line ea lists, cached by name-gen.
* app: _load_split_map fetches it off-thread into _split_eamap/_split_ea2line;
  _sync_split bands the full instruction region for a C line (decomp drives) and
  uses the exact ea-&gt;line inverse (listing drives), falling back to the single
  marker until the map lands. Maps cleared on leaving split.

Pilot split_view gains: decomp_map returns/aligns with the markers, and a
multi-instruction C line bands &gt;1 listing row (13/13). Full suite 154/2-flake.
The idalib spike ran on the pilot's own worker (the standalone worker kept
getting reaped in this sandbox).
</content>
</entry>
<entry>
<title>split-view phase 2: cursor sync + linked-row highlight</title>
<updated>2026-07-24T20:10:25Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-07-24T20:10:25Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=2d6541a93992790b7013feb3b0756c381f2c8fa6'/>
<id>urn:sha1:2d6541a93992790b7013feb3b0756c381f2c8fa6</id>
<content type='text'>
The Ghidra sync: in split, the focused pane drives and the companion shows a
subtle band (_S_LINK) on the linked location + scrolls it into view. The
companion's cursor never moves (band + scroll only), so there's no echo/
ping-pong and no guard is needed.

* _sync_split(source): listing drives -&gt; DecompView.line_for_ea (largest /*ea*/
  marker &lt;= cursor ea) bands the covering C line; decomp drives -&gt;
  ListingModel.ensure_ea bands the covering instruction row.
* wired into on_listing/decomp_view_cursor_moved (gated on the focused pane),
  the Tab focus-switch (re-link from the new driver), _apply_decomp (link once
  the pseudocode loads) and _apply_enter_split; bands cleared on leaving split.
* ListingView/DecompView gain _link_rows/_link_line + set_link/reveal, a
  render_line apply_style(_S_LINK) band, and DecompView.line_for_ea.

Still single-ea per line (one instruction highlighted) — the full instruction
range is phase 3 (the decomp_map tool). Pilot split_view now covers both sync
directions + that the band actually paints (10/10); full suite 151/2-flake.
</content>
</entry>
<entry>
<title>split-view phase 1: side-by-side listing &lt;-&gt; pseudocode layout</title>
<updated>2026-07-24T19:48:20Z</updated>
<author>
<name>blasty</name>
<email>blasty@local</email>
</author>
<published>2026-07-24T19:48:20Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/ida-tui.git/commit/?id=41b42e4e7ebb9303e7a861ee8c6d948d8cd813fa'/>
<id>urn:sha1:41b42e4e7ebb9303e7a861ee8c6d948d8cd813fa</id>
<content type='text'>
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&lt;-&gt;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.
</content>
</entry>
</feed>
