diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 4280410..459210c 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -656,6 +656,15 @@ class Completer(Configurable): for word in lst: if word[:n] == text and word != "__builtins__": match_append(word) + + snake_case_re = re.compile(r"[^_]+(_[^_]+)+?") + for lst in [self.namespace.keys(), + self.global_namespace.keys()]: + shortened = {"_".join([sub[0] for sub in word.split('_')]) : word + for word in lst if snake_case_re.fullmatch(word)} + for word in shortened.keys(): + if word[:n] == text and word != "__builtins__": + match_append(shortened[word]) return [cast_unicode_py2(m) for m in matches] def attr_matches(self, text): diff --git a/IPython/core/tests/test_completer.py b/IPython/core/tests/test_completer.py index 533ba42..a2019d4 100644 --- a/IPython/core/tests/test_completer.py +++ b/IPython/core/tests/test_completer.py @@ -858,3 +858,11 @@ def test_from_module_completer(): _, matches = ip.complete('B', 'from io import B', 16) nt.assert_in('BytesIO', matches) nt.assert_not_in('BaseException', matches) + +def test_snake_case_completion(): + ip = get_ipython() + ip.user_ns['some_three'] = 3 + ip.user_ns['some_four'] = 4 + _, matches = ip.complete("s_", "print(s_f") + nt.assert_in('some_three', matches) + nt.assert_in('some_four', matches) \ No newline at end of file