Изменить, как Python Cmd Module обрабатывает автозаполнение - PullRequest
8 голосов
/ 23 октября 2010

У меня есть консоль Cmd, настроенная на автоматическое заполнение имен карт для Magic: система управления коллекцией Gathering.

Он использует параметр text для запроса базы данных о картах и ​​использует результаты для автоматического заполнения / предложения карт.

Однако имена этих карт состоят из нескольких слов, и Cmd запускает автозаполнение с пробела last до конца строки.

Например:

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

Ответы [ 3 ]

10 голосов
/ 23 октября 2010

Это не должно быть слишком сложным. Примерно так:

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()
0 голосов
/ 17 августа 2015

Я переопределил функцию 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

Это сделало это для меня.В вашем случае вы можете удалить любой разделитель, который вызывает проблемы.

0 голосов
/ 23 октября 2010

Вы можете выполнить readline.set_completer_delims('').

Однако ваши функции complete_* больше не будут вызываться;вам придется переопределить Cmd.complete или Cmd.completenames.Подробности смотрите в исходном коде модуля cmd.

...