From 6c24cad22958dcd13379c0d16e6c07a7cbe2e931 2017-05-12 21:58:12 From: Sang Min Park Date: 2017-05-12 21:58:12 Subject: [PATCH] Add tab completion for %config --- diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 0b958da..cf1fb39 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -1050,6 +1050,7 @@ class IPCompleter(Completer): self.matchers = [ self.python_matches, self.file_matches, + self.magic_config_matches, self.magic_matches, self.python_func_kw_matches, self.dict_key_matches, @@ -1174,6 +1175,43 @@ class IPCompleter(Completer): comp += [ pre+m for m in line_magics if m.startswith(bare_text)] return [cast_unicode_py2(c) for c in comp] + def magic_config_matches(self, text): + """ Match class names and attributes for %config magic """ + # use line buffer instead of text (which is a word) + texts = self.line_buffer.strip().split() + + if len(texts) > 0 and \ + ('config'.startswith(texts[0]) or '%config'.startswith(texts[0])): + # get all configuration classes + classes = sorted(set([ c for c in self.shell.configurables + if c.__class__.class_traits(config=True) + ]), key=lambda x: x.__class__.__name__) + classnames = [ c.__class__.__name__ for c in classes ] + + # return all classnames if config or %config is given + if len(texts) == 1: + return classnames + + # match classname + classname_texts = texts[1].split('.') + classname = classname_texts[0] + classname_matches = [ c for c in classnames + if c.startswith(classname) ] + + # return matched classes or the matched class with attributes + if texts[1].find('.') < 0: + return classname_matches + elif len(classname_matches) == 1 and \ + classname_matches[0] == classname: + cls = classes[classnames.index(classname)].__class__ + help = cls.class_get_help() + # strip leading '--' from cl-args: + help = re.sub(re.compile(r'^--', re.MULTILINE), '', help) + return [ attr.split('=')[0] + for attr in help.strip().splitlines() + if attr.startswith(texts[1]) ] + return [] + def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str): """ @@ -1670,7 +1708,7 @@ class IPCompleter(Completer): lazy property) and can require some warm-up, more warm up than just computing the ``name`` of a completion. The warm-up can be : - - Long warm-up the fisrt time a module is encountered after + - Long warm-up the first time a module is encountered after install/update: actually build parse/inference tree. - first time the module is encountered in a session: load tree from diff --git a/IPython/core/tests/test_completer.py b/IPython/core/tests/test_completer.py index 3557c40..8d39d96 100644 --- a/IPython/core/tests/test_completer.py +++ b/IPython/core/tests/test_completer.py @@ -576,6 +576,35 @@ def test_magic_completion_order(): text, matches = c.complete('timeit') nt.assert_equal(matches, ["timeit", "%timeit", "%%timeit"]) + +def test_magic_config(): + ip = get_ipython() + c = ip.Completer + + s, matches = c.complete(None, 'conf') + nt.assert_in('%config', matches) + s, matches = c.complete(None, 'config ') + nt.assert_in('AliasManager', matches) + s, matches = c.complete(None, '%config ') + nt.assert_in('AliasManager', matches) + s, matches = c.complete(None, 'config Ali') + nt.assert_in('AliasManager', matches) + s, matches = c.complete(None, '%config Ali') + nt.assert_in('AliasManager', matches) + s, matches = c.complete(None, 'config AliasManager') + nt.assert_list_equal(['AliasManager'], matches) + s, matches = c.complete(None, '%config AliasManager') + nt.assert_list_equal(['AliasManager'], matches) + s, matches = c.complete(None, 'config AliasManager.') + nt.assert_in('AliasManager.default_aliases', matches) + s, matches = c.complete(None, '%config AliasManager.') + nt.assert_in('AliasManager.default_aliases', matches) + s, matches = c.complete(None, 'config AliasManager.de') + nt.assert_in('AliasManager.default_aliases', matches) + s, matches = c.complete(None, 'config AliasManager.de') + nt.assert_in('AliasManager.default_aliases', matches) + + def test_match_dict_keys(): """ Test that match_dict_keys works on a couple of use case does return what