Menulis pelengkapan tab sederhana di Bash dan Zsh
(mill-build.org)- Memperkenalkan cara mengimplementasikan fitur pelengkapan tab di Bash dan Zsh yang menampilkan deskripsi bahkan untuk kata yang sudah lengkap
- Bash dan Zsh menggunakan API pelengkapan tab yang berbeda, dan hanya Zsh yang secara bawaan menyediakan fitur menampilkan deskripsi pada pelengkapan
- Mengimplementasikan struktur yang menghasilkan kandidat dengan
_generate_foo_completionslalu mengembalikannya melaluiCOMPREPLYdi Bash dancompadddi Zsh - Untuk menerapkan fitur deskripsi Zsh di Bash juga, digunakan pendekatan menyertakan deskripsi dalam string kandidat lalu menghapus deskripsi itu hanya saat kandidatnya tunggal
- Bahkan saat kandidatnya tunggal, perilaku ini ditingkatkan dengan sengaja menambahkan ambiguitas agar deskripsi tetap ditampilkan saat menekan
<TAB> - Skrip akhirnya memberikan pengalaman pengguna yang sama di kedua shell, serta mendukung pelengkapan parsial, pelengkapan penuh, dan tampilan deskripsi kandidat
Latar belakang masalah
- Pelengkapan tab (tab-completion) berguna saat menjelajahi perintah atau flag, terutama ketika baru pertama kali menggunakan API atau alat CLI
- Secara bawaan, Zsh hanya menampilkan deskripsi ketika ada beberapa kandidat, sedangkan Bash hanya bisa melakukannya lewat konfigurasi tambahan
- Namun, untuk kata yang sudah lengkap, kedua shell tidak menampilkan deskripsi
- Akibatnya, pengguna harus melalui proses merepotkan seperti berikut untuk melihat deskripsi
- Menghapus beberapa karakter agar beberapa kandidat cocok
- Menekan tombol
<TAB>untuk melihat daftar kandidat - Mencari deskripsi yang diinginkan secara visual
- Mengetik ulang karakter yang tadi dihapus untuk menjalankan perintah
Ringkasan solusi
- Bahkan jika hanya ada satu kandidat, tambahkan kandidat dummy (dummy completion) agar kandidat menjadi ambigu
- Dengan begitu, baik Bash maupun Zsh akan menampilkan daftar kandidat beserta deskripsinya
- Namun, harus diperhatikan agar teks deskripsi tidak ikut disisipkan ke perintah sebenarnya
Konsep dasar
- Pelengkapan tab bekerja dengan menerima kata saat ini dan posisi kursor ketika
<TAB>ditekan, lalu mengembalikan daftar kandidat yang mungkin - Bash: menetapkan kandidat ke array
COMPREPLY - Zsh: mendaftarkan kandidat dengan perintah
compadd - Fungsi
_generate_foo_completionsmencetak string kandidat, dan dalam penggunaan nyata bisa dibuat secara dinamis berdasarkan status CLI
Mendukung Bash dan Zsh sekaligus
- Mengimplementasikan fungsi
_complete_foo_bashdan_complete_foo_zshsesuai shell masing-masing - Membedakannya dengan
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi - Pengguna menerapkan skrip ini setelah mendaftarkannya di
.bashrcatau.zshrc
Menampilkan deskripsi di Zsh
- Gunakan format
nama: deskripsipada string kandidat - Zsh: kirim nama dan deskripsi sebagai array paralel lewat
compadd -d raw -- $trimmed - Bash: hanya kirim kandidat tanpa bagian deskripsi ke
COMPREPLY(secara bawaan tidak mendukung deskripsi)
Mengimplementasikan deskripsi di Bash
- Jika ada beberapa kandidat, tampilkan apa adanya string yang sudah berisi deskripsi
- Jika kandidatnya tunggal, hapus deskripsinya
- Manfaatkan perilaku pelengkapan Bash yang hanya menyisipkan prefiks bersama agar deskripsi tidak benar-benar masuk ke input
Menampilkan deskripsi bahkan untuk kandidat tunggal
- Agar deskripsi tetap terlihat saat menekan
<TAB>pada kata yang sudah lengkap, tambahkan kandidat dummy untuk menciptakan ambiguitas - Zsh: tambahkan kandidat dummy ke kedua array paralel (
raw,trimmed) - Bash: jika kandidatnya tunggal, tambahkan hanya namanya ke
trimmed
Hasil akhir
- Saat ada banyak kandidat, nama+deskripsi semuanya ditampilkan
- Saat kandidat tunggal pun, deskripsi tetap bisa dilihat dengan
<TAB> - Bash dan Zsh sama-sama memberikan pengalaman yang identik
- Contoh penerapan:
$ foo <TAB> apple: a common fruit banana: starchy and high in potassium apricot: sour fruit... cherry: small and sweet...
1 komentar
Opini Hacker News
fish_update_completions~/.cache/fish/generated_completions/curluntuk-L→ 'Follow redirects',-O→ 'Write output to file named as remote file'car TABmeluas menjadiblkdiscard, sehingga cargo salah terdeteksi meski tidak ada di PATH, bisa diperbaiki--helptanpa halaman man, saya penasaran apakah fish punya fungsi seperti_gnu_genericdi zsh ataucomplete -F _longoptdi bashzypper search fish-completion, muncul lebih dari 200 paket sehingga terasa agak mencurigakancomplete-filenameyang dibind ke M-/, yang menyelesaikan nama file sambil mengabaikan kontekslsdulu lalu mengganti perintahnyacomplete -rsemuanya bekerja sesuai keinginan membuat saya curiga masalahnya ada di skrip bash-completion$fpathmembuatnya di-cache sehingga kecepatan startup menjadi lebih cepat_gnu_genericmemungkinkan completion sederhana berbasis--help--generatemilik ripgrep, dan pembuatan completion saat runtime di PHP Symfony--completionyang otomatis diimplementasikan oleh library parser umumcomplete_kill_1, maka akan tersedia completion untuk argumen pertama perintahkill_describedi fungsiset-java-homeagar daftar~/apps/java/*dilengkapi sebagai versi