@@ -30,6 +30,7 @@ import "codemirror/addon/hint/anyword-hint.js";
3030import "codemirror/addon/edit/matchbrackets.js" ;
3131import "./skulpt.min.js" ;
3232import "./skulpt-stdlib.js" ;
33+ import PyflakesCoach from "./coach-python-pyflakes.js" ;
3334// Used by Skulpt.
3435import embed from "vega-embed" ;
3536// Adapt for use outside webpack -- see https://github.com/vega/vega-embed.
@@ -65,6 +66,7 @@ export class ActiveCode extends RunestoneBase {
6566 this . python3 = true ;
6667 this . origElem = orig ;
6768 this . origText = this . origElem . textContent ;
69+ this . codeCoachList = [ ] ; //list of CodeCoaches that will be used to provide feedback
6870 this . divid = opts . orig . id ;
6971 this . code = $ ( orig ) . text ( ) || "\n\n\n\n\n" ;
7072 this . language = $ ( orig ) . data ( "lang" ) ;
@@ -92,7 +94,7 @@ export class ActiveCode extends RunestoneBase {
9294 }
9395 this . output = null ; // create pre for output
9496 this . graphics = null ; // create div for turtle graphics
95- this . codecoach = null ;
97+ this . codecoach = null ; // div for Code Coaches
9698 this . codelens = null ;
9799 this . controlDiv = null ;
98100 this . historyScrubber = null ;
@@ -137,6 +139,12 @@ export class ActiveCode extends RunestoneBase {
137139 this . caption = "ActiveCode" ;
138140 }
139141 this . addCaption ( "runestone" ) ;
142+
143+ //Setup CodeCoaches - add based on language
144+ if ( this . language == "python" || this . language == "python3" ) {
145+ this . codeCoachList . push ( new PyflakesCoach ( ) ) ;
146+ }
147+
140148 setTimeout (
141149 function ( ) {
142150 this . editor . refresh ( ) ;
@@ -274,6 +282,7 @@ export class ActiveCode extends RunestoneBase {
274282 if ( this . logResults ) {
275283 this . logCurrentAnswer ( ) ;
276284 }
285+ this . runCoaches ( ) ;
277286 this . renderFeedback ( ) ;
278287 // The run is finished; re-enable the button.
279288 this . runButton . disabled = false ;
@@ -722,15 +731,11 @@ export class ActiveCode extends RunestoneBase {
722731 } . bind ( this )
723732 ) ;
724733
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
729734 var coachDiv = document . createElement ( "div" ) ;
730735 coachDiv . classList . add ( "alert" , "alert-warning" , "codecoach" ) ;
731736 $ ( coachDiv ) . css ( "display" , "none" ) ;
732737 let coachHead = coachDiv . appendChild ( document . createElement ( "h3" ) ) ;
733- coachHead . textContent = "Code Coach" ;
738+ coachHead . textContent = $ . i18n ( "msg_activecode_code_coach" ) ;
734739 this . outerDiv . appendChild ( coachDiv ) ;
735740 this . codecoach = coachDiv ;
736741
@@ -1222,6 +1227,35 @@ Yet another is that there is an internal error. The internal error message is:
12221227 }
12231228 }
12241229
1230+ async runCoaches ( ) {
1231+ //Run all available code coaches and update code coach div
1232+
1233+ //clear anything after header in codecoach div and hide it
1234+ $ ( this . codecoach ) . children ( ) . slice ( 1 ) . remove ( ) ;
1235+ $ ( this . codecoach ) . css ( "display" , "none" ) ;
1236+
1237+ //get code, run coaches
1238+ let code = await this . buildProg ( false ) ;
1239+ let results = [ ] ;
1240+ for ( let coach of this . codeCoachList ) {
1241+ results . push ( coach . check ( code ) ) ;
1242+ }
1243+
1244+ //once all coaches are done, update div
1245+ Promise . allSettled ( results ) . then ( ( promises ) => {
1246+ for ( let p of promises ) {
1247+ if ( p . status === 'fulfilled' && p . value != null ) {
1248+ let checkDiv = document . createElement ( "div" ) ;
1249+ checkDiv . classList . add ( "python_check_results" ) ;
1250+ let checkPre = checkDiv . appendChild ( document . createElement ( "pre" ) ) ;
1251+ checkPre . textContent = p . value ;
1252+ this . codecoach . append ( checkDiv ) ;
1253+ $ ( this . codecoach ) . css ( "display" , "block" ) ;
1254+ }
1255+ }
1256+ } ) ;
1257+ }
1258+
12251259 renderFeedback ( ) {
12261260 // The python unit test code builds the table as it is running the tests
12271261 // In "normal" usage this is displayed immediately.
@@ -1342,9 +1376,6 @@ Yet another is that there is an internal error. The internal error message is:
13421376 this . saveCode = "True" ;
13431377 $ ( this . output ) . text ( "" ) ;
13441378
1345- //clear anything after header in codecoach
1346- $ ( this . codecoach ) . children ( ) . slice ( 1 ) . remove ( ) ;
1347-
13481379 while ( $ ( `#${ this . divid } _errinfo` ) . length > 0 ) {
13491380 $ ( `#${ this . divid } _errinfo` ) . remove ( ) ;
13501381 }
@@ -1386,9 +1417,6 @@ Yet another is that there is an internal error. The internal error message is:
13861417 queue : false ,
13871418 } ) ;
13881419 }
1389- if ( this . language == "python" || this . language == "python3" ) {
1390- this . checkPythonSyntax ( ) ;
1391- }
13921420 try {
13931421 await Sk . misceval . asyncToPromise ( function ( ) {
13941422 return Sk . importMainWithBody ( "<stdin>" , false , prog , true ) ;
0 commit comments