1

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?

Mark Wright
  • 705
  • 7
  • 20

2 Answers2

4

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
Mark Wright
  • 705
  • 7
  • 20
2

This post is 4 years old, so the solution I am about to suggest may not have been available at the time. But as of at least Python 3.7.7, the following code allows you to use whatever readline settings Python started with and automatically add tab completion:

import code, readline, rlcompleter

readline.parse_and_bind('tab: complete')
InteractiveConsole(locals()).interact()

It works because readline only needs to be imported to work.

Gringo Suave
  • 29,931
  • 6
  • 88
  • 75
N. Kern
  • 401
  • 2
  • 7
  • See https://stackoverflow.com/a/7116997/450917 for MacOS. You probably also will need to create the Completer to complete builtins, etc, because of namespaces. – Gringo Suave Mar 23 '22 at 03:30