I can't autocomplete for expressions containing white space

I wrote customm autocomplete logic in my code. But this autocomplete only performs word-based autocomplete. Spaces stop autocomplete.

function completions(context: any) {
    const word = context.matchBefore(/\w*/);

    // Return null if the current context is not explicitly triggered and doesn't match a word
    if (word && word.from === word.to && !context.explicit) {
      return null;
    }

    // Provide completion options based on the fetched data
    return {
      from: word!.from,
      options: [...functions, ...variables].map((option: any) => {
        return {
          label: option.label,
          type: option.type,
          apply:
            option.type === 'calculations' || option.type === 'inputs'
              ? `{{${option.id},y,x}}` // if the option is a formula (calculations or input), add the braces
              : `${option.insert}`, // if the option is a function, single braces and add the insert text
          detail: option.type,
          description: option.description,
        };
      }),
    };
  }

This is custom completions function. I know that the problem is caused by regex, but even if I updated the regex, it causes other problems.

There isn’t enough info given to answer your question, e.g.

  • it causes other problems
    • what other problems?

I personally use the parseTree to get the nodeBefore to determine when/what to autocomplete

import { syntaxTree } from '@codemirror/language'
const nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1)
1 Like

Thanks for answer.

/* eslint-disable import/no-extraneous-dependencies */

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

import functions from './Functions';

/**
 * Sets up autocompletion behavior in the editor based on a selected idiom.
 * Fetches options from a JSON file corresponding to the idiom and configures autocompletion.
 * @param {EditorView} editor - The CodeMirror EditorView instance.
 * @param {Compartment} autocompleteCompartment - The compartment responsible for autocompletion.
 * @param {NonNullable<Toptions['idiom']>} newIdiom - The new idiom to be used for autocompletion.
 * @returns {Promise<any>} - A promise resolving upon successful autocompletion configuration.
 * @throws {Error} - Throws an error if fetching the options fails.
 */
export async function setAutocompletionIdiom(
  editor: any,
  autocompleteCompartment: any,
  variables: any,
) {
  // Function to render additional content for the autocompletion options
  function renderAdditionalContent(_completion: any, _state: any, _view: any) {
    // Create a DOM node based on the completion
    const additionalNode = document.createElement('div');
    additionalNode.classList.add('cm-description');
    additionalNode.textContent = `${_completion.description}`;
    return additionalNode;
  }

  // Autocompletion configuration with additional options
  const additionalOptions = [
    {
      position: 100,
      render: (completion: any, state: any, view: any) =>
        renderAdditionalContent(completion, state, view),
    },
  ];

  // Define completions for autocompletion based on the fetched options
  function completions(context: any) {
    const word = context.matchBefore(/\w*/);

    // Return null if the current context is not explicitly triggered and doesn't match a word
    if (word && word.from === word.to && !context.explicit) {
      return null;
    }

    // Provide completion options based on the fetched data
    return {
      from: word!.from,
      options: [...functions, ...variables].map((option: any) => {
        return {
          label: option.label,
          type: option.type,
          apply:
            option.type === 'calculations' || option.type === 'inputs'
              ? `{{${option.id},y,x}}` // if the option is a formula (calculations or input), add the braces
              : `${option.insert}`, // if the option is a function, single braces and add the insert text
          detail: option.type,
          description: option.description,
        };
      }),
    };
  }

  /**
   * Dispatches autocompletion configuration to the editor, updating the autocompletion behavior.
   *
   * @param {EditorView} editor - The EditorView instance where autocompletion is configured
   * @param {Compartment} autocompleteCompartment - The Compartment managing autocompletion configurations
   * @param {any[]} additionalOptions - Additional options to include in the autocompletion
   * @param {any[]} completions - List of completions to override the default autocomplete options
   * @returns {void}
   */
  editor.dispatch({
    effects: autocompleteCompartment.reconfigure(
      autocompletion({
        /**
         * The maximum number of options to render in the autocomplete dropdown.
         * @type {number}
         */
        maxRenderedOptions: 10,

        /**
         * Determines whether the autocomplete dropdown should close on blur or not.
         * @type {boolean}
         */
        closeOnBlur: false,

        /**
         * Additional options to append to the default autocompletion options.
         * @type {any[]}
         */
        addToOptions: additionalOptions,

        /**
         * List of completions to override the default autocomplete options.
         * @type {any[]}
         */
        override: [completions],

        /**
         * Function providing a tooltip class for autocomplete options.
         * @returns {string} - The class name for the tooltip
         */
        tooltipClass: () => 'myTooltip',

        /**
         * Function providing an option class based on the option type.
         * @param {any} option - The autocomplete option
         * @returns {string} - The class name for the autocomplete option
         */
        optionClass: (option: any) =>
          option.type === 'secondary'
            ? 'cm-secondaryCompletion'
            : 'cm-custom-main',
      }),
    ),
  });
}

This is full of the code for autocomplate feature.

  • what other problems?
    When i use diffrent experession for this const word = context.matchBefore(/\w*/); , it autocomplete one time or it doesn’t work.

@AlexErrant How can i determine i am trying to check multiple words for the search? and not break on new spacE?

In this commit of my project I made spaces work for historical completions in my app’s search bar. Obviously YMMV, but a simple () => true was enough for me. (Mostly because historical completions only make sense when from === 0, i.e. when there are no other letters in the search bar.)

You can play with that search here. And here’s a screenshot of a search with a space working with completions.

image