Как сделать Python, программу командной строки автозаполнением произвольных вещей НЕ интерпретатором

98

Я знаю, как настроить автозаполнение объектов python в интерпретаторе python (в unix).

  • Google показывает множество обращений с объяснениями, как это сделать.
  • К сожалению, здесь так много ссылок, что мне трудно найти то, что мне нужно сделать, что немного отличается.

Мне нужно знать, как включить табуляцию / автоматическое завершение произвольных элементов в программе командной строки, написанной на python.

Мой конкретный вариант использования - это программа на Python из командной строки, которая должна отправлять электронные письма. Я хочу иметь возможность автозаполнения адресов электронной почты (адреса у меня есть на диске), когда пользователь вводит их часть (и при необходимости нажимает клавишу TAB).

Мне он не нужен для работы на windows или mac, только linux.

Пол Д. Иден
источник
Этот блог должен помочь с настройкой файла .pythonrc.
Kris Roofe

Ответы:

65

Используйте readlineпривязки Python . Например,

import readline

def completer(text, state):
    options = [i for i in commands if i.startswith(text)]
    if state < len(options):
        return options[state]
    else:
        return None

readline.parse_and_bind("tab: complete")
readline.set_completer(completer)

Официальная документация по модулю не намного более подробна, дополнительную информацию см. В документации для чтения.

эфемерный
источник
1
заметьте, что если вы пишете свою командную строку с помощью модуля cmd, есть лучшие способы сделать это.
Флориан Беш,
60

Следуйте документации cmd, и все будет в порядке

import cmd

addresses = [
    'here@blubb.com',
    'foo@bar.com',
    'whatever@wherever.org',
]

class MyCmd(cmd.Cmd):
    def do_send(self, line):
        pass

    def complete_send(self, text, line, start_index, end_index):
        if text:
            return [
                address for address in addresses
                if address.startswith(text)
            ]
        else:
            return addresses


if __name__ == '__main__':
    my_cmd = MyCmd()
    my_cmd.cmdloop()

Вывод для вкладки -> вкладка -> отправить -> вкладка -> вкладка -> f -> вкладка

(Cmd)
help  send
(Cmd) send
foo@bar.com            here@blubb.com         whatever@wherever.org
(Cmd) send foo@bar.com
(Cmd)
Флориан Бёш
источник
Есть ли способ контролировать, как строка чтения выводит его в столбцы? Итак, скажем, я бы хотел, чтобы он был столбцом с двумя пробелами между каждым элементом.
Fnord
Когда я запускаю этот код, вкладки просто печатаются в командной строке. На самом деле это верно независимо от того, использую ли я cmd или прямую строку чтения.
Hack Saw
38

Поскольку вы говорите «НЕ интерпретатор» в своем вопросе, я думаю, вам не нужны ответы, включающие строку чтения Python и тому подобное. ( править : оглядываясь назад, очевидно, что это не так. Хмм. Я думаю, что эта информация в любом случае интересна, поэтому я оставлю ее здесь. )

Я думаю, вы можете быть после этого .

Речь идет о добавлении автозавершения на уровне оболочки к произвольным командам, расширяя собственное завершение табуляции в bash.

Вкратце, вы создадите файл, содержащий функцию оболочки, которая будет генерировать возможные завершения, сохраните ее /etc/bash_completion.d/и зарегистрируйте с помощью команды complete. Вот фрагмент со связанной страницы:

_foo() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--help --verbose --version"

    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _foo foo

В этом случае набор foo --[TAB]даст вам значения в переменной opts, то есть --help, --verboseи --version. Для ваших целей вы, по сути, захотите настроить значения, которые помещаются вopts .

Взгляните на пример на связанной странице, все довольно просто.

Оуэн
источник
11
Собственно, я и приехал сюда из-за этого
user1767754 03
Спасибо, это именно то, что я искал!
Teekeks,
30

Я удивлен, что никто не упомянул argcomplete, вот пример из документации:

from argcomplete.completers import ChoicesCompleter

parser.add_argument("--protocol", choices=('http', 'https', 'ssh', 'rsync', 'wss'))
parser.add_argument("--proto").completer=ChoicesCompleter(('http', 'https', 'ssh', 'rsync', 'wss'))
qed
источник
Это старый пост, может, argcomplete тогда еще не было? Спасибо, что упомянули об этом, я думаю, это именно то, что нужно моему проекту!
FrustratedWithFormsDesigner
Очень хорошо в сочетании с argparse !
AstroFloyd,
14

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

import readline

addrs = ['angela@domain.com', 'michael@domain.com', 'david@test.com']

def completer(text, state):
    options = [x for x in addrs if x.startswith(text)]
    try:
        return options[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind("tab: complete")

while 1:
    a = raw_input("> ")
    print "You entered", a
Пол Д. Иден
источник
10
# ~/.pythonrc
import rlcompleter, readline
readline.parse_and_bind('tab:complete')

# ~/.bashrc
export PYTHONSTARTUP=~/.pythonrc
user178047
источник
1
Для mac os замените readline.parse_and_bind('tab:complete') наreadline.parse_and_bind ("bind ^I rl_complete")
Mani
Это круто. Работал у меня. Спасибо, что поделился.
Аджай
@Mani Я застрял в этом надолго. Большое вам спасибо
AnaS Kayed
5

Вы можете попробовать использовать Python Prompt Toolkit , библиотеку для создания интерактивных приложений командной строки на Python.

Библиотека упрощает добавление интерактивной функции автозаполнения, позволяя пользователю использовать Tabключ для визуального переключения доступных вариантов. Библиотека кроссплатформенная (Linux, OS X, FreeBSD, OpenBSD, Windows). Пример:

pgcli - Набор инструментов для подсказок Python

(Источник изображения: pcgli )

Поток
источник
1

Опубликованные ответы работают нормально, но у меня есть открытая библиотека автозаполнения, которую я написал на работе. Мы уже некоторое время используем его в производстве, и он быстрый, стабильный и простой в использовании. У него даже есть демонстрационный режим, поэтому вы можете быстро проверить, что вы получите при вводе слов.

Чтобы установить его, просто запустите: pip install fast-autocomplete

Вот пример:

>>> from fast_autocomplete import AutoComplete
>>> words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
>>> autocomplete = AutoComplete(words=words)
>>> autocomplete.search(word='b', max_cost=3, size=3)
[['book'], ['burrito']]
>>> autocomplete.search(word='bu', max_cost=3, size=3)
[['burrito']]
>>> autocomplete.search(word='barrito', max_cost=3, size=3)  # mis-spelling
[['burrito']]

Оформить заказ: https://github.com/wearefair/fast-autocomplete для исходного кода.

А вот объяснение того, как это работает: http://zepworks.com/posts/you-autocomplete-me/

Он имеет дело с неправильным написанием и опциональной сортировкой по весу слова. (скажем, burritoважнее, чем book, тогда вы дадите burritoболее высокий «счет», и он появится раньше bookв результатах.

Слова - это словарь, и каждое слово может иметь контекст. Например, «счетчик», как отображать слово, какой-то другой контекст вокруг слова и т. Д. В этом примере слова не имели никакого контекста.

Сеперман
источник