diff --git a/wasm/demo/package.json b/wasm/demo/package.json
index 321bef0902..2184c6db84 100644
--- a/wasm/demo/package.json
+++ b/wasm/demo/package.json
@@ -4,7 +4,8 @@
"description": "Bindings to the RustPython library for WebAssembly",
"main": "index.js",
"dependencies": {
- "codemirror": "^5.42.0"
+ "codemirror": "^5.42.0",
+ "xterm": "^3.8.0"
},
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "0.2.0",
diff --git a/wasm/demo/src/index.ejs b/wasm/demo/src/index.ejs
index 0cb2def1d5..a2a02d214b 100644
--- a/wasm/demo/src/index.ejs
+++ b/wasm/demo/src/index.ejs
@@ -30,6 +30,9 @@
Standard Output
+ Interactive shell
+
+
Here's some info regarding the rp.pyEval()
function
-
diff --git a/wasm/demo/src/index.js b/wasm/demo/src/index.js
index bf5257df2a..9b58afe398 100644
--- a/wasm/demo/src/index.js
+++ b/wasm/demo/src/index.js
@@ -1,5 +1,6 @@
import './style.css';
import 'codemirror/lib/codemirror.css';
+import 'xterm/dist/xterm.css';
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `index.js` file does the single async import, so
diff --git a/wasm/demo/src/main.js b/wasm/demo/src/main.js
index 0735f8d227..2f6de563d1 100644
--- a/wasm/demo/src/main.js
+++ b/wasm/demo/src/main.js
@@ -2,6 +2,7 @@ import * as rp from '../../lib/pkg';
import CodeMirror from 'codemirror';
import 'codemirror/mode/python/python';
import 'codemirror/addon/comment/comment';
+import { Terminal } from 'xterm';
// so people can play around with it
window.rp = rp;
@@ -72,3 +73,58 @@ snippets.addEventListener('change', updateSnippet);
// Run once for demo (updateSnippet b/c the browser might try to keep the same
// option selected for the `select`, but the textarea won't be updated)
updateSnippet();
+
+const prompt = ">>>>> ";
+
+const term = new Terminal();
+term.open(document.getElementById('terminal'));
+term.write(prompt);
+
+function removeNonAscii(str) {
+ if ((str===null) || (str===''))
+ return false;
+ else
+ str = str.toString();
+
+ return str.replace(/[^\x20-\x7E]/g, '');
+}
+
+function printToConsole(data) {
+ term.write(removeNonAscii(data) + "\r\n");
+}
+
+const terminalVM = rp.vmStore.init("term_vm");
+terminalVM.setStdout(printToConsole);
+
+var input = "";
+term.on("data", (data) => {
+ const code = data.charCodeAt(0);
+ if (code == 13) { // CR
+ if (input[input.length - 1] == ':') {
+ input += data
+ term.write("\r\n.....");
+ } else {
+ term.write("\r\n");
+ try {
+ terminalVM.exec(input);
+ } catch (err) {
+ if (err instanceof WebAssembly.RuntimeError) {
+ err = window.__RUSTPYTHON_ERROR || err;
+ }
+ printToConsole(err);
+ }
+ term.write(prompt);
+ input = "";
+ }
+ } else if (code == 127) {
+ if (input.length > 0) {
+ term.write("\b \b");
+ input = input.slice(0, -1);
+ }
+ } else if (code < 32 || code == 127) { // Control
+ return;
+ } else { // Visible
+ term.write(data);
+ input += data;
+ }
+});