autocomplete snippetCompletion info is not a function

Hi CodeMirror community,

I’m developing a customized snippetCompletion functionality for the editor and have tried the example from the manual of autocomplete, which works like a charm. However, I can only specify the info field of snippetCompletion’s Completion field with string type instead of the function type(2nd alternative) or a Javascript Object type/Dictionary(3rd alternative).

Here’s the part of the code that triggers error when I switch the info from string type to dictionary type.

async function autocompleteAPIcall(context, word) {
    const BASE_API_URL = 'http://127.0.0.1:5000'
    const config = {
        baseURL: BASE_API_URL,
        headers: {
            'Content-Type': 'application/JSON',
            'Access-Control-Allow-Origin':'*'
        }
    };
    const data = {context_obj: context, word_obj: word};
    try{
        const response = await axios.post('/', data, config);  
        console.log("response: ", response);

        const snippets = response.data.map((snippet_dict) => {
            const lines = snippet_dict.info.split('|');
            const snippet_dom = document.createElement("div");
            snippet_dom.className = "container";
            for (var i=0; i <= lines.length - 1;i++) {
                const line_dom = document.createElement('div');
                line_dom.textContent = lines[i];
                snippet_dom.appendChild(line_dom);
            }

            return snippetCompletion(snippet_dict.tmp_str, {label: snippet_dict.label, info: {dom: snippet_dom}});
        });
        console.log("snippets:");
        console.log(snippets);
        console.log("-----------------");
        return snippets;
    } catch(error) {
        console.log("error: ", error);
        return [
            {label: "match", type: "keyword"},
            {label: "hello", type: "variable", info: "(World)"},
            {label: "magic", type: "text", apply: "⠁⭒*.✩.*⭒⠁", detail: "macro"}
        ];
    }
}

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

in line 25, it works with return snippetCompletion(snippet_dict.tmp_str, {label: snippet_dict.label, info: snippet_dict.info}) since snippet_dict.info is a string. However, I may like to provide some layout structures in the info and followed the other alternatives of the info field according to the document.

I got the following error in browser when using the {dom: Node, destroy⁠?: fn()} option as shown in the code block above.

index.js:1 CodeMirror plugin crashed: TypeError: info is not a function
    at CompletionTooltip.updateSel (index.js:536:1)
    at CompletionTooltip.mount (index.js:490:1)
    at push../node_modules/@codemirror/view/dist/index.js.ViewPlugin.fromClass.eventHandlers.scroll.createTooltip (index.js:8784:1)
    at TooltipViewManager.createTooltipView (index.js:8709:1)
    at TooltipViewManager.update (index.js:8657:1)
    at push../node_modules/@codemirror/view/dist/index.js.ViewPlugin.fromClass.eventHandlers.scroll.update (index.js:8747:1)
    at PluginInstance.update (index.js:1993:1)
    at EditorView.updatePlugins (index.js:6796:1)
    at EditorView.update (index.js:6703:1)
    at EditorView._dispatch (index.js:6561:1)
    at EditorView.dispatch (index.js:6629:1)
    at push../node_modules/@codemirror/autocomplete/dist/index.js._codemirror_view__WEBPACK_IMPORTED_MODULE_1__.ViewPlugin.fromClass.eventHandlers.blur.accept (index.js:1139:1)
    at push../node_modules/@codemirror/autocomplete/dist/index.js._codemirror_view__WEBPACK_IMPORTED_MODULE_1__.ViewPlugin.fromClass.eventHandlers.blur.scheduleAccept (index.js:1092:1)
    at index.js:1084:1

I have tried to look for similar problems/questions on the forum and github issues for a while but haven’t found any solutions yet so decide to post it here for any kind help from the community.
Appreciate your comments and help! :pray:

I think you’re reading this type wrong. It can’t be a {dom} object, but can be a function returning such an object.

1 Like

Hi marijn,

Thank you very much for your reply. I thought the pipes in the document means valid alternative types for the info field, in this case it means the returning type of the fn(the alternative type besides the string)?

info?: string |
fn(completion: Completion) → Node |
{dom: Node, destroy?: fn()} |
Promise |
null

I created a function with a completion as input with an extra infolines field, now it works! Thanks a lot for your help marijn.

here’s the code:

function infoDomCreater(completion){
    console.log("completion: ", completion);
    const lines = completion.infolines;
    const snippet_dom = document.createElement("div");
    snippet_dom.className = "container";
    for (var i=0; i <= lines.length - 1;i++) {
        const line_dom = document.createElement('div');
        const line_text = document.createTextNode(lines[i]);
        line_dom.appendChild(line_text);
        snippet_dom.appendChild(line_dom);
    }
    return snippet_dom;
};