Search code examples
sublimetext3sublimetextsublime-text-pluginpackage-controlsublimetext-snippet

Autocompletion list RESET when typing a dot on SublimeText


I implemented a SublimeText autocompletion plugin:

import sublime_plugin
import sublime

tensorflow_functions = ["tf.test","tf.AggregationMethod","tf.Assert","tf.AttrValue", (etc....)]

class TensorflowAutocomplete(sublime_plugin.EventListener):

    def __init__(self):

        self.tf_completions = [("%s \tTensorflow" % s, s) for s in tensorflow_functions]

    def on_query_completions(self, view, prefix, locations):

        if view.match_selector(locations[0], 'source.python'):
            return self.tf_completions
        else:
            return[]

It works great but the problem is when I type a "." it resets the completion suggestions.

For example I type "tf" it suggests me all my custom list but then I type "tf." it suggests me a list as I didn't type "tf" before. I want my script to take consideration of what was typed before dots.

It's hard to explain. Do you have any idea what I need to do?

EDIT :

Here's what it does:

enter image description here

You can see here that "tf" isn't highlighted.


Solution

  • Usually Sublime Text replaces everything until the last word separator (i.e. the dot) and inserts your completion text.

    If you want to insert a completion with a word separator you just need to strip the content, which will not be replaced. So you just look at the line before, extract the text before the last dot, filter and strip you completions. This is my general pattern to do this:

    import re
    
    import sublime_plugin
    import sublime
    
    tensorflow_functions = ["tf.AggregationMethod()","tf.Assert()","tf.AttrValue()","tf.AttrValue.ListValue()"]
    
    RE_TRIGGER_BEFORE = re.compile(
        r"\w*(\.[\w\.]+)"
    )
    
    
    class TensorflowAutocomplete(sublime_plugin.EventListener):
    
        def __init__(self):
    
            self.tf_completions = [("%s \tTensorflow" % s, s) for s in tensorflow_functions]
    
        def on_query_completions(self, view, prefix, locations):
    
            loc = locations[0]
            if not view.match_selector(loc, 'source.python'):
                return
    
            completions = self.tf_completions
            # get the inverted line before the location
            line_before_reg = sublime.Region(view.line(loc).a, loc)
            line_before = view.substr(line_before_reg)[::-1]
    
            # check if it matches the trigger
            m = RE_TRIGGER_BEFORE.match(line_before)
            if m:
                # get the text before the .
                trigger = m.group(1)[::-1]
                # filter and strip the completions
                completions = [
                    (c[0], c[1][len(trigger):]) for c in completions
                    if c[1].startswith(trigger)
                ]
    
            return completions