¿Cómo codificar autocompletado en python?

Me gustaría codificar el autocompletado en el terminal de Linux. El código debería funcionar de la siguiente manera.

Tiene una lista de cadenas (por ejemplo, “hola”, “hola”, “cómo estás”, “adiós”, “genial”, …).

En la terminal, el usuario comenzará a escribir y cuando haya alguna posibilidad de coincidencia, obtendrá la pista para posibles cadenas, entre las que puede elegir (de forma similar a como en el editor vim o búsqueda incremental de Google ).

por ejemplo, comienza a escribir “h” y se da cuenta de la pista

Hola”

_ “yo”

_”Cómo estás”

Y mejor aún sería si completara las palabras no solo desde el principio sino desde una parte arbitraria de la cadena.

Gracias por asesorarme.

(Estoy consciente de que esto no es exactamente lo que está pidiendo, pero) Si está satisfecho con las finalizaciones automáticas / sugerencias que aparecen en TAB (como se usa en muchos shells), entonces puede ponerse en marcha rápidamente. utilizando el módulo readline .

Aquí hay un ejemplo rápido basado en la reseña de PyMOTW de Doug Hellmann en readline .

import readline class MyCompleter(object): # Custom completer def __init__(self, options): self.options = sorted(options) def complete(self, text, state): if state == 0: # on first trigger, build possible matches if text: # cache matches (entries that start with entered text) self.matches = [s for s in self.options if s and s.startswith(text)] else: # no text entered, all matches possible self.matches = self.options[:] # return match indexed by state try: return self.matches[state] except IndexError: return None completer = MyCompleter(["hello", "hi", "how are you", "goodbye", "great"]) readline.set_completer(completer.complete) readline.parse_and_bind('tab: complete') input = raw_input("Input: ") print "You entered", input 

Esto da como resultado el siguiente comportamiento ( representa una tecla de tabulación presionada):

 Input:  goodbye great hello hi how are you Input: h hello hi how are you Input: hoow are you 

En la última línea ( H O TAB ingresada), solo hay una coincidencia posible y toda la frase “como estas” se completa automáticamente.

Echa un vistazo a los artículos vinculados para obtener más información en readline .


“Y mejor aún sería si completara las palabras no solo desde el principio … la finalización desde una parte arbitraria de la cadena”.

Esto se puede lograr simplemente modificando los criterios de coincidencia en la función de completador, es decir. desde:

 self.matches = [s for s in self.options if s and s.startswith(text)] 

a algo como:

 self.matches = [s for s in self.options if text in s] 

Esto te dará el siguiente comportamiento:

 Input:  goodbye great hello hi how are you Input: o goodbye hello how are you 

Actualizaciones: usando el búfer de historial (como se menciona en los comentarios)

Una forma sencilla de crear un pseudo-menú para desplazamiento / búsqueda es cargar las palabras clave en el búfer histórico. A continuación, podrá desplazarse por las entradas con las teclas de flecha arriba / abajo y usar Ctrl + R para realizar una búsqueda inversa.

Para probar esto, haga los siguientes cambios:

 keywords = ["hello", "hi", "how are you", "goodbye", "great"] completer = MyCompleter(keywords) readline.set_completer(completer.complete) readline.parse_and_bind('tab: complete') for kw in keywords: readline.add_history(kw) input = raw_input("Input: ") print "You entered", input 

Cuando ejecute el script, intente escribir Ctrl + r seguido de a . Eso devolverá la primera coincidencia que contenga “a”. Ingresa Ctrl + r nuevamente para la próxima partida. Para seleccionar una entrada, pulse ENTER .

También intente usar las teclas ARRIBA / ABAJO para desplazarse por las palabras clave.

Supongo que tendrá que presionar una tecla por el usuario.

Puedes lograrlo (sin pulsar Intro) con un método como este:

 import termios, os, sys def getkey(): fd = sys.stdin.fileno() old = termios.tcgetattr(fd) new = termios.tcgetattr(fd) new[3] = new[3] & ~termios.ICANON & ~termios.ECHO new[6][termios.VMIN] = 1 new[6][termios.VTIME] = 0 termios.tcsetattr(fd, termios.TCSANOW, new) c = None try: c = os.read(fd, 1) finally: termios.tcsetattr(fd, termios.TCSAFLUSH, old) return c 

Luego, si esta tecla es una tecla de tabulación (por ejemplo, eso es algo que necesita implementar), entonces muestre todas las posibilidades al usuario. Si esa es cualquier otra clave, imprímela en la salida estándar.

Oh, por supuesto, necesitarás tener getkey () en bucle por un tiempo, siempre que el usuario presione enter. También puede obtener un método como raw_input, que obtendrá toda la palabra signo por signo, o mostrará todas las posibilidades, cuando llegue a una pestaña.

Al menos ese es el objeto, puedes empezar con. Si logras algún otro problema, entonces escribe sobre ellos.

EDITAR 1:

El método get_word puede verse así:

 def get_word(): s = "" while True: a = getkey() if a == "\n": break elif a == "\t": print "all possibilities" else: s += a return s word = get_word() print word 

El problema que estoy ocurriendo ahora mismo es la forma de mostrar un letrero, usted acaba de ingresar sin ningún tipo de espacios y espacios, lo que print a e print a, hace.

Para habilitar el autocompletado en un shell de Python, escriba esto:

 import rlcompleter, readline readline.parse_and_bind('tab:complete') 

(Gracias a http://blog.e-shell.org/221 )

Pasos:

  1. Cree un archivo .pythonrc en el directorio de inicio con este comando: vi .pythonrc

  2. Introduce este contenido:

     import rlcompleter, readline readline.parse_and_bind('tab:complete') 
  3. Cierra el archivo

  4. Ahora corre

    echo "export PYTHONSTARTUP=~/.pythonrc" >> ~/.bashrc

  5. Reiniciar la terminal

Para aquellos (como yo) que terminan aquí buscando autocompletar en el intérprete:

https://web.archive.org/web/20140214003802/http://conjurecode.com/enable-auto-complete-in-python-interpreter/

Esto implica crear un archivo .pythonrc , modificar .bashrc y un sistema de import sys que debe importar cada vez que inicie el intérprete de Python.

Me pregunto si este último puede ser automatizado para ganar aún más.