64

I would like to get auto-completion on my python scripts also in the arguments.

I had never really understood how the bash_completion worked (for arguments), but after I digged in I understood that:

  1. it uses "complete" to bind a completing function to a command
  2. every completing function basically is a copy of the argument parser

The second point in particular is not great, because I would like to have it automatically generated.

The best thing would be that the shell asks to my program at every TAB about what to complete, but I have the impression that this can't really work, is that correct?

The second option is probably just to write a converter from an argparse parser to a shell function which completes correctly.

unwind
  • 391,730
  • 64
  • 469
  • 606
andrea_crotti
  • 3,004
  • 2
  • 28
  • 33
  • 5
    Have you seen this thread http://bugs.python.org/issue4256? It also seems that `optparse` has automatic shell completion support: http://pypi.python.org/pypi/optcomplete – Chris Dec 05 '11 at 16:28

2 Answers2

79

Shameless self-promotion: https://github.com/kislyuk/argcomplete

argcomplete provides bash completion for argparse.

weaver
  • 1,763
  • 15
  • 16
  • Also _exactly_ what @andrea-crotti is looking for – Thomas Feb 18 '13 at 15:32
  • @weaver From the docs, it looks like either global completion has to be enabled or a specific eval statement needs to be added to bashrc. Is there a way to create a completion script and let bash know where the script is? – balki Aug 06 '13 at 17:31
  • 1
    @balki: I'm not sure exactly what you're trying to do, but you can run `register-python-argcomplete my-script.py` > completion-script.sh. You can similarly save the global completion activation script as per the docs. Then you have to somehow get the user to source that script (running the script won't work, since that's a subprocess). – weaver Aug 06 '13 at 18:32
  • 2
    Is it possible to distribute the `completion-script.sh` with the package so that a user does not need to eval anything? – Franklin Yu Oct 24 '17 at 14:44
  • This is absolutely fantastic. One of the few times bash has clearly superior solution than zsh. From what I've researched zsh doesn't have anything close – Max Coplan Oct 17 '19 at 14:40
14

Bash "completion" really is great. And easy for programs written in Python....

I think this is just what you want: optcomplete: Shell Completion Self-Generator for Python. It is available, e.g., as the "python-optcomplete" package in Ubuntu.

You insert a few lines in your python program, and the user (one time) runs the bash "complete" program to tell bash how to complete the arguments:

complete -F _optcomplete <program>

and now the user has completion! By default it gives simple completion on program options. See the example for how to customize how completion works for a particular option. It is beautifully written, and easy to extend to handle sub-commands, alternate completion options, etc.!

Update:

For completion in zsh (for both optparse and argparse) see genzshcomp 0.3.1 : Python Package Index

As noted by @englebip, we still need something similar for the new argparse module, introduced in Python 2.7 and 3.2, since optparse is now deprecated.

Here is the discussion on moving in that direction:

See also this background on how it is done: How does argparse (and the deprecated optparse) respond to 'tab' keypress after python program name, in bash? - Stack Overflow

Community
  • 1
  • 1
nealmcb
  • 12,479
  • 7
  • 66
  • 91
  • 3
    This is indeed very cool, but it works for the now-obsolete `optparse` module and not for the current `argparse`. Any ideas of a re-implementation with `argparse`? – englebip Aug 06 '12 at 13:52
  • @englebip Well it's hard to describe `optparse` as obsolete since its replacement, argparse, was first introduced in Python 2.7 and Python 3.2. The official term is "Deprecated", which can last a long time. But I would indeed like to see something like optcomplete for argparse, and there are efforts to make that happen. – nealmcb Aug 07 '12 at 14:47