21

Мне действительно нравится общая скорость Zsh, но две вещи раздражают меня до чертиков.

  1. Мне нужно подождать мгновение между нажатием escape и косой чертой, чтобы перейти к поиску истории (если он слишком быстро коснулся косой черты, появится сообщение zsh: do you wish to see all 514 possibilities (172 lines))
  2. После ввода в режим вставки из - за попадания a или A я не могу мимо символ назад момент , когда я вошел в режим вставки.

Я знаю, что 2 похожа на классический vi, но мне больше нравится стиль vim.

2 ответа2

18

(1). По какой-то причине bindkey ведет себя странно, когда дело доходит до «/»: <esc> за которым быстро следует / , интерпретируется как <esc-/> . (Я наблюдал это поведение на днях; не совсем уверен, что его вызывает.) Я не знаю, является ли это ошибкой или функцией, и если это функция, если ее можно отключить, но вы можете обойти ее довольно легко.

Эта ключевая комбинация, вероятно, связана с _history-complete-older , которая генерирует нежелательный результат - вы можете использовать bindkey -L чтобы увидеть, так ли это.

В любом случае, если вы не возражаете пожертвовать фактической привязкой <esc-/> (сжатой вместе как аккорд), вы можете повторно привязать ее к команде поиска истории vi-mode, чтобы набрать <esc> / делает то же самое на любой скорости печати. знак равно

Так как это будет восприниматься как аккорд, оно не будет иметь эффекта при первом входе в командный режим vi, поэтому сначала нужно убедиться, что это произойдет. Во-первых, вам нужно определить функцию; поместите это где-нибудь в свой fpath если вы используете это, или поместите его в ваш .zshrc в противном случае:

vi-search-fix() {
zle vi-cmd-mode
zle .vi-history-search-backward
}

Остальное идет в вашем .zshrc в любом случае:

autoload vi-search-fix
zle -N vi-search-fix
bindkey -M viins '\e/' vi-search-fix

Должно быть хорошо идти.

(2). Вы можете исправить клавишу Backspace следующим образом:

`bindkey "^?" backward-delete-char`

Также, если вы хотите подобное поведение для других команд в стиле vi:

bindkey "^W" backward-kill-word 
bindkey "^H" backward-delete-char      # Control-h also deletes the previous char
bindkey "^U" backward-kill-line            
13

Я только собираюсь ответить на вопрос (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.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .