@@ -63,7 +63,6 @@ export class ActiveCode extends RunestoneBase {
6363 this . containerDiv = opts . orig ;
6464 this . useRunestoneServices = opts . useRunestoneServices ;
6565 this . python3 = true ;
66- this . alignVertical = opts . vertical ;
6766 this . origElem = orig ;
6867 this . origText = this . origElem . textContent ;
6968 this . divid = opts . orig . id ;
@@ -159,7 +158,7 @@ export class ActiveCode extends RunestoneBase {
159158 var linkdiv = document . createElement ( "div" ) ;
160159 linkdiv . id = this . divid . replace ( / _ / g, "-" ) . toLowerCase ( ) ; // :ref: changes _ to - so add this as a target
161160 var codeDiv = document . createElement ( "div" ) ;
162- $ ( codeDiv ) . addClass ( "ac_code_div col-md-12 " ) ;
161+ $ ( codeDiv ) . addClass ( "ac_code_div" ) ;
163162 this . codeDiv = codeDiv ;
164163 this . outerDiv . lang = this . language ;
165164 $ ( this . origElem ) . replaceWith ( this . outerDiv ) ;
@@ -286,7 +285,6 @@ export class ActiveCode extends RunestoneBase {
286285 var ctrlDiv = document . createElement ( "div" ) ;
287286 var butt ;
288287 $ ( ctrlDiv ) . addClass ( "ac_actions" ) ;
289- $ ( ctrlDiv ) . addClass ( "col-md-12" ) ;
290288 // Run
291289 butt = document . createElement ( "button" ) ;
292290 $ ( butt ) . text ( $ . i18n ( "msg_activecode_run_code" ) ) ;
@@ -703,7 +701,7 @@ export class ActiveCode extends RunestoneBase {
703701 // to hold turtle graphics output. We use a div in case the turtle changes from
704702 // using a canvas to using some other element like svg in the future.
705703 var outDiv = document . createElement ( "div" ) ;
706- $ ( outDiv ) . addClass ( "ac_output col-md-12 " ) ;
704+ $ ( outDiv ) . addClass ( "ac_output" ) ;
707705 this . outDiv = outDiv ;
708706 this . output = document . createElement ( "pre" ) ;
709707 this . output . id = this . divid + "_stdout" ;
@@ -723,26 +721,28 @@ export class ActiveCode extends RunestoneBase {
723721 $ ( this . graphics ) . addClass ( "visible-ac-canvas" ) ;
724722 } . bind ( this )
725723 ) ;
726- var clearDiv = document . createElement ( "div" ) ;
727- $ ( clearDiv ) . css ( "clear" , "both" ) ; // needed to make parent div resize properly
728- this . outerDiv . appendChild ( clearDiv ) ;
724+
725+ //Anything that wants to add output to coachdiv can do so after the h3
726+ // all those elements will be cleared with each run and coach display will be
727+ // reset to none. Any component that adds content after a run should set display
728+ // to block to ensure visibility
729+ var coachDiv = document . createElement ( "div" ) ;
730+ coachDiv . classList . add ( "alert" , "alert-warning" , "codecoach" ) ;
731+ $ ( coachDiv ) . css ( "display" , "none" ) ;
732+ let coachHead = coachDiv . appendChild ( document . createElement ( "h3" ) ) ;
733+ coachHead . textContent = "Code Coach" ;
734+ this . outerDiv . appendChild ( coachDiv ) ;
735+ this . codecoach = coachDiv ;
736+
729737 outDiv . appendChild ( this . output ) ;
730738 outDiv . appendChild ( this . graphics ) ;
731739 this . outerDiv . appendChild ( outDiv ) ;
732740 var lensDiv = document . createElement ( "div" ) ;
741+ lensDiv . classList . add ( "codelens" ) ;
733742 lensDiv . id = `${ this . divid } _codelens` ;
734- $ ( lensDiv ) . addClass ( "col-md-12" ) ;
735743 $ ( lensDiv ) . css ( "display" , "none" ) ;
736744 this . codelens = lensDiv ;
737745 this . outerDiv . appendChild ( lensDiv ) ;
738- var coachDiv = document . createElement ( "div" ) ;
739- $ ( coachDiv ) . addClass ( "col-md-12" ) ;
740- $ ( coachDiv ) . css ( "display" , "none" ) ;
741- this . codecoach = coachDiv ;
742- this . outerDiv . appendChild ( coachDiv ) ;
743- clearDiv = document . createElement ( "div" ) ;
744- $ ( clearDiv ) . css ( "clear" , "both" ) ; // needed to make parent div resize properly
745- this . outerDiv . appendChild ( clearDiv ) ;
746746 }
747747
748748 disableSaveLoad ( ) {
@@ -911,38 +911,6 @@ export class ActiveCode extends RunestoneBase {
911911 div_id : this . divid ,
912912 } ) ;
913913 }
914- // <iframe id="%(divid)s_codelens" width="800" height="500" style="display:block"src="#">
915- // </iframe>
916- showCodeCoach ( ) {
917- var myIframe ;
918- var srcURL ;
919- var cl ;
920- var div_id = this . divid ;
921- if ( this . codecoach === null ) {
922- this . codecoach = document . createElement ( "div" ) ;
923- this . codecoach . style . display = "block" ;
924- }
925- cl = this . codecoach . firstChild ;
926- if ( cl ) {
927- this . codecoach . removeChild ( cl ) ;
928- }
929- srcURL = eBookConfig . app + "/admin/diffviewer?divid=" + div_id ;
930- myIframe = document . createElement ( "iframe" ) ;
931- myIframe . setAttribute ( "id" , div_id + "_coach" ) ;
932- myIframe . setAttribute ( "width" , "100%" ) ;
933- myIframe . setAttribute ( "height" , "500px" ) ;
934- myIframe . setAttribute ( "style" , "display:block" ) ;
935- myIframe . style . background = "#fff" ;
936- myIframe . style . width = "100%" ;
937- myIframe . src = srcURL ;
938- this . codecoach . appendChild ( myIframe ) ;
939- $ ( this . codecoach ) . show ( ) ;
940- this . logBookEvent ( {
941- event : "coach" ,
942- act : "view" ,
943- div_id : this . divid ,
944- } ) ;
945- }
946914
947915 toggleEditorVisibility ( ) { }
948916
@@ -1303,6 +1271,51 @@ Yet another is that there is an internal error. The internal error message is:
13031271 }
13041272 }
13051273
1274+ async checkPythonSyntax ( ) {
1275+ let code = this . editor . getValue ( ) ;
1276+ fetch ( '/ns/coach/python_check' , {
1277+ method : 'POST' ,
1278+ body : code
1279+ } )
1280+ . then ( ( response ) => {
1281+ return response . json ( ) ;
1282+ } )
1283+ . then ( ( data ) => {
1284+ if ( data . trim ( ) !== '' ) {
1285+ //clean up returned text
1286+ let errorLines = data . split ( "\n" ) ;
1287+ let codeLines = code . split ( "\n" ) ;
1288+ let message = "" ;
1289+ for ( let line of errorLines ) {
1290+ if ( line . indexOf ( ".py:" ) != - 1 ) {
1291+ //old pyflakes returns "file:line:col error"
1292+ //new pyflakes returns "file:line:col: error"
1293+ //handle either
1294+ const cleaner = / [ ^ . ] * .p y : ( \d + ) : ( \d + ) : ? ( .* ) / i;
1295+ let lineParts = line . match ( cleaner )
1296+ message += "Line " + lineParts [ 1 ] + ": " + lineParts [ 3 ] + "\n" ;
1297+ message += codeLines [ lineParts [ 1 ] - 1 ] + "\n" ;
1298+ message += " " . repeat ( lineParts [ 2 ] - 1 ) + "^\n" ;
1299+ } else {
1300+ message += line + "\n" ;
1301+ }
1302+ }
1303+ message = message . slice ( 0 , - 1 ) ; //remove trailing newline
1304+
1305+ //Render
1306+ let checkDiv = document . createElement ( "div" ) ;
1307+ checkDiv . classList . add ( "python_check_results" ) ;
1308+ let checkPre = checkDiv . appendChild ( document . createElement ( "pre" ) ) ;
1309+ checkPre . textContent = message ;
1310+ this . codecoach . append ( checkDiv ) ;
1311+ $ ( this . codecoach ) . css ( "display" , "block" ) ;
1312+ }
1313+ } )
1314+ . catch ( err => {
1315+ console . log ( "Error with ajax python check:" , err ) ;
1316+ } ) ;
1317+ }
1318+
13061319 /* runProg has several async elements to it.
13071320 * 1. Skulpt runs the python program asynchronously
13081321 * 2. The history is restored asynchronously
@@ -1328,6 +1341,10 @@ Yet another is that there is an internal error. The internal error message is:
13281341 var prog = await this . buildProg ( true ) ;
13291342 this . saveCode = "True" ;
13301343 $ ( this . output ) . text ( "" ) ;
1344+
1345+ //clear anything after header in codecoach
1346+ $ ( this . codecoach ) . children ( ) . slice ( 1 ) . remove ( ) ;
1347+
13311348 while ( $ ( `#${ this . divid } _errinfo` ) . length > 0 ) {
13321349 $ ( `#${ this . divid } _errinfo` ) . remove ( ) ;
13331350 }
@@ -1369,6 +1386,9 @@ Yet another is that there is an internal error. The internal error message is:
13691386 queue : false ,
13701387 } ) ;
13711388 }
1389+ if ( this . language == "python" || this . language == "python3" ) {
1390+ this . checkPythonSyntax ( ) ;
1391+ }
13721392 try {
13731393 await Sk . misceval . asyncToPromise ( function ( ) {
13741394 return Sk . importMainWithBody ( "<stdin>" , false , prog , true ) ;
0 commit comments