Skip to content

Commit f3e866b

Browse files
committed
WIP
1 parent 9d357d2 commit f3e866b

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

packages/editor/src/lib/Workspace.svelte.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import type { CompileError, CompileResult } from 'svelte/compiler';
2-
import { Compartment, EditorState } from '@codemirror/state';
2+
import { Compartment, EditorState, StateEffect, StateField } from '@codemirror/state';
33
import { compile_file } from './compile-worker';
44
import { BROWSER } from 'esm-env';
55
import { basicSetup, EditorView } from 'codemirror';
66
import { javascript } from '@codemirror/lang-javascript';
77
import { html } from '@codemirror/lang-html';
88
import { svelte } from '@replit/codemirror-lang-svelte';
99
import { autocomplete_for_svelte } from '@sveltejs/site-kit/codemirror';
10-
import { keymap } from '@codemirror/view';
10+
import { Decoration, keymap, type DecorationSet } from '@codemirror/view';
1111
import { acceptCompletion } from '@codemirror/autocomplete';
1212
import { indentWithTab } from '@codemirror/commands';
1313
import { indentUnit } from '@codemirror/language';
@@ -51,6 +51,32 @@ function file_type(file: Item) {
5151
return file.name.split('.').pop();
5252
}
5353

54+
const set_highlight = StateEffect.define<{ start: number; end: number } | null>();
55+
56+
const highlight_field = StateField.define<DecorationSet>({
57+
create() {
58+
return Decoration.none;
59+
},
60+
update(highlights, tr) {
61+
// Apply the effect
62+
for (let effect of tr.effects) {
63+
if (effect.is(set_highlight)) {
64+
if (effect.value) {
65+
const { start, end } = effect.value;
66+
const deco = Decoration.mark({ class: 'highlight' }).range(start, end);
67+
return Decoration.set([deco]);
68+
} else {
69+
// Clear highlight
70+
return Decoration.none;
71+
}
72+
}
73+
}
74+
// Map decorations for document changes
75+
return highlights.map(tr.changes);
76+
},
77+
provide: (field) => EditorView.decorations.from(field)
78+
});
79+
5480
const tab_behaviour = new Compartment();
5581
const vim_mode = new Compartment();
5682

@@ -60,7 +86,8 @@ const default_extensions = [
6086
tab_behaviour.of(keymap.of([{ key: 'Tab', run: acceptCompletion }])),
6187
indentUnit.of('\t'),
6288
theme,
63-
vim_mode.of([])
89+
vim_mode.of([]),
90+
highlight_field
6491
];
6592

6693
export interface ExposedCompilerOptions {
@@ -225,6 +252,14 @@ export class Workspace {
225252
});
226253
}
227254

255+
highlight_range(node: { start: number; end: number } | null) {
256+
if (!this.#view) return;
257+
258+
this.#view.dispatch({
259+
effects: set_highlight.of(node)
260+
});
261+
}
262+
228263
mark_saved() {
229264
this.modified = {};
230265
}

packages/editor/src/lib/codemirror.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,9 @@
304304
}
305305
}
306306
}
307+
308+
.highlight {
309+
background: hsl(60, 100%, 80%);
310+
padding: 4px 0;
311+
}
307312
}

packages/repl/src/lib/Output/AstNode.svelte

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
path_nodes?: Ast[];
1313
autoscroll?: boolean;
1414
depth?: number;
15+
onhover: (node: { type: string; start: number; end: number } | null) => void;
1516
}
1617
17-
let { key = '', value, path_nodes = [], autoscroll = true, depth = 0 }: Props = $props();
18+
let { key = '', value, path_nodes = [], autoscroll = true, onhover, depth = 0 }: Props = $props();
1819
1920
const { toggleable } = get_repl_context();
2021
@@ -97,7 +98,14 @@
9798
{/if}
9899
</span>
99100
{:else}
100-
<details bind:open>
101+
<!-- svelte-ignore a11y_mouse_events_have_key_events (seems like a false positive) -->
102+
<details
103+
bind:open
104+
onfocusin={() => onhover(value)}
105+
onfocusout={(e) => onhover(null)}
106+
onmouseover={() => onhover(value)}
107+
onmouseleave={() => onhover(null)}
108+
>
101109
<summary>
102110
{#if key}
103111
<span class="key">{key}</span>:
@@ -123,6 +131,7 @@
123131
value={v}
124132
{path_nodes}
125133
{autoscroll}
134+
{onhover}
126135
depth={depth + 1}
127136
/>
128137
{/each}

packages/repl/src/lib/Output/AstView.svelte

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,19 @@
6565
<code>
6666
{#if typeof ast === 'object'}
6767
<ul>
68-
<AstNode value={ast} {path_nodes} {autoscroll} />
68+
<AstNode
69+
value={ast}
70+
{path_nodes}
71+
{autoscroll}
72+
onhover={(node) => {
73+
if (
74+
node === null ||
75+
(node.type !== undefined && node.start !== undefined && node.end !== undefined)
76+
) {
77+
workspace.highlight_range(node);
78+
}
79+
}}
80+
/>
6981
</ul>
7082
{:else}
7183
<p>No AST available</p>

0 commit comments

Comments
 (0)