46 votes

Comment écrire du code pour l'autocomplétion de mots et de phrases ?

J'aimerais écrire un code qui fasse de l'autocomplétion dans le terminal Linux. Le code devrait fonctionner comme suit.

Il contient une liste de chaînes de caractères (par exemple "hello", "hi", "how are you", "goodbye", "great", ...).

Dans le terminal, l'utilisateur commence à taper et lorsqu'il y a une possibilité de correspondance, il obtient un indice des chaînes possibles, parmi lesquelles il peut choisir (de la même manière que dans éditeur vim o Recherche incrémentale de Google ).

par exemple, il commence à taper "h", et il comprend l'indice

h "ello"

_ "i"

_"Comment allez-vous ?"

Mieux encore, il pourrait compléter les mots non seulement à partir du début, mais aussi à partir d'une partie arbitraire de la chaîne.

59voto

Shawn Chin Points 29756

(Je suis conscient que ce n'est pas exactement ce que vous demandez, mais) Si vous êtes satisfait de l'auto-complétion/suggestions qui apparaissent sur TAB (tel qu'il est utilisé dans de nombreux shells), vous pouvez alors être rapidement opérationnel en utilisant la commande ligne de lecture module.

Voici un exemple rapide basé sur L'article de Doug Hellmann sur readline dans PyMOTW .

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 pression sur la touche de tabulation) :

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 ( HOTAB ), il n'y a qu'une seule correspondance possible et la phrase entière "how are you" est complétée automatiquement.

Consultez les articles en lien pour plus d'informations sur readline .


"Et mieux encore, il pourrait compléter les mots non seulement à partir du début... mais aussi à partir de n'importe quelle partie de la chaîne de caractères.

Pour ce faire, il suffit de modifier les critères de correspondance dans la fonction d'achèvement, 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]

Vous obtiendrez 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 le défilement/la recherche consiste à charger les mots-clés dans la mémoire tampon de l'historique. Vous pourrez alors faire défiler les entrées à l'aide des touches fléchées haut/bas et utiliser la fonction Ctrl + R pour effectuer une recherche inversée.

Pour l'essayer, procédez aux 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 suivi de a . Cela renverra la première correspondance qui contient "a". Entrer Ctrl + r pour le match suivant. Pour sélectionner une entrée, appuyez sur ENTER .

Essayez également d'utiliser les touches UP/DOWN pour faire défiler les mots-clés.

9voto

Nicolas S Points 81

Pour activer l'autocomplétion dans un shell Python, tapez ceci :

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

(merci à http://blog.e-shell.org/221 )

9voto

Erasmose Points 165

Il peut être utile de vérifier fast-autocomplete : https://github.com/seperman/fast-autocomplete

Il dispose d'un mode démo qui vous permet de taper et d'obtenir des résultats au fur et à mesure que vous tapez : https://zepworks.com/posts/you-autocomplete-me/#part-6-demo

Il est très facile à utiliser :

>>> from fast_autocomplete import AutoComplete
>>> words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
>>> autocomplete = AutoComplete(words=words)
>>> autocomplete.search(word='b', max_cost=3, size=3)
[['book'], ['burrito']]
>>> autocomplete.search(word='bu', max_cost=3, size=3)
[['burrito']]
>>> autocomplete.search(word='barrito', max_cost=3, size=3)  # mis-spelling
[['burrito']]

Clause de non-responsabilité : j'ai écrit "fast-autocomplete".

7voto

Gandi Points 1447

Je suppose que vous devrez obtenir une touche pressée par l'utilisateur.

Vous pouvez y parvenir (sans appuyer sur la touche 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 touche est une touche de tabulation (par exemple, c'est quelque chose que vous devez implémenter), alors affichez toutes les possibilités à l'utilisateur. S'il s'agit d'une autre touche, elle est affichée sur stdout.

Oh, bien sûr, vous devrez faire tourner getkey() en boucle pendant un certain temps, tant que l'utilisateur appuie sur enter. Vous pouvez également utiliser une méthode comme raw_input, qui récupère le mot entier, signe par signe, ou qui affiche toutes les possibilités, lorsque vous appuyez sur une touche de tabulation.

C'est du moins l'objet avec lequel vous pouvez commencer. Si vous rencontrez d'autres problèmes, écrivez-les.

EDIT 1 :

La méthode get_word peut se présenter comme suit :

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 actuellement est la façon d'afficher un signe, vous venez d'entrer sans les entrées et les espaces, ce que les deux print a y print a, ne.

4voto

AMAN JAIN Points 31

Les étapes :

  1. Créez un fichier .pythonrc dans votre répertoire personnel à l'aide de cette commande : vi .pythonrc

  2. Saisir ce contenu :

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

  4. Exécuter maintenant

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

  5. Redémarrer le terminal

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X