Skip to content

Decorations ​

What a language server or version control knows reaches the editor as decorations. Each setter replaces what was set before, and most decorations follow their text through edits until the host sets them again.

tsx
import { useCallback, useState } from 'react';
import type { Editor } from '@adecore/editor';
import { EditorFrame } from '../shared/editor-frame.tsx';
import { SAMPLE, useEditor } from '../shared/editor.ts';

const OPTIONS = { text: SAMPLE, language: 'typescript', theme: 'demo' } as const;

const range = (line: number, from: number, to: number) => ({ start: { line, character: from }, end: { line, character: to } });

/* What a language server and a version control system would hand the editor, set once by hand. */
function decorate(editor: Editor): void {
    editor.setMarkers([
        { range: range(3, 34, 43), severity: 'error', message: "Cannot find name 'OrderLine'." },
        { range: range(6, 35, 43), severity: 'warning', deprecated: true, message: "'quantity' is deprecated." }
    ]);
    editor.setInlayHints([
        { position: { line: 4, character: 13 }, label: ': number' },
        { position: { line: 12, character: 29 }, label: 'lines:' }
    ]);
    editor.setHighlights([
        { range: range(4, 8, 13), kind: 'write' },
        { range: range(6, 8, 13), kind: 'write' },
        { range: range(8, 11, 16), kind: 'read' }
    ]);
    editor.setChangeMarks([
        { kind: 'modified', startLine: 7, endLine: 7 },
        { kind: 'added', startLine: 12, endLine: 15 }
    ]);
    editor.setGutterAction({ line: 3, label: 'Show fixes' });
}

export default function DecorationsDemo() {
    const [pressed, setPressed] = useState<number | null>(null);
    const setup = useCallback((editor: Editor) => {
        decorate(editor);
        return editor.onGutterAction(setPressed);
    }, []);
    const { host } = useEditor(OPTIONS, setup);

    return (
        <EditorFrame
            host={host}
            toolbar={
                <span className="px-1 text-xs text-text-muted">
                    {pressed === null ? 'Press the button in the gutter of line 4.' : `The gutter action of line ${pressed + 1} was pressed.`}
                </span>
            }
        />
    );
}

Problems ​

setMarkers(markers) draws problems: a squiggle under the range and a tick in the scroll track, colored by severity (error, warning, info or hint). unnecessary: true fades the text and deprecated: true strikes it through. A message is what the tick says under the pointer, and a press on the tick goes to the problem.

ts
editor.setMarkers([
    {
        range: { start: { line: 3, character: 34 }, end: { line: 3, character: 43 } },
        severity: 'error',
        message: "Cannot find name 'OrderLine'."
    }
]);

The editor draws no message card of its own. @adecore/editor-react shows one on hover.

Names and hints ​

  • setHighlights(highlights) marks the other uses of the name at the caret, each with a kind of text, read or write. The next edit clears them.
  • setLink(range) underlines a range as a link under the pointer, such as a name while Mod is held, until the next setLink or edit; null removes it.
  • setInlayHints(hints) draws a label as a soft pill between two characters, such as a parameter name or a type. It is not part of the text.

Semantic colors ​

setSemanticTokens(tokens) colors ranges by what a language server knows, over what the grammar made of them. Each EditorSemanticToken has a line, character, length and the TextMate scopes it stands for; the theme decides the color. That needs scopeColors on the engine, usually shikiScopeColors; without it the tokens are ignored. null removes them. See Theme and syntax.

Change marks ​

setChangeMarks(marks) draws how the text differs from the version the app compares against, in the gutter and in the scroll track. An EditorChangeMark has a kind of added, modified or deleted and one-based, inclusive startLine and endLine. A deleted mark sits above the line the removed lines were above, so its two lines are the same.

Gutter buttons ​

  • setGutterAction(action) puts one button in the gutter, { line, label }, such as a lightbulb for code actions. onGutterAction reports a press with the zero-based line. null removes it.
  • setGutterMarkers(markers, owner?) puts small buttons on lines, { id, line, label }, such as the mark of a saved inline edit. Each owner has its own set and default is the owner without one. onGutterMarker reports a press with the id.

Lines, from one or from zero ​

The decorations that cover whole lines take one-based, inclusive lines: change marks, attribution marks and line highlights. Everything placed on a single line takes a zero-based line: widgets, line actions, code vision, gutter actions and gutter markers. Markers, highlights, links, inlay hints and remote cursors take EditorPositions.

Licenses and third-party notices are listed in each package.