如何实现Python命令行自动补全,但不仅限于字符串开头
Python通过它的readline绑定,可以实现很棒的命令行自动补全功能(详细内容可以在这里找到)。
不过,这种补全功能似乎只在字符串的开头有效。如果你想在字符串的中间或结尾进行匹配,readline就不管用了。
我想在一个命令行的Python程序中实现字符串的自动补全,方法是将我输入的内容与一个可用字符串的列表进行匹配。
- 我想要的自动补全类型可以参考GMail的“收件人”字段。当你输入某个联系人的姓氏时,它会像输入名字一样显示出来。
- 可能需要使用上下箭头或其他方法来选择匹配的字符串(在readline的情况下可能不需要),这对我来说没问题。
- 我具体的使用场景是一个命令行程序,用于发送电子邮件。
- 提供一些具体的代码示例会非常有帮助。
使用像curses这样的终端模拟器也可以。这个程序只需要在Linux上运行,不需要在Mac或Windows上运行。
举个例子:假设我有以下三个字符串在一个列表中
['Paul Eden <paul@domain.com>',
'Eden Jones <ejones@domain.com>',
'Somebody Else <somebody@domain.com>']
我希望有一些代码可以在我输入'Eden'后自动补全列表中的前两个项目,然后让我选择其中一个(全部通过命令行和键盘操作)。
1 个回答
10
我不太明白这个问题。你可以使用readline.clear_history和readline.add_history来设置你想要的可补全字符串,然后按控制键加r(control-r)可以在历史记录中向后搜索(就像你在命令行提示符下那样)。例如:
#!/usr/bin/env python
import readline
readline.clear_history()
readline.add_history('foo')
readline.add_history('bar')
while 1:
print raw_input('> ')
另外,你也可以自己写一个补全器,并把合适的按键绑定到它上面。这个版本使用了缓存,以防你的匹配列表非常大:
#!/usr/bin/env python
import readline
values = ['Paul Eden <paul@domain.com>',
'Eden Jones <ejones@domain.com>',
'Somebody Else <somebody@domain.com>']
completions = {}
def completer(text, state):
try:
matches = completions[text]
except KeyError:
matches = [value for value in values
if text.upper() in value.upper()]
completions[text] = matches
try:
return matches[state]
except IndexError:
return None
readline.set_completer(completer)
readline.parse_and_bind('tab: menu-complete')
while 1:
a = raw_input('> ')
print 'said:', a