Как повторно использовать дополнения из PathCompleter в prompt_toolkit

Я создаю инструмент REPL для своего проекта, который (упрощенный для ясности) либо непосредственно выполняет введенные команды, либо (если введена команда ".x some/path/to/file") читает и выполняет их из файла. Мой вопрос связан с автозаполнением пользовательского ввода (с использованием prompt_toolkit).

У меня есть что-то вроде (минимальный исполняемый пример):

import prompt_toolkit
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.document import Document
from prompt_toolkit.contrib.completers import PathCompleter


class CommandCompleter(Completer):
    def __init__(self):
        self.path_completer = PathCompleter()
        self.commands = [".x", "command1", "command2"]

    def get_completions(self, document, complete_event):
        if document.text.startswith(".x "):
            sub_doc = Document(document.text[3:])
            yield from (Completion(cmd.text, -document.cursor_position)
#                                  ????????  ?????????????????????????
                        for cmd
                        in self.path_completer.get_completions(sub_doc, complete_event))
#                                                              ???????
        else:
            yield from (Completion(cmd, -document.cursor_position)
                        for cmd in self.commands
                        if cmd.startswith(document.text))

if __name__ == "__main__":
    while True:
        other_args = {}
        input = prompt_toolkit.prompt(">>> ", completer=CommandCompleter(), **other_args)
        # Do something with input (omitted)

Вторая ветвь if (для команд) работает правильно, но я не знаю, как правильно вызвать PathCompleter.get_completions() метод и реконструировать Completion объекты из его результата (где???) в первой ветви. Хитрость в том, что я использую завершение только для части ввода, а различные подстроки, расчеты положения и т. Д. (Пока) не привели к удовлетворительному поведению (то есть предложили пути и построили правильную строку ввода).

Я определенно продолжу поиск, но если кто-нибудь знает, как переписать это, это было бы очень полезно.

Замечания: yield from self.path_completer.get_completions(document, complete_event) будет использоваться, если весь вход будет только путь (и это работает правильно).

1 ответ

Решение

Вероятно, следующее должно это исправить:

sub_doc = Document(document.text[3:])
yield from (Completion(completion.text, completion.start_position, display=completion.display)
            for completion
            in self.path_completer.get_completions(sub_doc, complete_event))
  • completion.text содержит текст, который будет вставлен;
  • completion.start_position содержит место, куда будет вставляться текст относительно позиции курсора (в этом конкретном примере мы можем взять значение из вложенного завершителя).
  • completion.display это значение, отображаемое во всплывающем меню. (В этом случае все имя файла, а не только вставленная строка.

Не стесняйтесь, чтобы открыть вопрос GitHub, если у вас есть еще вопросы.

Другие вопросы по тегам