Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit bb628d7

Browse files
Request pyflakes info from server and render to page on Python activecode run
1 parent ec49e57 commit bb628d7

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

runestone/activecode/css/activecode.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@
7474
background-color: lightgray;
7575
}
7676

77+
.python_check_results {
78+
margin-top: 20px;
79+
padding-top: 0px;
80+
padding-bottom: 0px;
81+
}
82+
83+
.python_check_results pre {
84+
background-color: #f5f5f5;
85+
}
86+
7787
.ac_caption {
7888
text-align: center;
7989
font-weight: bold;

runestone/activecode/js/activecode.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,61 @@ Yet another is that there is an internal error. The internal error message is:
13031303
}
13041304
}
13051305

1306+
async checkPythonSyntax() {
1307+
let checkDiv = this.outerDiv.querySelector("div.python_check_results");
1308+
if( checkDiv != null )
1309+
checkDiv.remove();
1310+
1311+
let code = this.editor.getValue();
1312+
1313+
fetch('http://localhost/ns/books/python_check', {
1314+
method: 'POST',
1315+
body: code
1316+
})
1317+
.then((response) => {
1318+
return response.json();
1319+
})
1320+
.then((data) => {
1321+
if(data.trim() !== '') {
1322+
//clean up returned text
1323+
let errorLines = data.split("\n");
1324+
let codeLines = code.split("\n");
1325+
let message = "";
1326+
for(let line of errorLines) {
1327+
if(line.indexOf(".py:") != -1) {
1328+
//old pyflakes returns "file:line:col error"
1329+
//new pyflakes returns "file:line:col: error"
1330+
//handle either
1331+
const cleaner = /[^.]*.py:(\d+):(\d+):? (.*)/i;
1332+
let lineParts = line.match(cleaner)
1333+
message += "Line " + lineParts[1] + ": " + lineParts[3] + "\n";
1334+
message += codeLines[lineParts[1] - 1] + "\n";
1335+
message += " ".repeat(lineParts[2] - 1) + "^\n";
1336+
} else {
1337+
message += line + "\n";
1338+
}
1339+
}
1340+
message = message.slice(0,-1); //remove trailing newline
1341+
1342+
//Render
1343+
checkDiv = document.createElement("div");
1344+
checkDiv.classList.add("python_check_results","alert", "alert-warning");
1345+
let checkHead = checkDiv.appendChild(document.createElement("h3"));
1346+
checkHead.textContent = "Syntax tips:";
1347+
let checkPre = checkDiv.appendChild(document.createElement("pre"));
1348+
//checkPre.classList.add("alert-warning");
1349+
checkPre.textContent = message;
1350+
1351+
//Squeeze check_results right before output pane
1352+
const outDiv = this.outDiv;
1353+
outDiv.parentNode.insertBefore(checkDiv, outDiv);
1354+
}
1355+
})
1356+
.catch(err => {
1357+
console.log("Error with ajax python check:", err);
1358+
});
1359+
}
1360+
13061361
/* runProg has several async elements to it.
13071362
* 1. Skulpt runs the python program asynchronously
13081363
* 2. The history is restored asynchronously
@@ -1369,6 +1424,9 @@ Yet another is that there is an internal error. The internal error message is:
13691424
queue: false,
13701425
});
13711426
}
1427+
if (this.language == "python" || this.language == "python3") {
1428+
this.checkPythonSyntax();
1429+
}
13721430
try {
13731431
await Sk.misceval.asyncToPromise(function () {
13741432
return Sk.importMainWithBody("<stdin>", false, prog, true);

0 commit comments

Comments
 (0)