Tambahkan argumen dari perintah sebelumnya ke penyelesaian zsh

22

Di zsh (dan juga bash) Anda dapat menggunakan beberapa ekspansi kata sejarah untuk menunjukkan argumen dari perintah sebelumnya.

Contoh ini menunjukkan mendapatkan parameter ke-2 dari perintah sebelumnya dalam sejarah dengan !:#ekspansi:

% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar

Saya sering lupa persis apa parameter # argumen tertentu dan mengetik !:#tidak selalu cepat ketika saya ingat argumen mana itu. Saya tahu akan meta-.mengganti argumen terakhir, tetapi kadang-kadang itu bukan argumen terakhir yang saya inginkan.

Saya ingin menambahkan argumen dari perintah sebelumnya sebagai saran untuk menyelesaikan semua perintah yang saya ketikkan di zsh.

Saya bisa mengetahui cara membuat fungsi shell yang dapat membuat array argumen (0..N) dari perintah terakhir dan mengikatnya ke perintah tertentu.

_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

Ini seperti apa rasanya menyelesaikan hanya foo di mana saya menekan tombol tab di <TAB>:

% echo bar baz qux
bar baz qux
% foo <TAB>
bar   baz   echo  qux 

Ini berfungsi baik untuk menyelesaikan perintah "foo", tapi saya ingin ini menjadi opsi pada ekspansi zsh apa pun yang saya lakukan. Saya pikir itu ada hubungannya dengan hal-hal yang melengkapi zstyle, tetapi setelah beberapa jam peretasan di sekitar saya menyadari saya keluar dari kedalaman saya.

Bagaimana saya bisa mendapatkan argumen dari perintah saya sebelumnya sebagai penyelesaian yang disarankan untuk setiap perintah di zsh?

Saya punya file lengkap zshrc saya yang dibagikan di bitbucket jika itu membantu. Banyak yang ditulis dari berbagai sumber dan beberapa di antaranya saya peretas sendiri.

MEMPERBARUI:

@Julien Jawaban Nicoulaud membuat saya dekat, saya menandainya sebagai diterima karena membuat saya di mana saya perlu.

Dengan konfigurasi khusus saya, gunakan yang disarankan:

zstyle ':completion:*' completer _last_command_args _complete

Tidak cukup bekerja untuk saya karena itu menyebabkan penyelesaian tab hanya menampilkan daftar argumen dari perintah terakhir (meskipun itu sebenarnya lengkap dengan nama file juga, hanya tidak menampilkannya). Mengubah urutan untuk _complete _last_command_argsmelakukan yang sebaliknya. Itu akan menampilkan nama file normal, tetapi tidak last_command_args

Saya kira ini ada hubungannya dengan cara kerja pelengkap. Saya pikir ini hanya menampilkan output dari metode pertama yang berhasil kembali, tapi saya mengalami masalah dalam menguraikan sumber zsh untuk memahami sepenuhnya apa yang terjadi. Saya dapat mengubah metode saya untuk memasukkan panggilan ke _completesehingga menunjukkan kedua perintah argumen terakhir serta hal-hal autocomplete biasa. Tidak begitu terpisah, tetapi bekerja cukup baik untuk saya.

Inilah fungsi lengkap yang saya gunakan bersama dengan barang-barang zstyle lainnya yang saya miliki:

# 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 

Baris zstyle lain yang saya miliki, tidak perlu agar ini berfungsi, tetapi dapat memengaruhi mengapa ini bekerja untuk saya:

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

Sekarang, jika saya berada di direktori dengan file1.txtdan file2.txt, dan perintah terakhir saya adalah echo foo bar baz, saya mendapatkan ini untuk autocomplete yang persis seperti yang saya inginkan:

% ls
bar   baz   echo  foo 
- files -
file1.txt   file2.txt 
Ted Naleid
sumber
2
Ini adalah ide yang spektakuler
Michael Mrozek
2
Untuk melengkapi ^[ .( insert-last-word), saya suka copy-earlier-word, yang siklus antara kata-kata dari garis tercapai insert-last-word. Untuk Anda .zshrc:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word
Gilles 'SO- stop being evil'
@Gilles terima kasih! Itu membuat saya lebih dekat ke fungsi jika saya tidak bisa mendapatkan pelengkapan otomatis penuh. ~ 80% dari waktu, jika ini bukan argumen terakhir, argumen ke 2 ke terakhir yang saya inginkan dan C-. + C-, cukup bagus.
Ted Naleid

Jawaban:

6

Anda dapat menambahkan pelengkap Anda ke daftar pelengkap yang digunakan secara default:

zstyle ':completion:*' completer _last_command_args _complete
nicoulaj
sumber
1
Jika ada _last_command_argspenyelesaian, yang lain tidak akan ditampilkan. Bagaimana Anda mendapatkannya selain yang biasa?
Gilles 'SO- stop being evil'
1
Terima kasih atas jawabannya, ini membuat saya cukup dekat untuk membuat sesuatu bekerja untuk saya, jadi saya menerimanya. Apa yang saya lakukan secara berbeda dicatat sebagai pembaruan untuk pertanyaan di atas. Solusi Anda tidak mencetak argumen dari perintah terakhir serta file, dll dari pelengkap normal. Saya menyusun _completedi dalam fungsi yang saya buat dan berfungsi seperti yang saya inginkan.
Ted Naleid
Anda benar, jawaban saya tidak benar.
nicoulaj