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:
-
What is Sublime’s official behavior when it reorders completions? (Seems like it’s based on number of “words” in the symbol)
-
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? -
Is there a way to prevent Sublime from do this post processing and just accepting the completions from the plugin as is?