aboutsummaryrefslogtreecommitdiffstats
path: root/idatui
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-10 13:02:05 +0200
committerblasty <blasty@local>2026-07-10 13:02:05 +0200
commitae3399da08a54e3ecdc8b4c3e622efbf54b55dae (patch)
treebbe05236c8e077fe39dd276e012839c9048bccfc /idatui
parentstruct editor: loud save errors + guard unsaved edits (diff)
downloadida-tui-ae3399da08a54e3ecdc8b4c3e622efbf54b55dae.tar.gz
ida-tui-ae3399da08a54e3ecdc8b4c3e622efbf54b55dae.tar.xz
ida-tui-ae3399da08a54e3ecdc8b4c3e622efbf54b55dae.zip
struct editor: auto-format the definition on save
After a successful declare, re-fetch the canonical struct_source and put it back in the editor, so the normalized layout/types show immediately instead of only after re-selecting the struct from the list (e.g. a pasted one-liner becomes multi-line, 'unsigned long' -> 'unsigned __int64'). _loaded_src is updated to the formatted text so it isn't considered dirty. Pilot check. full suite 92/92.
Diffstat (limited to 'idatui')
-rw-r--r--idatui/app.py21
1 files changed, 18 insertions, 3 deletions
diff --git a/idatui/app.py b/idatui/app.py
index 271d8f7..32a0698 100644
--- a/idatui/app.py
+++ b/idatui/app.py
@@ -1334,9 +1334,18 @@ class StructEditor(ModalScreen):
return
m = re.search(r"\b(?:struct|union)\s+([A-Za-z_]\w*)", text)
name = m.group(1) if m else None
- self.app.call_from_thread(self._after_save, name, err, text)
+ # On success, pull the canonical source back so the editor shows the
+ # normalized layout/types (auto-format on save).
+ formatted = None
+ if not err and name:
+ try:
+ formatted = self._program.struct_source(name)
+ except Exception: # noqa: BLE001
+ formatted = None
+ self.app.call_from_thread(self._after_save, name, err, text, formatted)
- def _after_save(self, name: str | None, err: str | None, text: str) -> None:
+ def _after_save(self, name: str | None, err: str | None, text: str,
+ formatted: str | None) -> None:
if err:
# IDA's parse error is usually empty/cryptic; name the likely cause.
msg = err.strip()
@@ -1348,7 +1357,13 @@ class StructEditor(ModalScreen):
self._set_status(f"save failed — {msg}", error=True)
return
self._loaded = name
- self._loaded_src = text.strip() # editor now matches the saved type
+ if formatted:
+ # Reformat the editor to IDA's canonical layout (keeps cursor at top).
+ ta = self.query_one("#se-edit", TextArea)
+ ta.text = formatted
+ self._loaded_src = formatted
+ else:
+ self._loaded_src = text.strip() # editor already matches the saved type
if getattr(self.app, "_dirty", None) is not None:
self.app._dirty = True # unsaved-to-disk until Ctrl+S in the app
self._refresh(select=name)