How to append to existing JavaScript autocompletions and snippets?

I know how to override the current autocompletions. But I just want to append my own list of autocompletions to the existing built-in CodeMirror v6 autocompletions.

Is there a way to do that? I thought maybe I could append my array of completions to the built-in set, but I haven’t been able to figure out how to get the current list in order to append mine to them.

Thanks,

Brendan

Just define another completion source through language data, and its result will be combined with other sources.

Thanks for the suggestion. I’m trying that now, but not getting anywhere unfortunately. This is what I’ve tried so far after hunting down examples and looking through the source code of CodeMirror to try and find out how to use languageDataOf. I’m sorry, but I’m new to CodeMirror and not super adept at JavaScript. I’m more of an Objective-C and Swift developer.

const completions = [
    {label: "fetchRecords", type: "keyword"},
    {label: "record", type: "variable", info: "The current selected record"},
    {label: "form", type: "variable", info: "The current selected form"},
    {label: "search", type: "variable", info: "The current selected search"},
    {label: "document", type: "variable", info: "The current opened document"},
    {label: "Utils", type: "keyword"},
];

function myCompletions(context) {
    let word = context.matchBefore(/\w*/)
    if (word.from == word.to && !context.explicit)
        return null
        return {
            from: word.from,
        options: completions
        }
};

function javascriptCompletions(context) {
    let word = context.matchBefore(/\w*/)
    if (word.from == word.to && !context.explicit)
        return null
        return {
            from: word.from,
        options: editorView.state.languageDataAt("autocomplete")
        }
};


const editorView = new CodeMirror.EditorView({
  doc: "",
  state: EditorState.create({
  extensions: [
      lineNumbers(),
      highlightActiveLineGutter(),
      highlightSpecialChars(),
      history(),
      foldGutter(),
      drawSelection(),
      dropCursor(),
      indentOnInput(),
      syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
      bracketMatching(),
      closeBrackets(),
      autocompletion({override: [myCompletions, javascriptCompletions]}),
      rectangularSelection(),
      crosshairCursor(),
      highlightActiveLine(),
      highlightSelectionMatches(),
      keymap.of([
          ...closeBracketsKeymap,
             ...defaultKeymap,
             ...searchKeymap,
             ...historyKeymap,
             ...foldKeymap,
             ...completionKeymap,
             indentWithTab,
      ]),
      readOnly.of([]),
      lineWrapping.of([]),
      baseTheme,
      theme.of(oneDark),
      language.of(javascript()),
      listener.of([]),
  ],
  }),
  
  parent: document.body,
});

Ok, I figured it out. It was helpful for me to look at the source code of the web page that held the autocompletion documentation and sample entry field. I didn’t realize you had to setup this const and then add it to the EditorView extensions along side the autocompletion() bit.

const myNewCompletions = javascriptLanguage.data.of({
autocomplete: myCompletions
});

new EditorView({
    doc: "/** Complete tags here\n    @pa\n */\n",
    extensions: [
      basicSetup,
      javascriptLanguage,
      myNewCompletions,
      autocompletion()
    ],
    parent: document.querySelector("#editor-javascript")
  });
2 Likes

I can see above, my approach is more brute-force, I try to go to the source code to make changes.I found the following code in the source code.

let kwCompletion = (name) => ({ label: name, type: "keyword" });
let fnCompletion = (name) => ({ label: name, type: "function" });
let clCompletion = (name) => ({ label: name, type: "class" });
// const keywords = "break case const continue default delete export extends false finally in instanceof let new return static super switch this throw true typeof var yield".split(" ").map(kwCompletion);
//TODO:
const keywords = "break case catch class const continue debugger default delete do else export extends false finally for function if import in instanceof let new null return super switch this throw true try typeof var void while with yield await async enum implements interface package private protected public static".split(" ").map(kwCompletion);

const functions = "alert prompt confirm setTimeout setInterval clearTimeout clearInterval eval parseInt parseFloat isNaN isFinite encodeURI decodeURI encodeURIComponent decodeURIComponent Math Date JSON console window document navigator location history screen fetch async await".split(" ").map(fnCompletion);

const classes = "String Array Object Number Boolean RegExp Function Promise Map Set WeakMap WeakSet Symbol Error TypeError SyntaxError RangeError ReferenceError URIError EvalError Proxy Reflect Generator GeneratorFunction AsyncFunction ArrayBuffer DataView Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array BigInt64Array BigUint64Array BigInt".split(" ").map(clCompletion);

const typescriptKeywords = keywords.concat(["declare", "implements", "private", "protected", "public"].map(kwCompletion));
/**
JavaScript support. Includes [snippet](https://codemirror.net/6/docs/ref/#lang-javascript.snippets)
completion.
*/
function javascript(config = {}) {
    let lang = config.jsx ? (config.typescript ? tsxLanguage : jsxLanguage)
        : config.typescript ? typescriptLanguage : javascriptLanguage;
    let completions = config.typescript ? typescriptSnippets.concat(typescriptKeywords) : snippets.concat(keywords).concat(functions).concat(classes);
    return new language.LanguageSupport(lang, [
        javascriptLanguage.data.of({
            autocomplete: autocomplete.ifNotIn(dontComplete, autocomplete.completeFromList(completions))
        }),
        javascriptLanguage.data.of({
            autocomplete: localCompletionSource
        }),
        config.jsx ? autoCloseTags : [],
    ]);

You can see that the top method turns the array into an autocomplete set,kwCompletion is the original, and the other two are added by myself,In addition, I’ve expanded the keyword array.
The other thing I changed is I changed let completions = config.typescript ? typescriptSnippets.concat(typescriptKeywords) : snippets.concat(keywords) to let completions = config.typescript ? typescriptSnippets.concat(typescriptKeywords) : snippets.concat(keywords).concat(functions).concat(classes);.
Everything looks fine, but it doesn’t work, autocompletion is still old, I don’t understand why