2008-10-09 14 views
73

Soy consciente de cómo configurar el autocompletado de objetos de python en el intérprete de python (en Unix).Cómo hacer un programa de línea de comando de python, autocompletar cosas arbitrarias NO intérprete

  • Google muestra muchos resultados para obtener explicaciones sobre cómo hacer esto.
  • Lamentablemente, hay tantas referencias que es difícil encontrar lo que tengo que hacer, que es un poco diferente.

Necesito saber cómo habilitar, tabulación/finalización automática de elementos arbitrarios en un programa de línea de comandos escrito en python.

Mi caso de uso específico es un programa de línea de comando python que necesita enviar correos electrónicos. Quiero poder autocompletar las direcciones de correo electrónico (tengo las direcciones en el disco) cuando el usuario escribe una parte (y opcionalmente presiona la tecla TAB).

No lo necesito para trabajar en Windows o Mac, solo en Linux.

+0

Esto [el blog] (http://blog.e-shell.org/ 221) debería hacer los trucos con config el archivo .pythonrc. –

Respuesta

46

Utilice las vinculaciones de Python readline. Por ejemplo,

import readline 

def completer(text, state): 
    options = [i for i in commands if i.startswith(text)] 
    if state < len(options): 
     return options[state] 
    else: 
     return None 

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

El funcionario module docs no son mucho más detallada, ver el readline docs para obtener más información.

+1

, tenga en cuenta que si escribe su línea de comandos con el módulo cmd, hay mejores formas de hacerlo. –

52

Siga el cmd documentation y se le multa

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() 

de salida para la lengüeta -> ficha -> Enviar -> ficha -> ficha -> f -> pestaña

(Cmd) 
help send 
(Cmd) send 
[email protected]   [email protected]   [email protected] 
(Cmd) send [email protected] 
(Cmd) 
+0

¿Hay alguna manera de controlar cómo readline publica su salida? Así que digamos que me gustaría que columnize con dos espacios entre cada elemento. – Fnord

+0

Cuando ejecuto este código, las pestañas simplemente se imprimen en la línea de comando. De hecho, esto es cierto independientemente de si uso cmd o readline directo. –

24

Puesto que usted diga "NO intérprete" en su pregunta, supongo que no quiere respuestas que involucren python readline y cosas por el estilo. (edición: en retrospectiva, que obviamente no es el caso de Ho hum creo que esta información es interesante, de todos modos, así que voy a dejar aquí...)

Creo que es posible que después de this.

Se trata de agregar la finalización del nivel de shell a comandos arbitrarios, extendiendo la terminación de pestañas de bash.

En pocas palabras, creará un archivo que contiene una función shell que generará posibles terminaciones, guárdelo en /etc/bash_completion.d/ y regístrelo con el comando complete. He aquí un fragmento de la página enlazada:

_foo() 
{ 
    local cur prev opts 
    COMPREPLY=() 
    cur="${COMP_WORDS[COMP_CWORD]}" 
    prev="${COMP_WORDS[COMP_CWORD-1]}" 
    opts="--help --verbose --version" 

    if [[ ${cur} == -* ]] ; then 
     COMPREPLY=($(compgen -W "${opts}" -- ${cur})) 
     return 0 
    fi 
} 
complete -F _foo foo 

En este caso, el foo --[TAB] escribir le dará los valores de la variable opts, es decir --help, --verbose y --version. Para sus propósitos, esencialmente querrá personalizar los valores que se ponen en opts.

Echa un vistazo al ejemplo en la página vinculada, todo es bastante sencillo.

+2

En realidad vine aquí por eso – user1767754

10

Aquí está una versión de trabajo completo del código que fue muy provisto por ephemient here (gracias).

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 
7
# ~/.pythonrc 
import rlcompleter, readline 
readline.parse_and_bind('tab:complete') 

# ~/.bashrc 
export PYTHONSTARTUP=~/.pythonrc 
17

me sorprende que nadie ha mencionado argcomplete, aquí es un ejemplo de los documentos:

from argcomplete.completers import ChoicesCompleter 

parser.add_argument("--protocol", choices=('http', 'https', 'ssh', 'rsync', 'wss')) 
parser.add_argument("--proto").completer=ChoicesCompleter(('http', 'https', 'ssh', 'rsync', 'wss')) 
+0

Es una publicación anterior, ¿quizás no existía en ese momento? Gracias por mencionarlo, creo que es exactamente lo que necesita mi proyecto. – FrustratedWithFormsDesigner

Cuestiones relacionadas