Saya hanya akan menjawab pertanyaan (1).
Masalah Anda adalah KEYTIMEOUT. Saya mengutip dari zshzle (1):
Ketika ZLE membaca perintah dari terminal, ia dapat membaca urutan yang terikat pada beberapa perintah dan juga merupakan awalan dari string terikat yang lebih panjang. Dalam hal ini ZLE akan menunggu waktu tertentu untuk melihat apakah lebih banyak karakter yang diketik, dan jika tidak (atau mereka tidak cocok dengan string yang lebih panjang) akan dilakukan pengikatan. Batas waktu ini ditentukan oleh parameter KEYTIMEOUT; standarnya adalah 0,4 detik. Tidak ada batas waktu jika string awalan tidak terikat dengan perintah.
0.4s adalah keterlambatan yang Anda alami setelah memukul ESC. Cara mengatasinya adalah menetapkan KEYTIMEOUT hingga 0,01 dalam salah satu file startup shell:
export KEYTIMEOUT=1
Sayangnya ini memiliki efek knock-on: Hal-hal lain mulai salah ...
Pertama, sekarang ada masalah dalam mode perintah vi: Mengetik ESC menyebabkan kursor hang, dan kemudian karakter apa pun yang Anda ketik selanjutnya akan tertelan. Ini karena ESC tidak terikat dengan apa pun secara default dalam mode perintah vi, namun ada widget multi-karakter yang dimulai dengan ESC (tombol kursor!). Jadi ketika Anda menekan ESC, ZLE menunggu karakter berikutnya ... dan kemudian mengkonsumsinya.
Cara mengatasinya adalah untuk mengikat ESC ke sesuatu dalam mode perintah, sehingga memastikan bahwa sesuatu akan diteruskan ke ZLE setelah $ KEYTIMEOUT centiseconds. Sekarang kita dapat tetap mengikat mulai dengan ESC dalam mode perintah tanpa efek buruk ini. Saya mengikat ESC ke karakter bel, yang menurut saya lebih tidak mengganggu daripada memasukkan sendiri (dan shell saya dibungkam):
bindkey -sM vicmd '^[' '^G'
Pembaruan 2017:
Saya telah menemukan solusi yang lebih baik untuk mengikat ESC - undefined-key
widget. Saya tidak yakin apakah widget ini tersedia di zsh ketika saya awalnya menulis jawaban ini.
bindkey -M vicmd '^[' undefined-key
Masalah berikutnya: Secara default ada beberapa widget dua-kunci yang dimulai dengan ^ X dalam mode insert vi; ini menjadi tidak dapat digunakan jika $ KEYTIMEOUT disetel sepenuhnya. Apa yang saya lakukan adalah unbind ^ X dalam mode insert vi (self-insert secara default); ini memungkinkan widget dua tombol untuk terus bekerja.
bindkey -rM viins '^X'
Anda kehilangan ikatan untuk disisipkan sendiri, tetapi Anda dapat mengikatnya dengan sesuatu yang lain tentu saja. (Aku tidak, karena aku tidak menggunakannya.)
Masalah terakhir (saya telah menemukan sejauh ini): Ada beberapa keybindings default yang tersisa yang kita "kehilangan" karena pengaturan $ KEYTIMEOUT segera, untuk menjelaskan: yang dimulai dengan ESC dalam mode insert vi yang bukan merupakan kunci kursor. Saya pribadi membukanya kembali dengan ^ ^ sebagai gantinya:
bindkey -M viins '^X,' _history-complete-newer \
'^X/' _history-complete-older \
'^X`' _bash_complete-word
Pembaruan 2018:
Ternyata seluruh bagian di atas (setelah "Pembaruan 2017") tidak selalu diperlukan. Dimungkinkan untuk mengatur kunci META agar setara dengan ESC di pemetaan keyboard menggunakan:
bindkey -mv
Karena itu dimungkinkan untuk tidak melepas ^ X, dan untuk mengakses ikatan kunci yang dimulai pada ESC dengan menekan META sebagai pemimpin sebagai gantinya (ALT atau OPT pada keyboard modern).
Jika Anda memiliki akses ke buku From Bash to Z Shell oleh Kiddle et al., Kesetaraan ESC dan META dalam ikatan kunci dibahas dalam bilah sisi Bab 4 pada hal. 78-79.
i
dua kali untuk kembali ke mode insert, saya akan sangat merekomendasikan perbaikan ini !