Как кодировать автозаполнение в python?

Я хотел бы закодировать автозаполнение в терминале Linux. Код должен работать следующим образом.

Он имеет список строк (например, "Привет", "привет"," как дела"," до свидания"," отлично",...).

в терминале пользователь начнет печатать, и когда есть возможность совпадения, он получает подсказку для возможных строк, из которых он может выбрать (аналогично как в редактор vim или гугл поиск).

например, он начинает печатать "H" и он понимает намек

h "ello"

_ "i"

_"Ой ты"

а еще лучше было бы, если бы он заполнял слова не только с самого начала, но и из произвольной части строки.

Спасибо за совет.

5 ответов


(Я знаю, что это не совсем то, что вы просите, но), если вы довольны автозаполнением/предложениями, появляющимися на TAB (как используется во многих оболочках), то вы можете быстро встать и запустить с помощью readline модуль.

вот краткий пример, основанный на запись PyMOTW Дуга Хеллмана на 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

это приводит к следующему поведению (<TAB> представление клавиши tab нажата):

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

в последней строке (HOTAB введено), есть только одно возможное совпадение, и все предложение "как вы" автоматически завершено.

Проверьте связанные статьи для получения дополнительной информации о readline.


" а еще лучше было бы, если бы она завершала слова не только с самого начала ... завершение из произвольной части строки."

этот может быть достигнуто путем простого изменения критериев соответствия в функции completer, т. е. от:

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

что-то вроде:

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

это даст вам следующее поведение:

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

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

обновления: использование буфера истории (как указано в комментариях)

простой способ создать псевдо-меню для прокрутки / поиска-загрузить ключевые слова в буфер истории. Затем вы сможете прокручивать записи, используя клавиши со стрелками вверх / вниз, а также использовать Ctrl+R для выполнения обратного поиска.

чтобы попробовать это, сделайте следующие изменения:

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

при запуске скрипта, попробуйте ввести Ctrl+r следовал по a. Это вернет первый матч, который содержит "a". Enter Ctrl+r снова для следующего матча. Чтобы выбрать запись, нажмите ENTER.

также попробуйте использовать клавиши вверх/вниз для прокрутки слова.


Я думаю, вам нужно будет нажать клавишу пользователем.

вы можете достичь этого (без нажатия enter) с помощью такого метода:

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

затем, если этот ключ является клавишей tab (например, это то, что вам нужно реализовать), затем отобразите все возможности для пользователя. Если это какой-либо другой ключ, распечатайте его на stdout.

О, конечно, вам нужно будет зациклить getkey () через некоторое время, пока пользователь нажимает enter. Вы также можете получить такой метод, как raw_input, который получит весь знак слова по знаку или отобразит все возможности, когда вы нажмете вкладку.

по крайней мере, это элемент, с которого вы можете начать. Если вы достигнете каких-либо других проблем, то пишите о них.

EDIT 1:

метод get_word может выглядеть следующим образом:

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

проблема, с которой я сталкиваюсь прямо сейчас, - это способ отображения знака, вы только что вошли без каких-либо входов и пробелов, что оба print a и print a, делает.


чтобы включить автозаполнение в оболочке Python, введите следующее:

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

(спасибо http://blog.e-shell.org/221)


действия:

  1. создайте файл .pythonrc в домашнем каталоге по этой команде: vi .pythonrc

  2. ввод такого содержания:

    import rlcompleter, readline  
    readline.parse_and_bind('tab:complete') 
    
  3. закрыть файл

  4. Теперь бегите

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

  5. перезапустить терминал


для тех (как я), которые в конечном итоге здесь ищут автозаполнение в интерпретаторе:

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

Это включает в себя создание файла .pythonrc, модификации .bashrc и import sys вы должны импортировать каждый раз, когда вы запустите интерпретатор Python.

интересно, можно ли автоматизировать последнее для еще большего выигрыша.