Python2.7CMD自动完成读取行缓冲区似乎过时了

Python2.7CMD自动完成读取行缓冲区似乎过时了,python,autocomplete,cmd,readline,Python,Autocomplete,Cmd,Readline,我在Mac OS(和Red Hat Linux)上使用基于readline的cmd模块,并启用了制表符完成功能。除了我引入自己的逻辑来处理基于正则表达式匹配的“sub-command”完成之外,它似乎工作得很好。下面是一个简单的地址簿示例,其中我有一个基于树的结构: 代码: 输出: (Cmd) assign <TAB> employee manager (Cmd) assign employee <TAB> address phone name (C

我在Mac OS(和Red Hat Linux)上使用基于readline的cmd模块,并启用了制表符完成功能。除了我引入自己的逻辑来处理基于正则表达式匹配的“sub-command”完成之外,它似乎工作得很好。下面是一个简单的地址簿示例,其中我有一个基于树的结构:

代码:

输出:

(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
(Cmd)分配
员工经理
(Cmd)指派员工
地址电话号码
(Cmd)指定员工姓名
最后中间第一
(Cmd)首先指定员工姓名
员工姓名在先

(Cmd)assign多亏了这篇文章,我想我解决了这个问题:

在浏览
BufferAwareCompleter
代码时,我无意中发现了这一行:

being_completed = origline[begin:end]
这让我认为我应该能够利用CompleterAPI中提供的行索引来发挥我的优势,这正是我的帮助所在

因为我不关心缓冲区的“过时”部分,所以我只使用结束索引来标定我的行边界。这就成功了:

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()
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