@webwriter/code
Version:
Write and run code as a code cell. Supports several languages (HTML/CSS/JS, TypeScript, Python).
100 lines (88 loc) • 3.42 kB
text/typescript
import { pythonLanguage } from '@codemirror/lang-python';
import { CompletionContext, snippetCompletion } from '@codemirror/autocomplete';
import { LanguageSupport } from '@codemirror/language';
import Code from '../ww-code-python';
import workerurl from './pyWorker'
const pyodideWorker: Worker = new Worker(workerurl, {type: "classic"})
const callbacks: object = {};
pyodideWorker.onmessage = (event) => {
const { id, ...data } = event.data;
const onSuccess = callbacks[id];
delete callbacks[id];
onSuccess(data);
};
const asyncRun = (() => {
let id = 0;
return (script: any, context: any) => {
id = (id + 1) % Number.MAX_SAFE_INTEGER;
return new Promise((onSuccess) => {
callbacks[id] = onSuccess;
pyodideWorker.postMessage({
...context,
python: script,
id,
});
});
};
})();
//define the autocompletion for python
//these are probably not all the keywords
function pythonCompletions(context: CompletionContext) {
let word = context.matchBefore(/\w*/);
if (word?.from == word?.to && !context.explicit) return null;
return {
from: word?.from,
options: [
{ label: 'match', type: 'keyword' },
{ label: 'case', type: 'keyword' },
{ label: 'class', type: 'keyword' },
{ label: 'def', type: 'keyword' },
{ label: 'for', type: 'keyword' },
{ label: 'if', type: 'keyword' },
{ label: 'lambda', type: 'keyword' },
{ label: 'try', type: 'keyword' },
{ label: 'while', type: 'keyword' },
{ label: 'with', type: 'keyword' },
{ label: 'yield', type: 'keyword' },
{ label: 'and', type: 'keyword' },
{ label: 'as', type: 'keyword' },
{ label: 'assert', type: 'keyword' },
{ label: 'break', type: 'keyword' },
{ label: 'continue', type: 'keyword' },
{ label: 'del', type: 'keyword' },
{ label: 'elif', type: 'keyword' },
{ label: 'else', type: 'keyword' },
{ label: 'except', type: 'keyword' },
{ label: 'finally', type: 'keyword' },
{ label: 'from', type: 'keyword' },
{ label: 'global', type: 'keyword' },
{ label: 'return', type: 'keyword' },
//this way you can add your own snippets
snippetCompletion('range(${variable})', {
label: 'range',
detail: 'definition',
type: 'keyword',
}),
],
};
}
const executePython = async (code: string, context: Code) => {
let res: object = await asyncRun(code, "undefiend") as object
if(typeof res["error"] != "undefined"){
let errText: string = "File "+res["error"].split("File").pop()
context.results.push({text: errText, color: "red"})
}else{
context.results.push({text: res["results"], color: "0x0000"})
}
// console.log(res)
return "res"
};
//add the autocompletion to the language function
function python() {
return new LanguageSupport(pythonLanguage, [pythonLanguage.data.of({ autocomplete: pythonCompletions })]);
}
export const pythonModule = {
name: 'Python',
executionFunction: executePython,
languageExtension: python(),
};