Skip to content

Commit ea7d9ce

Browse files
feat(playground): support keyboard shortcuts Ctrl+Enter to run and Ctrl+Shift+L to clear (#1716)
1 parent 7a9faa4 commit ea7d9ce

3 files changed

Lines changed: 82 additions & 16 deletions

File tree

web-app/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ <h2 class="playground-title">🐍 Python Playground</h2>
382382
</p>
383383
<p class="playground-hint">
384384
<kbd>Ctrl</kbd>+<kbd>Enter</kbd> runs code &nbsp;·&nbsp;
385+
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>L</kbd> clears console &nbsp;·&nbsp;
385386
<kbd>Tab</kbd> inserts 4 spaces
386387
</p>
387388
</div>

web-app/js/playground.js

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,15 @@
489489
return true;
490490
},
491491
},
492+
/* Ctrl/Cmd + Shift + L → Clear Console */
493+
{
494+
key: "Ctrl-Shift-l",
495+
mac: "Cmd-Shift-l",
496+
run: function () {
497+
resetConsole();
498+
return true;
499+
},
500+
},
492501
]),
493502

494503
/* Update listener — keeps `editor.value` semantic alive */
@@ -1004,24 +1013,56 @@
10041013
});
10051014
}
10061015

1007-
// Keyboard shortcut for copy: Ctrl+Shift+C in editor
1008-
if (cmView) {
1009-
document.addEventListener("keydown", function (event) {
1010-
if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.code === "KeyC") {
1011-
// Check if focus is in the editor
1012-
if (
1013-
editorMount &&
1014-
(editorMount.contains(document.activeElement) ||
1015-
document.activeElement === editorMount)
1016-
) {
1017-
event.preventDefault();
1018-
if (copyEditorCodeBtn) {
1019-
copyEditorCodeBtn.click();
1020-
}
1016+
/* ──────────────────────────────────────────────────────────────
1017+
Keyboard Shortcuts — Issue #1716 & Issue #1215
1018+
- Ctrl/Cmd + Enter: Run Python Code
1019+
- Ctrl/Cmd + Shift + L: Clear Output Console
1020+
- Ctrl/Cmd + Shift + C: Copy Code (when focused in editor)
1021+
────────────────────────────────────────────────────────────── */
1022+
document.addEventListener("keydown", function (event) {
1023+
if (event.defaultPrevented) return;
1024+
1025+
// Only process if playground section is active/visible
1026+
if (!playgroundSection || playgroundSection.style.display === "none") return;
1027+
1028+
var isMod = event.ctrlKey || event.metaKey;
1029+
if (!isMod) return;
1030+
1031+
// Ctrl/Cmd + Shift + C: Copy editor code
1032+
if (
1033+
event.shiftKey &&
1034+
(event.key === "c" || event.key === "C" || event.code === "KeyC")
1035+
) {
1036+
if (
1037+
editorMount &&
1038+
(editorMount.contains(document.activeElement) ||
1039+
document.activeElement === editorMount)
1040+
) {
1041+
event.preventDefault();
1042+
if (copyEditorCodeBtn) {
1043+
copyEditorCodeBtn.click();
10211044
}
10221045
}
1023-
});
1024-
}
1046+
return;
1047+
}
1048+
1049+
// Ctrl/Cmd + Enter: Run Code
1050+
if (event.key === "Enter" || event.code === "Enter") {
1051+
event.preventDefault();
1052+
runCode();
1053+
return;
1054+
}
1055+
1056+
// Ctrl/Cmd + Shift + L: Clear Output Console
1057+
if (
1058+
event.shiftKey &&
1059+
(event.key === "l" || event.key === "L" || event.code === "KeyL")
1060+
) {
1061+
event.preventDefault();
1062+
resetConsole();
1063+
return;
1064+
}
1065+
});
10251066
if (saveDraftBtn) {
10261067
saveDraftBtn.addEventListener("click", function () {
10271068
var draftName = prompt("Enter a name for this draft:");

web-app/tests-e2e/playground.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,28 @@ test.describe('Python Playground', () => {
2929
const consoleOutput = page.locator('#consoleOutput');
3030
await expect(consoleOutput).toContainText('Hello, World!');
3131
});
32+
33+
test('should trigger run code via Ctrl+Enter and clear console via Ctrl+Shift+L', async ({ page }) => {
34+
await page.goto('/');
35+
36+
const playgroundTab = page.locator('button[data-sticky-category="playground"]');
37+
await expect(playgroundTab).toBeVisible();
38+
await playgroundTab.click();
39+
40+
const statusText = page.locator('#statusText');
41+
await expect(statusText).toHaveText(/Pyodide Ready/, { timeout: 30000 });
42+
43+
const consoleOutput = page.locator('#consoleOutput');
44+
45+
// Focus editor and press Control+Enter
46+
const editor = page.locator('.cm-content');
47+
await editor.focus();
48+
await page.keyboard.press('Control+Enter');
49+
50+
await expect(consoleOutput).toContainText('Hello, World!');
51+
52+
// Press Control+Shift+L to clear console
53+
await page.keyboard.press('Control+Shift+L');
54+
await expect(consoleOutput).toContainText('Console output will appear here');
55+
});
3256
});

0 commit comments

Comments
 (0)