Я только собираюсь ответить на вопрос (1).
Ваша проблема - KEYTIMEOUT. Я цитирую из zshzle(1):
Когда ZLE читает команду из терминала, он может прочитать последовательность, которая привязана к какой-либо команде и также является префиксом строки с более длинной привязкой. В этом случае ZLE будет ждать определенное время, чтобы увидеть, набрано ли больше символов, и если нет (или они не соответствуют более длинной строке), то выполнит связывание. Это время ожидания определяется параметром KEYTIMEOUT; его значение по умолчанию составляет 0,4 сек. Тайм-аут не существует, если строка префикса сама не связана с командой.
Эти 0,4 секунды - это задержка, которую вы испытываете после нажатия ESC. Исправление состоит в том, чтобы установить KEYTIMEOUT вплоть до 0,01 с в одном из файлов запуска оболочки:
export KEYTIMEOUT=1
К сожалению, это имеет эффект: другие вещи начинают работать неправильно ...
Во-первых, теперь есть проблема в командном режиме vi: ввод ESC приводит к зависанию курсора, а затем любой символ, который вы вводите следующим, проглатывается. Это связано с тем, что ESC по умолчанию не связан ни с чем в командном режиме vi, однако существуют многосимвольные виджеты, которые начинаются с ESC (клавиши курсора!). Поэтому, когда вы нажимаете ESC, ZLE ждет следующего символа ... и затем использует его.
Исправление состоит в том, чтобы привязать ESC к чему-либо в командном режиме, таким образом гарантируя, что что- то будет передано в ZLE через $ KEYTIMEOUT сантисекунды. Теперь мы можем поддерживать привязки, начиная с ESC, в командном режиме без этих вредных последствий. Я связываю ESC с персонажем колокольчика, который я считаю еще менее навязчивым, чем само вставка (и моя оболочка заставлена замолчать):
bindkey -sM vicmd '^[' '^G'
Обновление 2017:
С тех пор я нашел еще лучшее решение для привязки ESC - виджет undefined-key
. Я не уверен, был ли этот виджет доступен в zsh, когда я изначально писал этот ответ.
bindkey -M vicmd '^[' undefined-key
Следующая проблема: по умолчанию есть некоторые виджеты с двумя ключами, начинающиеся с ^ X в режиме вставки vi; они становятся непригодными, если $ KEYTIMEOUT установлен полностью вниз. Что я делаю, так это отсоединяю ^ X в режиме вставки vi (по умолчанию это самостоятельная вставка); это позволяет этим двухключевым виджетам продолжать работать.
bindkey -rM viins '^X'
Вы теряете привязку для самостоятельной вставки, но, конечно, можете привязать ее к чему-то другому. (Не знаю, так как мне это не нужно.)
Последняя проблема (которую я нашел до сих пор): Есть некоторые оставшиеся по умолчанию комбинации клавиш, которые мы "теряем" из-за установки $ KEYTIMEOUT прямо вниз, то есть: те, которые начинаются с ESC в режиме вставки vi, которые не являются клавишами курсора. Я лично связываю их, чтобы начать с ^ X вместо этого:
bindkey -M viins '^X,' _history-complete-newer \
'^X/' _history-complete-older \
'^X`' _bash_complete-word
Обновление 2018:
Оказывается, весь приведенный выше раздел (после «Обновления 2017») не обязательно требуется. Можно установить клавишу META эквивалентной ESC в отображениях клавиатуры, используя:
bindkey -mv
Поэтому можно не откреплять ^ X и получить доступ к сочетаниям клавиш, начинающимся в ESC, нажав вместо этого META в качестве лидера (ALT или OPT на современных клавиатурах).
Если у вас есть доступ к книге « От Bash до Z Shell » Киддла и др., Эквивалентность ESC и META в сочетаниях клавиш обсуждается в боковой панели главы 4 на стр. 78–79.