Zajmę się tylko pytaniem (1).
Twój problem to KEYTIMEOUT. Cytuję z zshzle (1):
Gdy ZLE odczytuje polecenie z terminala, może odczytać sekwencję powiązaną z jakimś poleceniem, a także przedrostek dłuższego łańcucha. W takim przypadku ZLE poczeka pewien czas, aby sprawdzić, czy zostanie wpisanych więcej znaków, a jeśli nie (lub nie pasują one do żadnego dłuższego ciągu), wykona wiązanie. Limit czasu jest zdefiniowany przez parametr KEYTIMEOUT; jego domyślna wartość to 0,4 sekundy. Nie ma limitu czasu, jeśli ciąg prefiksu nie jest związany z poleceniem.
Te 0,4 s to opóźnienie występujące po uderzeniu w ESC. Rozwiązaniem jest ustawienie KEYTIMEOUT aż do 0,01 s w jednym z plików startowych powłoki:
export KEYTIMEOUT=1
Niestety ma to efekt domina: inne rzeczy zaczynają się dziać źle…
Po pierwsze, występuje teraz problem w trybie komend vi: Wpisanie ESC powoduje zawieszenie się kursora, a następnie którykolwiek z wpisanych znaków zostanie połknięty. Wynika to z faktu, że ESC nie jest domyślnie powiązany z niczym w trybie komend vi, ale istnieją widżety wieloznakowe, które zaczynają się od ESC (klawisze kursora!). Więc kiedy wciśniesz ESC, ZLE czeka na następną postać… a następnie ją pochłania.
Rozwiązaniem jest powiązanie ESC z czymś w trybie poleceń, co zapewnia, że coś zostanie przekazane do ZLE po centisekundach $ KEYTIMEOUT. Teraz możemy utrzymywać wiązania zaczynające się od ESC w trybie poleceń bez tych złych efektów. Wiążę ESC z postacią dzwonka, co wydaje mi się mniej inwazyjne niż samodzielne wstawianie (a moja skorupa jest wyciszona):
bindkey -sM vicmd '^[' '^G'
Aktualizacja 2017:
Od tego czasu znalazłem jeszcze lepsze rozwiązanie dla wiązania ESC - undefined-key
widgetu. Nie jestem pewien, czy ten widget był dostępny w Zsh, kiedy pierwotnie napisałem tę odpowiedź.
bindkey -M vicmd '^[' undefined-key
Następny problem: Domyślnie istnieją dwa widżety z dwoma kluczami, zaczynające się od ^ X w trybie wstawiania vi; stają się one bezużyteczne, jeśli $ KEYTIMEOUT jest ustawiony do końca. To, co robię, to unbindowanie ^ X w trybie wstawiania vi (domyślnie jest to automatyczne wstawianie); pozwala to dwóm kluczowym widżetom kontynuować pracę.
bindkey -rM viins '^X'
Tracisz wiązanie do samodzielnego wstawiania, ale możesz oczywiście powiązać je z czymś innym. (Nie mam, bo nie mam z tego pożytku.)
Ostatni problem (do tej pory znalazłem): Są pewne domyślne skróty klawiszowe, które „tracimy” z powodu ustawienia $ KEYTIMEOUT w dół, to znaczy: te zaczynające się od ESC w trybie wstawiania vi, które nie są klawiszami kursora. Osobiście wiążę je ponownie, aby zacząć od ^ X:
bindkey -M viins '^X,' _history-complete-newer \
'^X/' _history-complete-older \
'^X`' _bash_complete-word
Aktualizacja 2018:
Okazuje się, że cała sekcja powyżej (po „Aktualizacji 2017”) niekoniecznie jest wymagana. Możliwe jest ustawienie klawisza META tak, aby był równoważny klawiszowi ESC w mapowaniu klawiatury za pomocą:
bindkey -mv
Jest zatem możliwe, aby nie cofać wiązania ^ X i uzyskać dostęp do skrótów klawiszowych rozpoczynających się w ESC, naciskając zamiast tego META jako lidera (ALT lub OPT na nowoczesnych klawiaturach).
Jeśli masz dostęp do książki From Bash to Z Shell autorstwa Kiddle i wsp., Równoważność ESC i META w skrótach klawiszowych omówiono w pasku bocznym rozdziału 4 na str. 78–79.
i
dwukrotnego naciśnięcia przycisku, aby wrócić do trybu wstawiania, zdecydowanie polecam tę poprawkę!