aboutsummaryrefslogtreecommitdiffstats
path: root/idatui/app.py (follow)
Commit message (Collapse)AuthorAgeFilesLines
...
* track pseudocode-view cursor position across jumpsblasty2026-07-091-7/+43
| | | | | | | | | | NavEntry now also stores dec_cursor/dec_cursor_x. DecompView posts a CursorMoved (with the line's /*0xEA*/ address) on move/click; the app keeps the top-of-history pseudocode position current and DecompView.show restores it when returning to a function. So Esc after a jump lands on the exact pseudocode line+column too, independent of the disasm position. pilot suite 38/38.
* preserve cursor line+column in the jump historyblasty2026-07-091-4/+11
| | | | | | | | | NavEntry now stores cursor_x too; the top-of-history position is kept current (line + column) on every disasm cursor move, and DisasmView.load restores the column (clamped once the line is cached). So Esc after a jump lands exactly on the symbol you left from, not the line start. pilot suite 37/37 (adds 'back restores the exact line + column').
* mouse: click to place cursor, double-click to followblasty2026-07-091-0/+32
| | | | | | | | | | | - ColumnCursor.on_click maps the click to a virtual (line, column) via event.get_content_offset (handles padding/border) + scroll_offset, then places the line+column cursor (disasm posts CursorMoved for the status line). - double-click (event.chain>=2) = place cursor + follow the symbol under it, identical to selecting it and pressing Enter. - works in both views (verified: disasm click on 'call sub_XXXX' lands on the exact token; pseudocode click maps columns with no padding). - pilot suite 36/36.
* column cursor: real left/right movement + follow the ref UNDER the cursorblasty2026-07-091-41/+236
| | | | | | | | | | | | | | - ColumnCursor mixin for both views: h/l/left/right, w/b word-hops, 0/$ line ends; block cursor cell + word-under-cursor highlight rendered on the cursor line (region-refresh so it stays cheap). vertical moves clamp the column. - follow/xrefs now use the token under the cursor, so a line with multiple refs follows the one you're pointing at (proven: 'return sub_A(sub_B,..)' -> cursor on sub_B follows sub_B). decomp matches a decompiler ref by exact name; disasm resolves the symbol, falling back to the line's from-xref (address column / hex operands are excluded so the default position still follows the target). - horizontal scroll follows the cursor in the pseudocode view. - dropped the f/b paging aliases (b is now word-back). - pilot suite 34/34.
* xrefs + follow-under-cursor (disasm & pseudocode)blasty2026-07-091-6/+184
| | | | | | | | | | | | | | | - Enter follows the reference under the cursor: disasm uses xref_query(from) to find the code target; pseudocode matches a decompiler ref name on the line. Navigates to the containing function at the exact line (address-history push). - x opens an xrefs popup (XrefsScreen modal): xrefs_to the subject under cursor (call target if any, else the current item); Enter jumps to a referencing site, Esc closes. - domain: Program.function_of (mid-addr -> containing func via lookup_funcs), xrefs_from/xrefs_to (xref_query), Xref model, DisasmModel ea->index map for landing on an exact address. - fix: goto to a mid-function address now lands on the right line (was opening it as a bogus function start). - pilot suite 32/32; domain 17/17.
* function-name filter: incremental + highlight + clearblasty2026-07-091-28/+105
| | | | | | | | | | | | - Incremental client-side filter over the cached function list (no per-keystroke server round-trips): narrows + highlights the matched substring in each name as you type, debounced ~80ms. Substring or glob (*/?), smartcase. - Clear the filter: Esc in the filter box, OR Esc on the focused list, OR empty Enter. Status shows 'filter <q>: N/total'. - streaming pauses while a filter is active; re-applied over the full set once load completes. Row selection resolves the name from the index (cells can now be styled Text). - FunctionIndex.all_loaded(); pilot suite 27/27.
* search UX: visible prompt + incremental (as-you-type) highlightingblasty2026-07-091-13/+90
| | | | | | | | | | | | | - Fix overlap: #search, #status and Footer all docked bottom, and Input defaults to a 3-row bordered widget squeezed into 1 row. Now the search bar is a clean 1-row (border:none) that REPLACES the status line while active (status hidden), so the query is always visible. - Incremental search: highlight all matches + preview-jump from the origin on every keystroke (Input.Changed), not just on submit. Disasm indexes once then each keystroke is instant. Enter keeps; empty Enter repeats last; Esc cancels and restores the origin cursor + status line. - pilot suite 23/23 (adds: bar-visible/no-overlap, incremental-before-Enter, Esc-cancel).
* vim-style search in disasm + pseudocode viewsblasty2026-07-091-7/+244
| | | | | | | | | | | | | - SearchMixin shared by both views: '/' search forward, '?' backward, empty query repeats last; n/N next/prev. Smartcase. All matches highlighted (substring overlay), cursor lands on current match; status shows k/N. - disasm indexes line text lazily in a worker (handles huge funcs); pseudocode has text in hand. Substring highlight via crop/join Strip overlay. - app: bottom search prompt, SearchRequested routing; '/' is context-sensitive (filters when the function table is focused, searches in code views). - gotcha fixed: Textual only merges BINDINGS from DOMNode subclasses, so mixin bindings are ignored -> each view lists SEARCH_BINDINGS explicitly. - pilot suite 20/20 (adds search finds/hl/repeat-fwd/repeat-back).
* fix decompiler highlighting + cursor jankblasty2026-07-091-18/+108
| | | | | | | | | | | | | | | | | | Highlighting: Textual has NO C/C++ tree-sitter grammar (and the syntax extra wasn't installed), so language='cpp' was a silent no-op. Replace TextArea with a virtualized, Pygments-highlighted ScrollView: - idatui/highlight.py: CLexer -> Rich styles, per-line Segment lists - DecompView: lines highlighted ONCE at load, cached as Strips; O(1) scroll Jank: profiling showed our code is ~3.6ms/move (render_line 0.018ms) -- the cost was terminal repaint volume, since every cursor move refreshed the whole ~43-line viewport. Now: - cursor reactive repaint=False (no implicit full refresh) - region-limited refresh: in-place moves repaint only the 2 changed rows (measured 43 -> 2 render_line calls/move), full refresh only on scroll Applied to both DisasmView and DecompView. pilot suite 15/15 (adds highlighting assertion).
* decompiler view: Tab/Shift+Tab toggle disasm<->pseudocode, full bodiesblasty2026-07-091-12/+82
| | | | | | | | | | | - domain.decompile now fetches the FULL body: server caps responses at 50KB and clips strings to 1KB, but caches the full output and exposes it at _meta.ida_mcp.download_url -> we GET that so pseudocode is complete (main: 43257 chars, not a 1KB stub). include_addresses gives per-line /*0xEA*/. - DecompView (read-only TextArea, cpp highlighting best-effort, line numbers) - Tab and Shift+Tab toggle the code pane; lazy decompile in a worker, cached; hard-failures ('decompilation failed') shown gracefully with disasm fallback - pilot suite 14/14 (adds tab->pseudocode, full-body, shift+tab->disasm)
* tui: --open PATH to create/attach a session for an arbitrary binaryblasty2026-07-091-2/+15
| | | | | | | - app: when open_path is set, idb_open (idle_ttl=1e9, long timeout) and pin the returned session; clean status on failure (e.g. non-writable dir) - tui.py: --open flag + usage docs (attach vs open) - verified: --open targets/cat -> new session, 161 funcs loaded
* add Ctrl+B toggle to show/hide the functions paneblasty2026-07-091-0/+10
| | | | | | - action_toggle_functions: collapse/restore left pane, disasm takes full width; focus follows (disasm when hidden, table when shown) - pilot test covers the toggle (11/11)
* Phase 1 TUI: two-pane functions<->disasm, virtualized listing, nav backboneblasty2026-07-091-0/+443
- idatui/app.py: keyboard-first Textual app * FunctionsPanel: lazy-streamed function list (DataTable) with glob filter * DisasmView: line-VIRTUALIZED ScrollView -- paints from domain block cache, background-fetches misses, prefetches neighbors. Proven: 52,120-insn func, jump-to-bottom in 0.31s with only ~6 blocks (~1.5k lines) ever materialized. * address-history nav stack (Enter follow / Esc back); goto by name or 0xADDR * bump_idle_ttl + KeepAlive on startup so the session never idles out * all MCP work on Textual worker threads; UI never blocks - idatui/tui.py: launcher (python -m idatui.tui / console script 'idatui') - tests/test_tui.py: headless Pilot test, 9/9 (boot, load 10k funcs, open, scroll, bg-cache, goto-bottom, filter) - pyproject: textual extra + idatui script entry