mirror of
https://github.com/ParkerTenBroeck/automata.git
synced 2026-06-07 05:28:45 -04:00
starting work on highlights
This commit is contained in:
parent
ba996ee942
commit
58fb1b956c
3 changed files with 73 additions and 1 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import {
|
||||
Decoration,
|
||||
DecorationSet,
|
||||
EditorView,
|
||||
highlightActiveLine,
|
||||
highlightActiveLineGutter,
|
||||
|
|
@ -10,7 +11,7 @@ import {
|
|||
lineNumbers,
|
||||
} from "npm:@codemirror/view";
|
||||
|
||||
import { EditorState, StateField, Text } from "npm:@codemirror/state";
|
||||
import { EditorState, RangeSetBuilder, StateEffect, StateField, Text } from "npm:@codemirror/state";
|
||||
import {
|
||||
defaultKeymap,
|
||||
history,
|
||||
|
|
@ -45,6 +46,57 @@ function compile(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export type HighlightKind = "focus" | "success" | "warning" | "error";
|
||||
|
||||
export type HighlightSpan = {
|
||||
from: number;
|
||||
to: number;
|
||||
kind: HighlightKind;
|
||||
};
|
||||
|
||||
function decoForKind(kind: HighlightKind) {
|
||||
// Use a class per kind so each gets a distinct color via CSS
|
||||
return Decoration.mark({ class: `cm-highlight cm-highlight-${kind}` });
|
||||
}
|
||||
|
||||
export function applyHighlights(view: EditorView, spans: HighlightSpan[]) {
|
||||
view.dispatch({ effects: setHighlights.of(spans) });
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const highlightsField = StateField.define<DecorationSet>({
|
||||
create() {
|
||||
return Decoration.none;
|
||||
},
|
||||
|
||||
update(highlights, tr) {
|
||||
// Keep highlights aligned with document edits
|
||||
// highlights = highlights.map(tr.changes);
|
||||
|
||||
for (const e of tr.effects) {
|
||||
if (e.is(setHighlights)) {
|
||||
const spans = e.value;
|
||||
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
for (const s of spans) {
|
||||
const from = Math.max(0, Math.min(s.from, tr.state.doc.length));
|
||||
const to = Math.max(0, Math.min(s.to, tr.state.doc.length));
|
||||
if (to > from) builder.add(from, to, decoForKind(s.kind));
|
||||
}
|
||||
highlights = builder.finish();
|
||||
}
|
||||
}
|
||||
|
||||
return highlights;
|
||||
},
|
||||
|
||||
provide: (f) => EditorView.decorations.from(f),
|
||||
});
|
||||
|
||||
export const setHighlights = StateEffect.define<HighlightSpan[]>();
|
||||
|
||||
const eventBusConnection = StateField.define({
|
||||
create(state) {
|
||||
const text = state.doc.toString();
|
||||
|
|
@ -198,6 +250,7 @@ const state = EditorState.create({
|
|||
keymap.of([...defaultKeymap, ...historyKeymap]),
|
||||
|
||||
eventBusConnection,
|
||||
highlightsField,
|
||||
diagHover,
|
||||
|
||||
EditorView.lineWrapping,
|
||||
|
|
@ -223,3 +276,11 @@ bus.on("controls/editor/set_text", ({ text }) => {
|
|||
bus.on("example/selected", ({ example }) => {
|
||||
bus.emit("controls/editor/set_text", { text: example.machine });
|
||||
});
|
||||
|
||||
|
||||
applyHighlights(editor, [
|
||||
{ from: 0, to: 10, kind: "focus" },
|
||||
{ from: 10, to: 20, kind: "success" },
|
||||
{ from: 20, to: 30, kind: "warning" },
|
||||
{ from: 30, to: 40, kind: "error" },
|
||||
])
|
||||
0
web/root/src/focus.ts
Normal file
0
web/root/src/focus.ts
Normal file
|
|
@ -132,3 +132,14 @@
|
|||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.cm-highlight {
|
||||
border-radius: 4px;
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
.cm-highlight-warning { background: color-mix(in srgb, var(--warning) 40%, var(--bg-0)); }
|
||||
.cm-highlight-focus { background: color-mix(in srgb, var(--focus) 40%, var(--bg-0)); }
|
||||
.cm-highlight-success { background: color-mix(in srgb, var(--success) 40%, var(--bg-0)); }
|
||||
.cm-highlight-error { background: color-mix(in srgb, var(--error) 40%, var(--bg-0)); }
|
||||
Loading…
Add table
Add a link
Reference in a new issue