Reputation: 397
I'm trying to create a prompt with tab completion. I have two files. main.py and prompt.py. main.py imports prompt.py and runs prompt.py's main()
function. The main()
function sets up a tab completer using readline and repeatedly waits for user input. It prints whatever is inputted and should have tab completion which completes according to whatever text is in the COMMANDS list.
main.py:
import prompt
prompt.main()
prompt.py:
import readline
import colorama
colorama.init()
COMMANDS = ['qwerty','uiop','asdf','ghjkl']
def complete(text, state):
for cmd in COMMANDS:
if cmd.startswith(text):
if not state:
return cmd
else:
state -= 1
def main():
readline.parse_and_bind("tab: complete")
readline.set_completer(complete)
while True:
test_input=raw_input(':')
print test_input
main()
What should happen is when I press the tab button the program tries to autocomplete to whatever is in the COMMANDS list. So if I type in "qwe" and press tab the program tab completes to "qwerty". However when I press tab in the program, nothing happens.
Upon commenting the line colorama.init()
, the code can now autocomplete. So the line colorama.init()
is affecting tab completing. Why is this so? How can I run that line without it affecting the tab as I need the colorama module to output colored text on the windows command prompt.
Upvotes: 1
Views: 1404
Reputation: 8958
The problem is that readline
uses the standard output stream, which is equivalent to sys.__stdout__
, to control the terminal.
However, when you call colorama.init()
, Python's default stream, sys.stdout
, is redirected to colorama
's own wrapper.
readline
then no longer sees the unadulterated standard output and fails to function. Notably, colorama
strips the special escape codes that readline
uses.
This problem will also occur if you manually redirect sys.stdout
- for instance to apply your own formatting or send output to a GUI.
The solution in all cases is to restore sys.stdout
to the default, sys.__stdout__
, for the duration of any input
, for instance via:
original_stdout = sys.stdout
sys.stdout = sys.__stdout__
foo = input()
sys.stdout = original_stdout
Note that colorama
s OS-indenpendent colouring features now won't work during this input
, so if you want colours in your input prompt, you'll have to branch and make the relevant escape calls for your supported platforms (Windows/Unix) independently.
Upvotes: 1