UNPKG

@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
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(), };