Буферы 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 
Другие вопросы по тегам