Trong zsh (cũng như bash), bạn có thể sử dụng một số mở rộng từ lịch sử để biểu thị các đối số từ các lệnh trước đó.
Ví dụ này cho thấy nhận được tham số thứ 2 từ lệnh trước đó trong lịch sử với !:#
việc mở rộng:
% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar
Tôi thường quên chính xác # tham số của một đối số cụ thể là gì và gõ !:#
không phải lúc nào cũng nhanh khi tôi nhớ đó là đối số nào. Tôi biết về meta-.
việc thay thế đối số cuối cùng, nhưng đôi khi đó không phải là đối số cuối cùng mà tôi muốn.
Tôi muốn thêm các đối số từ lệnh trước làm gợi ý để hoàn thành bất kỳ lệnh nào tôi đang nhập trong zsh.
Tôi đã có thể tìm ra cách tạo một hàm shell có thể tạo một mảng các đối số (0..N) từ lệnh cuối cùng và liên kết nó với một lệnh cụ thể.
_last_command_args() {
last_command=$history[$[HISTCMD-1]]
last_command_array=("${(s/ /)last_command}")
_sep_parts last_command_array
}
# trying to get last_command_args to be suggested for any command, this just works for foo
compdef _last_command_args foo
Đây là những gì nó trông giống như để hoàn thành chỉ foo nơi tôi nhấn phím tab tại <TAB>
:
% echo bar baz qux
bar baz qux
% foo <TAB>
bar baz echo qux
Điều này hoạt động rất tốt để hoàn thành lệnh "foo", nhưng tôi muốn đây là các tùy chọn trên bất kỳ bản mở rộng zsh nào tôi làm. Tôi nghĩ rằng nó có một cái gì đó để làm với công cụ hoàn thành zstyle, nhưng sau vài giờ hack xung quanh tôi nhận ra tôi đã vượt quá giới hạn của mình.
Làm cách nào tôi có thể nhận được các đối số từ lệnh trước của mình dưới dạng hoàn thành được đề xuất cho bất kỳ lệnh nào trong zsh?
Tôi đã có tệp cài đặt zshrc đầy đủ của mình được chia sẻ trên bitbucket nếu điều đó có ích. Rất nhiều trong số đó được đưa vào từ nhiều nguồn khác nhau và một số trong đó tôi đã tự mình hack.
CẬP NHẬT:
Câu trả lời của @Julien Nicoulaud đã khiến tôi gần gũi, tôi đánh dấu nó là được chấp nhận vì nó đưa tôi đến nơi tôi cần đến.
Với cấu hình cụ thể của tôi, sử dụng đề xuất:
zstyle ':completion:*' completer _last_command_args _complete
Tôi không làm việc được lắm vì nó khiến việc hoàn thành tab chỉ hiển thị danh sách các đối số từ lệnh cuối cùng (mặc dù nó cũng thực sự hoàn thành với tên tệp, chỉ không hiển thị chúng). Thay đổi thứ tự để _complete _last_command_args
làm ngược lại. Nó sẽ hiển thị tên tệp thông thường, nhưng không hiển thị last_command_args
Tôi đoán điều này có liên quan đến cách thức hoạt động của công cụ hoàn thành. Tôi nghĩ rằng nó chỉ hiển thị đầu ra từ phương thức đầu tiên trả về thành công, nhưng tôi gặp khó khăn khi phân tích nguồn zsh để hiểu đầy đủ những gì đang diễn ra. Tôi đã có thể điều chỉnh phương thức của mình để bao gồm một lệnh gọi để _complete
nó hiển thị cả các lệnh đối số cuối cùng cũng như các công cụ tự động hoàn thành thông thường. Không hoàn toàn như tách ra, nhưng hoạt động đủ tốt cho tôi.
Đây là chức năng đầy đủ mà tôi đã sử dụng cùng với các công cụ zstyle khác mà tôi có:
# adds the arguments from the last commadn to the autocomplete list
# I wasn't able to get this to work standalone and still print out both regular
# completion plus the last args, but this works well enough.
_complete_plus_last_command_args() {
last_command=$history[$[HISTCMD-1]]
last_command_array=("${(s/ /)last_command}")
_sep_parts last_command_array
_complete
}
_force_rehash() {
(( CURRENT == 1 )) && rehash
return 1 # Because we didn't really complete anything
}
zstyle ':completion:::::' completer _force_rehash _complete_plus_last_command_args _approximate
Các dòng zstyle khác mà tôi có, không cần thiết để nó hoạt động, nhưng có thể ảnh hưởng đến lý do tại sao nó hoạt động với tôi:
zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
zstyle ':completion:*:descriptions' format "- %d -"
zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes
Bây giờ, nếu tôi đang ở trong một thư mục có file1.txt
và file2.txt
, và lệnh cuối cùng của tôi là echo foo bar baz
, tôi nhận được điều này để tự động hoàn thành, đó là điều tôi muốn:
% ls
bar baz echo foo
- files -
file1.txt file2.txt
^[ .
( insert-last-word
), tôi thích copy-earlier-word
, chu kỳ giữa các từ của dòng đạt được insert-last-word
. Dành cho bạn .zshrc
:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word