Tự động hoàn thành zsh cho các lệnh tùy chỉnh


18

Tôi đang cố gắng viết các chức năng hoàn thành cho một số chức năng tùy chỉnh mà tôi đã viết, nhưng dường như đang thực sự vật lộn với ngay cả những chức năng cơ bản nhất.

Một chức năng ví dụ là:

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"
}

Điều này có hai đối số vị trí, <aws profile name><environment name>

Tôi muốn các tùy chọn hoàn thành <aws profile name>sẵn sàng tự động bằng cách chạy sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' 'và các hoàn thành <environment name>sẽ có sẵn bằng cách chạy một chức năng khác mà tôi đã gọi eb_names.

Tôi đang tìm tài liệu khá thưa thớt và khó theo dõi. Tôi cũng đã thấy repo zsh-hoàn thành cho các lệnh tương tự nhưng dường như không thể tìm thấy thứ gì đó tương tự với những gì tôi cần.

Bất kỳ trợ giúp bắt đầu sẽ được nhiều đánh giá cao!

Cập nhật

Dựa trên câu trả lời của @ cuonglm , tôi đã sử dụng:

#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 "$@"

Điều tôi quên đề cập đến trong câu hỏi ban đầu là, tôi cũng muốn việc hoàn thành đối số thứ hai phụ thuộc vào đối số thứ nhất (cả hai đều dựa trên mã thực thi một số mã), ví dụ:

$ eb_instances <cursor>TAB
cuonglm  test

được hoàn thành tôi muốn. Khi tôi chọn nói câu đầu tiên và cố gắng tự động hoàn thành:

$ eb_instances cuonglm <cursor>TAB

Tôi muốn tạo các tùy chọn hoàn thành bằng cách thực thi eb_names cuonglm, và nếu có thể, cũng vậy, hãy đi sâu vào các phần hoàn thành, ví dụ nếu ứng viên chính xác là foo-bar,

$ eb_instances cuonglm foo<cursor>TAB

Tôi muốn tạo các tùy chọn hoàn thành bằng cách thực hiện eb_names cuonglm foo

Câu trả lời:


21

Lúc đầu, Hệ thống hoàn thành zsh dường như rất phức tạp và khó nắm bắt. Hãy thử một ví dụ.

Điều đầu tiên bạn cần biết, zshhệ thống hoàn thành sẽ tải các chức năng hoàn thành từ $fpath. Đảm bảo thư mục hoàn thành của bạn xuất hiện trong:

print -rl -- $fpath

(Nếu bạn đã sử dụng oh-my-zsh , đã .oh-my-zsh/completionstồn tại $fpath, bạn chỉ cần tạo nó và đặt các chức năng hoàn thành của mình ở đó)

Bây giờ, bạn phải tạo một tệp hoàn thành cho chức năng của mình, tên của nó phải bắt đầu bằng dấu gạch dưới _, cộng với tên hàm của bạn. Trong trường hợp của bạn, tên của nó là _eb_instances.

Thêm các dòng luận án vào _eb_instancestập tin:

#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 "$@"

Bạn xong việc rồi. Lưu tệp và bắt đầu phiên mới để kiểm tra hoàn thành. Bạn sẽ thấy một số thứ như thế này:

$ eb_instances <cursor>TAB
cuonglm  test

$ eb_instances cuonglm <cursor>TAB
dev      prod     staging

Bạn có thể đọc tài liệu hệ thống hoàn thành zsh về _argumentschức năng, statebiến. Ngoài ra, bạn cần thay đổi (cuonglm test)với sedlệnh của bạn và thay đổi chức năng prod staging devcủa bạn eb_names.

Nếu bạn muốn tạo cơ sở đối số thứ 2 dựa trên những gì đối số 1 đã thông qua, bạn có thể sử dụng $words[2]biến:

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

Thay thế echobằng chức năng thực sự của bạn, trong trường hợp của bạn, đó là $(eb_names $words[2]).

Nếu bạn vẫn cảm thấy khó có thể thực hiện điều này, chỉ cần xác định _eb_instanceseb_instancestrong bạn .zshrchoàn thành cuộc gọi sau đó là:

compdef _eb_instances eb_instances

Bạn cần khởi tạo hệ thống hoàn thành với:

autoload -U compinit
compinit

(Nếu bạn đã sử dụng oh-my-zsh, nó đã được tải)


Cảm ơn rất nhiều vì đã trả lời chi tiết. Vấn đề mặc dù tôi dường như không thể tìm ra một cách để làm tài liệu tốt, là nếu các tùy chọn hoàn thành của tôi là động hoặc đến từ các hàm / tập lệnh khác, ví dụ, trong ví dụ của bạn, nếu tôi muốn cuonglm testđến từsed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' '
zsapes

@zsapes: Chỉ cần thay thế (cuonglm test)bằng ($(sed -n -E 's/\[([a-zA-Z0-9_\-]+)\]/\1/p' ~/.aws/credentials | tr \\n ' ')), đổi compadd "$@" prod staging devthành compadd "$@" $(eb_names).
cuonglm

điều này có thể kéo dài nó một chút, nhưng, tôi quên đề cập đến, đó là cần thiết để vượt qua eb_namescác đối số đầu tiên, tức là, productionhoặc staging, làm thế nào để làm điều đó? Cảm ơn rất nhiều, tôi đã nhận được khá nhiều thứ được sắp xếp với điều này.
zsapes

Ý tôi là tôi không muốn sử dụng đối số đầu tiên để truyền cho eb_names. Tôi đã thử tham khảo $1hoặc $2, nhưng không có xúc xắc.
zsapes

1
Bạn là một phù thủy, Harry.
quay phim
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.