Search code examples
pythongnureadline

Is there any way to combine readline/rlcompleter and InteractiveConsole in python?


I'm trying to extend the python shell (I can't use IPython, sadly). I'd like the ability to both keyword complete and interpret some custom input (that won't be valid python). But I can't get readline/rlcompleter and InteractiveConsole to work together. To demonstrate the problem:

$ python -c "import code; code.InteractiveConsole().interact()"
Python 2.7.10 (default, Jun  1 2015, 18:05:38)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import readline
>>> import rlcompleter
>>> readline.parse_and_bind("tab: complete")
>>> import string
>>> stri

Hitting tab here does nothing.

$ python
Python 2.7.10 (default, Jun  1 2015, 18:05:38)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import readline
>>> import rlcompleter
>>> readline.parse_and_bind("tab: complete")
>>> import string
>>> stri

Hitting tab now completes to "string".

Can anyone explain why this is and if there's a way around this?


Solution

  • OK - some digging around in the python source reveals the answer. The problem is that in InteractiveConsole the namespace is set to something other than __main__. But rlcompleter completes from builtins and __main__. Import string above imports into the current namespace, which isn't __main__ and isn't searched by rlcompleter.

    So, a solution is to construct your own rlcompleter.Completer and pass in the locals() to the ctor:

    $ python -c "import code; code.InteractiveConsole().interact()"
    Python 2.7.10 (default, Jun  1 2015, 18:05:38) [GCC 4.9.2] on cygwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> import readline
    >>> from rlcompleter import Completer
    >>> readline.parse_and_bind("tab: complete")
    >>> readline.set_completer(Completer(locals()).complete)
    >>> import string
    >>> str
    str(    string