Skip to content

Commit 6595dce

Browse files
committed
initial console functionality
1 parent 54dca61 commit 6595dce

File tree

11 files changed

+103
-12
lines changed

11 files changed

+103
-12
lines changed

src/assets/stylesheets/PythonRunner.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
.pythonrunner-input {
4242
caret-color: inherit;
4343
color: rgb(36, 103, 236);
44-
display: block;
4544
line-height: 20px;
4645
padding: 2px 1px 2px 0;
4746
}

src/components/Editor/Output/Output.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ExternalFiles from "../../ExternalFiles/ExternalFiles";
44
import RunnerFactory from "../Runners/RunnerFactory";
55
import RunBar from "../../RunButton/RunBar";
66

7-
const Output = ({ outputPanels = ["text", "visual"] }) => {
7+
const Output = ({ outputPanels = ["text", "visual"] }, autoRun = false) => {
88
const project = useSelector((state) => state.editor.project);
99
const isEmbedded = useSelector((state) => state.editor.isEmbedded);
1010
const searchParams = new URLSearchParams(window.location.search);
@@ -17,6 +17,7 @@ const Output = ({ outputPanels = ["text", "visual"] }) => {
1717
<RunnerFactory
1818
projectType={project.project_type}
1919
outputPanels={outputPanels}
20+
autoRun={autoRun}
2021
/>
2122
{isEmbedded && !isBrowserPreview && <RunBar embedded />}
2223
</div>

src/components/Editor/Project/Project.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { projContainer } from "../../../utils/containerQueries";
1818
const Project = (props) => {
1919
const webComponent = useSelector((state) => state.editor.webComponent);
2020
const {
21+
autoRun = false,
2122
nameEditable = true,
2223
withProjectbar = true,
2324
withSidebar = true,
@@ -75,7 +76,7 @@ const Project = (props) => {
7576
>
7677
<EditorInput />
7778
</ResizableWithHandle>
78-
<Output />
79+
<Output autoRun={autoRun} />
7980
</div>
8081
)}
8182
</div>

src/components/Editor/Runners/PythonRunner/PyodideRunner/PyodideRunner.jsx

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
setError,
88
codeRunHandled,
99
loadingRunner,
10+
triggerCodeRun,
1011
} from "../../../../../redux/EditorSlice";
1112
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
1213
import { useMediaQuery } from "react-responsive";
@@ -31,7 +32,7 @@ const getWorkerURL = (url) => {
3132
};
3233

3334
const PyodideRunner = (props) => {
34-
const { active } = props;
35+
const { active, consoleMode = false, autoRun = false } = props;
3536

3637
// Blob approach + targeted headers - no errors but headers required in host app to interrupt code
3738
const workerUrl = getWorkerURL(`${process.env.PUBLIC_URL}/PyodideWorker.js`);
@@ -60,6 +61,53 @@ const PyodideRunner = (props) => {
6061
const [hasVisual, setHasVisual] = useState(showVisualTab || senseHatAlways);
6162
const [visuals, setVisuals] = useState([]);
6263
const [showRunner, setShowRunner] = useState(active);
64+
const [inputStack, setInputStack] = useState([]);
65+
const prependToInputStack = (input) => {
66+
setInputStack((prevInputStack) => {
67+
if (prevInputStack[0] === "") {
68+
console.log("overwriting...");
69+
const newStack = [...prevInputStack];
70+
newStack[0] = input;
71+
return newStack;
72+
} else {
73+
console.log("prepending...");
74+
console.log(prevInputStack);
75+
return [input, ...prevInputStack];
76+
}
77+
});
78+
};
79+
const [inputStackIndex, setInputStackIndex] = useState(0);
80+
81+
useEffect(() => {
82+
const handleKeyDown = (event) => {
83+
if (event.key === "ArrowUp") {
84+
if (inputStackIndex < inputStack.length - 1) {
85+
setInputStackIndex(inputStackIndex + 1);
86+
}
87+
} else if (event.key === "ArrowDown") {
88+
if (inputStackIndex > 0) {
89+
setInputStackIndex(inputStackIndex - 1);
90+
}
91+
}
92+
};
93+
if (consoleMode) {
94+
const inputElement = getInputElement();
95+
inputElement?.removeEventListener("keydown", handleKeyDown);
96+
inputElement?.addEventListener("keydown", handleKeyDown);
97+
}
98+
}, [inputStack, inputStackIndex, consoleMode]);
99+
100+
useEffect(() => {
101+
console.log("inputStack", inputStack);
102+
}, [inputStack]);
103+
104+
useEffect(() => {
105+
console.log("inputStackIndex", inputStackIndex);
106+
const inputElement = getInputElement();
107+
if (inputElement) {
108+
inputElement.innerText = inputStack[inputStackIndex];
109+
}
110+
}, [inputStackIndex]);
63111

64112
useEffect(() => {
65113
if (pyodideWorker) {
@@ -99,6 +147,13 @@ const PyodideRunner = (props) => {
99147
}
100148
}, []);
101149

150+
useEffect(() => {
151+
if (autoRun) {
152+
console.log("autorunning...");
153+
dispatch(triggerCodeRun());
154+
}
155+
}, []);
156+
102157
useEffect(() => {
103158
if (codeRunTriggered && active) {
104159
console.log("running with pyodide");
@@ -137,11 +192,19 @@ const PyodideRunner = (props) => {
137192
return;
138193
}
139194

195+
prependToInputStack("");
196+
setInputStackIndex(0);
140197
const outputPane = output.current;
141-
outputPane.appendChild(inputSpan());
198+
// remove last new line character from last line
199+
outputPane.lastChild.innerText = outputPane.lastChild.innerText.slice(
200+
0,
201+
-1,
202+
);
203+
outputPane.lastChild.appendChild(inputSpan());
142204

143205
const element = getInputElement();
144206
const { content, ctrlD } = await getInputContent(element);
207+
prependToInputStack(content);
145208

146209
const encoder = new TextEncoder();
147210
const bytes = encoder.encode(content + "\n");
@@ -305,6 +368,7 @@ const PyodideRunner = (props) => {
305368
if (element) {
306369
element.removeAttribute("id");
307370
element.removeAttribute("contentEditable");
371+
element.addEventListener("keydown");
308372
}
309373
};
310374

src/components/Editor/Runners/PythonRunner/PythonRunner.jsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const SKULPT_ONLY_MODULES = [
1313
"turtle",
1414
];
1515

16-
const PythonRunner = () => {
16+
const PythonRunner = ({ autoRun = false }) => {
1717
const project = useSelector((state) => state.editor.project);
1818
const codeRunTriggered = useSelector(
1919
(state) => state.editor.codeRunTriggered,
@@ -22,6 +22,7 @@ const PythonRunner = () => {
2222
(state) => state.editor.senseHatAlwaysEnabled,
2323
);
2424
const [usePyodide, setUsePyodide] = useState(true);
25+
const [consoleMode, setConsoleMode] = useState(false);
2526
const { t } = useTranslation();
2627

2728
useEffect(() => {
@@ -64,6 +65,12 @@ const PythonRunner = () => {
6465
break;
6566
} else {
6667
setUsePyodide(true);
68+
if (imports.includes("IPython")) {
69+
setConsoleMode(true);
70+
break;
71+
} else {
72+
setConsoleMode(false);
73+
}
6774
}
6875
} catch (error) {
6976
console.error("Error occurred while getting imports:", error);
@@ -73,7 +80,11 @@ const PythonRunner = () => {
7380
}, [project, codeRunTriggered, senseHatAlwaysEnabled, t]);
7481
return (
7582
<>
76-
<PyodideRunner active={usePyodide} />
83+
<PyodideRunner
84+
active={usePyodide}
85+
consoleMode={consoleMode}
86+
autoRun={autoRun}
87+
/>
7788
<SkulptRunner active={!usePyodide} />
7889
</>
7990
);

src/components/Editor/Runners/PythonRunner/SkulptRunner/SkulptRunner.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ const SkulptRunner = ({ active, outputPanels = ["text", "visual"] }) => {
259259
Sk.sense_hat.mz_criteria.noInputEvents = false;
260260
}
261261
const outputPane = output.current;
262-
outputPane.appendChild(inputSpan());
262+
outputPane.lastChild.appendChild(inputSpan());
263263

264264
const input = getInput();
265265
input.focus();

src/components/Editor/Runners/RunnerFactory.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import React from "react";
22
import PythonRunner from "./PythonRunner/PythonRunner";
33
import HtmlRunner from "./HtmlRunner/HtmlRunner";
44

5-
const RunnerFactory = ({ projectType, outputPanels = ["text", "visual"] }) => {
5+
const RunnerFactory = ({
6+
autoRun,
7+
projectType,
8+
outputPanels = ["text", "visual"],
9+
}) => {
610
const Runner = () => {
711
if (projectType === "html") {
812
return HtmlRunner;
@@ -13,7 +17,7 @@ const RunnerFactory = ({ projectType, outputPanels = ["text", "visual"] }) => {
1317

1418
const Selected = Runner();
1519

16-
const props = projectType === "html" ? {} : { outputPanels };
20+
const props = projectType === "html" ? {} : { outputPanels, autoRun };
1721

1822
return <Selected {...props} />;
1923
};

src/components/Mobile/MobileProject/MobileProject.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ import { useTranslation } from "react-i18next";
1414
import Sidebar from "../../Menus/Sidebar/Sidebar";
1515
import { showSidebar } from "../../../redux/EditorSlice";
1616

17-
const MobileProject = ({ withSidebar, sidebarOptions = [] }) => {
17+
const MobileProject = ({
18+
autoRun = false,
19+
withSidebar,
20+
sidebarOptions = [],
21+
}) => {
1822
const projectType = useSelector((state) => state.editor.project.project_type);
1923
const sidebarShowing = useSelector((state) => state.editor.sidebarShowing);
2024
const codeRunTriggered = useSelector(
@@ -55,7 +59,7 @@ const MobileProject = ({ withSidebar, sidebarOptions = [] }) => {
5559
<EditorInput />
5660
</TabPanel>
5761
<TabPanel>
58-
<Output />
62+
<Output autoRun={autoRun} />
5963
</TabPanel>
6064
<MobileProjectBar />
6165
<div className="react-tabs__tab-container mobile-nav">

src/components/WebComponentProject/WebComponentProject.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
} from "../../events/WebComponentCustomEvents";
2525

2626
const WebComponentProject = ({
27+
autoRun = false,
2728
withProjectbar = false,
2829
nameEditable = false,
2930
withSidebar = false,
@@ -97,11 +98,13 @@ const WebComponentProject = ({
9798
{!outputOnly &&
9899
(isMobile ? (
99100
<MobileProject
101+
autoRun={autoRun}
100102
withSidebar={withSidebar}
101103
sidebarOptions={sidebarOptions}
102104
/>
103105
) : (
104106
<Project
107+
autoRun={autoRun}
105108
nameEditable={nameEditable}
106109
withProjectbar={withProjectbar}
107110
withSidebar={withSidebar}

src/containers/WebComponentLoader.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const WebComponentLoader = (props) => {
3131
const {
3232
assetsIdentifier,
3333
authKey,
34+
autoRun = false,
3435
identifier,
3536
code,
3637
senseHatAlwaysEnabled = false,
@@ -175,6 +176,7 @@ const WebComponentLoader = (props) => {
175176
closeButton={ToastCloseButton}
176177
/>
177178
<WebComponentProject
179+
autoRun={autoRun}
178180
withProjectbar={withProjectbar}
179181
nameEditable={projectNameEditable}
180182
withSidebar={withSidebar}

0 commit comments

Comments
 (0)