Maafkan saya jika saya melakukan sesuatu yang bodoh di sini, dokumentasinya sangat besar dan pencarian belum menghasilkan apa-apa.
Saya mencoba membuat penyelesaian shell untuk skrip khusus saya yang disebut fab
. Untuk bash itu mudah, cukup taruh di /etc/bash_completion.d
dan mereka bekerja. Tapi astaga, apakah zsh adalah PITA…
Saya memiliki fungsi penyelesaian _fab
dan berfungsi dengan baik saat diaktifkan dengan compdef _fab fab
. Saya memasukkannya ke /usr/share/zsh/vendor-completions/_fab
yang sudah ada di $fpath
saya . File dimulai dengan #compdef fab
dan diakhiri dengan compdef _fab fab
. Terlihat bagus:
$ type _fab
_fab is an autoload shell function
Tetapi setiap kali saya memulai shell baru, fab
penyelesaian tidak berfungsi (fungsi lain dari vendor-completions
, seperti _docker
, kami baik-baik saja). compinit
memperbaiki ini untuk shell khusus itu. Saya menemukan bahwa rm ~/.zcompdump ~/.zcompdump-$(hostname)-5.1.1; compinit
membuatnya bekerja secara permanen (5.1.1 =versi zsh saya).
Pertanyaan:
- Apa dan kapan membaca
~/.zcompdump
untuk menyiapkan penyelesaian awal? -
man zshall
mengatakan:Pemanggilan compinit berikutnya akan membaca file yang dibuang alih-alih melakukan inisialisasi penuh.
Jika itu masalahnya,
compinit
tidak akan memperbaiki penyelesaian saya sebelum saya menghapus~/.zcompdump
, Baik? Apakah saya melewatkan sesuatu? - Apa itu
~/.zcompdump-$(hostname)-5.1.1
dan bagaimana hubungannya dengan.zcompdump
? Satu-satunya perbedaan adalah satu penyelesaian yang ada di~/.oh-my-zsh/completions
(karena$ZSH
menunjuk ke~/.oh-my-zsh
). Apakah ini hal yang aneh? - Jika saya mengemas penyelesaian ini ke dalam paket yang dapat didistribusikan ulang atau membuat skrip penginstal, di mana saya harus meletakkan penyelesaian zsh dan apa lagi yang harus saya lakukan selama penginstalan untuk memastikan semuanya berfungsi?
Saya menargetkan Ubuntu 16.04, 18.04 dan 19.04, tetapi informasi khusus non-distro diterima. Saya menguji ini di Ubuntu 16.04 dengan zsh 5.1.1 dan terbaru oh-my-zsh.
Jawaban yang Diterima:
TL,DR:Dalam operasi normal, cukup letakkan file ke direktori yang sesuai. Saat menguji, Anda perlu menghapus file cache (.zcompdump
secara default, tetapi pengguna dapat meletakkannya di lokasi yang berbeda, dan oh-my-zsh meletakkannya di lokasi yang berbeda).
Jawaban sederhananya adalah menulis fungsi penyelesaian dalam file di mana baris pertama adalah #compdef fab
. File harus berada dalam direktori di $fpath
.
File dapat berisi badan fungsi, atau definisi fungsi yang diikuti dengan panggilan ke fungsi tersebut. Artinya, file tersebut berisi sesuatu seperti
#compdef fab
_arguments …
atau
#compdef fab
function _fab {
_arguments …
}
_fab "[email protected]"
File harus ada di $fpath
sebelum compinit
berjalan. Itu berarti Anda perlu memperhatikan urutan hal-hal di .zshrc
:pertama tambahkan direktori khusus apa pun ke $fpath
, lalu panggil compinit
. Jika Anda menggunakan kerangka kerja seperti oh-my-zsh, pastikan untuk menambahkan direktori khusus apa pun ke $fpath
sebelum kode oh-my-zsh.
compinit
adalah fungsi yang menginisialisasi sistem penyelesaian. Ia membaca semua file di $fpath
dan memeriksa baris pertama mereka untuk arahan ajaib #autoload
dan #compdef
.
.zcompdump
adalah file cache yang digunakan oleh compinit
. ~/.zcompdump
adalah lokasi default; Anda dapat memilih lokasi yang berbeda saat menjalankan compinit
. Astaga, panggilan compinit
dengan -d
opsi untuk menggunakan nama file cache yang berbeda yang diberikan oleh variabel ZSH_COMPDUMP
, yang defaultnya adalah
ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
Nama host disertakan untuk kepentingan orang-orang yang direktori home-nya dibagi antara mesin dan yang mungkin memiliki perangkat lunak berbeda yang diinstal pada mesin yang berbeda. Versi zsh disertakan karena file cache tidak kompatibel antar versi (termasuk kode yang berubah dari versi ke versi).
Terkait:Apa yang dilakukan CTRL+V di vim?
Saya pikir semua masalah Anda disebabkan oleh file cache yang basi (dan itu membuat Anda terlalu memperumit situasi). Sayangnya, algoritma zsh untuk menentukan apakah file cache basi tidak sempurna, mungkin demi kecepatan. Itu tidak memeriksa konten atau stempel waktu file di $fpath
, itu hanya menghitung mereka. Sebuah .zcompdump
file dimulai dengan baris seperti
#files: 858 version: 5.1.1
Jika versi zsh dan jumlah file sudah benar, zsh akan memuat file cache.
File cache hanya berisi asosiasi antara nama perintah, bukan kode fungsi penyelesaian. Berikut adalah beberapa skenario umum di mana cache bekerja secara transparan:
- Jika Anda menambahkan file baru ke
$fpath
, ini membuat cache menjadi tidak valid. - Lebih umum lagi, jika Anda menambahkan dan menghapus file di
$fpath
, dan jumlah total file yang dihapus tidak sama dengan jumlah total file yang dihapus, ini membuat cache menjadi tidak valid. - Jika Anda memindahkan file ke direktori lain di
$fpath
tanpa mengubah namanya, ini tidak mempengaruhi apa pun yang ada di cache, jadi cache tetap benar. - Jika Anda memodifikasi file di
$fpath
tanpa mengubah baris pertama, ini tidak mempengaruhi apa pun yang ada di cache, jadi cache tetap benar.
Berikut adalah beberapa skenario umum di mana cache menjadi tidak valid, tetapi zsh tidak menyadarinya.
- Anda menambahkan beberapa file ke
$fpath
dan hapus jumlah file yang sama persis. - Anda mengganti nama file di
$fpath
. - Anda menambah atau mengubah
#compdef
(atau#autoload
) baris di bagian atas file.
Poin terakhir itulah yang cenderung menggigit selama pengujian. Jika Anda mengubah #compdef
baris, Anda harus menghapus .zcompdump
file dan mulai ulang zsh (atau jalankan kembali compinit
).
Jika Anda memasukkan penyelesaian dalam paket yang dapat didistribusikan ulang, cukup letakkan file penyelesaian ke dalam direktori yang ada di $fpath
seluruh sistem . Untuk paket Ubuntu, tempat yang sesuai adalah /usr/share/zsh/vendor-completions
. Untuk sesuatu yang diinstal di bawah /usr/local
, itu /usr/local/share/zsh/site-functions
. Hanya itu yang perlu Anda lakukan.
Satu hal yang tidak transparan adalah jika Anda perlu mengubah #compdef
baris dalam peningkatan, atau jika Anda menghapus atau mengganti nama beberapa file. Dalam kasus seperti itu, pengguna harus menghapus file cache mereka, dan itu bukan sesuatu yang dapat Anda lakukan dari paket yang diinstal pada mesin multipengguna.