Fix #18: replace 'Continue?' popups with wait-box + Cancel#24
Merged
Conversation
Replace the bare 0/1/2/3 magic numbers in SigMakerPlugin.run with a named IntEnum. Values still mirror the rAction radio-group order so the form mapping is unchanged. Adds TestActionEnum to lock the mapping against accidental reordering.
Previously, InstructionWalker.__next__ raised StopIteration when the user pressed Cancel on the wait box. The generators above caught it as 'iteration finished naturally' and surfaced the confusing 'Signature not unique' error instead of a clean cancellation. UserCanceledError propagates out of make_signature() and is caught by SigMakerPlugin.run's existing handler, which logs 'Operation cancelled by user'.
…d_cancel Previously, should_cancel() only checked its internal _user_canceled flag, which is set when the modal 'Continue?' prompt is dismissed. This meant that pressing Cancel on IDA's wait box was a no-op for the progress reporter even though the underlying flag was set. Add a poll of idaapi_user_canceled() so cancellation works regardless of whether the exponential continue prompts are enabled. Also tighten the TestProgressReporter fixture: with idaapi mocked at module level, idaapi_user_canceled (a top-level wrapper) returns a truthy MagicMock instance by default, which fires the new wait-box poll on every call. Reset it explicitly in setUp.
…inel) Per issue #18 the original requester wanted a Cancel button, not recurring 'Continue?' popups. Default enable_continue_prompt to False and prompt_interval to -1 (the documented sentinel for 'no prompts'). Users can still opt in via the form checkbox. _should_prompt already guards on prompt_interval > 0, so both -1 and 0 disable prompting; -1 is chosen as the canonical sentinel for documentation clarity.
Flip the cGroupOptions default bitmask 13 -> 5 to drop bit 8 (enable_continue_prompt). Wait-box Cancel covers the cancellation need for the default user; the checkbox stays as an opt-in for those who want the periodic 'Continue?' dialog. Tooltip updated to make the trade-off explicit.
Add a numeric field to 'Other options...' so users can configure the wait time before the optional 'Continue?' popup fires, or set -1 to disable the popup entirely (default). Mirrors the existing pattern where ConfigureOptionsForm reads from and writes to SigMakerConfig class attributes.
The XREF and Search code paths already show a wait box with a Cancel button. The CREATE_UNIQUE and COPY_RANGE paths did not, so the user had no way to interrupt a long-running unique-signature generation short of the modal continue prompt (now opt-in). Wrap both branches with the existing ProgressDialog context manager. The cancellation path now reads as: wait-box Cancel -> idaapi_user_canceled() -> InstructionWalker raises UserCanceledError -> caught by SigMakerPlugin.run's existing handler. display() stays outside the with-block so the wait box closes before any console/clipboard output. FIND_XREF already wraps internally and is intentionally left alone.
5143bc8 to
8d319f6
Compare
…parser bukowa reported on issue #18 that the form failed with 'form: error at %/'. IDA Form treats ':' as the label/control delimiter; a colon inside the tooltip (between the # delimiters) confuses the parser and the failure surfaces later when the group terminator %/ is reached. The tooltip I added in #24 was the only one in the file with a colon. Rewrite it without one. Same fix will need to apply to the issue-22 branch's tooltip too.
mahmoudimus
added a commit
that referenced
this pull request
May 27, 2026
* docs: add CHANGELOG.md covering 1.7.0 (#24, #25) Keep a Changelog format. Documents the wait-box cancel UX from issue #18 (PR #24) and the opt-in partial-on-cancel output from issue #22 (PR #25), including the user-visible behavior changes, the new opt-in form controls, and the bug fixes that were folded in along the way. * fix: use US spelling in user-facing cancel message The output line on UserCanceledError was 'Operation cancelled by user' (UK), the only UK-spelled user-visible string left in the plugin. Align with the rest of the codebase which uses 'canceled' throughout (per the comment at line 87). * chore: bump version to 1.7.0 Cuts the 1.7.0 release covering the wait-box cancel UX (#24) and opt-in partial-on-cancel output (#25). See CHANGELOG.md for the full set of user-visible and internal changes.
mahmoudimus
added a commit
that referenced
this pull request
May 27, 2026
Brings in PR #24 (issue #18 cancel), PR #25 (issue #22 partial on cancel), and PR #28 (1.7.0 release). The auto-merge handled src/sigmaker/__init__.py cleanly; tests/unit_test_sigmaker.py had overlapping test-class insertions at the same anchor, resolved by taking main's test file as the base and appending PR #26's three new test classes (TestMinimalFunctionSignatureGenerator, TestActionEnumAddsFunctionSig, TestGeneratedSignatureOrdering) before the if __name__ block.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #18.
Background
The original cancelable-search work I shipped in PR #20 gave users an exponential-backoff modal "Continue?" prompt every 10s/20s/40s of generation.
@bukowareported in the issue that this was "ultra confusing" and clarified the actual ask:This PR delivers that. I kept the exponential-backoff path around as an opt-in for anyone who liked it.
Four bugs I fixed
SigMakerConfigdefaults made popups loud. I had shippedenable_continue_prompt=Trueandprompt_interval=10as defaults, so popups fired 10s into every generation.SignatureMaker.make_signatureinProgressDialog, so there was no Cancel button in the CREATE_UNIQUE and COPY_RANGE modes. The XREF and Search paths were already wrapped.CheckContinuePrompt.should_cancelignored the wait-box flag. It only checked an internal_user_canceledflag and never polledidaapi_user_canceled(), so even if a wait box had been shown, hitting Cancel wouldn't have propagated.InstructionWalker.__next__swallowed cancellations. On cancel it raisedStopIteration("Aborted by user"), which the generators above it read as "ran out of instructions" and reported as the confusing"Signature not unique"error instead of a clean cancellation.Changes
refactor: introduce Action IntEnum for SigMakerPlugin dispatch0/1/2/3magic inSigMakerPlugin.runwithAction.CREATE_UNIQUE / FIND_XREF / COPY_RANGE / SEARCH.fix(walker): raise UserCanceledError on cancel instead of StopIterationexcept UserCanceledErrorhandler.fix(progress): poll idaapi_user_canceled in CheckContinuePrompt.should_cancelfeat: flip SigMakerConfig defaults to off-by-default prompts (-1 sentinel)enable_continue_prompt=False,prompt_interval=-1. I picked-1as the canonical "off" sentinel.feat(form): default 'Enable continue prompt' OFF; clarify tooltipSignatureMakerForm.cGroupOptions.value: 13 to 5 (drops bit 8).feat(form): expose prompt_interval in ConfigureOptionsForm (-1 disables)feat: wrap single/range make_signature in ProgressDialog for cancelNet behavior
Operation cancelled by userlog with no traceback.Verification
tests/unit_test_sigmaker.py)idapro-tests(9.0/9.1)idapro-tests-9.2Zero regressions. The new test coverage I added:
TestActionEnum. LocksActionvalues to the radio order.TestInstructionWalkerCancellation. Cancel raisesUserCanceledError, notStopIteration.TestProgressReporter.test_should_cancel_polls_idaapi_user_canceled+test_should_cancel_returns_false_when_no_cancel. The wait-box poll fires regardless of prompt state, and once flagged it stays canceled.TestSigMakerConfigDefaults. Defaults areenable_continue_prompt=Falseandprompt_interval=-1.Notes
src/sigmaker/__init__.py.ExponentialBackoffTimerand its tests are untouched. The opt-in path is fully intact.