簡體   English   中英

更改Python Cmd模塊處理自動完成的方式

[英]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 cmdcmd.__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.completeCmd.completenames 有關詳細信息,請查看cmd模塊的源代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM