Có thể sử dụng tập lệnh hoàn thành tab Bash trong zsh không?


87

Tôi có một tập lệnh hoàn thành tab Bash cho Hadoop của Apache. Thông thường, tôi sử dụng zsh làm trình bao hàng ngày của mình. Nó có xu hướng khá giống như bash khi tôi cần, nhưng có vẻ như hệ thống hoàn thành tab hoàn toàn khác nhau giữa chúng. Có cách nào đơn giản để "chuyển đổi" các định nghĩa bash-tab-hoàn thành hiện có thành hoạt động trong zsh không? Tôi không muốn đầu tư nhiều thời gian cho việc này, nhưng nếu dễ dàng thì tôi sẽ tiết kiệm được một lượng công sức vừa phải.

Câu trả lời:


39

Từ trang này (ngày 01/01/2010):

Zsh có thể xử lý các chức năng hoàn thành bash. Phiên bản phát triển mới nhất của zsh có một hàm bashcompinit, khi chạy sẽ cho phép zsh đọc các thông số kỹ thuật và chức năng hoàn thành bash. Điều này được ghi lại trong trang người đàn ông của zshcompsys. Để sử dụng nó, tất cả những gì bạn cần làm là chạy bashcompinit bất kỳ lúc nào sau compinit. Nó sẽ xác định các hàm hoàn chỉnh và hàm compgen tương ứng với các nội trang bash.


Tin tốt: Tôi nghĩ điều này sẽ hoạt động, vì vậy cảm ơn rất nhiều. Tin xấu: vì một số lý do, hệ thống mà tôi đang cố gắng thực hiện điều này dường như không tải / etc / zshrc khi tôi đăng nhập qua SSH. Tôi không biết đủ về quy trình đăng nhập để nói tại sao lại như vậy. Có lẽ đã đến lúc để hỏi một câu hỏi khác ...
Coderer

1
@Coderer: Trước hết, bạn nói "/ etc / zshrc". Trên hệ thống của tôi, nó /etc/zsh/zshrc. Ngoài ra, kiểm tra các tập tin sau đây theo thứ tự ngược (được liệt kê theo thứ tự chúng có nguồn gốc trong quá trình startup zsh): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofile$ZDOTDIR/.zprofile(có thể ~/.zprofile) để xem nếu RCSbiến là unset. Nếu đúng như vậy, điều đó sẽ ngăn không cho các tệp tiếp theo sau tệp mà nó chưa được xác lập nguồn. Cuối cùng, kiểm tra trình bao cho người dùng /etc/passwdvà đảm bảo rằng nó zshvà đảm bảo rằng nó không có -fđối số.
Tạm dừng cho đến khi có thông báo mới.

Cảm ơn tất cả các phản hồi - tôi đã sử dụng phương pháp hack lập trình viên cổ điển số 1, "stdout debugging" (câu lệnh echo trong mỗi tập lệnh khởi động) và phát hiện ra vấn đề. Vì một số lý do, / etc / zprofile của chúng tôi đang tìm nguồn cung cấp các tập lệnh /etc/profile.d khác nhau, sau đó được lấy lại nguồn trong / etc / zshrc. Chỉ cần di chuyển các câu lệnh autoload lên đầu / etc / zprofile đã khắc phục được sự cố.
Coderer

157
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file

10
Đây là câu trả lời tốt hơn vì nó cho bạn biết cách sử dụng bashcompinit. Công việc tốt.
pyrospade

5
Cảm ơn, câu trả lời tuyệt vời, rất tiếc điều này không hoạt động nếu tập lệnh sử dụng lệnh bash _init_completion.
0fnt

6
Điều này không hiệu quả với tôi. Tôi vẫn nhận được complete:13: command not found: compdeflỗi.
Jatin Kumar

Nếu nó không hoạt động, hãy kiểm tra tập lệnh (doh :)) - nó có thể có if is-bashdấu kiểm ở trên cùng.
olejorgenb

Điều này không hoạt động đối với một số tập lệnh sử dụng _get_comp_words_by_refkhông được định nghĩa bởi bashcompinit. Hầu hết các hoàn thành không sử dụng chức năng này.
Franklin Yu

39
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Tôi đang chạy zsh zsh 5.0.2 (x86_64-apple-darwin13.0) mà không có bất kỳ ~ / .zshrc nào và trình tự trên đã hoạt động trong một trình bao zsh mới tạo.

Cảm ơn git-complete.bash script cho gợi ý: D


Đọc tiếp để biết thêm chi tiết về 3 dòng trên:

Bash có tuyệt vời trong xây dựng hỗ trợ tự động hoàn tất nhưng các kịch bản bash autocomplete không làm việc trực tiếp Zsh như môi trường zsh không có autocomplete bash thiết yếu chức năng helper thích compgen, complete. Nó làm như vậy với nỗ lực giữ cho phiên zsh nhanh.

Ngày nay, zsh được vận chuyển với các tập lệnh hoàn thành thích hợp như compinitbashcompinitcó các chức năng cần thiết để hỗ trợ các tập lệnh tự động hoàn thành bash.

autoload <func_name>: Lưu ý rằng autoload được định nghĩa trong zsh chứ không phải bash. autoloadtìm kiếm một tệp có tên trong các đường dẫn thư mục được trả về bởi fpathlệnh và đánh dấu một hàm để tải giống như khi nó được gọi lần đầu tiên.

  • -U: Bỏ qua bất kỳ bí danh nào khi tải một hàm như compinit hoặc bashcompinit
  • + X: Chỉ cần tải hàm fow được đặt tên ngay bây giờ và không thực thi nó

Ví dụ trên hệ thống của tôi echo $fpathtrả lại /usr/share/zsh/site-functions/usr/share/zsh/5.0.5/functionsvà cả hai compinitbashcompinitcó sẵn tại /usr/share/zsh/5.0.5/functions.

Ngoài ra, đối với hầu hết mọi người, chỉ có thể được autoload -U +X bashcompinit && bashcompinityêu cầu vì một số tập lệnh khác như git autocomplete hoặc của riêng họ ~/.zshrccó thể đang làm autoload -U +X compinit && compinit, nhưng sẽ an toàn nếu chỉ chạy cả hai.


Là gì -U+Xđể làm gì?
jmk

Cập nhật câu trả lời với nhiều chi tiết hơn.
Jatin Kumar

6
Điều này vẫn còn ít ý nghĩa; manpage mô tả điểm +X foogiống như thực hiện cùng một quá trình tải tự động chỉ cần gọi foothực hiện, nhưng không thực hiện ngay lập tức… vì vậy autoload +X foo && foocó vẻ như hoàn toàn thừa. Bạn có thể giải thích lý do tại sao bạn chọn mẫu này?
ELLIOTTCABLE

2
@ELLIOTTCABLE Điểm cần làm autoload -U +X bashcompinit && bashcompinitlà (do &&) nó sẽ thực thi bashcompinitIFF mà mô-đun thực sự được tìm thấy. Bình thường autoload fooluôn trả về true. Sau đó, khi bạn cố gắng chạy foo, thì cuối cùng zsh sẽ cho bạn biết "không tìm thấy tệp định nghĩa hàm". Với autoload +Xbạn nhận được lỗi ngay lập tức.
FeRD

1
Trang người đàn ông vẫn còn hơi rõ ràng về điểm đó, có vẻ như đối với tôi: autoload +Xtải hàm mà không thực thi nó - điều này còn hơn là autoloadkhông có +X. Nếu không có +X, autoload thậm chí không tải chức năng; Nó chỉ đánh dấu tên là tham chiếu đến một hàm sẽ được tải sau này. Quá trình tải thực tế không được thử cho đến khi hàm được gọi lần đầu tiên. Nếu bạn muốn xác định xem chức năng đã đặt tên có tải thành công hay không , bạn cần sử dụng +Xđể thực hiện bước tải ngay lập tức.
FeRD

4

Để zshsử dụng:

  • compdef
  • compadd

Ví dụ của tôi:

# bash completion for bxrun (/home/ecuomo/projects/bashx/bxrun)
_bxrun_methods() {
    grep "^\s*\(function\s\+\)\?__.\+()\s*{.*$" "${1}" | while read line ; do
        echo "$line" | sed "s/()\s*{.*//g" | sed "s/\s*\(function\s\+\)\?__//g"
    done
}
_bxrun_lst() {
    if [ -d "/home/ecuomo/projects/bashx/src/actions" ]; then
        for f in /home/ecuomo/projects/bashx/src/actions/* ; do
            if [ -f "${f}" ]; then
                basename "${f}" | sed 's/\..*$//g'
            fi
        done
    fi
    _bxrun_methods "/home/ecuomo/projects/bashx/bxrun"
    _bxrun_methods "/home/ecuomo/projects/bashx/src/bashx.sh"
}
_bxrun() {
    local cur
    COMPREPLY=()
    cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $( compgen -W '$( _bxrun_lst )' -- $cur  ) )
}
_bxrun_zsh() {
    compadd `_bxrun_lst`
}
if type complete >/dev/null 2>/dev/null; then
    # bash
    complete -F _bxrun bxrun
else if type compdef >/dev/null 2>/dev/null; then
    # zsh
    compdef _bxrun_zsh bxrun
fi; fi

Nguồn: Mã của tôi https://github.com/reduardo7/bashx


1
Bạn nên tiết lộ rằng bạn là tác giả của khung bashx được liên kết.
Ben

4

Tôi đang chạy Antigen với tư cách là trình quản lý plugin Oh-My-Zsh. Tôi đã có một vài tập lệnh hoàn thành bash do đồng nghiệp viết mà tôi muốn tải vào Zsh một cách đơn giản source /path/to/completion.

Tôi đã gặp một số rắc rối, vì có vẻ như Antigen hoặc OMZ (khó nói) tự lo lắng về việc chỉ tải các tập lệnh hoàn thành từ plugin của họ. Cuối cùng tôi đã giải quyết vấn đề này bằng cách tự động tải bashcompinit compinit sau đó antigen apply. Chỉ đơn giản bashcompinitlà tự động điền là không đủ.

source ~/.antigen/antigen.zsh
antigen use oh-my-zsh
antigen apply

autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit

source /path/to/bash_completion

Antigen tạo ra .zcompdumptệp của nó $ANTIGEN_COMPDUMPmà đối với tôi là~/.antigen/.zcompdump

Việc gọi lại compinit và bashcompinit tạo ra .zcompdump thứ hai tại $HOME/.zcompdump

Điều đó dường như tất cả đều thành công, bởi vì tôi có thể sử dụng các phần hoàn chỉnh được thiết lập bởi /path/to/bash_completion. Tôi đã xóa cả hai tệp .zcompdump một vài lần để đảm bảo chúng được tạo lại và dường như hoạt động.

Tôi đã phải rm các tệp .zcompdump một vài lần sau khi máy khởi động lại do lỗi xảy ra khi cố gắng hoàn thành tab, nhưng tôi không chắc đó là do thiết lập này hay do điều gì khác. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPvà một vỏ mới sẽ sửa lỗi đó cho tôi.

Các phiên bản được sử dụng tại thời điểm viết bài:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3

0

Câu trả lời của @ JatinKumar đã giúp tôi đi đúng hướng, nhưng tôi phải sử dụng completethay thế source. Vì vậy, tất cả cùng nhau:

autoload -Uz compinit && compinit
autoload -U +X bashcompinit && bashcompinit

complete -C /usr/local/bin/terraform terraform
complete -C /usr/local/aws/bin/aws_completer aws
complete -C /usr/local/bin/az az
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.