Jak kodować autocompletion w Pythonie?

Chciałbym kodować autocompletion w Terminalu Linuksa. Kod powinien działać w następujący sposób.

Posiada listę ciągów (np. "hello", "hi", "how are you", "goodbye", "great",...).

W terminalu użytkownik zacznie wpisywać i gdy będzie jakaś możliwość dopasowania, otrzyma podpowiedź dla możliwych ciągów, z których może wybrać (podobnie jak w vim editor lub Google incremental search).

Np. zaczyna wpisywać " h " i dostaje hint

H "ello"

_ "i"

_"ow are you"

I jeszcze lepiej byłoby, gdyby dopełniało słowa nie tylko od początku, ale od dowolnej części łańcucha.

Dziękuję za radę.

Author: xralf, 2011-10-19

5 answers

(wiem, że nie jest to dokładnie to, o co prosisz, ale) jeśli jesteś zadowolony z automatycznego uzupełniania / sugestii pojawiających się na karcie (używanej w wielu powłokach), możesz szybko rozpocząć pracę za pomocą modułu readline.

Oto szybki przykład oparty na Doug Hellmann ' s PyMOTW writeup on 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
W tym celu należy wykonać następujące czynności:]}
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

W ostatniej linijce (HOTAB wprowadzony), jest tylko jedno możliwe dopasowanie i całe zdanie "jak się masz" jest automatycznie uzupełniane.

Sprawdź połączone artykuły, aby uzyskać więcej informacji na temat readline.


"i jeszcze lepiej byłoby, gdyby dopełniały słowa nie tylko od początku ... dopełnienie z dowolnej części łańcucha."

Można to osiągnąć po prostu modyfikując kryteria dopasowania w funkcji completer, tj. from:

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

Do czegoś takiego:

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

To daje następujące zachowanie:

Input: <TAB><TAB>
goodbye      great        hello        hi           how are you

Input: o<TAB><TAB>
goodbye      hello        how are you

Aktualizacje: korzystanie z bufora historii (jak wspomniano w komentarzach)

Prostym sposobem utworzenia pseudo-menu do przewijania/wyszukiwania jest załadowanie słów kluczowych do bufora historii. Następnie będziesz mógł przewijać wpisy za pomocą klawiszy strzałek w górę/w dół oraz za pomocą Ctrl+R , aby wykonać wyszukiwanie odwrotne.

Aby spróbować tego out, wprowadzić następujące zmiany:

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

Po uruchomieniu skryptu spróbuj wpisać Ctrl+r , po którym następuje a . To zwróci pierwszy mecz, który zawiera "a". Enter Ctrl+r ponownie na następny mecz. Aby wybrać wpis, naciśnij ENTER .

Spróbuj również użyć klawiszy GÓRA/DÓŁ, aby przewijać słowa kluczowe.

 43
Author: Shawn Chin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-01 20:40:01

Myślę, że będziesz musiał nacisnąć klawisz przez użytkownika.

Możesz to osiągnąć (bez wciśnięcia enter) za pomocą metody takiej jak Ta:

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

Następnie, jeśli ten klucz jest klawiszem tab (na przykład jest to coś, co musisz zaimplementować), wyświetl wszystkie możliwości dla użytkownika. Jeśli to jakiś inny klucz, wydrukuj go na stdout.

Oh, oczywiście musisz mieć zapętloną getkey () za jakiś czas, o ile użytkownik naciśnie enter. Możesz również uzyskać metodę taką jak raw_input, która otrzyma cały znak słowa Po znaku lub wyświetl wszystkie możliwości, po naciśnięciu karty.

Przynajmniej od tego możesz zacząć. Jeśli osiągniesz jakieś inne problemy, napisz o nich.

EDIT 1:

Metoda get_word może wyglądać tak:

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

Problem, który obecnie występuje, to sposób wyświetlania znaku, który właśnie wszedłeś bez żadnych enteres i spacji, co robi zarówno print a, jak i print a,.

 6
Author: Gandi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-03 07:44:59

Aby włączyć autouzupełnianie w powłoce Pythona, wpisz:

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

(dzięki http://blog.e-shell.org/221 )

 4
Author: Nicolas S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-23 19:50:00

Kroki:

  1. Utwórz plik .pythonrc w katalogu domowym za pomocą tego polecenia: vi .pythonrc

  2. Wpisz tę treść:

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

  4. Teraz biegnij

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

  5. Uruchom ponownie terminal

 2
Author: AMAN JAIN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-02 09:30:39

Dla tych (jak ja), którzy kończą tutaj szukając autouzupełniania w interpreterze:

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

Wiąże się to z utworzeniem pliku .pythonrc, modyfikacją .bashrc i import sys, które należy zaimportować przy każdym uruchomieniu interpretera Pythona.

Zastanawiam się, czy ta ostatnia może być zautomatyzowana dla jeszcze większej wygranej.

 0
Author: Mark Jeronimus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 12:27:13