Как кодировать автозаполнение в 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)
действия:
создайте файл .pythonrc в домашнем каталоге по этой команде:
vi .pythonrc
-
ввод такого содержания:
import rlcompleter, readline readline.parse_and_bind('tab:complete')
закрыть файл
-
Теперь бегите
echo "export PYTHONSTARTUP=~/.pythonrc" >> ~/.bashrc
перезапустить терминал
для тех (как я), которые в конечном итоге здесь ищут автозаполнение в интерпретаторе:
Это включает в себя создание файла .pythonrc
, модификации .bashrc
и import sys
вы должны импортировать каждый раз, когда вы запустите интерпретатор Python.
интересно, можно ли автоматизировать последнее для еще большего выигрыша.