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"
.
Tab Completion and History Editing. Completion of variable and module names is automatically enabled at interpreter startup so that the Tab key invokes the completion function; it looks at Python statement names, the current local variables, and the available module names.
Using autocomplete is as simple as pressing the [TAB] and the active command line options will fill-in. If more than one option is available, you can hit [TAB] twice to display all possible choices and continue typing until there is only one matching choice left.
All of the modern shells have command and filename completion via the <TAB> key. Bourne shell and csh do not, but ksh, bash, tcsh, and zsh all have tab completion to varying degrees.
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:
An excellent example of how to do tab-completion in cooperation with readline is supplied in the standard library as the rlcompleter module — you can't use it as-is (it completes based on names currently defined in the Python's main and builtin), but it shows how to do the general task and how to hook it up to readline
.
You should almost certainly be using the cmd module, which already implements tab completion and so on, and probably other parts of what you're trying to do, using the readline module and so on. There's no point reinventing the wheel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With