Как сделать автозаполнение командной строки Python, но НЕ только в начале строки - PullRequest
6 голосов
/ 16 октября 2008

Python, благодаря привязкам readline, обеспечивает отличное автозаполнение командной строки (как описано в здесь ).

Но завершение работает только в начале строки. Если вы хотите сопоставить середину или конец строки, readline не работает.

Я хотел бы автоматически завершать строки в программе Python для командной строки, сопоставляя то, что я печатаю, с любой из строк в списке доступных строк.

  • Хорошим примером типа автозаполнения, который я хотел бы иметь, является тип, который происходит в GMail при вводе в поле «Кому». Если вы введете фамилию одного из ваших контактов, она появится так же, как если бы вы ввели ее имя.
  • Может потребоваться некоторое использование стрелок вверх и вниз или какой-либо другой метод для выбора из подходящих строк (и не требуется в случае readline), и это хорошо в моем случае.
  • Мой конкретный вариант использования - это программа командной строки, которая отправляет электронные письма.
  • Конкретные примеры кода были бы очень полезны.

Было бы неплохо использовать эмуляторы терминала, такие как curses. Он должен работать только на Linux, а не на Mac или Windows.

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

['Paul Eden <paul@domain.com>', 
'Eden Jones <ejones@domain.com>', 
'Somebody Else <somebody@domain.com>']

Мне нужен код, который автоматически заполняет первые два элемента в списке после того, как я наберу 'Eden', а затем позволит мне выбрать один из них (через командную строку с помощью клавиатуры).

1 Ответ

10 голосов
/ 16 октября 2008

Я не уверен, что понимаю проблему. Вы можете использовать readline.clear_history и readline.add_history, чтобы установить требуемые завершаемые строки, а затем control-r для поиска по ключевому слову в истории (как если бы вы были в приглашении оболочки). Например:

#!/usr/bin/env python

import readline

readline.clear_history()
readline.add_history('foo')
readline.add_history('bar')

while 1:
    print raw_input('> ')

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

#!/usr/bin/env python

import readline

values = ['Paul Eden <paul@domain.com>', 
          'Eden Jones <ejones@domain.com>', 
          'Somebody Else <somebody@domain.com>']
completions = {}

def completer(text, state):
    try:
        matches = completions[text]
    except KeyError:
        matches = [value for value in values
                   if text.upper() in value.upper()]
        completions[text] = matches
    try:
        return matches[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind('tab: menu-complete')

while 1:
    a = raw_input('> ')
    print 'said:', a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...