refactor(engine): leave the menu accept rule in one place - #1210
Conversation
93a7c2e to
2a043ad
Compare
| // itself, which is what leaves `Enter` free to reach the line | ||
| // instead of appearing dead. | ||
| match self.menus.iter_mut().find(|menu| menu.is_active()) { | ||
| Some(menu) if !menu.get_values().is_empty() => { |
There was a problem hiding this comment.
Fold the provisional check in here, since this PR makes MenuAccept the only accept path.
With provisional results the splice is refused downstream, but Deactivate still runs and the arm reports Handled, so Enter closes the menu and does nothing else.
Decline when menu.results_are_provisional(), the way MenuNext and decide_menu_completion already refuse a stale accept.
There was a problem hiding this comment.
Folded in. The guard now also declines when menu.results_are_provisional(), so the arm refuses anything it cannot actually splice — an empty menu and a stale one alike — and Enter reaches the line instead of dying against a menu that was never going to accept.
Two cases cover it: MenuAccept over a stale menu reports Inapplicable and leaves the menu open, and Enter over the same menu runs the line as typed. Both fail without the check.
2a043ad to
a809898
Compare
`Enter` grew a guard that accepts an open menu's selection, and `MenuAccept` landed with the same rule written a second way: the guard filters on `is_active() && !get_values().is_empty()`, `MenuAccept` finds the first active menu and checks emptiness after. Nothing can tell them apart today, since `ReedlineEvent::Menu` will not activate a second menu while one is open, but the two are already spelled differently and only one of them is the one anybody reads. `Enter`, `Submit` and `SubmitOrNewline` now offer an open menu first refusal and carry on to the submit path when it declines, which is what the guard was arranging for. The rule lives in the `MenuAccept` arm, and the reasoning that used to sit above `Enter` describing the guard sits with it. That arm is now the only accept path, so it also refuses a provisional answer, the way `MenuNext` and `decide_menu_completion` already do. A stale value is rejected downstream because its span belongs to another line, and accepting one would still deactivate the menu and report the key handled — closing the menu over a completion that never happened, and spending an `Enter` on nothing. Declining hands the key back to the line. The new cases pin all of it from both sides: three submit events accept an open menu and run the line once the menu has nothing to offer, and a stale menu is refused through both `MenuAccept` and `Enter`.
a809898 to
0774bc0
Compare
|
Nice, looks good to land for me. |
Summary
The follow-up from #1175, as suggested there.
Entergrew a guard that accepts an open menu's selection, and #1203 landedMenuAcceptcarrying the same rule a second time. They are not even spelled thesame way: the guard filters on
is_active() && !get_values().is_empty(), whileMenuAcceptfinds the first active menu and checks emptiness afterwards. Thosedisagree when the first active menu is the empty one — unreachable today, since
ReedlineEvent::Menurefuses to activate whileactive_menu()isSome, but it isthe drift worth removing rather than documenting.
Enter,SubmitandSubmitOrNewlinenow tryMenuAcceptfirst and carry on tothe submit path when it declines, which is what the guard was arranging for. The
guarded arm goes away, the rule lives in the
MenuAcceptarm, and each submit armsays plainly that a menu gets first refusal.
Behavior
Unchanged.
MenuAcceptreportsInapplicablefor exactly the cases the guardexcluded — no menu open, or an open menu with nothing to accept — and the
delegation sits at the top of each arm, ahead of the bashisms and abbreviation
expansion, so the ordering is what it was.
Worth noting the guard covered
SubmitandSubmitOrNewlineas well asEnter,and nothing tested that. It does now.
One thing this surfaced, not fixed here
MenuAcceptdoes not checkresults_are_provisional(), so accepting over stalesuggestions splices nothing — the span belongs to another line and is refused
downstream — while
Deactivatestill runs and the arm still reportsHandled. Adead key, reachable with an async completer.
decide_menu_completionandMenuNextboth guard this explicitly and their comments say exactly why.
This is not a regression: the deleted guard had no provisional check either, so
Enterbehaved this way already. But this PR is what makesMenuAcceptthe singlepath, and the rule it now owns is missing a check its two siblings have. Happy to fix
it in a follow-up, or fold it in here if you would rather it not land as-is.
Tests
Two
rstestcases over all three events:every_submit_event_accepts_an_open_menu— the menu takes the keypress, closes,and its selection reaches the buffer
every_submit_event_passes_an_empty_menu— once the menu has nothing to offer,the line runs
Both pass on the two-rule version as well, which is the point: they pin the
behavior, and this does not move it.
cargo fmt --checkandcargo clippy --all-targets --all-features -- -D warningsare clean; the suite passes with default and with all features.