Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
rwols opened this issue Nov 28, 2020 · 5 comments
Assignees

Comments

@rwols
Copy link

rwols commented Nov 28, 2020

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.

@rchl
Copy link

rchl commented Feb 5, 2022

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
Copy link

rchl commented Aug 6, 2022

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
Copy link

rchl commented Aug 6, 2022

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.

@BenjaminSchaaf BenjaminSchaaf self-assigned this Oct 26, 2023
@BenjaminSchaaf
Copy link
Member

Fixed in build 4161.

@rchl
Copy link

rchl commented Nov 8, 2023

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).

@BenjaminSchaaf BenjaminSchaaf reopened this Nov 9, 2023
@BenjaminSchaaf BenjaminSchaaf removed this from the Build 4162 milestone Nov 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants