Завершение табуляции в интерфейсе командной строки Python - как перехватывать события табуляции

Я пишу немного CLI на Python (как расширение для Mercurial) и хотел бы поддержать завершение табуляции. В частности, я хотел бы поймать вкладки в приглашении и показать список подходящих опций (как в bash).

Пример: введите название раздела:

 ext*TAB*  
 extensions  
 extras

Проблема в том, что я не уверен, как отлавливать события Tab. Я использую ui.prompt() API Mercurial, который просто звонит raw_input() под капотом.

Насколько я знаю, raw_input() возвращается только при вводе, и если пользователь заходит на вкладку, возвращаемая строка просто включает "\t",

3 ответа

Решение

Для этого вы используете readline модуль.

Простейший код, который я могу подумать:

import readline
COMMANDS = ['extra', 'extension', 'stuff', 'errors',
            'email', 'foobar', 'foo']

def complete(text, state):
    for cmd in COMMANDS:
        if cmd.startswith(text):
            if not state:
                return cmd
            else:
                state -= 1

readline.parse_and_bind("tab: complete")
readline.set_completer(complete)
raw_input('Enter section name: ')

Пример использования:

Enter section name: <tab>
email      errors     extension  extra      foo        foobar    stuff
Enter section name: e<tab>
email      errors     extension  extra      
Enter section name: ext<tab>
extension  extra      

Помимо завершения, readline предоставляет вам:

  • Линия редактирования
  • Конфигурация привязки клавиш (включая режимы emacs и vi)
  • История (стрелка вверх, чтобы вызвать предыдущие значения)
  • Поиск, сохранение и загрузка истории

Отличный пример того, как выполнить завершение табуляции в сотрудничестве с readline, предоставляется в стандартной библиотеке как модуль rlcompleter - вы не можете использовать его как есть (он завершается на основе имен, определенных в настоящее время в основном и встроенном Python), но это показывает, как сделать общую задачу и как подключить ее к readline,

Вы почти наверняка должны использовать модуль cmd, который уже реализует завершение табуляции и так далее, и, возможно, другие части того, что вы пытаетесь сделать, используя модуль readline и так далее. Нет смысла изобретать велосипед.

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