Як зробити python, програму командного рядка автозаповненням довільних речей, які НЕ інтерпретуються


92

Я знаю, як налаштувати автозаповнення об’єктів python в інтерпретаторі python (на unix).

  • Google показує багато звернень для пояснень, як це зробити.
  • На жаль, посилань на них так багато, що важко знайти те, що мені потрібно зробити, що дещо відрізняється.

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

Моїм конкретним випадком використання є програма python з командного рядка, яка повинна надсилати електронні листи. Я хочу мати можливість автозаповнення адрес електронної пошти (адреси у мене є на диску), коли користувач вводить їх частину (і за бажанням натискає клавішу TAB).

Мені це не потрібно для роботи на Windows або Mac, просто Linux.


Цей блог повинен виконати трюки з конфігурацією файлу .pythonrc.
Kris Roofe

Відповіді:


63

Використовуйте 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)

Офіційні документи модуля не набагато більш докладно, см Readline документів для отримання додаткової інформації.


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)

Чи є спосіб контролювати те, як рядок читання відображає стовпці своїх результатів? Отже, скажімо, я хотів би, щоб він містився у колонці з двома пробілами між кожним елементом.
Фнорд

Коли я запускаю цей код, вкладки просто друкуються в командному рядку. Насправді це вірно, незалежно від того, використовую я cmd або пряму лінію зчитування.
Hack Saw

38

Оскільки у вашому запитанні ви говорите "НЕ перекладач", я думаю, ви не хочете відповідей, пов'язаних із python readline тощо. ( редагувати : оглянувшись назад, це, очевидно, не так. Хо гу, я думаю, що ця інформація все одно цікава, тому я залишу її тут. )

Я думаю, ти можеш після цього .

Йдеться про додавання завершення рівня оболонки до довільних команд, розширення власного завершення вкладки 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.

Подивіться на приклад на пов’язаній сторінці, все досить просто.


10
Насправді я прийшов сюди через це
user1767754

Дякую, це саме те, що я шукав!
Teekeks

27

Я здивований, що ніхто не згадував 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'))

Це стара публікація, можливо, argcomplete тоді ще не існувало? Дякую за згадку, хоча, я думаю, це саме те, що потрібно моєму проекту!
FrustratedWithFormsDesigner

Дуже приємно в поєднанні з аргпарсом також!
AstroFloyd

13

Ось повноправна версія коду, яку дуже надав 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

1
Для mac os замінити readline.parse_and_bind('tab:complete') наreadline.parse_and_bind ("bind ^I rl_complete")
Mani

Це круто. Працював у мене. Дякую, що поділились.
Ajay Ahuja

@Mani Я застряг у цьому надовго. Щиро дякую
AnaS Kayed

5

Ви можете спробувати скористатися Python Prompt Toolkit , бібліотекою для створення інтерактивних програм командного рядка в Python.

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

pgcli - Підказка Python Toolkit

(Джерело зображення: 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в результатах.

Слова - це словник, і кожне слово може мати контекст. Наприклад, "count", як відображати слово, якийсь інший контекст навколо слова тощо. У цьому прикладі слова не мали жодного контексту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.