Thêm đối số từ lệnh trước để hoàn thành zsh


21

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_argslà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 để _completenó 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.txtfile2.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 

2
Đây là một ý tưởng ngoạn mục
Michael Mrozek

2
Để bổ sung ^[ .( 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
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles cảm ơn! Điều đó giúp tôi gần hơn với chức năng nếu tôi không thể tự động hoàn thành. ~ 80% thời gian, nếu đó không phải là cuộc tranh luận cuối cùng, thì đó là cuộc tranh luận thứ 2 đến lần cuối mà tôi muốn và C-. + C-, là khá tốt.
Ted Naleid

Câu trả lời:


6

Bạn có thể thêm trình hoàn thành của mình vào danh sách các trình hoàn thành được sử dụng theo mặc định:

zstyle ':completion:*' completer _last_command_args _complete

1
Nếu có bất kỳ sự _last_command_argshoàn thành nào , những cái khác sẽ không được hiển thị. Làm thế nào để bạn có được chúng ngoài những người bình thường?
Gilles 'SO- ngừng trở nên xấu xa'

1
Cảm ơn câu trả lời, điều này đã cho tôi đủ gần để có được một cái gì đó làm việc cho tôi, vì vậy tôi chấp nhận nó. Những gì tôi đã làm khác nhau được ghi nhận là một bản cập nhật cho câu hỏi ở trên. Giải pháp của bạn đã không in ra cả các đối số từ lệnh cuối cùng cũng như các tệp, v.v. từ trình hoàn thành bình thường. Tôi sáng tác _completebên trong hàm tôi đã tạo và nó hoạt động giống như tôi muốn.
Ted Naleid

Bạn nói đúng, câu trả lời của tôi không đúng.
nicoulaj
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.