mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Improve the terminal's navigation
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"codemirror": "^5.42.0",
|
||||
"local-echo": "^0.2.0",
|
||||
"xterm": "^3.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -14,11 +15,11 @@
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"raw-loader": "^1.0.0",
|
||||
"serve": "^11.0.2",
|
||||
"start-server-and-test": "^1.7.11",
|
||||
"webpack": "^4.16.3",
|
||||
"webpack-cli": "^3.1.0",
|
||||
"webpack-dev-server": "^3.1.5",
|
||||
"start-server-and-test": "^1.7.11",
|
||||
"serve": "^11.0.2"
|
||||
"webpack-dev-server": "^3.1.5"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server -d",
|
||||
|
||||
@@ -3,6 +3,7 @@ import CodeMirror from 'codemirror';
|
||||
import 'codemirror/mode/python/python';
|
||||
import 'codemirror/addon/comment/comment';
|
||||
import { Terminal } from 'xterm';
|
||||
import LocalEchoController from 'local-echo';
|
||||
|
||||
// so people can play around with it
|
||||
window.rp = rp;
|
||||
@@ -35,7 +36,7 @@ function runCodeFromTextarea() {
|
||||
|
||||
const code = editor.getValue();
|
||||
try {
|
||||
const result = rp.pyEval(code, {
|
||||
rp.pyEval(code, {
|
||||
stdout: output => {
|
||||
const shouldScroll =
|
||||
consoleElement.scrollHeight - consoleElement.scrollTop ===
|
||||
@@ -46,9 +47,6 @@ function runCodeFromTextarea() {
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result !== null) {
|
||||
consoleElement.value += `\n${result}\n`;
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof WebAssembly.RuntimeError) {
|
||||
err = window.__RUSTPYTHON_ERROR || err;
|
||||
@@ -82,24 +80,16 @@ snippets.addEventListener('change', updateSnippet);
|
||||
// option selected for the `select`, but the textarea won't be updated)
|
||||
updateSnippet();
|
||||
|
||||
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 term = new Terminal();
|
||||
term.open(document.getElementById('terminal'));
|
||||
|
||||
const terminalVM = rp.vmStore.init('term_vm');
|
||||
terminalVM.setStdout(printToConsole);
|
||||
const localEcho = new LocalEchoController(term);
|
||||
|
||||
function getPrompt(name = 'ps1') {
|
||||
const terminalVM = rp.vmStore.init('term_vm');
|
||||
|
||||
terminalVM.setStdout(data => localEcho.println(data));
|
||||
|
||||
function getPrompt(name) {
|
||||
terminalVM.exec(`
|
||||
try:
|
||||
import sys as __sys
|
||||
@@ -112,64 +102,37 @@ finally:
|
||||
return String(terminalVM.eval('__prompt'));
|
||||
}
|
||||
|
||||
term.write(getPrompt());
|
||||
async function readPrompts() {
|
||||
let continuing = false;
|
||||
|
||||
function resetInput() {
|
||||
continuedInput = [];
|
||||
input = '';
|
||||
continuing = false;
|
||||
}
|
||||
|
||||
let continuedInput, input, continuing;
|
||||
resetInput();
|
||||
|
||||
let ps2;
|
||||
|
||||
term.on('data', data => {
|
||||
const code = data.charCodeAt(0);
|
||||
if (code == 13) {
|
||||
// CR
|
||||
term.write('\r\n');
|
||||
continuedInput.push(input);
|
||||
while (true) {
|
||||
const ps1 = getPrompt('ps1');
|
||||
const ps2 = getPrompt('ps2');
|
||||
let input;
|
||||
if (continuing) {
|
||||
if (input === '') {
|
||||
continuing = false;
|
||||
} else {
|
||||
input = '';
|
||||
term.write(ps2);
|
||||
return;
|
||||
}
|
||||
const prom = localEcho.read(ps2, ps2);
|
||||
localEcho._activePrompt.prompt = ps1;
|
||||
localEcho._input = localEcho.history.entries.pop() + '\n';
|
||||
localEcho._cursor = localEcho._input.length;
|
||||
localEcho._active = true;
|
||||
input = await prom;
|
||||
if (!input.endsWith('\n')) continue;
|
||||
} else {
|
||||
input = await localEcho.read(ps1, ps2);
|
||||
}
|
||||
try {
|
||||
terminalVM.execSingle(continuedInput.join('\n'));
|
||||
terminalVM.execSingle(input);
|
||||
} catch (err) {
|
||||
if (err instanceof SyntaxError && err.message.includes('EOF')) {
|
||||
ps2 = getPrompt('ps2');
|
||||
term.write(ps2);
|
||||
continuing = true;
|
||||
input = '';
|
||||
return;
|
||||
continue;
|
||||
} else if (err instanceof WebAssembly.RuntimeError) {
|
||||
err = window.__RUSTPYTHON_ERROR || err;
|
||||
}
|
||||
printToConsole(err);
|
||||
localEcho.println(err);
|
||||
}
|
||||
resetInput();
|
||||
term.write(getPrompt());
|
||||
} else if (code == 127 || code == 8) {
|
||||
// Backspace
|
||||
if (input.length > 0) {
|
||||
term.write('\b \b');
|
||||
input = input.slice(0, -1);
|
||||
}
|
||||
} else if (code < 32) {
|
||||
// Control
|
||||
term.write('\r\n' + getPrompt());
|
||||
input = '';
|
||||
continuedInput = [];
|
||||
} else {
|
||||
// Visible
|
||||
term.write(data);
|
||||
input += data;
|
||||
continuing = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
readPrompts().catch(err => console.error(err));
|
||||
|
||||
Reference in New Issue
Block a user