Saya ingin membuat aturan penyelesaian untuk daftar parameter yang dipisahkan koma. Misalnya saya punya perintah yang menerima daftar nama server:
myscript -s name1,name2,name3
Saat ini saya sudah berhasil menulis penyelesaian sebagai berikut:
_myscript () {
local cur prev opts
_get_comp_words_by_ref cur prev
opts='-s'
servers='name1 name2 name3'
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
else
case "${prev}" in
-s)
if [[ "$cur" == *,* ]]; then
local realcur prefix
realcur=${cur##*,}
prefix=${cur%,*}
COMPREPLY=( $(compgen -W "${servers}" -P "${prefix}," -- ${realcur}) )
else
COMPREPLY=( $(compgen -W "${servers}" -- ${cur}) )
fi
;;
*)
# do nothing
;;
esac
fi
}
Tetapi memiliki setidaknya 2 masalah:
- Saran untuk nilai saat ini mencakup semua nilai sebelumnya dalam awalannya.
- Itu tidak mempertimbangkan nilai duplikat.
Apa praktik terbaik untuk kasus seperti itu? Mungkin bash-completions memiliki beberapa fungsi yang dibundel untuk csv-list?
bash
autocomplete
diffycat
sumber
sumber
IFS=, LIST=("$VARIABLE")
mana $ VARIABLE berisi nilai yang dipisahkan koma Anda.$VARIABLE
, jika tidak kata tidak akan terjadi. gunakan sajaIFS=, LIST=($VARIABLE)
.Jawaban:
Pada dasarnya tidak ada cara untuk memperbaiki masalah yang Anda gambarkan, karena bash menggunakan nilai-nilai di
COMPREPLY
secara langsung di layar dan kemudian mengganti teks pengguna - sementara untuk mendapatkan apa yang Anda inginkan, Anda harus terlebih dahulu menghasilkan penyelesaian yang mungkin (hanya tambahan nama server, tanpa awalan) untuk ditampilkan bash, maka ketika bash hendak mengganti teks pengguna dengan string non-konflik terpanjang, Anda perlu memanggil skrip Anda lagi untuk menghasilkan teks dengan awalan - dan bash tidak memiliki fasilitas untuk itu.Yang terbaik yang bisa saya buat adalah memiliki
COMPREPLY
dihasilkan dengan hanya kata pertama yang memiliki seluruh awalan (COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )
), sehingga jika hanya ada satu kemungkinan penyelesaian, itu selesai secara otomatis dengan benar, sedangkan jika ada lebih dari satu kemungkinan penyelesaian , maka bash tidak akan menghapus apa yang diketik sejauh ini (karena kata pertama dalamCOMPREPLY
memiliki seluruh awalan dan dengan demikian cocok dengan teks yang diketik saat ini dan akan dipilih oleh bash untuk mengganti teks pengguna) dan akan menampilkan opsi tanpa awalan - kecuali untuk itu satu kata yang sudah berisi awalan, sehingga hasilnya akan terlihat seperti ini:"apple" sebagai yang terakhir disortir dalam opsi penyelesaian karena membawa awalan yang dimulai dengan "b" - sangat membingungkan. Jadi saya tidak merekomendasikan melakukan itu.
Mengenai duplikat - agar tidak menunjukkan duplikat, Anda hanya perlu membobol
$prefix
bagiannya (mudahIFS="," prefix_parts=($prefix)
:) dan kemudian beralih pada mereka dan hanya meninggalkan$servers
nama-nama yang belum terdaftar. Itu membosankan untuk mengetik, jadi saya tidak akan menunjukkannya di sini, tetapi relatif sepele jadi saya yakin Anda dapat mengelola :-).Untuk meringkas, saya tidak berpikir Anda harus menggunakan nilai yang dipisahkan koma untuk opsi input, setidaknya jika Anda mengharapkan bash untuk membantu Anda dengan penyelesaian.
Anda dapat mendukung format opsi yang seperti ini:
command -s <server> [<server> [..]]
dan kemudian untuk penyelesaian entri selain yang segera setelah-s
opsi, cukup memindai kembali melalui$COMP_WORDS
array dari$COMP_CWORD
sampai Anda menemukan opsi (string yang cocok-*
) dan jika "-s" maka Anda perlu melakukan penyelesaian nama server.sumber