Comment coder l'auto-complétion en python?
Je voudrais coder l'auto-complétion dans le terminal Linux. Le code devrait fonctionner comme suit.
Il a une liste de chaînes (par exemple "Bonjour, "salut", "comment allez-vous", "au revoir", "génial",...).
Dans le terminal, l'utilisateur va commencer à taper et quand il y a une possibilité de correspondance, il obtient l'indice pour les chaînes possibles, à partir de laquelle il peut choisir (de la même manière que dans vim editor ou google incrémental search).
Par exemple, il commence à taper " h " et il obtient le indice
H "ello"
_ "je"
_"ux de vous"
Et mieux encore serait si elle complétait les mots non seulement depuis le début mais à partir d'une partie arbitraire de la chaîne.
Merci pour conseiller.
5 réponses
(je suis conscient que ce n'est pas exactement ce que vous demandez, mais) si vous êtes satisfait de l'auto-complétion/suggestions apparaissant sur TAB (comme utilisé dans de nombreux shells), alors vous pouvez rapidement démarrer en utilisant le module readline.
Voici un exemple rapide basé sur l'écriture Pymotw de Doug Hellmann sur 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
Il en résulte le comportement suivant (<TAB>
représentant une touche de tabulation enfoncée):
Input: <TAB><TAB>
goodbye great hello hi how are you
Input: h<TAB><TAB>
hello hi how are you
Input: ho<TAB>ow are you
Dans la dernière ligne (HOONGLET entré), il n'est qu'un match et l'ensemble de la phrase "comment êtes-vous" est automatiquement terminée.
Découvrez les articles liés pour plus d'informations sur readline
.
" et mieux encore serait si elle complète les mots non seulement depuis le début ... complétion à partir d'une partie arbitraire de la chaîne."
Cela peut être réalisé en modifiant simplement les critères de correspondance dans la fonction completer, c'est-à-dire. de:
self.matches = [s for s in self.options
if s and s.startswith(text)]
À quelque chose comme:
self.matches = [s for s in self.options
if text in s]
Cela vous donnera le comportement suivant:
Input: <TAB><TAB>
goodbye great hello hi how are you
Input: o<TAB><TAB>
goodbye hello how are you
Mises à jour: Utilisation du tampon d'historique (comme mentionné dans les commentaires)
Un moyen simple de créer un pseudo-menu pour faire défiler/rechercher est de charger les mots clés dans le tampon d'historique. Vous pourrez ensuite faire défiler les entrées à l'aide des touches fléchées Haut/Bas et utiliser Ctrl+R {[10] } pour effectuer une recherche inverse.
Pour essayer ceci sortir, faire les modifications suivantes:
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
Lorsque vous exécutez le script, essayez de taper Ctrl+r, suivie par un. Cela renverra la première correspondance qui contient "a". Saisissez Ctrl+r de nouveau pour le prochain match. Pour sélectionner une entrée, appuyez sur ENTER .
Essayez également d'utiliser les touches HAUT/BAS pour faire défiler les mots-clés.
Je suppose que vous devrez obtenir une touche enfoncée par l'utilisateur.
Vous pouvez y parvenir (sans appuyer sur Entrée) avec une méthode comme celle-ci:
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
Ensuite, si cette clé est une touche de tabulation (par exemple, c'est quelque chose que vous devez implémenter), alors affichez toutes les possibilités à l'utilisateur. Si c'est une autre clé, imprimez-la sur stdout.
Oh, bien sûr, vous aurez besoin d'avoir getkey() en boucle dans un certain temps, tant que l'utilisateur frappe entrée. Vous pouvez également obtenir une méthode comme raw_input, qui obtiendra le mot entier signe par signe, ou afficher toutes les possibilités, lorsque vous appuyez sur un onglet.
, Au moins, c'est l'élément, vous pouvez commencer avec. Si vous avez d'autres problèmes, que d'écrire à leur sujet.
Édition 1:
La méthode get_word peut ressembler à ceci:
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
Le problème que je rencontre en ce moment est la façon d'afficher un signe, vous venez d'entrer sans entrées et espaces, ce que font à la fois print a
et print a,
.
Pour activer la saisie semi-automatique dans un shell Python, tapez ceci:
import rlcompleter, readline
readline.parse_and_bind('tab:complete')
(merci à http://blog.e-shell.org/221)
Étapes:
Créer un fichier .pythonrc dans le répertoire personnel par cette commande:
vi .pythonrc
-
Entrez ce contenu:
import rlcompleter, readline readline.parse_and_bind('tab:complete')
Fermez le fichier
-
Exécutez maintenant
echo "export PYTHONSTARTUP=~/.pythonrc" >> ~/.bashrc
Redémarrez le terminal
Pour ceux (comme moi) qui finissent ici par chercher la saisie semi-automatique dans l'interpréteur:
Cela implique la création d'un fichier .pythonrc
, modifiant .bashrc
et import sys
vous devez importer chaque fois que vous lancez l'interpréteur Python.
Je me demande si ce dernier peut être automatisé pour encore plus de gagner.