@@ -19,12 +19,15 @@ class Python {
1919 $page = null ;
2020 $runBtn = null ;
2121 $wrapBtn = null ;
22+ $status = null ;
2223 $style = null ;
2324 #codes = [ ] ;
2425 #niddle = 0 ;
2526 #inputCount = 0 ;
2627 #state = 0 ;
2728 #initPromise = Promise . resolve ( false ) ;
29+ /** number of code runs still waiting for the worker */
30+ #running = 0 ;
2831
2932 INITIALIZING = 1 ;
3033 INITIALIZED = 2 ;
@@ -46,6 +49,9 @@ class Python {
4649 $page . onhide = ( ) => {
4750 this . #state = this . NOT_INTIALIZED ;
4851 this . #worker?. terminate ( ) ;
52+ // runs on the terminated worker never reply
53+ this . #running = 0 ;
54+ this . #isInput = false ;
4955 this . initWorker ( ) ;
5056 onhide ( ) ;
5157 } ;
@@ -69,10 +75,12 @@ class Python {
6975 this . $wrapBtn = tag ( "span" , {
7076 className : "icon wrap_py" ,
7177 innerHTML : WRAP_ICON ,
72- attr : { action : "toggle-wrap" , title : "Wrap lines" , role : "button" } ,
78+ attr : { action : "toggle-wrap" , role : "button" } ,
7379 onclick : ( ) => this . #setWrap( ! this . $page . classList . contains ( "wrap" ) ) ,
7480 } ) ;
75- this . $page . header ?. append ( this . $wrapBtn ) ;
81+ // Acode's spinner, shown while Python loads or code runs
82+ this . $status = tag ( "span" , { className : "icon hidden" } ) ;
83+ this . $page . header ?. append ( this . $status , this . $wrapBtn ) ;
7684 this . #setWrap( loadWrap ( ) ) ;
7785 this . $style = tag ( "style" , { textContent : style } ) ;
7886 this . $input = tag ( "div" , {
@@ -105,6 +113,7 @@ class Python {
105113
106114 async #startWorker( ) {
107115 this . #state = this . INITIALIZING ;
116+ this . #updateStatus( ) ;
108117 this . $page . settitle ( strings [ "loading..." ] ) ;
109118 this . #worker?. terminate ( ) ;
110119
@@ -135,6 +144,7 @@ class Python {
135144 return false ;
136145 } finally {
137146 this . $page . settitle ( "Python" ) ;
147+ this . #updateStatus( ) ;
138148 }
139149 }
140150
@@ -151,29 +161,45 @@ class Python {
151161 }
152162
153163 async runCode ( code ) {
154- if ( ! ( await this . initWorker ( ) ) ) return ;
155- this . #worker. postMessage ( {
156- action : "run" ,
157- code,
158- } ) ;
164+ this . #running += 1 ;
165+ this . #updateStatus( ) ;
159166 try {
167+ if ( ! ( await this . initWorker ( ) ) ) return ;
168+ this . #worker. postMessage ( {
169+ action : "run" ,
170+ code,
171+ } ) ;
160172 const res = await new Promise ( ( resolve , error ) => {
161173 this . #onRunSuccess = resolve ;
162174 this . #onRunError = error ;
163175 } ) ;
164176 this . print ( res , "output" ) ;
165177 } catch ( error ) {
166178 this . print ( error , "error" ) ;
179+ } finally {
180+ this . #running = Math . max ( 0 , this . #running - 1 ) ;
181+ this . #updateStatus( ) ;
167182 }
168183 }
169184
185+ /** Spinner while Python is busy, hidden while it waits for input() */
186+ #updateStatus( ) {
187+ if ( ! this . $status ) return ;
188+ const busy =
189+ ( this . #state === this . INITIALIZING || this . #running > 0 ) &&
190+ ! this . #isInput;
191+ this . $status . classList . toggle ( "loading" , busy ) ;
192+ this . $status . classList . toggle ( "hidden" , ! busy ) ;
193+ }
194+
170195 destroy ( ) {
171196 if ( this . $runBtn ) {
172197 this . $runBtn . onclick = null ;
173198 this . $runBtn . remove ( ) ;
174199 }
175200
176201 this . $wrapBtn ?. remove ( ) ;
202+ this . $status ?. remove ( ) ;
177203 this . #worker?. terminate ( ) ;
178204 editorManager . off ( "switch-file" , this . checkRunnable . bind ( this ) ) ;
179205 editorManager . off ( "rename-file" , this . checkRunnable . bind ( this ) ) ;
@@ -197,8 +223,6 @@ class Python {
197223 /** Wraps long output lines instead of scrolling them horizontally */
198224 #setWrap( wrap ) {
199225 this . $page . classList . toggle ( "wrap" , wrap ) ;
200- this . $wrapBtn . classList . toggle ( "active" , wrap ) ;
201- this . $wrapBtn . setAttribute ( "aria-pressed" , String ( wrap ) ) ;
202226 saveWrap ( wrap ) ;
203227 }
204228
@@ -253,6 +277,7 @@ class Python {
253277
254278 case "input" :
255279 this . #isInput = true ;
280+ this . #updateStatus( ) ;
256281 if ( text ) this . print ( text ) ;
257282 await this . #cacheFile. writeFile ( "" ) ;
258283 this . $input . get ( "textarea" ) . focus ( ) ;
@@ -324,6 +349,7 @@ class Python {
324349 if ( value . endsWith ( "\n" ) ) {
325350 if ( this . #isInput) {
326351 this . #isInput = false ;
352+ this . #updateStatus( ) ;
327353 value = value . slice ( 0 , - 1 ) ;
328354 this . #cacheFile. writeFile ( `${ value } \0${ this . #inputCount++ } ` ) ;
329355 this . print ( value , "input" ) ;
0 commit comments