Tab Completion in Python Command Line Interface - how to catch Tab events

mercurial, python, raw-input, tab-completion

Solution

For that you use the `readline` module.

Simplest code I can think:

import readline
COMMANDS = ['extra', 'extension', 'stuff', 'errors',
            'email', 'foobar', 'foo']

def complete(text, state):
    for cmd in COMMANDS:
        if cmd.startswith(text):
            if not state:
                return cmd
            else:
                state -= 1

readline.parse_and_bind("tab: complete")
readline.set_completer(complete)
raw_input('Enter section name: ')

Example usage:

Enter section name: <tab>
email      errors     extension  extra      foo        foobar    stuff
Enter section name: e<tab>
email      errors     extension  extra      
Enter section name: ext<tab>
extension  extra      

Besides completion, `readline` provides you with:

- Line editing

- Keybinding configuration (emacs and vi modes included)

- History (up arrow to recall previous values)

- History searching, saving and loading

Problem

I'm writing a little CLI in Python (as an extension to Mercurial) and would like to support tab-completion. Specifically, I would like catch tabs in the prompt and show a list of matching options (just like bash). Example: Enter section name: ``` ext*TAB* extensions extras ``` The problem is I'm not sure how to catch the Tab events. I'm using the `ui.prompt()` API of Mercurial, which is just calling `raw_input()` under the hood. As far as I know, `raw_input()` only returns on 'enter' and if a user enters a tab, the string returned simply includes a `"\t"`.

Original source