diff options
| -rw-r--r-- | docs/RPC.md | 2 | ||||
| -rw-r--r-- | idatui/app.py | 4 | ||||
| -rw-r--r-- | tests/test_scenarios.py | 16 |
3 files changed, 17 insertions, 5 deletions
diff --git a/docs/RPC.md b/docs/RPC.md index 5cb73ee..4a68fbe 100644 --- a/docs/RPC.md +++ b/docs/RPC.md @@ -81,7 +81,7 @@ predicate so the returned state is final. |--------|--------|--------| | `goto` / `open` | `target`, `delay_ms?`, `timeout?` | `g` prompt → name or `0xADDR` → Enter. | | `rename` | `name`, `word?`, `delay_ms?` | `n` on the token under the cursor → replace → Enter. `word` first places the cursor on that token (see `cursor_on`). | -| `comment` | `text`, `delay_ms?` | `;` on the current line. | +| `comment` | `text`, `delay_ms?` | `;` on the current line (a literal `\n` in `text` becomes a real newline → multi-line comment). | | `retype` | `proto`, `word?`, `delay_ms?` | `y` on the token/function under the cursor (`word` places it first). | | `follow` | `word?` | Enter: follow the reference under the cursor (`word` places it first); waits for the jump. | | `back` | — | Escape: pop the nav stack. | diff --git a/idatui/app.py b/idatui/app.py index 8fc259e..d7bc390 100644 --- a/idatui/app.py +++ b/idatui/app.py @@ -2413,6 +2413,10 @@ class IdaTui(App): @work(thread=True, exclusive=True, group="comment") def _do_comment(self, ea: int, text: str) -> None: assert self.program is not None + # The prompt is single-line, so a literal '\n' (backslash-n) means a real + # newline — Hex-Rays renders each as its own '//' line. Lets long notes + # wrap instead of running off the right edge and clipping. + text = text.replace("\\n", "\n") try: res = self.program.set_comment(ea, text) except IDAToolError as e: diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py index 0cad008..b16cd98 100644 --- a/tests/test_scenarios.py +++ b/tests/test_scenarios.py @@ -1070,11 +1070,19 @@ async def s_comment_func(c: Ctx): c.check("';' on the signature line opens a function-comment prompt", ci.display and "function comment" in str(ci.placeholder).lower(), f"display={ci.display} ph={ci.placeholder!r}") - ci.value = note + # literal '\n' in the comment becomes a real newline -> multi-line render + a, b = f"{note}_A", f"{note}_B" + ci.value = f"{a}\\n{b}" await c.press("enter") - await c.wait(lambda: dec.loaded_ea == fn.addr and any(note in t for t in dec._texts), 25) - c.check("function comment appears in the pseudocode", - any(note in t for t in dec._texts), "not shown") + await c.wait(lambda: dec.loaded_ea == fn.addr + and any(a in t for t in dec._texts) + and any(b in t for t in dec._texts), 25) + la = next((i for i, t in enumerate(dec._texts) if a in t), None) + lb = next((i for i, t in enumerate(dec._texts) if b in t), None) + c.check("multi-line function comment renders on separate lines", + la is not None and lb is not None and lb > la + and a not in dec._texts[lb], + f"la={la} lb={lb}") app.program.client.call("set_comments", items=[{"addr": hex(fn.addr), "comment": ""}]) |
