¿Cómo responde argparse (y el optparse en desuso) a la pulsación de la tecla ‘tab’ después del nombre del progtwig python, en bash?

He probado optcomplete trabajando con el módulo optparse . Su ejemplo es un archivo simple para que pueda hacer que funcione. También lo probé usando el módulo argparse ya que el anterior está en desuso. Pero realmente no entiendo cómo y por quién se llama al progtwig Python en las pulsaciones de tabs. Sospecho que bash junto con la línea shebang y el argparse (o optparse ) están involucrados de alguna manera. He estado tratando de resolver esto (ahora voy a leer el código fuente).

Tengo una estructura de progtwig un poco más compleja, que incluye una envoltura alrededor de la pieza de código que maneja los argumentos. Su instancia argparse.ArgumentParser() y las llamadas a add_argument() , que están superclasificadas en otro módulo intermedio para evitar la duplicación de código, y la envoltura alrededor de la que se llama, están dentro de una función.

Quiero entender la forma en que funciona esta terminación de tabs entre bash y python (o, para el caso, cualquier otro interpretador como perl ).

NOTA: Tengo una comprensión justa de la finalización de bash (que aprendí hace un momento), y creo que entiendo la finalización personalizada de bash (solo).

NOTA: He leído otras preguntas de SO similares, y ninguna responde realmente esta Q.

Edición: Aquí está la función de bash.
Ya entendí cómo el módulo de Python conoce las palabras escritas en la línea de comandos al leer los valores de las variables de os.environ

 $COMP_WORDS $COMP_CWORD $COMP_LINE $COMP_POINT $COMPREPLY 

Estas variables tienen valores solo al presionar la pestaña. Mi pregunta es ¿cómo se activa el módulo de Python?

Para entender lo que está sucediendo aquí, verifiquemos qué hace realmente esa función de bash:

 COMPREPLY=( $( \ COMP_LINE=$COMP_LINE COMP_POINT=$COMP_POINT \ COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ OPTPARSE_AUTO_COMPLETE=1 $1 ) ) 

¿Ves los $1 al final? ¡Eso significa que realmente llama al archivo Python que queremos ejecutar con el conjunto de variables de entorno especiales! Para rastrear lo que está sucediendo, preparemos un pequeño script para interceptar lo que optcomplete.autocomplete hace:

 #!/usr/bin/env python2 import os, sys import optparse, optcomplete from cStringIO import StringIO if __name__ == '__main__': parser = optparse.OptionParser() parser.add_option('-s', '--simple', action='store_true', help="Simple really simple option without argument.") parser.add_option('-o', '--output', action='store', help="Option that requires an argument.") opt = parser.add_option('-p', '--script', action='store', help="Option that takes python scripts args only.") opt.completer = optcomplete.RegexCompleter('.*\.py') # debug env variables sys.stderr.write("\ncalled with args: %s\n" % repr(sys.argv)) for k, v in sorted(os.environ.iteritems()): sys.stderr.write(" %s: %s\n" % (k, v)) # setup capturing the actions of `optcomplete.autocomplete` def fake_exit(i): sys.stderr.write("autocomplete tried to exit with status %d\n" % i) sys.stdout = StringIO() sys.exit = fake_exit # Support completion for the command-line of this script. optcomplete.autocomplete(parser, ['.*\.tar.*']) sys.stderr.write("autocomplete tried to write to STDOUT:\n") sys.stderr.write(sys.stdout.getvalue()) sys.stderr.write("\n") opts, args = parser.parse_args() 

Esto nos da lo siguiente cuando intentamos autocompletarlo:

 $ ./test.py [tab] called with args: ['./test.py'] ... COMP_CWORD: 1 COMP_LINE: ./test.py COMP_POINT: 10 COMP_WORDS: ./test.py ... OPTPARSE_AUTO_COMPLETE: 1 ... autocomplete tried to exit with status 1 autocomplete tried to write to STDOUT: -o -h -s -p --script --simple --help --output 

Así que optcomplete.autocomplete simplemente lee el entorno, prepara las coincidencias, las escribe en STDOUT y sale. El resultado -o -h -s -p --script --simple --help --output se coloca en una matriz bash ( COMPREPLY=( ... ) ) y se devuelve a bash para presentar las opciones al usuario. No hay magia involucrada 🙂