sublime_text icon indicating copy to clipboard operation
sublime_text copied to clipboard

[ST4] Cancel pending completion future when one of the items in auto_complete_triggers matches

Open rwols opened this issue 4 years ago • 3 comments
trafficstars

Problem description

When a plugin takes a long time to prepare results for on_query_completions using the sublime.CompletionList future, it can be the case that the user has finished typing the identifier. The user then types some sort of punctuation.accessor and wants to know the properties/methods of that identifier.

However, ST ignores this event and instead presents the completion results from when the user started typing the first character of the identifier.

Preferred solution

When one of the items in view.settings().get("auto_complete_triggers") (could be a "selector") matches the position to the left of the caret, cancel the inflight future, and re-do the on_query_completions callback.

Alternatives

N/A

Additional Information

incorrect In the above GIF, you can see me typing s.. The on_query_completions is called for the s character. After the plugin is done computing the completions, we are too late in presenting the completions. The user is already wanting to see the methods of the s String.

correct In this GIF, you can see me typing .. The on_query_completions is called because . matches one of the items in "auto_complete_triggers". This provides the user with the desired properties/methods.

rwols avatar Nov 28 '20 15:11 rwols

It seems to me like ST re-triggers the on_query_complitions now in that case (typing .).

Either that or behavior differs with and without the sublime.DYNAMIC_COMPLETIONS flag. I've only tried on an LSP server that doesn't set it. I guess we should have a simple test case for it that delays completions.

That said, even if fixed, that doesn't help the case when the initial request is slow (because of being very unspecific) and user expects the second request to trigger immediately on typing .. ST only triggers the second on_query_completions after first one is handled. There is no way that ST can indicate that the first request is to be canceled early.

rchl avatar Feb 05 '22 22:02 rchl

A small plugin for testing:

import sublime_plugin
from typing import List
from sublime import AutoCompleteFlags, CompletionItem, CompletionList, set_timeout


class CompletionListener(sublime_plugin.ViewEventListener):
    def on_query_completions(self, prefix, locations):
        print('on_query_completions, prefix: {}'.format(prefix))
        if prefix in ['a', 'aa']:
            return create_delayed_completions(['aaa'], 3000)
        elif prefix == '':
            return create_delayed_completions(['fast'], 1)


def create_delayed_completions(completions: List[str], delay: int) -> CompletionList:
    completion_list = CompletionList()
    flags = AutoCompleteFlags.INHIBIT_WORD_COMPLETIONS | AutoCompleteFlags.INHIBIT_EXPLICIT_COMPLETIONS
    # flags |= AutoCompleteFlags.DYNAMIC_COMPLETIONS
    set_timeout(lambda: completion_list.set_completions(completions, flags=flags), delay)
    return completion_list

Reproduction

  1. Open empty view and set syntax to JavaScript or Python.
  2. Type aa. quickly.

Expected: The completions show up immediately after the . character is typed

Actual: The completions requested when typing the first a character delay completions requested for the following . character.

Since completions requested for a are no longer relevant, those should be cancelled immediately and on_query_completions should be triggered right away.

Ideally the plugin code would also be notified when the completion request is canceled but it's probably not strictly necessary.

rchl avatar Aug 06 '22 19:08 rchl

I've also left out disabled line that sets the DYNAMIC_COMPLETIONS flag. With it enabled there is another, possibly a separate, issue with ST not triggering on_query_completions when typing the second a character.

Reproduction

  1. Enable commented out flags |= AutoCompleteFlags.DYNAMIC_COMPLETIONS line.
  2. Open empty view and set syntax to JavaScript or Python.
  3. Type aa

Expected: the on_query_completions should trigger separately both when typing the first and the second a

Actual: After typing aa, on_query_completions is only triggered once.

rchl avatar Aug 06 '22 19:08 rchl

Fixed in build 4161.

BenjaminSchaaf avatar Nov 08 '23 05:11 BenjaminSchaaf

I think this change has unintended side effect.

When I type a twice in a Python file, then on_query_completions is triggered twice. And that's without the DYNAMIC_COMPLETIONS flag. This can be seen with the plugin above since it triggers print on on_query_completions.

The expected behavior is that ST will re-trigger on_query_completions but only in cases where it would do that previously so in cases where completions should be triggered (like at the start of a word or on punctuation).

rchl avatar Nov 08 '23 09:11 rchl