@@ -182,6 +182,29 @@ def _mode_effects(mode: PromptMode) -> tuple[PromptEffect, ...]:
182182 return SelectCompleter (mode ), SetEraseWhenDone (mode is PromptMode .AGENT ), Invalidate ()
183183
184184
185+ def _suspend_restore_effects (
186+ old_active : ModalState | None ,
187+ new_active : ModalState | None ,
188+ suspended : Document | None ,
189+ document : Document ,
190+ ) -> tuple [Document | None , tuple [PromptEffect , ...]]:
191+ """Compute the suspended-document/effects transition shared by modal
192+ attach and detach: suspend the live input when a hides-input modal takes
193+ over, restore it when the last such modal leaves."""
194+ old_hides_input = old_active is not None and old_active .hides_input
195+ new_hides_input = new_active is not None and new_active .hides_input
196+ if not old_hides_input and new_hides_input and document .text :
197+ if suspended is None :
198+ return document , (SuspendDocument (document ),)
199+ return suspended , ()
200+ if old_hides_input and not new_hides_input and suspended is not None :
201+ effects : tuple [PromptEffect , ...] = (
202+ (RestoreDocument (suspended ),) if not document .text else ()
203+ )
204+ return None , effects
205+ return suspended , ()
206+
207+
185208def transition (state : PromptState , event : PromptEvent ) -> PromptTransition :
186209 """Return the next prompt state and ordered facade effects without doing I/O."""
187210 if isinstance (event , TurnStarting ):
@@ -231,18 +254,9 @@ def transition(state: PromptState, event: PromptEvent) -> PromptTransition:
231254 ModalState (event .delegate , event .priority , event .hides_input ),
232255 )
233256 new_active = _active_modal (stack )
234- suspended = state .suspended_document
235- effects : tuple [PromptEffect , ...] = ()
236- old_hides_input = old_active is not None and old_active .hides_input
237- new_hides_input = new_active is not None and new_active .hides_input
238- if not old_hides_input and new_hides_input and event .document .text :
239- if suspended is None :
240- suspended = event .document
241- effects = (SuspendDocument (event .document ),)
242- elif old_hides_input and not new_hides_input and suspended is not None :
243- if not event .document .text :
244- effects = (RestoreDocument (suspended ),)
245- suspended = None
257+ suspended , effects = _suspend_restore_effects (
258+ old_active , new_active , state .suspended_document , event .document
259+ )
246260 next_state = replace (
247261 state ,
248262 modal_stack = stack ,
@@ -257,18 +271,9 @@ def transition(state: PromptState, event: PromptEvent) -> PromptTransition:
257271 old_active = _active_modal (state .modal_stack )
258272 stack = tuple (modal for modal in state .modal_stack if modal .delegate is not event .delegate )
259273 new_active = _active_modal (stack )
260- suspended = state .suspended_document
261- effects : tuple [PromptEffect , ...] = ()
262- old_hides_input = old_active is not None and old_active .hides_input
263- new_hides_input = new_active is not None and new_active .hides_input
264- if not old_hides_input and new_hides_input and event .document .text :
265- if suspended is None :
266- suspended = event .document
267- effects = (SuspendDocument (event .document ),)
268- elif old_hides_input and not new_hides_input and suspended is not None :
269- if not event .document .text :
270- effects = (RestoreDocument (suspended ),)
271- suspended = None
274+ suspended , effects = _suspend_restore_effects (
275+ old_active , new_active , state .suspended_document , event .document
276+ )
272277 next_state = replace (state , modal_stack = stack , suspended_document = suspended )
273278 return PromptTransition (next_state , (* effects , Invalidate ()))
274279
0 commit comments