
Я использую оболочку zsh в качестве оболочки по умолчанию как в Ubuntu, так и в Arch.
Я настроил сочетание клавиш (стрелка вверх) для автодополнения из истории в моей оболочке zsh, используя следующую строку в моем .zshrc
:
bindkey "^[[A" history-beginning-search-backward
Однако, когда я запускаю .zshrc
и/или перезагружаюсь в Ubuntu, сочетание клавиш не работает (я получаю только предыдущую команду, независимо от того, что я начал вводить), тогда как в Arch оно работает нормально (я получаю только последнюю команду, начинающуюся с того, что я ввел).
Кто-нибудь знает, как решить эту проблему?
решение1
На большинстве терминалов, подобных xterm, Up(и это похоже на большинство навигационных клавиш) отправляет либо ␛[A
или ␛OA
в зависимости от того, был ли терминал переведен в режимпередача с клавиатурырежим или нет. Записи smkx
и rmkx
terminfo могут использоваться для перевода терминала в этот режим или выхода из него.
Запись kcuu1
terminfo (курсор вверх на 1) описывает последовательность, отправленную Upприпередача с клавиатурырежим, то есть ␛OA
.
Debian и производные имеют /etc/zsh/zshrc
файл, который делает
function zle-line-init () {
emulate -L zsh
printf > /dev/tty '%s' ${terminfo[smkx]}
}
Что переводит терминал в этот режим, когда zle активен, а это значит, что теперь вы можете положиться на базу данных terminfo, чтобы узнать, какие последовательности символов передают клавиши.
Файл такжеопределяет $key
ассоциативный массивна основе записей terminfo, чтобы помочь вам сопоставить их с виджетами. Так что в этих системах вы можете сделать:
(($+key[Up])) && bindkey $key[Up] history-beginning-search-backward
Для чего-то, что работает в системах, где терминал находится впередача с клавиатурыmode и те, у которых нет или нет хеша $key
, вы можете сделать:
bindkey $terminfo[kcuu1] history-beginning-search-backward
bindkey ${terminfo[kcuu1]/O/[} history-beginning-search-backward
Смотрите также:
- Мои клавиши курсора не работают(часто задаваемые вопросы по ncurses)
- Почему я не могу использовать клавиши управления курсором в (какой бы то ни было) оболочке?(часто задаваемые вопросы по xterm)
решение2
Клавиши курсора — это весело.
Хотя это и не так весело, как редактирование ключей, котороеДействительновеселье.
У вас естьдва набораклавиш курсора на клавиатуре, те наклавиатура курсораи те, что наклавиатура калькулятора.
Большинство эмуляторов терминала пытаются (иногда довольно неудачно) использовать модель виртуальных терминалов DEC, где каждый набор клавиш индивидуально переключается междурежим приложенияинормальный режимиспользуя настройки частного режима DECCKM
(Режим курсорной клавиатуры) и DECNKM
(Режим цифровой клавиатуры) соответственно. Идея режима приложения по сути заключается в том, что клавиши на соответствующей клавиатуре превращаются в дополнительные функциональные клавиши приложения.
-
⇐ Это клавиатура курсора.
-
- В обычном режиме клавиши со стрелками отправляют управляющие последовательности ECMA-48
CUB
,CUF
,CUU
, и , если только не действует модификатор; в этом случае они отправляют управляющие последовательности.CUD
⎇ AltDECFNK
- В режиме приложения клавиши со стрелками отправляют
SS3
последовательности из 3-х клавиш с одним смещением.
- В обычном режиме клавиши со стрелками отправляют управляющие последовательности ECMA-48
-
⇐ Это клавиатура калькулятора.
-
- В обычном режиме клавиши со стрелками отправляют управляющие последовательности ECMA-48
CUB
,CUF
,CUU
, и , если только не действует модификатор, в этом случае они отправляют управляющие последовательности, или если комбинация цифровой блокировки и Shift не заставляет их отправлять цифры.CUD
⎇ AltDECFNK
- В режиме приложения клавиши со стрелками отправляютдругой набор
SS3
последовательности из 3 одинарных сдвигов (если, опять же, комбинация цифровой блокировки и сдвига не заставляет их отправлять цифры).
- В обычном режиме клавиши со стрелками отправляют управляющие последовательности ECMA-48
Последовательность ␛
[
A
, которую вы указали ZLE для привязки к виджету, является 7-битным псевдонимом ECMA-48 для CSI
A
управляющей последовательности, которая является CUP
управляющей последовательностью ("Cursor UP"). Эта управляющая последовательность генерируется только VT DEC и их имитаторами-эмуляторами терминалов, когда клавиатура находится в обычном режиме и модификатор ⎇ Altне действует. Она не будет соответствовать последовательностям смещений, отправленным, когда соответствующие клавиатуры находятся в режиме приложения.
База данных terminfo мутит воду и вызывает здесь дополнительное веселье, потому что она не использует эту модель для терминального ввода-вывода. Вместо этого она использует свою собственнуюдругоймодель, которая воплощает понятия «локальных» и «дистанционных» ключей, что на самом деле не является тем, что DEC VT приложение/переключение нормального режима на самом деле подразумевает; и она имеет единый механизм переключения локального/дистанционного режима, который в конечном итоге переключаетобаклавиатуры между режимами приложений и обычным режимом неразделимы.
terminfo — это способ не привязывать к одному конкретному типу терминала то, как вы настраиваете ZLE, на всякий случай, если вы обнаружите, что у вас есть терминал или эмулятор терминала, который не имитирует DEC VT. И оболочка Z предоставляет вам способы доступа к необходимым записям возможностей из записи базы данных. Таким образом, вы можете прочитать из terminfo, какие управляющие последовательности terminfo ожидает получить от клавиш курсора вверх/вниз/влево/вправо, и выдать соответствующие bindkey
команды, которые сопоставляют эти управляющие последовательности с виджетами.
Проблема в том, что terminfo не подходит для этой работы. Он может только записыватьодинпоследовательность управления для каждой клавиши, тогда как, как вы видите, клавиши могут отправлятьпо меньшей меретри различные последовательности, зависящие от режима и нажатых модификаторов. (Модификаторы могут существенно влиять на отправляемые управляющие последовательности в модели DEC VT.) Поэтому вам нужно переключить терминал в режим, который генерирует то, что terminfo говорит вам ожидать.
Но становится еще хуже: terminfo не является согласованным. Единственная последовательность управления иногда является последовательностью режима приложения DEC VT, как записи terminfo дляputty
тип терминала, иногда последовательность нормального режима DEC VT, как записывает terminfo дляrxvt
тип терминала, но никогда не DECFNK
последовательность. Таким образом, у вас нет способа узнать, следует ли вам переключиться в режим приложения или в обычный режим с любым данным терминалом или эмулятором терминала. То, что будет работать правильно для одного, будет работать неправильно для другого.
Другой подход, таким образом, заключается в том, чтобы игнорировать terminfo и осознать, что выужеи вполне счастливо предполагая, что ваш терминал всегда будет как DEC VT с вашей исходной bindkey
командой. Вам просто нужны два из них, чтобы убедиться, что независимо от того, находится ли ваш терминал в режиме приложения или в обычном режиме, последовательность управления, которую он отправляет, будет соответствовать:
bindkey "^[OA" история-начало-поиск-назад
Однако это не справится с нажатием клавиш-модификаторов, что добавляет дополнительные параметры в CUP
последовательность управления, что приводит к сбою упрощенного сопоставления строк, используемого ZLE, когда все, что он ищет, — это простое безпараметрическое CUP
. Вам придется вручную вводить дополнительную bindkey
команду для каждой возможной CUP
последовательности управления, полученной из каждой возможной комбинации модификаторов.
последовательность 1 8 | пока читаю -ri делать bindkey "^[[1;${i}A" история-начало-поиск-назад сделанный
ZLE здесь не одинок. Другие программы на основе terminfo, такие как fish
shell, страдают тем же самым образом. ( fish
Сотрудники shell тоже обнаружили, что выбор режима приложения/нормального режима, который работает правильно для одного эмулятора терминала, будет работать неправильно для другого.) Перепроектирование этого (сравнитеlibtermkey
(который имеет фактический анализатор управляющей последовательности ECMA-48 для ввода) в этих программах давно назрел. Но никто за это еще не брался.
дальнейшее чтение
- https://unix.stackexchange.com/a/444270/5132
- «Возможности клавиатуры». Информация о программаторе видеотерминала VT510. EK-VT510-RM. Ноябрь 1993. Цифровой.
- https://unix.stackexchange.com/a/289871/5132
- Джонатан де Бойн Поллард (14.05.2018).Некоторым терминалам требуется режим клавиатуры (smkx). ошибка в виде рыбьего панциря № 2139.
- https://unix.stackexchange.com/a/419092/5132