From 31f00a82ab992add03dd3891c96a5e6292be2ed2 Mon Sep 17 00:00:00 2001 From: blasty Date: Fri, 24 Jul 2026 16:17:58 +0200 Subject: palette: replace the stock Ctrl+P command palette with real ida-tui actions The Ctrl+P palette was Textual's stock system commands (change theme / take screenshot / quit) -- useless for RE. Add an IdaCommands command Provider and set IdaTui.COMMANDS = {IdaCommands} so the palette lists real actions instead: goto, find symbol, follow, xrefs, toggle disasm/pseudocode, continuous listing, hex, rename, retype, comment, define code/func, make data/string, undefine, toggle opcodes, structs editor, filter, names pane, save, quit -- each with its keybind as help text, fuzzy-searchable. App-level actions run directly; cursor-scoped ones (rename/xrefs/comment/...) are dispatched to the active code view via IdaTui._palette_action (focus + run the view's action_*), so a palette pick does exactly what the key does. Verified live over RPC: 'hex' switches view, 'goto' opens the prompt, 'struct' opens the StructEditor modal, and the stock 'theme' command is gone. Pilot command_palette scenario: Ctrl+P opens it and a command executes (7/7). --- tests/test_scenarios.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'tests/test_scenarios.py') diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py index 1a07fb4..94baf93 100644 --- a/tests/test_scenarios.py +++ b/tests/test_scenarios.py @@ -315,6 +315,29 @@ async def s_palette(c: Ctx): c.check("Esc closes the palette", not isinstance(app.screen, SymbolPalette)) +@scenario("command_palette") +async def s_command_palette(c: Ctx): + app = c.app + await c.open_biggest("listing") + await c.press("ctrl+p") + opened = await c.wait( + lambda: type(app.screen).__name__ == "CommandPalette", 10) + c.check("Ctrl+P opens the command palette", opened, + f"screen={type(app.screen).__name__}") + if not opened: + return + inp = app.screen.query_one(Input) + inp.value = "hex" # filter to the 'Hex view' command + await c.pause(0.5) # let the async search + option list settle + await c.press("enter") + landed = await c.wait(lambda: app._active == "hex", 10) + c.check("a palette command executes (Hex view opens)", landed, + f"active={app._active}") + if landed: + await c.press("backslash") # leave hex + await c.wait(lambda: app._active != "hex", 5) + + @scenario("decomp_fallback") async def s_fallback(c: Ctx): app = c.app -- cgit v1.3.1-sl0p