Saya bermain dengan skrip yang, antara lain, daftar pilihan-daftar. Seperti dalam:
1) Item 1 # (disorot) 2) Butir 2 3) Item 3 # (dipilih) 4) Item 4
- Ketika pengguna menekan
down-arrow
item berikutnya disorot - Saat pengguna menekan
up-arrow
item sebelumnya disorot - dll.
- Ketika
tab
item pengguna tekan dipilih - Ketika pengguna menekan
shift+tab
semua item dipilih / tidak dipilih - Ketika pengguna menekan
ctrl+a
semua item dipilih - ...
Ini berfungsi dengan baik pada penggunaan saat ini, yang merupakan penggunaan pribadi saya di mana input difilter oleh pengaturan saya sendiri.
Pertanyaannya adalah bagaimana membuat ini dapat diandalkan di berbagai terminal.
Saya menggunakan solusi yang agak peretasan untuk membaca input:
while read -rsn1 k # Read one key (first byte in key press)
do
case "$k" in
[[:graph:]])
# Normal input handling
;;
$'\x09') # TAB
# Routine for selecting current item
;;
$'\x7f') # Back-Space
# Routine for back-space
;;
$'\x01') # Ctrl+A
# Routine for ctrl+a
;;
...
$'\x1b') # ESC
read -rsn1 k
[ "$k" == "" ] && return # Esc-Key
[ "$k" == "[" ] && read -rsn1 k
[ "$k" == "O" ] && read -rsn1 k
case "$k" in
A) # Up
# Routine for handling arrow-up-key
;;
B) # Down
# Routine for handling arrow-down-key
;;
...
esac
read -rsn4 -t .1 # Try to flush out other sequences ...
esac
done
Dan seterusnya.
Seperti disebutkan, pertanyaannya adalah bagaimana membuat ini dapat diandalkan di berbagai terminal: yaitu urutan byte apa yang menentukan kunci tertentu. Apakah itu layak di bash?
Satu pemikiran adalah menggunakan salah satu dan tput
atau infocmp
memfilter berdasarkan hasil yang diberikan oleh hal itu. Namun saya dalam kesulitan karena keduanya tput
dan infocmp
berbeda dari apa yang sebenarnya saya baca ketika benar-benar menekan tombol. Sama berlaku misalnya menggunakan C over bash.
for t in $(find /lib/terminfo -type f -printf "%f\n"); {
printf "%s\n" "$t:";
infocmp -L1 $t | grep -E 'key_(left|right|up|down|home|end)';
}
Sekuens hasil dibaca seperti yang didefinisikan misalnya linux
, tetapi tidak xterm
, yang ditetapkan oleh TERM
.
Misal panah kiri:
tput
/infocmp
:\x1 O D
read
:\x1 [ D
Apa yang saya lewatkan?
dialog
varian, atau gunakan bahasa denganncurses
dukungan yang layak (perl atau python misalnya, jika Anda ingin tetap menggunakan bahasa "scripting").zsh
memiliki dukungan kutukan bawaan (dalam modul zsh / kutukan) di samping kueri terminfo dasar dengan arrayechoti
bawaan dan$terminfo
asosiatifnya.Jawaban:
Apa yang Anda lewatkan adalah bahwa sebagian besar deskripsi terminal (
linux
ada dalam minoritas di sini, karena penggunaan string-code yang sulit dikenali.inputrc
) menggunakan mode aplikasi untuk kunci khusus. Itu membuat kunci kursor seperti yang ditunjukkan olehtput
daninfocmp
berbeda dari apa yang dikirim terminal Anda (tidak diinisialisasi). aplikasi kutukan selalu menginisialisasi terminal, dan data base terminal digunakan untuk itu tujuan.dialog
memiliki kegunaannya, tetapi tidak secara langsung menjawab pertanyaan ini. Di sisi lain, itu merepotkan (secara teknis bisa dilakukan , jarang dilakukan ) untuk memberikan solusi bash-only. Secara umum kami menggunakan bahasa lain untuk melakukan ini.Masalah dengan membaca kunci khusus adalah bahwa mereka sering beberapa byte, termasuk karakter canggung seperti escapedan ~. Anda dapat melakukan ini dengan bash, tetapi kemudian Anda harus menyelesaikan masalah menentukan kunci khusus apa yang bisa dibawa-bawa.
dialog
keduanya menangani input tombol khusus dan mengambil alih (sementara) tampilan Anda. Jika Anda benar-benar menginginkan program baris perintah yang sederhana, itu tidak benardialog
.Berikut ini adalah program sederhana dalam C yang membaca kunci khusus dan mencetaknya dalam bentuk yang dapat dicetak (dan portabel):
Seandainya ini disebut
tgetch
, Anda akan menggunakannya dalam skrip Anda seperti ini:Bacaan lebih lanjut:
dialog
- Widget kutukan yang digerakkan oleh skrip (aplikasi dan perpustakaan)sumber
inputrc
memang pelakunya yang saya cari. Harus melihatnya lagi. Telah mempertimbangkan untuk menggunakan python atau C, tetapi merasa senang untuk melakukan hack sebagai skrip bash juga. Saya juga mencoba untuk melihat sumber ncurses untuk melihat apakah saya dapat mengekstrak bit yang saya butuhkan - tetapi setelah beberapa waktu menggali sumber saya meninggalkannya di atas es. The "proyek" dimulai sebagai perintah sederhana, kemudian menjadi script interaktif sederhana, dan kemudian diperpanjang pada itu lagi. Di suatu tempat di sepanjang jalan saya harus pergi bahasa lain , tetapi mendapat sedikit keras kepala (dan seperti yang disebutkan itu menyenangkan untuk di-hack di bash 2 :)/usr/share/doc/readline-common/inputrc.arrows
,. Karena saya sudah memiliki fungsi "read_key" generik yang saya gunakan di skrip, saya berharap ada cara yang lebih mudah untuk menentukan urutan (dalam skrip) dari apa yang sebenarnya disajikan ketika tombol ditekan. Yaitu mirip dengan mengekstraksi definisi dariinfocmp
. Tapi tebak tidak dan harus membiarkannya apa adanya atau beralih ke bahasa lain. Sebuah kompromi tentu saja bisa menggunakan potongan-C Anda yang bagus. Tapi kemudian saya bisa menulis semuanya dalam C sebagai gantinya. (Maaf karena-lncurses
, dll.Sudahkah Anda mencoba menggunakan
dialog
? Muncul standar dengan sebagian besar distro Linux dan dapat membuat semua jenis dialog berbasis teks, termasuk daftar periksa.Sebagai contoh:
Anda akan mendapatkan sesuatu seperti ini:
Dan hasilnya adalah:
(atau item mana saja yang Anda pilih).
man dialog
akan memberi Anda informasi tentang jenis dialog lain yang dapat Anda buat, dan cara menyesuaikan tampilan.sumber
Curses
,DBI
danDBD::SQLite
modul. atau setara python mereka.