Empty list of autocompletions in CompletionSource

Hi everyone. Can anyone help me with this problem?

Goal:
I’d like to produce additional completions in context of html document. When user start typing AttributeName type of node I want to provide additional completion with ="" at the end.

Poblem:
Currently I have a problem with syncing default html autocompletions in my custom CompletionSource.

When I’m trying to get currentCompletions(context.state) I’m getting an empty array, despite having a list of autocompletions displayed in the UI, e.g. start typing “c” → I’m getting class, contenteditable, contextmenu autocompletions, but array returned from currentCompletions is empty. When I enter 2nd character, i.e. “cl” → I’m getting class and onclick autocompletion and array returned from currentCompletions is not empty and contains these values.

So for some reason I’m able to get relevant list of autocompletion only after typing 2nd symbol.

Code sample (completion source):

export const getAttrCompletion: CompletionSource = (context) => {
  const nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1)

  if (nodeBefore.name === 'AttributeName') {
    const autoCompletions = currentCompletions(context.state)

    if (!autoCompletions.length) {
      return null
    }

    const match = context.matchBefore(/\w*/)

    if (!match) {
      return null
    }

    const {from} = match

    return {
      from,
      options: autoCompletions.map(completion => {
        const attrWithQuotes = completion.label + '=""'

        return [
          completion,
          {
            label: attrWithQuotes,
            boost: 99,
            type: 'text',
            apply: (view, completion, from, to) => {
              const cursorEndPosition = from + attrWithQuotes.length - 1

              view.dispatch({
                changes: {from, to, insert: attrWithQuotes},
                selection: {anchor: cursorEndPosition, head: cursorEndPosition}
              })
            },
          } as Completion
        ]
      }).flat()
    }
  }

  return null
}

That’s the list of completion sources I have:

return [
  html(),
  htmlLanguage.data.of({autocomplete: getAttrCompletion}),
]

What I tried to do:
Change the order between default html() source and my custom source, but since I’m getting correct list starting from 2nd character, I guess the order is not a problem.

Also tried to remove boost property from options, didn’t help.

Playground link
Custom completion source

I appreciate any help!

1 Like

You cannot query the current completions from a completion source—that runs when the completions are being recalculated, so there are no completions available then.

You could try wrapping the HTML completion source to do this.

Could you please clarify what you mean by “wrapping” in this context?

A completion source is a function. You can create a function that calls the regular source, does something with its results, and returns those, and use that as completion source instead.

Does it mean that I need to do something with returned LanguageSupport object from html extension?

  function customHtmlCompletion() {
    const ext = html()

    ...

    return ext
  }

I’m not sure how I can get autocompletion results and process them further with my custom logic, didn’t found a way to do that in docs.

Thanks in advance.

It means you probably don’t want to use the default html().support, but just the HTML language, and put together your own support extensions, one of which registers an HTML completion source that calls htmlCompletionSource.