wip live coding mode

This commit is contained in:
2025-10-15 02:53:48 +02:00
parent a4432fa3d9
commit 46925f5c2e
12 changed files with 1599 additions and 24 deletions

View File

@ -14,13 +14,21 @@
import { oneDark } from '@codemirror/theme-one-dark';
import { vim } from '@replit/codemirror-vim';
import type { EditorSettingsStore } from '../../stores/editorSettings';
import {
flashField,
flash,
getSelection,
getBlock,
getDocument
} from '../../editor/block-eval';
interface Props {
value: string;
language?: 'javascript' | 'html' | 'css';
onChange?: (value: string) => void;
onExecute?: (code: string) => void;
onExecute?: (code: string, source: 'selection' | 'block' | 'document') => void;
editorSettings: EditorSettingsStore;
mode?: 'composition' | 'livecoding';
}
let {
@ -28,7 +36,8 @@
language = 'javascript',
onChange,
onExecute,
editorSettings
editorSettings,
mode = 'composition'
}: Props = $props();
let editorContainer: HTMLDivElement;
@ -44,14 +53,35 @@
const lineWrappingCompartment = new Compartment();
const vimCompartment = new Compartment();
function handleExecute() {
if (!editorView) return;
if (mode === 'composition') {
// Composition mode: always evaluate entire document
const doc = getDocument(editorView.state);
flash(editorView, doc.from, doc.to);
onExecute?.(doc.text, 'document');
} else {
// Live coding mode: evaluate selection or block
const selection = getSelection(editorView.state);
if (selection.text) {
flash(editorView, selection.from, selection.to);
onExecute?.(selection.text, 'selection');
} else {
const block = getBlock(editorView.state);
if (block.text) {
flash(editorView, block.from, block.to);
onExecute?.(block.text, 'block');
}
}
}
}
const evaluateKeymap = keymap.of([
{
key: 'Mod-e',
run: (view) => {
if (onExecute) {
const code = view.state.doc.toString();
onExecute(code);
}
run: () => {
handleExecute();
return true;
}
}
@ -93,6 +123,7 @@
languageExtensions[language],
oneDark,
evaluateKeymap,
flashField(),
lineNumbersCompartment.of(initSettings.showLineNumbers ? lineNumbers() : []),
lineWrappingCompartment.of(initSettings.enableLineWrapping ? EditorView.lineWrapping : []),
vimCompartment.of(initSettings.vimMode ? vim() : []),
@ -141,6 +172,30 @@
});
}
});
export function getSelectedText(): string | null {
if (!editorView) return null;
const { text } = getSelection(editorView.state);
return text || null;
}
export function getCurrentBlock(): string | null {
if (!editorView) return null;
const { text } = getBlock(editorView.state);
return text || null;
}
export function getFullDocument(): string {
if (!editorView) return '';
const { text } = getDocument(editorView.state);
return text;
}
export function evaluateWithFlash(text: string, from: number | null, to: number | null) {
if (editorView && from !== null && to !== null) {
flash(editorView, from, to);
}
}
</script>
<div class="editor-wrapper">