วิธีสร้าง python โปรแกรมบรรทัดคำสั่งเติมข้อความอัตโนมัติโดยพลการไม่ล่าม


98

ฉันทราบวิธีตั้งค่าการเติมข้อความอัตโนมัติของออบเจ็กต์ python ในตัวแปล python (บน unix)

  • Google แสดงเพลงฮิตมากมายสำหรับคำอธิบายเกี่ยวกับวิธีการทำเช่นนี้
  • น่าเสียดายที่มีข้อมูลอ้างอิงมากมายทำให้ยากที่จะหาสิ่งที่ฉันต้องทำซึ่งแตกต่างกันเล็กน้อย

ฉันต้องการทราบวิธีเปิดใช้งานแท็บ / การเติมรายการโดยพลการโดยอัตโนมัติในโปรแกรมบรรทัดคำสั่งที่เขียนด้วย python

กรณีการใช้งานเฉพาะของฉันคือโปรแกรม python บรรทัดคำสั่งที่ต้องการส่งอีเมล ฉันต้องการเติมที่อยู่อีเมลอัตโนมัติ (ฉันมีที่อยู่ในดิสก์) เมื่อผู้ใช้พิมพ์บางส่วน (และกดปุ่ม TAB เป็นทางเลือก)

ฉันไม่ต้องการให้มันทำงานบน windows หรือ mac เพียง แต่ linux


บล็อกนี้ควรทำเทคนิคด้วย config ไฟล์. 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)

เอกสารโมดูลอย่างเป็นทางการไม่มีรายละเอียดมากนักโปรดดูเอกสาร Readlineสำหรับข้อมูลเพิ่มเติม


1
โปรดทราบว่าหากคุณเขียนบรรทัดคำสั่งด้วยโมดูล cmd ว่ามีวิธีใดที่ดีกว่านี้
Florian Bösch

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)

มีวิธีใดในการควบคุมวิธีการจัดเรียงคอลัมน์ของ readline หรือไม่? สมมติว่าฉันต้องการให้มันเรียงคอลัมน์โดยเว้นวรรคสองช่องระหว่างแต่ละรายการ
Fnord

เมื่อฉันเรียกใช้รหัสนี้แท็บต่างๆจะถูกพิมพ์ลงในบรรทัดคำสั่ง ในความเป็นจริงนี่เป็นความจริงไม่ว่าฉันจะใช้ cmd หรือ readline แบบตรง
เลื่อยตัด

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หลัก

ลองดูตัวอย่างในหน้าที่เชื่อมโยงทั้งหมดตรงไปตรงมา


11
ที่จริงฉันมาที่นี่เพราะอย่างนั้น
user1767754

ขอบคุณนี่คือสิ่งที่ฉันกำลังมองหา!
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'))

มันเป็นโพสต์เก่าอาจจะไม่มีข้อโต้แย้งในตอนนั้น? ขอบคุณที่พูดถึง แต่ฉันคิดว่ามันเป็นสิ่งที่โครงการของฉันต้องการ!
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

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 Prompt 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ในผลลัพธ์

คำเป็นพจนานุกรมและแต่ละคำสามารถมีบริบทได้ ตัวอย่างเช่น "จำนวน" วิธีแสดงคำบริบทอื่น ๆ รอบ ๆ คำเป็นต้นในคำตัวอย่างนี้ไม่มีบริบทใด ๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.