Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/lib/components/editor/RealtimeEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@
};

let isSynced = $derived(connectionStatus !== 'connecting');

export function focus() {
editor?.focus();
}
</script>

<div class={`tw-forms-disable tw-forms-disable-all-descendants relative h-full ${className}`}>
Expand Down
49 changes: 49 additions & 0 deletions src/lib/components/editor/monaco/MainMonacoEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,51 @@ attached to the promise, so when the promise is cancelled, it logs an error.
});
});

// Ctrl+1 / Cmd+1 to focus main editor
$effect(() => {
if (!editor) return;
const disposable = editor.addAction({
id: 'focus-main',
label: 'Focus Main Editor',
keybindings: [
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Digit1,
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Numpad1
],
run: () => onShortcut?.('focus-main')
});
return () => disposable.dispose();
});

// Ctrl+2 / Cmd+2 to focus input editor
$effect(() => {
if (!editor) return;
const disposable = editor.addAction({
id: 'focus-input',
label: 'Focus Input Editor',
keybindings: [
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Digit2,
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Numpad2
],
run: () => onShortcut?.('focus-input')
});
return () => disposable.dispose();
});

// Ctrl+3 / Cmd+3 to focus output editor
$effect(() => {
if (!editor) return;
const disposable = editor.addAction({
id: "focus-output",
label: "Focus Output Editor",
keybindings: [
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Digit3,
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Numpad3
],
run: () => onShortcut?.('focus-output')
});
return () => disposable.dispose();
});

// Ctrl+Enter / Cmd+Enter shortcut to run code
$effect(() => {
if (!editor) return;
Expand Down Expand Up @@ -391,6 +436,10 @@ attached to the promise, so when the promise is cancelled, it logs an error.
export const getValue = () => {
return editor?.getValue();
};

export function focus() {
editor?.focus();
}
</script>

<div class="dark:bg-monaco-editor-bg flex h-full min-h-0 flex-col bg-white">
Expand Down
22 changes: 19 additions & 3 deletions src/lib/components/editor/monaco/SecondaryMonacoEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
language = 'plaintext',
readOnly = false,
value,

yjsInfo
yjsInfo,
onShortcut,
}: {
language?: Language | 'plaintext';
readOnly?: boolean;
value?: string;
yjsInfo?: YjsInfo;

// Ignored: Only the main editor can configure the global editor mode
editorMode?: 'normal' | 'vim';
onShortcut?: (name: string) => void;
} = $props();

let editor: monaco.editor.IStandaloneCodeEditor | null = $state.raw(null);
Expand Down Expand Up @@ -76,6 +76,18 @@
};
});

$effect(() => {
if (!editor) return;

editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Digit1, () => onShortcut?.('focus-main'));
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Digit2, () => onShortcut?.('focus-input'));
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Digit3, () => onShortcut?.('focus-output'));

editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Numpad1, () => onShortcut?.('focus-main'));
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Numpad2, () => onShortcut?.('focus-input'));
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Numpad3, () => onShortcut?.('focus-output'));
});

$effect(() => {
if (!editor) return;
editor.updateOptions({
Expand All @@ -91,6 +103,10 @@
export const getValue = () => {
return editor?.getValue();
};

export function focus() {
editor?.focus();
}
</script>

<div bind:this={editorElement} class="h-full min-h-0 w-full bg-white dark:bg-monaco-editor-bg"></div>
20 changes: 16 additions & 4 deletions src/routes/[id]/IDE.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script module>
<script module lang="ts">
import { isExecuteResponse, type CommandOutput, type ExecuteResponse, type FileData, type FileSettings, type JudgeResponse, type USACOJudgeSubmissionResult, type UserData } from '$lib/types';

export type JudgeState = {
Expand Down Expand Up @@ -30,6 +30,8 @@

let mainEditor: RealtimeEditor | undefined = $state(undefined);
let inputEditor: RealtimeEditor | undefined = $state(undefined);
let outputEditor: any = $state(undefined);
let scribbleEditor: RealtimeEditor | undefined = $state(undefined);

let inputPaneTab: 'input' | 'judge' = $state(fileData.settings.problem ? 'judge' : 'input');
let outputPaneTab = $state('stdout');
Expand Down Expand Up @@ -172,15 +174,20 @@
// Keyboard shortcut handler for Monaco editor
const handleShortcut = (shortcutName: string) => {
if (shortcutName === 'run-code') {
if (canRunCode) {
runCode();
}
if (canRunCode) runCode();
} else if (shortcutName === 'download-file') {
onDownloadFile();
} else if (shortcutName === 'clone-file') {
onCloneFile();
} else if (shortcutName === 'new-file') {
onNewFile();
} else if (shortcutName === 'focus-main') {
mainEditor?.focus?.();
} else if (shortcutName === 'focus-input') {
if (inputPaneTab === 'input') inputEditor?.focus?.();
} else if (shortcutName === 'focus-output') {
if (outputPaneTab === 'scribble') scribbleEditor?.focus?.();
else outputEditor?.focus?.();
}
};

Expand Down Expand Up @@ -273,6 +280,7 @@
Editor={SecondaryEditor}
bind:this={inputEditor}
readOnly={isReadOnly}
onShortcut={handleShortcut}
/>
{:else if inputPaneTab === 'judge'}
<USACOJudgePane {fileData} {mainEditor} bind:judgeState={judgeState} />
Expand Down Expand Up @@ -300,6 +308,8 @@
{theme}
Editor={SecondaryEditor}
readOnly={isReadOnly}
bind:this={scribbleEditor}
onShortcut={handleShortcut}
/>
{:else}
<div class="flex h-full min-h-0 flex-col">
Expand All @@ -309,6 +319,8 @@
value={outputPaneValue}
{editorMode}
{theme}
bind:this={outputEditor}
onShortcut={handleShortcut}
/>
<OutputStatusBar {judgeState} theme={userData.theme} />
</div>
Expand Down