From 67d47511d5c0968a55a5b95e34f34817ba8faff7 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 3 Jul 2024 13:03:31 +0200 Subject: [PATCH] Fix MicroPython terminal input when no REPL is used/needed (#2113) * Fix terminal input when no REPL is used/needed * Fix input backspace too --- pyscript.core/package-lock.json | 72 ++++++++++---------- pyscript.core/package.json | 10 +-- pyscript.core/src/plugins/py-terminal/mpy.js | 29 +++++--- pyscript.core/test/py-terminals.html | 2 +- pyscript.core/test/py-terminals/index.html | 18 +++++ pyscript.core/test/py-terminals/no-repl.html | 20 ++++++ pyscript.core/test/py-terminals/repl.html | 28 ++++++++ 7 files changed, 129 insertions(+), 50 deletions(-) create mode 100644 pyscript.core/test/py-terminals/index.html create mode 100644 pyscript.core/test/py-terminals/no-repl.html create mode 100644 pyscript.core/test/py-terminals/repl.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index e3af4581..50d58194 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.53", + "version": "0.4.55", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.53", + "version": "0.4.55", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -21,8 +21,8 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.2", - "@playwright/test": "^1.45.0", + "@codemirror/view": "^6.28.3", + "@playwright/test": "^1.45.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -32,13 +32,13 @@ "bun": "^1.1.17", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.5.0", + "eslint": "^9.6.0", "flatted": "^3.3.1", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.5.2", + "typescript": "^5.5.3", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -136,9 +136,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.28.2", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.2.tgz", - "integrity": "sha512-A3DmyVfjgPsGIjiJqM/zvODUAPQdQl3ci0ghehYNnbt5x+o76xq+dL5+mMBuysDXnI3kapgOkoeJ0sbtL/3qPw==", + "version": "6.28.3", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.3.tgz", + "integrity": "sha512-QVqP+ko078/h9yrW+u5grX3rQhC+BkGKADRrlDaJznfPngJOv5zObiVf0+SgAWhL/Yt0nvZ+10rO3L+gU5IbFw==", "dev": true, "license": "MIT", "dependencies": { @@ -187,15 +187,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", - "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", + "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", - "minimatch": "^3.0.5" + "minimatch": "^3.1.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -226,9 +226,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", - "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", "dev": true, "license": "MIT", "engines": { @@ -585,13 +585,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.0.tgz", - "integrity": "sha512-TVYsfMlGAaxeUllNkywbwek67Ncf8FRGn8ZlRdO291OL3NjG9oMbfVhyP82HQF0CZLMrYsvesqoUekxdWuF9Qw==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.1.tgz", + "integrity": "sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.45.0" + "playwright": "1.45.1" }, "bin": { "playwright": "cli.js" @@ -1752,17 +1752,17 @@ } }, "node_modules/eslint": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", - "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.16.0", + "@eslint/config-array": "^0.17.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.5.0", + "@eslint/js": "9.6.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -1773,7 +1773,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.0.1", "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", + "espree": "^10.1.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2882,13 +2882,13 @@ "license": "ISC" }, "node_modules/playwright": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0.tgz", - "integrity": "sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", + "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.0" + "playwright-core": "1.45.1" }, "bin": { "playwright": "cli.js" @@ -2901,9 +2901,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0.tgz", - "integrity": "sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz", + "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4189,9 +4189,9 @@ "license": "ISC" }, "node_modules/typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/pyscript.core/package.json b/pyscript.core/package.json index d84a354d..fae49983 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.53", + "version": "0.4.55", "type": "module", "description": "PyScript", "module": "./index.js", @@ -54,8 +54,8 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.2", - "@playwright/test": "^1.45.0", + "@codemirror/view": "^6.28.3", + "@playwright/test": "^1.45.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -65,13 +65,13 @@ "bun": "^1.1.17", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.5.0", + "eslint": "^9.6.0", "flatted": "^3.3.1", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.5.2", + "typescript": "^5.5.3", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, diff --git a/pyscript.core/src/plugins/py-terminal/mpy.js b/pyscript.core/src/plugins/py-terminal/mpy.js index 6e4a163e..deb1cfeb 100644 --- a/pyscript.core/src/plugins/py-terminal/mpy.js +++ b/pyscript.core/src/plugins/py-terminal/mpy.js @@ -49,11 +49,12 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { const writer = encoder.writable.getWriter(); sync.pyterminal_stream_write = (buffer) => writer.write(buffer); - pyterminal_ready(); interpreter.replInit(); }, }); + + pyterminal_ready(); }; export default async (element) => { @@ -163,13 +164,25 @@ export default async (element) => { }; terminal.onData((buffer) => { if (promisedChunks) { - readChunks += buffer; - terminal.write(buffer); - if (readChunks.endsWith("\r")) { - terminal.write("\n"); - promisedChunks.resolve(readChunks.slice(0, -1)); - promisedChunks = null; - readChunks = ""; + // handle backspace on input + if (buffer === "\x7f") { + // avoid over-greedy backspace + if (readChunks.length) { + readChunks = readChunks.slice(0, -1); + // override previous char position + // put an empty space to clear the char + // move back position again + buffer = "\b \b"; + } else buffer = ""; + } else readChunks += buffer; + if (buffer) { + terminal.write(buffer); + if (readChunks.endsWith("\r")) { + terminal.write("\n"); + promisedChunks.resolve(readChunks.slice(0, -1)); + promisedChunks = null; + readChunks = ""; + } } } else { stream.write(buffer); diff --git a/pyscript.core/test/py-terminals.html b/pyscript.core/test/py-terminals.html index ff72c551..a846ea7c 100644 --- a/pyscript.core/test/py-terminals.html +++ b/pyscript.core/test/py-terminals.html @@ -9,7 +9,7 @@ - + + + + + + + diff --git a/pyscript.core/test/py-terminals/repl.html b/pyscript.core/test/py-terminals/repl.html new file mode 100644 index 00000000..ee64bfe8 --- /dev/null +++ b/pyscript.core/test/py-terminals/repl.html @@ -0,0 +1,28 @@ + + + + + + PyTerminal Prompt: REPL + + + + + + + +