mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-25 23:01:29 -05:00
a very hacky and very very tentative implementation sketchy implementation of the py-terminal plugin
This commit is contained in:
109
pyscript.core/src/plugins/pyterminal.js
Normal file
109
pyscript.core/src/plugins/pyterminal.js
Normal file
@@ -0,0 +1,109 @@
|
||||
// PyScript py-terminal plugin
|
||||
import { hooks } from "../core.js";
|
||||
|
||||
// XXX TODO:
|
||||
// 1. these imports should be lazy?
|
||||
// 2. would be nice to automatically add xterm.css on demand
|
||||
import { Terminal } from 'https://cdn.jsdelivr.net/npm/xterm@5.3.0/+esm'
|
||||
import { Readline } from 'https://cdn.jsdelivr.net/npm/xterm-readline@1.1.1/+esm'
|
||||
const makePyTerminal = () => {
|
||||
const element = document.querySelector('py-terminal');
|
||||
if (element === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const term = new Terminal({
|
||||
theme: {
|
||||
background: "#191A19",
|
||||
foreground: "#F5F2E7",
|
||||
},
|
||||
cursorBlink: true,
|
||||
cursorStyle: "block",
|
||||
rows: 50
|
||||
});
|
||||
|
||||
const rl = new Readline();
|
||||
term.loadAddon(rl);
|
||||
term.open(element);
|
||||
term.focus();
|
||||
|
||||
async function readline(prompt) {
|
||||
//console.log("readline", prompt);
|
||||
const line = await rl.read(prompt);
|
||||
return line;
|
||||
}
|
||||
|
||||
async function write(line) {
|
||||
//console.log("write", line);
|
||||
rl.write(line);
|
||||
}
|
||||
|
||||
console.log("PyTerminal made?");
|
||||
return { term, readline, write };
|
||||
}
|
||||
|
||||
// this is ONLY for non-workers, correct?
|
||||
// TODO: how to make it working for workers?
|
||||
hooks.onInterpreterReady.add(function override(pyScript) {
|
||||
console.log("hello onInterpreterReady");
|
||||
const t = makePyTerminal();
|
||||
if (!t) {
|
||||
console.log("<py-terminal> not found, nothing to do");
|
||||
return;
|
||||
}
|
||||
const { stdout, stderr } = pyScript.io;
|
||||
|
||||
pyScript.io.stdout = (s, ...rest) => {
|
||||
// XXX: the + "\n" is conceptually wrong.
|
||||
// We probably need to configure pyodide's stdout as "raw mode"
|
||||
// instead of "batched mode":
|
||||
// https://pyodide.org/en/stable/usage/streams.html#a-raw-handler
|
||||
t.write(s + "\n");
|
||||
stdout(s, ...rest);
|
||||
}
|
||||
|
||||
pyScript.io.stderr = (s, ...rest) => {
|
||||
t.write(s + "\n"); // see above for the "\n"
|
||||
stderr(s, ...rest);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// this is mostly pseudo-code for what it *should* happen for the workers case
|
||||
/*
|
||||
addEventListener("py:ready", (event) => {
|
||||
console.log("hello py:ready");
|
||||
if (!event.detail.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
const t = makePyTerminal();
|
||||
if (!t) {
|
||||
console.log("<py-terminal> not found, nothing to do");
|
||||
return;
|
||||
}
|
||||
|
||||
const xworker = event.target.xworker;
|
||||
|
||||
xworker.sync.pyterminal_readline = t.readline;
|
||||
xworker.sync.pyterminal_write = t.write;
|
||||
|
||||
// XXX: I know that the following lines don't work, but this is more or
|
||||
// lesswhat I would like to happen
|
||||
pyScript.io.stdout = (s, ...rest) => {
|
||||
// this is JS code, and we cannot send arbitrary JS code from the main
|
||||
// to the worker. So maybe a solution is to hardcode this logic
|
||||
// directly inside the worker code?
|
||||
xworker.sync.pyterminal_write(s);
|
||||
}
|
||||
pyScript.io.stderr = (s, ...rest) => {
|
||||
xworker.sync.pyterminal_write(s);
|
||||
}
|
||||
something.runPython(`
|
||||
import builtins
|
||||
import pyscript
|
||||
builtins.input = sync.pyterminal_readline
|
||||
`)
|
||||
|
||||
});
|
||||
*/
|
||||
31
pyscript.core/test/pyterminal.html
Normal file
31
pyscript.core/test/pyterminal.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PyScript Next</title>
|
||||
<script>
|
||||
addEventListener("py:ready", console.log);
|
||||
</script>
|
||||
<link rel="stylesheet" href="../dist/core.css">
|
||||
<script type="module" src="../dist/core.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.2.1/css/xterm.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<script type="py">
|
||||
import sys
|
||||
from pyscript import display
|
||||
display("Hello", "PyScript Next", append=False)
|
||||
print("this should go to the terminal")
|
||||
print("another line")
|
||||
|
||||
# XXX we have a problem with the error plugin: this line should
|
||||
# just go to the terminal, NOT to the red box in the DOM
|
||||
print("this goes to stderr", file=sys.stderr)
|
||||
</script>
|
||||
|
||||
<py-terminal></py-terminal>
|
||||
</body>
|
||||
</html>
|
||||
1
pyscript.core/types/plugins.d.ts
vendored
1
pyscript.core/types/plugins.d.ts
vendored
@@ -1,4 +1,5 @@
|
||||
declare namespace _default {
|
||||
function error(): Promise<typeof import("./plugins/error.js")>;
|
||||
function pyterminal(): Promise<typeof import("./plugins/pyterminal.js")>;
|
||||
}
|
||||
export default _default;
|
||||
|
||||
1
pyscript.core/types/plugins/pyterminal.d.ts
vendored
Normal file
1
pyscript.core/types/plugins/pyterminal.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Reference in New Issue
Block a user