Show More
@@ -2014,7 +2014,7 b' class IPCompleter(Completer):' | |||||
2014 |
|
2014 | |||
2015 | # Start with a clean slate of completions |
|
2015 | # Start with a clean slate of completions | |
2016 | matches = [] |
|
2016 | matches = [] | |
2017 | custom_res = self.dispatch_custom_completer(text) |
|
2017 | ||
2018 | # FIXME: we should extend our api to return a dict with completions for |
|
2018 | # FIXME: we should extend our api to return a dict with completions for | |
2019 | # different types of objects. The rlcomplete() method could then |
|
2019 | # different types of objects. The rlcomplete() method could then | |
2020 | # simply collapse the dict into a list for readline, but we'd have |
|
2020 | # simply collapse the dict into a list for readline, but we'd have | |
@@ -2025,29 +2025,24 b' class IPCompleter(Completer):' | |||||
2025 | full_text = line_buffer |
|
2025 | full_text = line_buffer | |
2026 | completions = self._jedi_matches( |
|
2026 | completions = self._jedi_matches( | |
2027 | cursor_pos, cursor_line, full_text) |
|
2027 | cursor_pos, cursor_line, full_text) | |
2028 | if custom_res is not None: |
|
2028 | ||
2029 | # did custom completers produce something? |
|
2029 | if self.merge_completions: | |
2030 | matches = [(m, 'custom') for m in custom_res] |
|
2030 | matches = [] | |
|
2031 | for matcher in self.matchers: | |||
|
2032 | try: | |||
|
2033 | matches.extend([(m, matcher.__qualname__) | |||
|
2034 | for m in matcher(text)]) | |||
|
2035 | except: | |||
|
2036 | # Show the ugly traceback if the matcher causes an | |||
|
2037 | # exception, but do NOT crash the kernel! | |||
|
2038 | sys.excepthook(*sys.exc_info()) | |||
2031 | else: |
|
2039 | else: | |
2032 | # Extend the list of completions with the results of each |
|
2040 | for matcher in self.matchers: | |
2033 | # matcher, so we return results to the user from all |
|
2041 | matches = [(m, matcher.__qualname__) | |
2034 | # namespaces. |
|
2042 | for m in matcher(text)] | |
2035 | if self.merge_completions: |
|
2043 | if matches: | |
2036 |
|
|
2044 | break | |
2037 | for matcher in self.matchers: |
|
2045 | ||
2038 | try: |
|
|||
2039 | matches.extend([(m, matcher.__qualname__) |
|
|||
2040 | for m in matcher(text)]) |
|
|||
2041 | except: |
|
|||
2042 | # Show the ugly traceback if the matcher causes an |
|
|||
2043 | # exception, but do NOT crash the kernel! |
|
|||
2044 | sys.excepthook(*sys.exc_info()) |
|
|||
2045 | else: |
|
|||
2046 | for matcher in self.matchers: |
|
|||
2047 | matches = [(m, matcher.__qualname__) |
|
|||
2048 | for m in matcher(text)] |
|
|||
2049 | if matches: |
|
|||
2050 | break |
|
|||
2051 | seen = set() |
|
2046 | seen = set() | |
2052 | filtered_matches = set() |
|
2047 | filtered_matches = set() | |
2053 | for m in matches: |
|
2048 | for m in matches: | |
@@ -2056,17 +2051,20 b' class IPCompleter(Completer):' | |||||
2056 | filtered_matches.add(m) |
|
2051 | filtered_matches.add(m) | |
2057 | seen.add(t) |
|
2052 | seen.add(t) | |
2058 |
|
2053 | |||
2059 | _filtered_matches = sorted( |
|
2054 | _filtered_matches = sorted(filtered_matches, key=lambda x: completions_sorting_key(x[0])) | |
2060 | set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))\ |
|
|||
2061 | [:MATCHES_LIMIT] |
|
|||
2062 |
|
2055 | |||
|
2056 | custom_res = [(m, 'custom') for m in self.dispatch_custom_completer(text) or []] | |||
|
2057 | ||||
|
2058 | _filtered_matches = custom_res or _filtered_matches | |||
|
2059 | ||||
|
2060 | _filtered_matches = _filtered_matches[:MATCHES_LIMIT] | |||
2063 | _matches = [m[0] for m in _filtered_matches] |
|
2061 | _matches = [m[0] for m in _filtered_matches] | |
2064 | origins = [m[1] for m in _filtered_matches] |
|
2062 | origins = [m[1] for m in _filtered_matches] | |
2065 |
|
2063 | |||
2066 | self.matches = _matches |
|
2064 | self.matches = _matches | |
2067 |
|
2065 | |||
2068 | return text, _matches, origins, completions |
|
2066 | return text, _matches, origins, completions | |
2069 |
|
2067 | |||
2070 | def fwd_unicode_match(self, text:str) -> Tuple[str, list]: |
|
2068 | def fwd_unicode_match(self, text:str) -> Tuple[str, list]: | |
2071 | if self._names is None: |
|
2069 | if self._names is None: | |
2072 | self._names = [] |
|
2070 | self._names = [] |
@@ -175,6 +175,20 b' class TestCompleter(unittest.TestCase):' | |||||
175 |
|
175 | |||
176 | ip.complete("x.") |
|
176 | ip.complete("x.") | |
177 |
|
177 | |||
|
178 | def test_custom_completion_ordering(self): | |||
|
179 | """Test that errors from custom attribute completers are silenced.""" | |||
|
180 | ip = get_ipython() | |||
|
181 | ||||
|
182 | _, matches = ip.complete('in') | |||
|
183 | assert matches.index('input') < matches.index('int') | |||
|
184 | ||||
|
185 | def complete_example(a): | |||
|
186 | return ['example2', 'example1'] | |||
|
187 | ||||
|
188 | ip.Completer.custom_completers.add_re('ex*', complete_example) | |||
|
189 | _, matches = ip.complete('ex') | |||
|
190 | assert matches.index('example2') < matches.index('example1') | |||
|
191 | ||||
178 | def test_unicode_completions(self): |
|
192 | def test_unicode_completions(self): | |
179 | ip = get_ipython() |
|
193 | ip = get_ipython() | |
180 | # Some strings that trigger different types of completion. Check them both |
|
194 | # Some strings that trigger different types of completion. Check them both |
General Comments 0
You need to be logged in to leave comments.
Login now