Làm thế nào để tạo một python, chương trình dòng lệnh tự động hoàn thành những thứ tùy ý KHÔNG phải trình thông dịch


92

Tôi biết cách thiết lập tự động hoàn thành các đối tượng python trong trình thông dịch python (trên unix).

  • Google hiển thị nhiều lượt truy cập để giải thích về cách thực hiện điều này.
  • Thật không may, có quá nhiều tài liệu tham khảo nên rất khó để tìm thấy những gì tôi cần làm, điều này hơi khác một chút.

Tôi cần biết cách bật, tab / tự động hoàn thành các mục tùy ý trong chương trình dòng lệnh được viết bằng python.

Trường hợp sử dụng cụ thể của tôi là một chương trình python dòng lệnh cần gửi email. Tôi muốn có thể tự động điền địa chỉ email (tôi có địa chỉ trên đĩa) khi người dùng nhập một phần của nó (và tùy chọn nhấn phím TAB).

Tôi không cần nó hoạt động trên windows hoặc mac, chỉ cần linux.


Blog này sẽ thực hiện các thủ thuật với cấu hình tệp .pythonrc.
Kris Roofe

Câu trả lời:


63

Sử dụng readlinecác ràng buộc của Python . Ví dụ,

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)

Tài liệu mô-đun chính thức không chi tiết hơn nhiều, hãy xem tài liệu dòng đọc để biết thêm thông tin.


1
lưu ý rằng nếu bạn viết dòng lệnh của mình bằng mô-đun cmd thì có nhiều cách tốt hơn để làm điều đó.
Florian Bösch 9/10/08

60

Làm theo tài liệu cmd và bạn sẽ ổn thôi

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

Đầu ra cho tab -> tab -> gửi -> tab -> tab -> f -> tab

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

Có cách nào để kiểm soát cách cột readline của nó xuất ra không? Vì vậy, giả sử tôi muốn nó nằm trong cột với hai khoảng trắng giữa mỗi mục.
Fnord

Khi tôi chạy mã này, các tab chỉ được in vào dòng lệnh. Trên thực tế, điều này đúng bất kể tôi sử dụng cmd hay đường dẫn thẳng.
Hack Saw

38

Vì bạn nói "KHÔNG thông dịch viên" trong câu hỏi của mình, tôi đoán bạn không muốn câu trả lời liên quan đến dòng đọc python và tương tự như vậy. ( chỉnh sửa : trong nhận thức muộn màng, rõ ràng là không phải vậy. Ho hum. Tôi nghĩ thông tin này dù sao cũng thú vị, vì vậy tôi sẽ để nó ở đây. )

Tôi nghĩ rằng bạn có thể sau này .

Đó là về việc thêm hoàn thành cấp trình bao vào các lệnh tùy ý, mở rộng quá trình hoàn thành tab của chính bash.

Tóm lại, bạn sẽ tạo một tệp chứa một hàm shell sẽ tạo ra các hoàn thành có thể có, lưu nó vào /etc/bash_completion.d/và đăng ký nó bằng lệnh complete. Đây là một đoạn trích từ trang được liên kết:

_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

Trong trường hợp này, việc nhập foo --[TAB]sẽ cung cấp cho bạn các giá trị trong biến opts, tức là --help, --verbose--version. Đối với mục đích của bạn, về cơ bản bạn sẽ muốn tùy chỉnh các giá trị được đưa vào opts.

Hãy xem ví dụ trên trang được liên kết, tất cả đều khá đơn giản.


10
Thực ra tôi đến đây vì lý do đó
user1767754

Cảm ơn, đây chính xác là những gì tôi đang tìm kiếm!
Teekeks

27

Tôi ngạc nhiên rằng không ai đề cập đến argcomplete, đây là một ví dụ từ tài liệu:

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

Đó là một bài viết cũ, có lẽ argcomplete hồi đó không tồn tại? Cảm ơn vì đã đề cập đến nó, tôi nghĩ nó chính xác là những gì dự án của tôi cần!
FrustratedWithFormsDesigner

Rất tốt khi kết hợp với argparse !
AstroFloyd

13

Đây là phiên bản hoạt động đầy đủ của mã được cung cấp bởi ephemient ở đây (cảm ơn bạn).

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
Đối với mac os, thay thế readline.parse_and_bind('tab:complete') bằngreadline.parse_and_bind ("bind ^I rl_complete")
Mani

Điều này thật tuyệt. Đã làm cho tôi. Cám ơn vì đã chia sẻ.
Ajay Ahuja

@Mani Tôi đã bị mắc kẹt trong này trong một thời gian dài. Cảm ơn bạn rất nhiều
AnaS Kayed

5

Bạn có thể thử sử dụng Bộ công cụ Dấu nhắc Python , một thư viện để xây dựng các ứng dụng dòng lệnh tương tác bằng Python.

Thư viện giúp dễ dàng thêm chức năng tự động hoàn thành tương tác, cho phép người dùng sử dụng Tabphím để chuyển qua các lựa chọn có sẵn một cách trực quan. Thư viện đa nền tảng (Linux, OS X, FreeBSD, OpenBSD, Windows). Thí dụ:

pgcli - Bộ công cụ nhắc Python

(Nguồn ảnh: pcgli )


1

Các câu trả lời đã đăng hoạt động tốt nhưng tôi đã mở nguồn thư viện tự động điền mà tôi đã viết tại nơi làm việc. Chúng tôi đã sử dụng nó một thời gian trong quá trình sản xuất và nó nhanh, ổn định và dễ sử dụng. Nó thậm chí còn có một chế độ demo để bạn có thể nhanh chóng kiểm tra những gì bạn sẽ nhận được khi bạn nhập từ.

Để cài đặt nó, chỉ cần chạy: pip install fast-autocomplete

Đây là một ví dụ:

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

Kiểm tra: https://github.com/wearefair/fast-autocomplete cho mã nguồn.

Và đây là giải thích về cách nó hoạt động: http://zepworks.com/posts/you-autocomplete-me/

Nó xử lý các lỗi viết sai chính tả và phân loại tùy chọn theo trọng lượng của từ. (giả sử burritolà quan trọng hơn book, sau đó bạn đưa ra burrito"số lượng" cao hơn và nó sẽ hiển thị đầu tiên trước booktrong kết quả.

Từ là một từ điển và mỗi từ có thể có một ngữ cảnh. Ví dụ: "số đếm", cách hiển thị từ, một số ngữ cảnh khác xung quanh từ, v.v. Trong ví dụ này, các từ không có bất kỳ ngữ cảnh nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.