codemirror-languageserver

Language Server Protocol support for CodeMirror 6 — completions, hover, diagnostics, and more.

⌨️ Code Completion

Autocomplete with resolve support, triggered by typing or trigger characters.

📚 Hover Documentation

Rich hover tooltips with Markdown rendering for any symbol.

🩺 Diagnostics

Real-time errors and warnings from the language server, shown inline.

🔍 Go to Definition

Jump to definition, declaration, or type definition with F12.

🔦 Document Highlight

All occurrences of a symbol are highlighted when the cursor is on it.

🎨 Formatting

Format the entire document or a selection via the language server.

✏️ Rename Symbol

Rename a symbol across the document with an inline prompt.

🔌 Custom Transport

WebSocket out of the box, or bring your own transport (Web Workers, MessagePort, etc.).

Live Demo

This editor is connected to a minimal JavaScript LSP server running entirely in a Web Worker — no backend needed.

Type console. for completions Hover over Math, document, JSON Click a word to see highlights Shift+Alt+F to format F2 to rename

Quick Start

1. Install

npm i codemirror-languageserver

2. Connect to a language server over WebSocket

import { EditorState } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { languageServer } from 'codemirror-languageserver';

const ls = languageServer({
    serverUri: 'ws://localhost:8080',
    rootUri: 'file:///',
    documentUri: 'file:///main.cpp',
    languageId: 'cpp',
});

const view = new EditorView({
    state: EditorState.create({
        extensions: [/* other extensions, */ ls],
    }),
});

3. Or use a custom transport (like this demo does)

import { languageServerWithTransport } from 'codemirror-languageserver';

const worker = new Worker('./lsp-worker.js', { type: 'module' });

// WorkerTransport implements the Transport interface:
//   send(), onMessage(), onClose(), onError(), close()
const transport = new WorkerTransport(worker);

const ls = languageServerWithTransport({
    transport,
    rootUri: 'file:///',
    documentUri: 'file:///demo.js',
    languageId: 'javascript',
});

4. Add keybindings for formatting and rename

import { keymap } from '@codemirror/view';
import {
    formatDocument,
    formatSelection,
    renameSymbol,
} from 'codemirror-languageserver';

keymap.of([
    { key: 'Shift-Alt-f', run: formatDocument },
    { key: 'Ctrl-k Ctrl-f', run: formatSelection },
    { key: 'F2', run: renameSymbol },
])

5. React to server capabilities

languageServer({
    serverUri: 'ws://localhost:8080',
    rootUri: 'file:///',
    documentUri: 'file:///main.cpp',
    languageId: 'cpp',
    onCapabilities(capabilities) {
        // Update your UI based on what the server supports
        // e.g. capabilities.documentFormattingProvider
    },
    onError(error) {
        console.error('LSP error:', error);
    },
    onClose() {
        console.log('LSP connection closed');
    },
})