Буферы Python 2.7 cmd с автозаполнением readline кажутся устаревшими
Я использую модуль cmd на основе readline в Mac OS (и Red Hat Linux) с включенным завершением табуляции. Кажется, он работает отлично, за исключением случаев, когда я представил свою собственную логику для обработки завершений "подкоманд", основанных на сопоставлении с регулярными выражениями Вот простой пример адресной книги, где у меня есть древовидная структура:
Код:
import cmd
import readline
import re
readline.parse_and_bind("bind ^I rl_complete")
class Test(cmd.Cmd):
def do_assign(self, line):
print line
def complete_assign(self, text, line, begidx, endidx):
if re.match('assign\s+employee\s+name', line):
return [i for i in ['first', 'middle', 'last']
if i.startswith(text)]
elif re.match('assign\s+employee', line):
return [i for i in ['name', 'address', 'phone']
if i.startswith(text)]
elif line.startswith("assign"):
return [i for i in ['employee', 'manager']
if i.startswith(text)]
Test().cmdloop()
Выход:
(Cmd) assign <TAB>
employee manager
(Cmd) assign employee <TAB>
address phone name
(Cmd) assign employee name <TAB>
last middle first
(Cmd) assign employee name first <RETURN>
employee name first
(Cmd) assign <TAB> <-- This is incorrect. Expecting ['employee', 'manager'] instead
last middle first
(Cmd) assign
Как вы видите разницу между первой и последней операциями "назначения", я получаю разные результаты, потому что line
переменная в функции complete_assign
кажется назначен assign employee name first
вместо просто assign
из-за предыдущей операции RETURN, из-за которой логика завершителя теперь соответствует неправильному блоку кода регулярного выражения и предоставляет неправильные завершения. Есть ли способ "сбрасывать" буфер readline stdin после каждой операции, чтобы он не запоминал буфер из предыдущего complete_assign
или же do_assign
испытания?
Спасибо!
1 ответ
Я думаю, что я решил это, благодаря этой статье: http://pymotw.com/2/readline/
Проходя через BufferAwareCompleter
код, я наткнулся на эту строку:
being_completed = origline[begin:end]
Это заставило меня подумать, что я должен иметь возможность использовать строковые индексы, предоставленные в законченном API, для своего преимущества, и это именно то, что помогло.
Поскольку меня не заботила "устаревшая" часть буфера, я просто использовал конечный индекс для разграничения границы моей строки. Это сделало трюк:
line = line[:endidx]
Обновлен рабочий код:
import cmd
import readline
import re
readline.parse_and_bind("bind ^I rl_complete")
class Test(cmd.Cmd):
def do_assign(self, line):
print line
def complete_assign(self, text, line, begidx, endidx):
line = line[:endidx] # <-- ADDED THIS
if re.match('assign\s+employee\s+name', line):
return [i for i in ['first', 'middle', 'last']
if i.startswith(text)]
elif re.match('assign\s+employee', line):
return [i for i in ['name', 'address', 'phone']
if i.startswith(text)]
elif line.startswith("assign"):
return [i for i in ['employee', 'manager']
if i.startswith(text)]
Test().cmdloop()
Обновить рабочий вывод:
(Cmd) assign
employee manager
(Cmd) assign employee
name phone address
(Cmd) assign employee name
last middle first
(Cmd) assign employee name first
employee name first
(Cmd) assign
manager employee
(Cmd) assign