CodeMirror autocomplete: replace the typed range with the chosen value

In CodeMirror 6, add autocompletion() and supply a completion source when the editor needs its own vocabulary. The source returns the replacement start and available options; CodeMirror filters the list as the author types. Return null outside the contexts your vocabulary supports. Official autocompletion example

Imagine a small source editor for an internal publishing tool. Authors enter uppercase tokens such as ROOM_NAME in a plain-text message template. Typing RO should offer ROOM_NAME; choosing it should produce ROOM_NAME, without leaving the typed RO in front. The saved template keeps a token, while a separate renderer supplies the room's actual name.

Define a completion source with a bounded range

This fragment is application source for a CodeMirror 6 build, with compatible packages installed:

import { autocompletion } from '@codemirror/autocomplete';

function messageTokens(context) {
  const word = context.matchBefore(/[A-Z_]*/);
  if (!word || (word.from === word.to && !context.explicit)) {
    return null;
  }
  return {
    from: word.from,
    options: [
      { label: 'ROOM_NAME', type: 'variable', detail: 'Assigned room' },
      { label: 'ARRIVAL_TIME', type: 'variable', detail: 'Expected arrival' }
    ],
    validFor: /^[A-Z_]*$/
  };
}

const messageCompletion = autocompletion({
  override: [messageTokens]
});

Add messageCompletion to the editor's existing extensions. This example intentionally targets a dedicated plain-text token editor. It does not parse HTML attribute positions, quoted strings, or a programming language's syntax.

from identifies the beginning of the typed token. The replacement ends at the completion position by default. label supplies both the displayed label and inserted text unless an option defines its own apply behavior. validFor permits reuse of these options while the edited range remains uppercase letters and underscores.

Preserve language suggestions when adding a local vocabulary

override replaces the normal language-data completion sources for this configuration. That is intentional for the small template editor. In an HTML or mixed-language editor, overriding all sources can remove useful element and attribute suggestions.

For a vocabulary tied to a language, follow CodeMirror's language-data integration and inspect the syntax around the cursor. The autocomplete reference describes completion contexts and results. Restrict a template-only source to the actual token syntax your application uses, rather than returning every token after every cursor movement.

If a token needs braces in the output while its label stays uncluttered, an option can provide a different inserted string:

const bracedRoomToken = {
  label: 'ROOM_NAME',
  type: 'variable',
  apply: '{{ROOM_NAME}}'
};

Use this option in a deliberately configured braced-token mode. Its replacement range still has to include whichever opening characters your matching rule considers part of the token. Changing the inserted string does not automatically change that rule.

Use the completion interface before adding custom keys

The default completion keymap provides an explicit completion command, selection, acceptance, and dismissal. Tab is not bound to completion acceptance by default. If your interface adds a Tab rule, account for ordinary focus navigation and indentation before shipping it.

The keyboard binding guide illustrates why visible actions and key handling need a deliberate policy, though its Quill API differs. Use CodeMirror's own commands and keymap mechanism here.

Check inserted text and saved text separately

In your running application, type RO, request completion if necessary, and choose ROOM_NAME. Inspect the actual editor document. It should contain the chosen token once. Try an empty position with an explicit completion request, type lowercase prose, and dismiss the picker without inserting anything.

Then capture view.state.doc.toString() at the application's save action. Reopen the stored template and confirm that ROOM_NAME remains a token. The completion source supplies authoring choices; it does not validate a recipient's room assignment or resolve the template's value.

Keep reading