![](/img/trans.png)
[英]Python readline tab-completion in cmd.Cmd, when sys.stdout has been replaced
[英]Python readline, tab completion cycling with the Cmd interface
我在Python中使用cmd.Cmd
類為我的程序提供了一個簡單的readline接口。
自包含的例子:
from cmd import Cmd
class CommandParser(Cmd):
def do_x(self, line):
pass
def do_xy(self, line):
pass
def do_xyz(self, line):
pass
if __name__ == "__main__":
parser = CommandParser()
parser.cmdloop()
按兩次選項卡將顯示可能性。 再次按下標簽也是如此。
我的問題是,如何在第三個標簽按下循環選項? 在readline術語中我認為這稱為Tab: menu-complete
,但我看不到如何將它應用於Cmd
實例。
我已經嘗試過:
readline.parse_and_bind('Tab: menu-complete')
在實例化解析器實例之前和之后。 沒運氣。
我還嘗試將"Tab: menu-complete"
傳遞給Cmd
構造函數。 在這里也沒有運氣。
有誰知道它是如何完成的?
干杯!
不幸的是,似乎唯一的方法cmdloop
從cmd.Cmd
類中修補方法cmdloop
,或者滾動自己的方法。
正確的方法是使用"Tab: menu-complete"
,但是它被類重寫,如第115行所示: readline.parse_and_bind(self.completekey+": complete")
,它永遠不會被激活。 (對於第115行和整個cmd
包,請參閱: https : //hg.python.org/cpython/file/2.7/Lib/cmd.py )。 我在下面展示了該功能的編輯版本,以及如何使用它:
import cmd
# note: taken from Python's library: https://hg.python.org/cpython/file/2.7/Lib/cmd.py
def cmdloop(self, intro=None):
"""Repeatedly issue a prompt, accept input, parse an initial prefix
off the received input, and dispatch to action methods, passing them
the remainder of the line as argument.
"""
self.preloop()
if self.use_rawinput and self.completekey:
try:
import readline
self.old_completer = readline.get_completer()
readline.set_completer(self.complete)
readline.parse_and_bind(self.completekey+": menu-complete") # <---
except ImportError:
pass
try:
if intro is not None:
self.intro = intro
if self.intro:
self.stdout.write(str(self.intro)+"\n")
stop = None
while not stop:
if self.cmdqueue:
line = self.cmdqueue.pop(0)
else:
if self.use_rawinput:
try:
line = raw_input(self.prompt)
except EOFError:
line = 'EOF'
else:
self.stdout.write(self.prompt)
self.stdout.flush()
line = self.stdin.readline()
if not len(line):
line = 'EOF'
else:
line = line.rstrip('\r\n')
line = self.precmd(line)
stop = self.onecmd(line)
stop = self.postcmd(stop, line)
self.postloop()
finally:
if self.use_rawinput and self.completekey:
try:
import readline
readline.set_completer(self.old_completer)
except ImportError:
pass
# monkey-patch - make sure this is done before any sort of inheritance is used!
cmd.Cmd.cmdloop = cmdloop
# inheritance of the class with the active monkey-patched `cmdloop`
class MyCmd(cmd.Cmd):
pass
一旦你修改了類方法(或實現了自己的類),它就會提供正確的行為(盡管沒有突出顯示和反向標記,但這些可以根據需要使用其他鍵實現)。
最簡單的技巧是在menu-complete
后添加一個空格:
parser = CommandParser(completekey="tab: menu-complete ")
執行的綁定表達式
readline.parse_and_bind(self.completekey+": complete")
然后會成為
readline.parse_and_bind("tab: menu-complete : complete")
第二個空格后的所有內容都被實際忽略,因此它與tab: menu-complete
相同tab: menu-complete
。
如果你不想依賴於readline解析的行為(我沒有看到它的文檔記錄),你可以使用str
的子類,拒絕擴展為completekey:
class stubborn_str(str):
def __add__(self, other):
return self
parser = CommandParser(completekey=stubborn_str("tab: menu-complete"))
self.completekey+": complete"
現在與self.completekey
相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.