LSP client request: Support for sortText on CompletionItem

Currently the Completion type in @codemirror/autocomplete supports the boost field to specify a custom ranking of results.

However, in the LSP specification for CompletionItem each item has the sortText field to specify a custom string-based sorting:

	/**
	 * A string that should be used when comparing this item
	 * with other items. When omitted the label is used
	 * as the sort text for this item.
	 */
	sortText?: string;

The two do differ in their types - boost: number and is sortText: string.

Would it be possible to include support for sortText in the LSP client?

I would expect it should be done in completion.ts, but I don’t know if it would align well with boost currently being number typed.

Thank you!

This discussion touched it briefly too: Codemirror 6 and Typescript LSP

I’ve tried implementing a “proxy” CompletionSource for it, and while doable, it will almost be identical to of the LSP serverCompletionSource implementation except for the handling of boost. It would be nice have some handle to control the sorting through the LSP CompletionItem without reimplementing the whole thing.

Some ideas (FWIW):

Would it be possible to pass in a function in the config for serverCompletion that would take the returned CompletionItem from the LSP Server and convert the sortText value to a boost number type? (This would also allow for the custom handling of the string to number conversion).

Or perhaps an ability to access the raw LSP CompletionItem on each Completion[] item on the options field in CompletionResult (both from @codemirror/autocomplete)? This would mean we could write a completion source wrapper that could do custom sorting and filtering, something like:

// Rough draft of transforming a completion result into a Completion with a boost field:
const transformedServerCompletion: CompletionSource = async (context: CompletionContext) => {
    const result = await serverCompletionSource(context);
    if (!result) return null;

    const transformedOptions = result.options.map((item) => ({
        ...item,
        boost: Number(item.lspServerCompletionResult.sortText),
    }));

    return {
        ...result,
        options: transformedOptions,
    };
};

boost does something very different from sortText, and there’s no reasonable way to implement the later in terms of the former. You can use the compareCompletions option to implement support for sortText already, but I guess if we’re going to support in in the LSP completions it might make sense to support it by default. Would that work for you?

Absolutely, it would be very nice if sortText had native support. And I agree that there’s no good general way to convert a string to a number in range -99..99.

I can’t use compareCompletions now because sortText is discarded before becoming a Completion (the type used in @codemirrorcodemirror/autocomplete).

So if I could access sortText somehow on a Completion, that would already solve the problem through compareCompletions. (That was my 2nd suggestion, ability to access the raw LSP CompletionItem on the Completion type).

However, implementing built-in support for sortText would be even better and easier to use.

Thank you for your reply!

1 Like

Try with @codemirror/lsp-client 6.2.1

Amazing, thanks! I’ll take a look!

I just tested it. It works great! Thank you!