diff -r 651aa21433ba Lib/rlcompleter.py --- a/Lib/rlcompleter.py Mon Feb 02 17:47:31 2015 -0500 +++ b/Lib/rlcompleter.py Wed Feb 11 11:21:04 2015 +0100 @@ -36,10 +36,10 @@ __all__ = ["Completer"] class Completer: - def __init__(self, namespace = None): + def __init__(self, namespace = None, tab_to_space_pos = None): """Create a new completer for the command line. - Completer([namespace]) -> completer instance. + Completer([namespace][, tab_to_space_pos]) -> completer instance. If unspecified, the default namespace where completions are performed is __main__ (technically, __main__.__dict__). Namespaces should be @@ -49,6 +49,10 @@ readline via the set_completer() call: readline.set_completer(Completer(my_namespace).complete) + + If 'tab_to_space_pos' is set, it must be a function that + returns the current line position. Tabs are then converted to + (up to) 4 spaces if there is nothing to complete. """ if namespace and not isinstance(namespace, dict): @@ -62,6 +66,7 @@ else: self.use_main_ns = 0 self.namespace = namespace + self.tab_to_space_pos = tab_to_space_pos def complete(self, text, state): """Return the next possible completion for 'text'. @@ -74,7 +79,11 @@ self.namespace = __main__.__dict__ if state == 0: - if "." in text: + if len(text) == 0 and self.tab_to_space_pos: + pos = self.tab_to_space_pos() + num_spaces = 4 - (pos % 4) + self.matches = [' ' * num_spaces] + elif "." in text: self.matches = self.attr_matches(text) else: self.matches = self.global_matches(text) @@ -158,7 +167,8 @@ except ImportError: pass else: - readline.set_completer(Completer().complete) + _getpos = readline.get_endidx + readline.set_completer(Completer(tab_to_space_pos=_getpos).complete) # Release references early at shutdown (the readline module's # contents are quasi-immortal, and the completer function holds a # reference to globals). diff -r 651aa21433ba Lib/test/test_rlcompleter.py --- a/Lib/test/test_rlcompleter.py Mon Feb 02 17:47:31 2015 -0500 +++ b/Lib/test/test_rlcompleter.py Wed Feb 11 11:21:04 2015 +0100 @@ -65,6 +65,15 @@ ['egg.{}('.format(x) for x in dir(str) if x.startswith('s')]) + def test_tab_to_space_pos(self): + completer = rlcompleter.Completer(tab_to_space_pos=lambda: pos) + pos = 0 + self.assertEqual(completer.complete('', 0), ' ') + pos = 41 + self.assertEqual(completer.complete('', 0), ' ') + pos = 43 + self.assertEqual(completer.complete('', 0), ' ') + def test_main(): support.run_unittest(TestRlcompleter)