Что означает оболочка в режиме «vi» или «emacs»?

32

Этот вопрос следует непосредственно из ответа . В этом случае я специально не могу понять ту часть, которая гласит:

В связи с этим его поведение ближе к emacs ', чем в режиме emacs bash (readline) / ksh / zsh, но отходит от встроенного редактора строк драйвера терминала (в каноническом режиме), где Ctrl-Wудаляет предыдущее слово (werase, также в vi). ).

Здесь речь идет о оболочках, а не редакторах, которые представляют собой две совершенно разные программы. Что значит сказать, что оболочка в каком-то режиме редактора?

PS: Вы можете основать свой ответ на предпосылке, что я понимаю, что такое оболочка и как использовать vim для базового редактирования.

Фанат
источник
Речь идет не о функциональности основной оболочки как таковой, а о редактировании строк (что вы делаете, когда делаете опечатку, возвращаетесь и исправляете себя).
нет. местоимения м.

Ответы:

27

В режиме «vi» вы можете редактировать / перемещаться по текущему приглашению оболочки, как в редакторе vi. Вы можете посмотреть на это как однострочный текстовый файл. Аналогично в режиме "emacs" вы можете редактировать / перемещаться по текущей командной строке, используя (некоторые) ярлыки Emacs.

пример

Например, в режиме vi вы можете сделать что-то вроде (в bash):

$ set -o vi
$ ls hello world
<ESC>
bbdw # results in
$ ls world

В Emacs-режиме вы можете нажать клавишу , например Ctrl+ , Aчтобы перейти в начало строки (VI: Ctrl+ [, 0или ESC, 0). Вы можете включить режим emacs через set -o emacs(в bash, ksh, zsh и т. Д.).

Readline

Многие интерактивные программы командной строки (включая bash ) используют библиотеку readline . Таким образом, вы можете настроить, какой режим ввода использовать (vi или emacs) и другие параметры в одном месте, чтобы каждая программа, использующая readline, имела одинаковый интерфейс редактирования / навигации.

Например, моя конфигурация readline выглядит так:

$ cat ~/.inputrc 
set editing-mode vi
set blink-matching-paren on

Например, zsh / ksh не использует readline, насколько я знаю, но также поддерживает режимы vi / emacs, которые очень похожи на режим bash / readline.

Конечно, режим vi / emacs в командной строке является лишь подмножеством полного набора функций редактора. Не каждая функция имеет смысл в командной строке, и некоторые функции сложнее поддерживать, чем другие.

Канонический режим

До того, как режимы интерактивных командных строк vi / emacs «были изобретены», ваша оболочка использовала только канонический режим вашего терминала, который предоставляет только ограниченный набор команд редактирования (например, Ctrl+ Wдля удаления последнего слова.

maxschlepzig
источник
Предположим, я не знаю, в каком режиме ввода я нахожусь. Могу ли я проверить это, введя какой-нибудь текст и нажав [Ctrl] + [A]? если курсор перемещается в начало своего emacs, иначе это vi?
Лимовала
2
@limovala, должно быть хорошее приближение. Конечно, зависит от вашей оболочки - если CTL + A не работает, другая возможность состоит в том, что ваша оболочка не включает какой-либо режим редактирования. Возможно, некоторые оболочки также реализуют другие режимы редактирования. Но на практике ваш метод должен быть достаточно хорошим. Вы также можете проверить с помощью команды vi после этого, чтобы быть более уверенным. В Bash вы также можете использовать что-то вроде set -o | grep 'emacs\|vi'. В zsh (где у меня есть vi-mode) это не работает.
maxschlepzig
bind -P также покажет, в каком режиме вы
Пол
23

Вы заметите, что когда вы запускаете catприглашение командной строки на терминале, catкоторый должен записать в stdout то, что он читает из stdin, и нажимаете a, вы видите aответное сообщение от драйвера терминала, но catне записывает это a(вы видите только один a, который повторяется драйвером терминала).

Однако, если вы печатаете a Backspace b Enter, вы не видите catвывод a\010b\015, но b\012( bи перевод строки).

Это потому, что драйвер терминала (мы говорим о программном обеспечении в ядре, а не в эмуляторе терминала xterm) реализует очень простой редактор строк в каноническом режиме. Драйвер терминала можно настроить с помощью ioctl()системных вызовов, например, при использовании sttyкоманды. Например, чтобы выйти из канонического режима, вы можете сделать stty -icanon. Если вы делаете:

stty -icanon; cat

Затем вы увидите одновременно и то, echoчто вы могли бы отключить, stty -echoи catвывод.

Этот редактор является линейным редактором. То есть пользователь должен редактировать одну строку текста до тех пор, пока она не будет отправлена ​​приложению, читающему оконечное устройство, после нажатия Enter.

Возможности редактирования этого редактора очень ограничены. В большинстве реализаций есть только 4 ключа редактирования (фактически символы), которые также можно настроить с помощью stty:

  • стереть ( ^Hили ^?обычно): стереть предыдущий символ
  • kill ( ^Uобычно): пусто (kill) введенная строка
  • werase ( ^W): стереть предыдущее слово
  • lnext ( ^V): буквально введите следующий символ (отмените специальное значение всего вышеперечисленного)

В прежние времена считалось, что этот редактор строки драйвера терминала будет расширен с более изощренными возможностями. Вот почему ни одна из ранних оболочек не имеет никаких возможностей редактирования командной строки (вы получите те же возможности редактирования строк в командной строке, что и при запуске, catкак мы делали выше).

Однако этого на самом деле никогда не происходило, возможно, одна из причин - беспорядок с разными терминалами, которые не посылали одинаковые символы при некоторых нажатиях клавиш, что давало понять, что это не должно быть реализовано в пространстве ядра.

Поэтому некоторые оболочки начали отбрасывать канонический режим драйвера терминала и реализовывать собственный редактор строк. В то время emacsи viбыли наиболее популярны визуальные текстовые редакторы с совершенно другой привязкой клавиш и режимом работы. В vi, у вас есть один режим для ввода текста и один для редактирования. В emacs, вы всегда находитесь в режиме ввода текста , но редактирование осуществляется нажатием комбинации клавиш (например, ^bчтобы переместить символ назад).

В то время оболочкам не было смысла придумывать свою собственную привязку ключей. Это вызвало бы разочарование у людей, которым пришлось бы учиться другому. Однако выбор одного ( emacsили vi) стиля поверх другого был бы верным способом оттолкнуть пользователей другого редактора.

Согласно https://www.usenix.org/legacy/publications/library/proceedings/vhll/full_papers/korn.ksh.a :

Популярные встроенные функции редактирования (режим vi и emacs) ksh были созданы разработчиками программного обеспечения в Bell Laboratories; режим редактирования строки vi от Pat Sullivan и режим редактирования строки emacs от Mike Veach. Каждый из них независимо модифицировал оболочку Bourne, чтобы добавить эти функции, и оба были в организациях, которые хотели использовать ksh, только если у ksh был свой соответствующий встроенный редактор. Первоначально идея добавления редактирования командной строки в ksh была отвергнута в надежде, что редактирование строки переместится в драйвер терминала. Однако, когда стало ясно, что это вряд ли произойдет в ближайшее время, оба режима редактирования строки были интегрированы в ksh и стали необязательными, чтобы их можно было отключить в системах, обеспечивающих редактирование как часть интерфейса терминала.

Таким образом, вместо этого они реализовали оба и интерфейс для пользователей, чтобы выбрать между ними. kshСкорее всего, он был первым в начале 80-х годов (повторное использование кода, который был написан отдельно для добавления режима vi и режима emacs в оболочку Bourne, как показано выше), за которым следовали tcsh( tcshпервоначально имелась только emacsпривязка клавиш, viрежим был добавлен позже) и позже bashи zshв начале 90-х годов.

Вы переключаетесь между двумя режимами в bash, zshили kshс помощью set -o viили set -o emacs, и с помощью bindkey -eили bindkey -vв tcshили zsh.

На самом деле POSIX указывает viрежим, а не emacsрежим sh(история гласит, что Ричард Столлман возражал против того, чтобы POSIX указывал emacsрежимsh ).

Режим по умолчанию bash, общественное достояние варианты ksh(pdksh, МКШ, oksh), tcshи zshявляется режим Emacs (хотя и с zsh, это , viесли ваш $EDITORесть vi), в то время как в AT & T ksh, это немой режим , если $EDITORили $VISUALнет упоминаний viили emacs.

kshТакже позже добавили gmacsрежим для размещения пользователей Гослинга, emacsкоторый обрабатывается по- Ctrl+Tразному.

Теперь обработка ^Win emacsили в tcshemacs режиме, вероятно, предшествует weraseсимволу в редакторе строки терминала, поэтому мы не можем винить их за это, и мое утверждение об «уходе ...» может быть воспринято как вводящее в заблуждение. Просто я нахожу это раздражающим, когда вещи нравятся emacs, tcshили infoведут себя иначе, чем все остальное, когда ты печатаешь Ctrl-W. Вы можете себе представить, что я нахожу гораздо более раздражающим, когда некоторые приложения начинают закрывать свое окно, когда вы печатаете Ctrl-W.

Стефан Шазелас
источник
1
pdkshтакже разбирает $EDITORдля viи переключает режимы при запуске; Я удалил это для mksh(тем более, что я все равно действительно поддерживаю режим Emacs).
Мирабилось
Спасибо большое дополнение, особенно с подробным обсуждением поведения и истории различных оболочек. Как человек, которому регулярно приходится работать в разных дистрибутивах с оболочками, которые я не настраивал, это чрезвычайно полезно.
BryKKan
Спасибо за отличный исторический контекст. Жаль, что более сложные встроенные функции редактирования не были добавлены в драйвер терминала в то время. Там не будет необходимости для программ, чтобы включать библиотеки, такие как Readline. Я также удивился, почему Emacs-режим не указан в POSIX, так что ссылка на Обоснование была интересной. (Я также разделяю ваше разочарование по поводу ^Wзакрытия окон).
Энтони Дж - справедливость для Моники
1
@AnthonyGeoghegan, нам все еще нужны такие вещи, как zle / readline, так как такие вещи, как завершение имени файла / команды не могут быть выполнены в драйвере терминала.
Стефан Шазелас