Skip to content

Commit

Permalink
Basic area highlighting
Browse files Browse the repository at this point in the history
  • Loading branch information
OAGr committed Sep 10, 2024
1 parent aaa0953 commit 42ff02c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 14 deletions.
53 changes: 50 additions & 3 deletions packages/components/src/components/CodeEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { StateEffect, StateField } from "@codemirror/state";
import { Decoration, DecorationSet, EditorView } from "@codemirror/view";
import { forwardRef, ReactNode, useImperativeHandle } from "react";

import { SqLocation, SqProject, SqValuePath } from "@quri/squiggle-lang";
Expand All @@ -6,6 +8,38 @@ import { Simulation } from "../../lib/hooks/useSimulator.js";
import { formatSquiggle } from "./formatSquiggleExtension.js";
import { useSquiggleEditorView } from "./useSquiggleEditorView.js";

const flashHighlight = StateEffect.define<{
from: number;
to: number;
} | null>();

const flashHighlightField = StateField.define<DecorationSet>({

Check failure on line 16 in packages/components/src/components/CodeEditor/index.tsx

View workflow job for this annotation

GitHub Actions / Build, test, lint

'flashHighlightField' is assigned a value but never used
create() {
return Decoration.none;
},
update(highlights, tr) {
highlights = highlights.map(tr.changes);
for (let e of tr.effects) {

Check failure on line 22 in packages/components/src/components/CodeEditor/index.tsx

View workflow job for this annotation

GitHub Actions / Build, test, lint

'e' is never reassigned. Use 'const' instead
if (e.is(flashHighlight)) {
if (e.value) {
highlights = highlights.update({
add: [
Decoration.mark({ class: "cm-flash-highlight" }).range(
e.value.from,
e.value.to
),
],
});
} else {
highlights = Decoration.none;
}
}
}
return highlights;
},
provide: (f) => EditorView.decorations.from(f),
});

export type CodeEditorProps = {
defaultValue: string;
onChange: (value: string) => void;
Expand Down Expand Up @@ -37,13 +71,18 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(
function CodeEditor(props, ref) {
const { view, ref: editorRef } = useSquiggleEditorView(props);

const scrollTo = (location: SqLocation, focus: boolean) => {
const scrollTo = (location: SqLocation, flash: boolean) => {

Check failure on line 74 in packages/components/src/components/CodeEditor/index.tsx

View workflow job for this annotation

GitHub Actions / Build, test, lint

'flash' is defined but never used. Allowed unused args must match /^_/u
if (!view) return;

view.dispatch({
selection: { anchor: location.start.offset, head: location.end.offset },
scrollIntoView: true,
effects: true

Check failure on line 79 in packages/components/src/components/CodeEditor/index.tsx

View workflow job for this annotation

GitHub Actions / Build, test, lint

Unexpected constant condition
? flashHighlight.of({
from: location.start.offset,
to: location.end.offset,
})
: undefined,
});
focus && view.focus();
};

useImperativeHandle(ref, () => ({
Expand All @@ -57,3 +96,11 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(
);
}
);

const style = document.createElement("style");
style.textContent = `
.cm-flash-highlight {
background-color: #ff9999;
}
`;
document.head.appendChild(style);
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import {
syntaxHighlighting,
} from "@codemirror/language";
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
import { EditorState } from "@codemirror/state";
import { EditorState, StateField } from "@codemirror/state";
import {
Decoration,
DecorationSet,
drawSelection,
dropCursor,
EditorView,
Expand All @@ -32,7 +34,7 @@ import {
useConfigureCodemirrorView,
} from "./codemirrorHooks.js";
import { errorsExtension } from "./errorsExtension.js";
import { showGutterFacet, useReactPropsField } from "./fields.js";
import { useReactPropsField } from "./fields.js";
import { formatSquiggleExtension } from "./formatSquiggleExtension.js";
import { gutterExtension } from "./gutter/gutterExtension.js";
import { CodeEditorProps } from "./index.js";
Expand All @@ -46,14 +48,34 @@ import { themeExtension } from "./themeExtension.js";
import { tooltipsExtension } from "./tooltips/index.js";
import { viewNodeExtension } from "./viewNodeExtension.js";

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function debugExtension() {
// Print state or specific fields on changes.
return EditorView.updateListener.of(({ state }) => {
// eslint-disable-next-line no-console
console.log(state.facet(showGutterFacet));
});
}
const flashHighlightField = StateField.define<DecorationSet>({
create() {
return Decoration.none;
},
update(highlights, tr) {
console.log("Update flash highlight field", highlights, tr.effects);

Check warning on line 56 in packages/components/src/components/CodeEditor/useSquiggleEditorView.ts

View workflow job for this annotation

GitHub Actions / Build, test, lint

Unexpected console statement
highlights = highlights.map(tr.changes);
let newHighlight: DecorationSet | null = null;
for (let e of tr.effects) {

Check failure on line 59 in packages/components/src/components/CodeEditor/useSquiggleEditorView.ts

View workflow job for this annotation

GitHub Actions / Build, test, lint

'e' is never reassigned. Use 'const' instead
if (e.value && "from" in e.value && "to" in e.value) {
// Create a new highlight, replacing any existing one
newHighlight = Decoration.set([
Decoration.mark({ class: "cm-flash-highlight" }).range(
e.value.from,
e.value.to
),
]);
} else if (e.value === null) {
// Remove all highlights when e.value is null
newHighlight = Decoration.none;
}
}
// If a new highlight was created or all highlights were removed, use it
// Otherwise, keep the existing highlights
return newHighlight !== null ? newHighlight : highlights;
},
provide: (f) => EditorView.decorations.from(f),
});

export function useSquiggleEditorExtensions(
view: EditorView | undefined,
Expand Down Expand Up @@ -87,6 +109,7 @@ export function useSquiggleEditorExtensions(
// uncomment for local debugging:
// debugExtension(),
highlightSpecialChars(),
flashHighlightField,
history(),
drawSelection(),
dropCursor(),
Expand Down Expand Up @@ -128,6 +151,7 @@ export function useSquiggleEditorExtensions(
height: params.height,
}),
tooltipsExtension(),
flashHighlightField,
];

return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export const ValueWithContextViewer: FC<Props> = ({
? "mb-2 px-0.5 py-1 focus:bg-indigo-50"
: "focus:bg-indigo-100"
)}
onFocus={(_) => {
onMouseEnter={(_) => {
scrollEditorToPath();
}}
onKeyDown={(event) => {
Expand Down

0 comments on commit 42ff02c

Please sign in to comment.