Cara membuat python, program command-line autocomplete hal-hal sewenang-wenang BUKAN interpreter


98

Saya mengetahui cara mengatur pelengkapan otomatis objek python di interpreter python (di unix).

  • Google menunjukkan banyak hits untuk penjelasan tentang bagaimana melakukan ini.
  • Sayangnya, ada begitu banyak referensi sehingga sulit untuk menemukan apa yang perlu saya lakukan, yang sedikit berbeda.

Saya perlu tahu cara mengaktifkan, tab / penyelesaian otomatis item sewenang-wenang dalam program baris perintah yang ditulis dengan python.

Kasus penggunaan khusus saya adalah program python baris perintah yang perlu mengirim email. Saya ingin dapat melengkapi alamat email secara otomatis (saya memiliki alamat di disk) saat pengguna mengetik bagiannya (dan secara opsional menekan tombol TAB).

Saya tidak membutuhkannya untuk bekerja di windows atau mac, cukup linux.


Blog ini harus melakukan trik dengan mengkonfigurasi file .pythonrc.
Kris Roofe

Jawaban:


65

Gunakan readlinebinding Python . Sebagai contoh,

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)

Dokumen modul resmi tidak lebih detail, lihat dokumen readline untuk info lebih lanjut.


1
Perhatikan bahwa jika Anda menulis baris perintah dengan modul cmd, ada cara yang lebih baik untuk melakukannya.
Florian Bösch

60

Ikuti dokumentasi cmd dan Anda akan baik-baik saja

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()

Output untuk tab -> tab -> send -> tab -> tab -> f -> tab

(Cmd)
help  send
(Cmd) send
foo@bar.com            here@blubb.com         whatever@wherever.org
(Cmd) send foo@bar.com
(Cmd)

Apakah ada cara untuk mengontrol bagaimana readline mengkolomisasi outputnya? Jadi katakanlah saya ingin membuat kolom dengan dua spasi di antara setiap item.
Fnord

Ketika saya menjalankan kode ini, tab hanya dicetak ke dalam baris perintah. Sebenarnya ini benar terlepas dari apakah saya menggunakan cmd atau garis baca lurus.
Hack Melihat

38

Karena Anda mengatakan "BUKAN juru bahasa" dalam pertanyaan Anda, saya rasa Anda tidak ingin jawaban yang melibatkan garis baca python dan semacamnya. ( edit : kalau dipikir-pikir, jelas bukan itu masalahnya. Ho hum. Menurut saya info ini menarik, jadi saya akan tinggalkan di sini. )

Saya pikir Anda mungkin setelah ini .

Ini tentang menambahkan penyelesaian tingkat shell ke perintah arbitrer, memperluas penyelesaian tab bash sendiri.

Singkatnya, Anda akan membuat file yang berisi fungsi shell yang akan menghasilkan kemungkinan penyelesaian, menyimpannya /etc/bash_completion.d/dan mendaftarkannya dengan perintah complete. Berikut cuplikan dari halaman tertaut:

_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

Dalam hal ini, pengetikan foo --[TAB]akan memberi Anda nilai dalam variabel opts, yaitu --help, --verbosedan --version. Untuk tujuan Anda, pada dasarnya Anda ingin menyesuaikan nilai yang dimasukkan opts.

Lihat contoh di halaman tertaut, semuanya cukup mudah.


11
Sebenarnya saya datang ke sini karena itu
pengguna1767754

Terima kasih, inilah yang saya cari!
Teekeks

30

Saya terkejut karena tidak ada yang menyebutkan argcomplete, berikut adalah contoh dari dokumen:

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'))

Itu posting lama, mungkin argcomplete tidak ada saat itu? Terima kasih telah menyebutkannya, saya pikir itulah yang dibutuhkan proyek saya!
FrustratedWithFormsDesigner

Sangat bagus dalam kombinasi dengan argparse juga!
AstroFloyd

14

Berikut adalah versi kode yang berfungsi penuh yang sangat disediakan oleh ephemient di sini (terima kasih).

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
Untuk mac os, ganti readline.parse_and_bind('tab:complete') denganreadline.parse_and_bind ("bind ^I rl_complete")
Mani

Ini Luar Biasa. Bekerja untuk saya. Terima kasih telah berbagi.
Ajay Ahuja

@Mani Saya terjebak dalam hal ini untuk waktu yang lama. Terima kasih banyak
AnaS Kayed

5

Anda dapat mencoba menggunakan Python Prompt Toolkit , pustaka untuk membuat aplikasi baris perintah interaktif dengan Python.

Pustaka membuatnya mudah untuk menambahkan fungsionalitas pelengkapan otomatis interaktif, yang memungkinkan pengguna menggunakan Tabkunci untuk melihat pilihan yang tersedia secara visual. Pustaka ini lintas platform (Linux, OS X, FreeBSD, OpenBSD, Windows). Contoh:

pgcli - Perangkat Perintah Python

(Sumber gambar: pcgli )


1

Jawaban yang diposting berfungsi dengan baik tetapi saya telah membuka sumber perpustakaan pelengkapan otomatis yang saya tulis di tempat kerja. Kami telah menggunakannya untuk beberapa waktu dalam produksi dan cepat, stabil, dan mudah digunakan. Ia bahkan memiliki mode demo sehingga Anda dapat dengan cepat menguji apa yang akan Anda dapatkan saat Anda mengetik kata-kata.

Untuk menginstalnya, cukup jalankan: pip install fast-autocomplete

Berikut ini contohnya:

>>> 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']]

Lihat: https://github.com/wearefair/fast-autocomplete untuk kode sumber.

Dan berikut ini penjelasan cara kerjanya: http://zepworks.com/posts/you-autocomplete-me/

Ini berhubungan dengan kesalahan ejaan dan secara opsional mengurutkan berdasarkan berat kata. (katakanlah burritolebih penting daripada book, maka Anda memberikan burrito"hitungan" yang lebih tinggi dan itu akan muncul terlebih dahulu sebelum bookdi hasil.

Kata adalah kamus dan setiap kata dapat memiliki konteks. Misalnya "hitungan", cara menampilkan kata, beberapa konteks lain di sekitar kata, dll. Dalam contoh ini, kata tidak memiliki konteks apa pun.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.