views:

2502

answers:

5

I am aware of how to setup autocompletion of python objects in the python interpreter (on unix).

  • Google shows many hits for explanations on how to do this.
  • Unfortunately, there are so many references to that it is difficult to find what I need to do, which is slightly different.

I need to know how to enable, tab/auto completion of arbitrary items in a command-line program written in python.

My specific use case is a command-line python program that needs to send emails. I want to be able to autocomplete email addresses (I have the addresses on disk) when the user types part of it (and optionally presses the TAB key).

I do not need it to work on windows or mac, just linux.

+10  A: 

Use Python's readline bindings. For example,

import readline
def completer(text, state):
    options = [x in addrs where x.startswith(text)]
    if state < options.length:
        return options[state]
    else
        return None
readline.set_completer(completer)

The official module docs aren't much more detailed, see the readline docs for more info.

ephemient
note tough that if you write your command line with the cmd module that there are better ways to do it.
Florian Bösch
+16  A: 

Follow the cmd documentation and you'll be fine

import cmd

addresses = [
    '[email protected]',
    '[email protected]',
    '[email protected]',
]

class MyCmd(cmd.Cmd):
    def do_send(self, line):
        pass

    def complete_send(self, text, line, start_index, end_index):
        if text:
            return [
                address for address in addresses
                if address.startswith(text)
            ]
        else:
            return addresses


if __name__ == '__main__':
    my_cmd = MyCmd()
    my_cmd.cmdloop()

Output for tab -> tab -> send -> tab -> tab -> f -> tab

(Cmd)
help  send
(Cmd) send
[email protected]            [email protected]         [email protected]
(Cmd) send [email protected]
(Cmd)
Florian Bösch
+1  A: 
Owen
A: 

Here is a full-working version of the code that was very supplied by ephemient here (thank you).

import readline

addrs = ['[email protected]', '[email protected]', '[email protected]']

def completer(text, state):
    options = [x for x in addrs if x.startswith(text)]
    try:
        return options[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind("tab: complete")

while 1:
    a = raw_input("> ")
    print "You entered", a
Paul D. Eden
A: 

See here for a version that matches any part of the string, not just the beginning, and is case insensitive.

Paul D. Eden