@@ -75,8 +75,13 @@ export interface CommandExecutionEventHandler {
75
75
* Callback that is invoked when the command is issued, i.e. sent to the
76
76
* terminal. At this point, the command is probably not yet finished
77
77
* executing.
78
+ *
79
+ * @param shellStillExists Whether the shell still exists after the command
80
+ * was issued. In certain scenarios (e.g. user manually exits the shell
81
+ * during Manim startup), the shell might not exist anymore after the
82
+ * command was issued.
78
83
*/
79
- onCommandIssued ?: ( ) => void ;
84
+ onCommandIssued ?: ( shellStillExists : boolean ) => void ;
80
85
81
86
/**
82
87
* Callback that is invoked when data is received from the active Manim
@@ -292,7 +297,7 @@ export class ManimShell {
292
297
let currentExecutionCount = this . iPythonCellCount ;
293
298
294
299
this . exec ( shell , command ) ;
295
- handler ?. onCommandIssued ?.( ) ;
300
+ handler ?. onCommandIssued ?.( this . activeShell !== null ) ;
296
301
297
302
this . waitUntilCommandFinished ( currentExecutionCount , ( ) => {
298
303
Logger . debug ( "π Command execution unlocked" ) ;
@@ -370,6 +375,10 @@ export class ManimShell {
370
375
/**
371
376
* Resets the active shell such that a new terminal is created on the next
372
377
* command execution.
378
+ *
379
+ * This will also remove all event listeners! Having called this method,
380
+ * you should NOT emit any events anymore before a new Manim shell is
381
+ * detected, as those events would not be caught by any listeners.
373
382
*/
374
383
public resetActiveShell ( ) {
375
384
Logger . debug ( "π« Reset active shell" ) ;
@@ -631,6 +640,29 @@ export class ManimShell {
631
640
this . resetActiveShell ( ) ;
632
641
}
633
642
} ) ;
643
+
644
+ /**
645
+ * This event is fired when a terminal is closed manually by the user.
646
+ * In this case, we can only do our best to clean up since the terminal
647
+ * is probably not able to receive commands anymore. It's mostly for us
648
+ * to reset all states such that we're ready for the next command.
649
+ *
650
+ * When closing while previewing a scene, the terminal is closed, however
651
+ * we are not able to send a keyboard interrupt anymore. Therefore,
652
+ * ManimGL will take a few seconds to actually close its window. When
653
+ * the user employs our "Quit preview" command instead, the preview will
654
+ * be closed immediately.
655
+ */
656
+ window . onDidCloseTerminal ( async ( terminal : Terminal ) => {
657
+ if ( terminal !== this . activeShell ) {
658
+ return ;
659
+ }
660
+ Logger . debug ( "π Active shell closed" ) ;
661
+ this . eventEmitter . emit ( ManimShellEvent . MANIM_NOT_STARTED ) ;
662
+ this . eventEmitter . emit ( ManimShellEvent . KEYBOARD_INTERRUPT ) ;
663
+ this . forceQuitActiveShell ( ) ; // don't await here on purpose
664
+ this . resetActiveShell ( ) ;
665
+ } ) ;
634
666
}
635
667
}
636
668
0 commit comments