[英]Change how Python Cmd Module handles autocompletion
我有一個Cmd控制台,用於自動完成Magic:收集管理系統的卡名稱。
它使用text參數查詢數據庫中的卡片,並使用結果自動完成/建議卡片。
但是,這些卡名稱有多個單詞,Cmd從最后一個空格到行尾自動完成。
例如:
mtgdb> add Mage<tab><tab>
Mage Slayer (Alara Reborn) Magefire Wings (Alara Reborn)
mtgdb> add Mage S<tab><tab>
Sages of the Anima (Alara Reborn)
Sanctum Plowbeast (Alara Reborn)
Sangrite Backlash (Alara Reborn)
Sanity Gnawers (Alara Reborn)
Sen Triplets (Alara Reborn)
[...]
mtgdb> add Mage Sl<tab>
mtgdb> add Mage Slave of Bolas (Alara Reborn)
我嘗試從line
參數手動抓取我想要的東西,它從數據庫中獲取我想要的結果,但是這無法覆蓋第一個單詞:
mtgdb> add Mage Sl<tab>
mtgdb> add Mage Mage Slayer (Alara Reborn)
最后,我需要自動完成器像這樣工作:
mtgdb> add Mage Sl<tab>
mtgdb> add Mage Slayer (Alara Reborn)
除了上面的手動解析嘗試之外,我還嘗試用加號替換空格,並發現Cmd也非常樂意拆分它們。 用下划線替換空格是有效的,但是Unhinged中有一張名為_____
卡片,因此我不得不通過雜技來開始弦樂,因為我不能只使用line.replace("_", " ")
。
這是一些可運行的測試代碼:
import cmd
commands = [
"foo",
"foo bar blah",
"bar",
"bar baz blah",
"baz",
"baz foo blah"]
class Console(cmd.Cmd):
intro = "Test console for" + \
"http://stackoverflow.com/questions/4001708/\n" + \
"Type \"cmd<space><tab><tab>\" to test " + \
"auto-completion with spaces in commands\nwith " + \
"similar beginings."
def do_cmd(self, line):
print(line)
def complete_cmd(self, text, line, start_index, end_index):
if text:
return [command for command in commands
if command.startswith(text)]
else:
return commands
if __name__ == "__main__":
command = Console()
command.cmdloop()
它不應該過於復雜。 類似於以下內容:
import cmd
completions = [
'Mage Slayer (Alara Reborn)',
'Magefire Wings (Alara Reborn)',
'Sages of the Anima (Alara Reborn)',
'Sanctum Plowbeast (Alara Reborn)',
'Sangrite Backlash (Alara Reborn)',
'Sanity Gnawers (Alara Reborn)',
'Sen Triplets (Alara Reborn)'
]
class mycmd(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
def do_quit(self, s):
return True
def do_add(self, s):
pass
def complete_add(self, text, line, begidx, endidx):
mline = line.partition(' ')[2]
offs = len(mline) - len(text)
return [s[offs:] for s in completions if s.startswith(mline)]
if __name__ == '__main__':
mycmd().cmdloop()
我確實覆蓋了cmdloop函數,它非常簡單。 我沒有必要改變其他任何東西。 只需從模塊中復制cmdloop函數(通過執行import cmd
, cmd.__file__
查找代碼),然后添加兩行來更改分隔符:
try:
import readline
self.old_completer = readline.get_completer()
readline.set_completer(self.complete)
readline.parse_and_bind(self.completekey+": complete")
# do not use - as delimiter
old_delims = readline.get_completer_delims() # <-
readline.set_completer_delims(old_delims.replace('-', '')) # <-
except ImportError:
pass
這樣做對我來說。 在您的情況下,您可能希望刪除導致問題的分隔符。
你可以做readline.set_completer_delims('')
。
但是,您的complete_*
函數將不再被調用; 您必須覆蓋Cmd.complete
或Cmd.completenames
。 有關詳細信息,請查看cmd
模塊的源代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.