การเติมข้อความอัตโนมัติแบบไดนามิก zsh สำหรับคำสั่งที่กำหนดเอง


19

ฉันกำลังพยายามเขียนฟังก์ชั่นเสร็จสิ้นสำหรับฟังก์ชั่นที่กำหนดเองบางอย่างที่ฉันเขียน แต่ดูเหมือนจะดิ้นรนกับแม้แต่พื้นฐานที่สุด

ฟังก์ชั่นตัวอย่างคือ:

function eb_instances() {
    if [ "$#" -ne 2 ]; then
        echo "Usage eb_instances <aws profile name> <environment name>"
        echo "e.g.:"
        echo " eb_instances production kraken-prod-api"
        return 1
    fi

    aws ec2 describe-instances --filters  "Name=instance-state-name,Values=running"   "Name=tag:Name,Values=$2" --profile=$1 --output=json | jq -r ".Reservations[].Instances[].PrivateIpAddress"
}

สิ่งนี้มีสองข้อโต้แย้งตำแหน่ง<aws profile name>และ<environment name>

ฉันต้องการตัวเลือกเสร็จสิ้นเพื่อ<aws profile name>ให้สามารถใช้ได้แบบไดนามิกโดยการทำงาน sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' 'และความสำเร็จในการที่จะสามารถใช้งานได้แบบไดนามิกโดยการเรียกใช้ฟังก์ชั่นอื่นเราได้เรียก<environment name>eb_names

ฉันพบเอกสารค่อนข้างเบาบางและติดตามยาก ฉันยังเห็น repo zsh-completions สำหรับคำสั่งที่คล้ายกัน แต่ดูเหมือนจะไม่พบสิ่งที่คล้ายกับสิ่งที่ฉันต้องการ

ความช่วยเหลือใด ๆ ในการเริ่มต้นจะได้รับการชื่นชมมาก!

ปรับปรุง

จากคำตอบของ @ cuonglmฉันใช้:

#compdef ebinstances

_ebinstances() {
  local state

  _arguments \
    '1: :->aws_profile'\
    '*: :->eb_name'

  case $state in
    (aws_profile) _arguments '1:profiles:($(sed -n -E "s/\[([a-zA-Z0-9_\-]+)\]/\1/p" ~/.aws/credentials | tr \\n " "))' ;;
              (*) compadd "$@" foo bar
  esac
}

_ebinstances "$@"

สิ่งที่ฉันลืมที่จะพูดถึงในคำถามเดิมคือฉันต้องการให้อาร์กิวเมนต์ที่สองสมบูรณ์ขึ้นอยู่กับข้อแรก (ซึ่งทั้งคู่เป็นแบบไดนามิกที่ใช้รหัสบางอย่าง):

$ eb_instances <cursor>TAB
cuonglm  test

ได้รับความสำเร็จที่ฉันต้องการ เมื่อฉันเลือกพูดคำแรกและพยายามทำให้สมบูรณ์โดยอัตโนมัติ:

$ eb_instances cuonglm <cursor>TAB

ฉันต้องการที่จะสร้างตัวเลือกเสร็จสิ้นโดยการดำเนินการeb_names cuonglmและถ้าเป็นไปได้ยังเจาะลึกเนื้อหาเกี่ยวกับความสำเร็จตัวอย่างเช่นถ้าผู้สมัครที่ถูกต้องคือfoo-bar,

$ eb_instances cuonglm foo<cursor>TAB

ฉันต้องการสร้างตัวเลือกการทำให้สมบูรณ์ด้วยการดำเนินการ eb_names cuonglm foo

คำตอบ:


23

ในครั้งแรกระบบเสร็จสมบูรณ์ของ zshดูเหมือนจะซับซ้อนและยากที่จะเข้าใจ ลองตัวอย่าง

สิ่งแรกที่คุณจำเป็นต้องรู้ระบบเสร็จสิ้นจะโหลดฟังก์ชั่นเสร็จสิ้นจากzsh $fpathตรวจสอบให้แน่ใจว่าไดเรกทอรีสำเร็จของคุณปรากฏใน:

print -rl -- $fpath

(หากคุณใช้oh-my-zshมี.oh-my-zsh/completionsอยู่$fpathแล้วคุณสามารถสร้างมันขึ้นมาและใส่ฟังก์ชั่นการเติมเต็มของคุณได้)

ตอนนี้คุณต้องสร้างไฟล์เสร็จสำหรับฟังก์ชั่นของคุณชื่อของมันจะต้องเริ่มต้นด้วยขีดล่าง_รวมถึงชื่อฟังก์ชั่นของคุณ _eb_instancesในกรณีของคุณชื่อของมันคือ

เพิ่มบรรทัดเหล่านี้ไปยัง_eb_instancesไฟล์:

#compdef eb_instances

_eb_instances() {
  local state

  _arguments \
    '1: :->aws_profile'\
    '*: :->eb_name'

  case $state in
    (aws_profile) _arguments '1:profiles:(cuonglm test)' ;;
              (*) compadd "$@" prod staging dev
  esac
}

_eb_instances "$@"

คุณทำเสร็จแล้ว บันทึกไฟล์และเริ่มเซสชันใหม่เพื่อทดสอบความสมบูรณ์ คุณจะเห็นบางสิ่งเช่นนี้:

$ eb_instances <cursor>TAB
cuonglm  test

$ eb_instances cuonglm <cursor>TAB
dev      prod     staging

คุณสามารถอ่านเอกสารระบบ zsh ที่สมบูรณ์เกี่ยวกับ_argumentsฟังก์ชั่นstateตัวแปร นอกจากนี้คุณต้องเปลี่ยน(cuonglm test)ด้วยsedคำสั่งของคุณและเปลี่ยนprod staging devเป็นeb_namesฟังก์ชั่นของคุณ

หากคุณต้องการสร้างอาร์กิวเมนต์อันดับที่ 2 ตามอาร์กิวเมนต์ที่ 1 ที่ส่งผ่านคุณสามารถใช้$words[2]ตัวแปร:

case $state in
  (aws_profile) _arguments '1:profiles:(cuonglm test)' ;;
            (*) compadd "$@" $(echo $words[2]) ;;
esac

แทนที่ด้วยฟังก์ชั่นที่แท้จริงของคุณในกรณีที่คุณต้องการได้echo$(eb_names $words[2])

หากคุณยังรู้สึกยากที่จะทำสิ่งนี้ให้กำหนด_eb_instancesและทำสิ่งที่eb_instancesคุณต้องการ.zshrcให้เสร็จสมบูรณ์ดังนี้

compdef _eb_instances eb_instances

คุณต้องเริ่มต้นระบบเติมเต็มด้วย:

autoload -U compinit
compinit

(ถ้าคุณใช้oh-my-zshมันถูกโหลดแล้ว)


ขอบคุณมากสำหรับคำตอบอย่างละเอียด ปัญหาที่ดูเหมือนว่าฉันไม่สามารถหาวิธีที่ดีที่จะทำคือถ้าตัวเลือกการเติมเต็มของฉันเป็นแบบไดนามิกหรือมาจากฟังก์ชั่น / สคริปต์อื่น ๆ เช่นในตัวอย่างของคุณจะทำอย่างไรถ้าฉันต้องการcuonglm testมาsed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' '
zsquare

@zsquare: เพียงแค่เปลี่ยน(cuonglm test)ที่มี($(sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' '))การเปลี่ยนแปลงไปcompadd "$@" prod staging dev compadd "$@" $(eb_names)
cuonglm

นี่อาจจะยืดออกไปเล็กน้อย แต่ฉันลืมที่จะพูดถึงว่าต้องผ่านeb_namesการโต้แย้งครั้งแรกคือproductionหรือstagingฉันจะทำอย่างไร ขอบคุณมากฉันได้รับบางสิ่งบางอย่างที่เรียงลำดับด้วยสิ่งนี้
zsquare

ฉันไม่ต้องการใช้อาร์กิวเมนต์แรกในการส่งผ่านไปยัง eb_names ฉันพยายามอ้างอิง$1หรือ$2แต่ไม่มีลูกเต๋า
zsquare

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