diff --git a/prompt_toolkit/completion/base.py b/prompt_toolkit/completion/base.py index 821cc5b72..d867b632f 100644 --- a/prompt_toolkit/completion/base.py +++ b/prompt_toolkit/completion/base.py @@ -87,7 +87,7 @@ def __eq__(self, other: object) -> bool: ) def __hash__(self) -> int: - return hash((self.text, self.start_position, self.display, self._display_meta)) + return hash((self.text, self.start_position, self.style)) @property def display_text(self) -> str: diff --git a/prompt_toolkit/completion/nested.py b/prompt_toolkit/completion/nested.py index 8b0978ca3..79f41083e 100644 --- a/prompt_toolkit/completion/nested.py +++ b/prompt_toolkit/completion/nested.py @@ -10,7 +10,7 @@ __all__ = ["NestedCompleter"] # NestedDict = Mapping[str, Union['NestedDict', Set[str], None, Completer]] -NestedDict = Mapping[str, Union[Any, Set[str], None, Completer]] +NestedDict = Mapping[Union[str, Completion], Union[Any, Set[str], None, Completer]] class NestedCompleter(Completer): @@ -86,6 +86,10 @@ def get_completions( if " " in text: first_term = text.split()[0] completer = self.options.get(first_term) + if completer is None: + matching = (c for c in self.options.keys() if + isinstance(c, Completion) and c.text==first_term) + completer = self.options.get(next(matching, None)) # If we have a sub completer, use this for the completions. if completer is not None: diff --git a/prompt_toolkit/completion/word_completer.py b/prompt_toolkit/completion/word_completer.py index 3e9b4b718..806c09b95 100644 --- a/prompt_toolkit/completion/word_completer.py +++ b/prompt_toolkit/completion/word_completer.py @@ -30,7 +30,7 @@ class WordCompleter(Completer): def __init__( self, - words: Union[List[str], Callable[[], List[str]]], + words: Union[List[Union[str, Completion]], Callable[[], Union[str, Completion]]], ignore_case: bool = False, meta_dict: Optional[Dict[str, str]] = None, WORD: bool = False, @@ -78,7 +78,12 @@ def word_matches(word: str) -> bool: else: return word.startswith(word_before_cursor) + start_position = -len(word_before_cursor) for a in words: - if word_matches(a): + if isinstance(a, Completion): + if word_matches(a.text): + a.start_position = start_position + yield(a) + elif word_matches(a): display_meta = self.meta_dict.get(a, "") - yield Completion(a, -len(word_before_cursor), display_meta=display_meta) + yield Completion(a, start_position, display_meta=display_meta)