Show More
@@ -753,7 +753,8 b' def get__all__entries(obj):' | |||||
753 | return [w for w in words if isinstance(w, str)] |
|
753 | return [w for w in words if isinstance(w, str)] | |
754 |
|
754 | |||
755 |
|
755 | |||
756 |
def match_dict_keys(keys: List[Union[str, bytes]], prefix: str, delims: str |
|
756 | def match_dict_keys(keys: List[Union[str, bytes, Tuple[Union[str, bytes]]]], prefix: str, delims: str, | |
|
757 | prefix_tuple: Tuple[str, bytes]=()) -> Tuple[str, int, List[str]]: | |||
757 | """Used by dict_key_matches, matching the prefix to a list of keys |
|
758 | """Used by dict_key_matches, matching the prefix to a list of keys | |
758 |
|
759 | |||
759 | Parameters |
|
760 | Parameters | |
@@ -761,9 +762,12 b' def match_dict_keys(keys: List[Union[str, bytes]], prefix: str, delims: str) -> ' | |||||
761 | keys: |
|
762 | keys: | |
762 | list of keys in dictionary currently being completed. |
|
763 | list of keys in dictionary currently being completed. | |
763 | prefix: |
|
764 | prefix: | |
764 |
Part of the text already typed by the user. |
|
765 | Part of the text already typed by the user. E.g. `mydict[b'fo` | |
765 | delims: |
|
766 | delims: | |
766 | String of delimiters to consider when finding the current key. |
|
767 | String of delimiters to consider when finding the current key. | |
|
768 | prefix_tuple: optional | |||
|
769 | Part of the text already typed in multi-key index cases. E.g. for | |||
|
770 | `mydict['foo', "bar", 'b`, this would be `('foo', 'bar')`. | |||
767 |
|
771 | |||
768 | Returns |
|
772 | Returns | |
769 | ======= |
|
773 | ======= | |
@@ -774,7 +778,23 b' def match_dict_keys(keys: List[Union[str, bytes]], prefix: str, delims: str) -> ' | |||||
774 | ``matches`` a list of replacement/completion |
|
778 | ``matches`` a list of replacement/completion | |
775 |
|
779 | |||
776 | """ |
|
780 | """ | |
777 | keys = [k for k in keys if isinstance(k, (str, bytes))] |
|
781 | Nprefix = len(prefix_tuple) | |
|
782 | def filter_by_prefix_tuple(key): | |||
|
783 | if len(key) < Nprefix: | |||
|
784 | return False | |||
|
785 | for k, pt in zip(key, prefix_tuple): | |||
|
786 | if k != pt: | |||
|
787 | return False | |||
|
788 | return True | |||
|
789 | ||||
|
790 | new_keys = [] | |||
|
791 | for k in keys: | |||
|
792 | if isinstance(k, (str, bytes)): | |||
|
793 | new_keys.append(k) | |||
|
794 | elif isinstance(k, tuple) and filter_by_prefix_tuple(k): | |||
|
795 | new_keys.append(k[Nprefix]) | |||
|
796 | ||||
|
797 | keys = new_keys | |||
778 | if not prefix: |
|
798 | if not prefix: | |
779 | return '', 0, [repr(k) for k in keys |
|
799 | return '', 0, [repr(k) for k in keys | |
780 | if isinstance(k, (str, bytes))] |
|
800 | if isinstance(k, (str, bytes))] | |
@@ -1641,6 +1661,7 b' class IPCompleter(Completer):' | |||||
1641 | ) |
|
1661 | ) | |
1642 | \[ # open bracket |
|
1662 | \[ # open bracket | |
1643 | \s* # and optional whitespace |
|
1663 | \s* # and optional whitespace | |
|
1664 | # Capture any number of str-like objects (e.g. "a", "b", 'c') | |||
1644 | ((?:[uUbB]? # string prefix (r not handled) |
|
1665 | ((?:[uUbB]? # string prefix (r not handled) | |
1645 | (?: |
|
1666 | (?: | |
1646 | '(?:[^']|(?<!\\)\\')*' |
|
1667 | '(?:[^']|(?<!\\)\\')*' | |
@@ -1670,10 +1691,11 b' class IPCompleter(Completer):' | |||||
1670 | } |
|
1691 | } | |
1671 |
|
1692 | |||
1672 | match = regexps[self.greedy].search(self.text_until_cursor) |
|
1693 | match = regexps[self.greedy].search(self.text_until_cursor) | |
|
1694 | ||||
1673 | if match is None: |
|
1695 | if match is None: | |
1674 | return [] |
|
1696 | return [] | |
1675 |
|
1697 | |||
1676 | expr, prefix = match.groups() |
|
1698 | expr, prefix0, prefix = match.groups() | |
1677 | try: |
|
1699 | try: | |
1678 | obj = eval(expr, self.namespace) |
|
1700 | obj = eval(expr, self.namespace) | |
1679 | except Exception: |
|
1701 | except Exception: | |
@@ -1685,7 +1707,13 b' class IPCompleter(Completer):' | |||||
1685 | keys = self._get_keys(obj) |
|
1707 | keys = self._get_keys(obj) | |
1686 | if not keys: |
|
1708 | if not keys: | |
1687 | return keys |
|
1709 | return keys | |
1688 | closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims) |
|
1710 | ||
|
1711 | if prefix0 != '': | |||
|
1712 | tuple_prefix = eval(prefix0) | |||
|
1713 | else: | |||
|
1714 | tuple_prefix = tuple() | |||
|
1715 | ||||
|
1716 | closing_quote, token_offset, matches = match_dict_keys(keys, tuple_prefix, prefix, self.splitter.delims) | |||
1689 | if not matches: |
|
1717 | if not matches: | |
1690 | return matches |
|
1718 | return matches | |
1691 |
|
1719 | |||
@@ -1695,7 +1723,7 b' class IPCompleter(Completer):' | |||||
1695 | # - the start of the completion |
|
1723 | # - the start of the completion | |
1696 | text_start = len(self.text_until_cursor) - len(text) |
|
1724 | text_start = len(self.text_until_cursor) - len(text) | |
1697 | if prefix: |
|
1725 | if prefix: | |
1698 |
key_start = match.start( |
|
1726 | key_start = match.start(3) | |
1699 | completion_start = key_start + token_offset |
|
1727 | completion_start = key_start + token_offset | |
1700 | else: |
|
1728 | else: | |
1701 | key_start = completion_start = match.end() |
|
1729 | key_start = completion_start = match.end() | |
@@ -2097,7 +2125,7 b' class IPCompleter(Completer):' | |||||
2097 |
|
2125 | |||
2098 | # Start with a clean slate of completions |
|
2126 | # Start with a clean slate of completions | |
2099 | matches = [] |
|
2127 | matches = [] | |
2100 |
|
2128 | |||
2101 | # FIXME: we should extend our api to return a dict with completions for |
|
2129 | # FIXME: we should extend our api to return a dict with completions for | |
2102 | # different types of objects. The rlcomplete() method could then |
|
2130 | # different types of objects. The rlcomplete() method could then | |
2103 | # simply collapse the dict into a list for readline, but we'd have |
|
2131 | # simply collapse the dict into a list for readline, but we'd have |
General Comments 0
You need to be logged in to leave comments.
Login now