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.

27
demandé sur xralf 2011-10-19 16:58:20

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.

43
répondu Shawn Chin 2016-08-01 20:40:01

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,.

6
répondu Gandi 2013-04-03 07:44:59

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)

4
répondu Nicolas S 2016-09-23 19:50:00

Étapes:

  1. Créer un fichier .pythonrc dans le répertoire personnel par cette commande: vi .pythonrc

  2. Entrez ce contenu:

    import rlcompleter, readline  
    readline.parse_and_bind('tab:complete') 
    
  3. Fermez le fichier

  4. Exécutez maintenant

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

  5. Redémarrez le terminal

2
répondu AMAN JAIN 2017-05-02 09:30:39

Pour ceux (comme moi) qui finissent ici par chercher la saisie semi-automatique dans l'interpréteur:

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

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.

0
répondu Mark Jeronimus 2018-02-22 12:27:13