From a21831e7f992a014d705cc09f40a5bc5bfaf7ee1 Mon Sep 17 00:00:00 2001 From: Jonathan Slenders Date: Tue, 28 May 2024 09:38:59 +0000 Subject: [PATCH] Improve performance of GrammarCompleter (faster deduplication of completions). --- .../contrib/regular_languages/completion.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/prompt_toolkit/contrib/regular_languages/completion.py b/src/prompt_toolkit/contrib/regular_languages/completion.py index 126e02752..19ebaad93 100644 --- a/src/prompt_toolkit/contrib/regular_languages/completion.py +++ b/src/prompt_toolkit/contrib/regular_languages/completion.py @@ -38,12 +38,10 @@ def get_completions( m = self.compiled_grammar.match_prefix(document.text_before_cursor) if m: - completions = self._remove_duplicates( + yield from self._remove_duplicates( self._get_completions_for_match(m, complete_event) ) - yield from completions - def _get_completions_for_match( self, match: Match, complete_event: CompleteEvent ) -> Iterable[Completion]: @@ -82,14 +80,21 @@ def _get_completions_for_match( display_meta=completion.display_meta, ) - def _remove_duplicates(self, items: Iterable[Completion]) -> list[Completion]: + def _remove_duplicates(self, items: Iterable[Completion]) -> Iterable[Completion]: """ Remove duplicates, while keeping the order. (Sometimes we have duplicates, because the there several matches of the same grammar, each yielding similar completions.) """ - result: list[Completion] = [] - for i in items: - if i not in result: - result.append(i) - return result + + def hash_completion(completion: Completion) -> tuple[str, int]: + return completion.text, completion.start_position + + yielded_so_far: set[tuple[str, int]] = set() + + for completion in items: + hash_value = hash_completion(completion) + + if hash_value not in yielded_so_far: + yielded_so_far.add(hash_value) + yield completion