Skip to content

Commit ded7acc

Browse files
Merge pull request #643 from palaviv/interactive-shell
Add interactive shell to WASM demo
2 parents e8ec497 + f27cb5b commit ded7acc

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

wasm/demo/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "Bindings to the RustPython library for WebAssembly",
55
"main": "index.js",
66
"dependencies": {
7-
"codemirror": "^5.42.0"
7+
"codemirror": "^5.42.0",
8+
"xterm": "^3.8.0"
89
},
910
"devDependencies": {
1011
"@wasm-tool/wasm-pack-plugin": "0.2.0",

wasm/demo/src/index.ejs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
<h3>Standard Output</h3>
3131
<textarea id="console" readonly>Loading...</textarea>
3232

33+
<h3>Interactive shell</h3>
34+
<div id="terminal"></div>
35+
3336
<p>Here's some info regarding the <code>rp.pyEval()</code> function</p>
3437
<ul>
3538
<li>

wasm/demo/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './style.css';
22
import 'codemirror/lib/codemirror.css';
3+
import 'xterm/dist/xterm.css';
34

45
// A dependency graph that contains any wasm must all be imported
56
// asynchronously. This `index.js` file does the single async import, so

wasm/demo/src/main.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as rp from '../../lib/pkg';
22
import CodeMirror from 'codemirror';
33
import 'codemirror/mode/python/python';
44
import 'codemirror/addon/comment/comment';
5+
import { Terminal } from 'xterm';
56

67
// so people can play around with it
78
window.rp = rp;
@@ -72,3 +73,58 @@ snippets.addEventListener('change', updateSnippet);
7273
// Run once for demo (updateSnippet b/c the browser might try to keep the same
7374
// option selected for the `select`, but the textarea won't be updated)
7475
updateSnippet();
76+
77+
const prompt = ">>>>> ";
78+
79+
const term = new Terminal();
80+
term.open(document.getElementById('terminal'));
81+
term.write(prompt);
82+
83+
function removeNonAscii(str) {
84+
if ((str===null) || (str===''))
85+
return false;
86+
else
87+
str = str.toString();
88+
89+
return str.replace(/[^\x20-\x7E]/g, '');
90+
}
91+
92+
function printToConsole(data) {
93+
term.write(removeNonAscii(data) + "\r\n");
94+
}
95+
96+
const terminalVM = rp.vmStore.init("term_vm");
97+
terminalVM.setStdout(printToConsole);
98+
99+
var input = "";
100+
term.on("data", (data) => {
101+
const code = data.charCodeAt(0);
102+
if (code == 13) { // CR
103+
if (input[input.length - 1] == ':') {
104+
input += data
105+
term.write("\r\n.....");
106+
} else {
107+
term.write("\r\n");
108+
try {
109+
terminalVM.exec(input);
110+
} catch (err) {
111+
if (err instanceof WebAssembly.RuntimeError) {
112+
err = window.__RUSTPYTHON_ERROR || err;
113+
}
114+
printToConsole(err);
115+
}
116+
term.write(prompt);
117+
input = "";
118+
}
119+
} else if (code == 127) {
120+
if (input.length > 0) {
121+
term.write("\b \b");
122+
input = input.slice(0, -1);
123+
}
124+
} else if (code < 32 || code == 127) { // Control
125+
return;
126+
} else { // Visible
127+
term.write(data);
128+
input += data;
129+
}
130+
});

0 commit comments

Comments
 (0)