Sublime Forum

How does autocomplete sorting work?

#1

TL;DR Sublime seems to reorder/filter completions returned by on_query_completions before presenting them to the user. Is there a way to stop this behavior?


Hello! I’m the author of a plugin that uses code analysis and machine learning to show relevant completions as the user types. (Full disclosure: I am an employee of Kite, the company behind the code engine.)

I’ve noticed that Sublime seems to do some sorting of completions under the hood before presenting them to the user in the completions UI. This is a problem for me because the order in which I send completions back is based on a relevance ranking, and so when Sublime reorders the completions, the user loses out on all the analysis and ML that has been performed.

To make this problem more clear, let’s assume the user’s editor is in the following state (the $ denotes the user’s cursor position):

the_right_one = 'foo'
thewrongone = 'bar'

t$

One thing I’ve noticed is that symbols with _ in them are ranked lower than symbols without, and so in this situation, even if I rank the the_right_one before thewrongone, Sublime will sort my completions and return thewrongone as the first completion!

Here is an example plugin that exhibits this behavior:

import sublime
import sublime_plugin

class EventDispatcher(sublime_plugin.EventListener):
    def on_modified(self, view):
        CompletionsHandler.run_completions(view)

class CompletionsHandler(sublime_plugin.EventListener):
    def on_query_completions(self, view, prefix, locations):
        print('showing completions')
        return [
            # ['foo bar', 'foo bar'],
            ['foo_bar', 'foo_bar'],
            ['fooBar', 'fooBar'],
            ['foobar', 'foobar'],
            ['defg', 'defg']
        ]

    @classmethod
    def run_completions(cls, view):
        print('running completions')
        view.run_command('auto_complete', {
            'api_completions_only': True,
            'disable_auto_insert': True,
            'next_completion_if_showing': False,
        })

This plugin essentially calls on_query_complete on every keystroke via the auto_complete command.

To reproduce the behavior that I’m describing above, start with an empty file and type the letter f.

Note: I used Sublime 3176 for all these examples.

What I would expect to see is the completions being shown in this order: ['foo_bar', 'fooBar', 'foobar']. Instead, the order is ['foobar', 'foo_bar', 'fooBar']. (Note that defg gets filtered out presumably due to the prefix not matching). Sublime has sorted the completions such that foobar is now the first item in the list.

Another unexpected thing happens when you uncomment the first completion on line 14 (['foo bar', 'foo bar']) in the CompletionsHandler.on_query_completions definition. In this case, defg is now returned as a completion! It seems like the addition of foo bar as a completion has changed the filtering rules that Sublime uses under the hood.

My questions are:

  1. What is Sublime’s official behavior when it reorders completions? (Seems like it’s based on number of “words” in the symbol)

  2. What is Sublime’s official behavior for deciding whether or not to filter out completions? e.g. why is defg filtered out in the first case but not the second case?

  3. Is there a way to prevent Sublime from do this post processing and just accepting the completions from the plugin as is?

0 Likes

#2

Did you get anywhere with this in the end? I am interested in a way of prioritising matches from the local file over those from plugins.

0 Likes

#3

Unfortunately not. I don’t think there’s a way to bypass the ranking that Sublime does automatically.

0 Likes