外壳处于“ vi”模式或“ emacs”模式意味着什么?


32

这个问题直接来自答案。在这种情况下,我特别无法理解以下内容:

在这方面,它的行为比bash(readline)/ ksh / zsh emacs模式更接近emacs,但与终端驱动程序嵌入式行编辑器(在规范模式下)不同,后者在其中Ctrl-W删除了前一个单词(werase,也在vi中) )。

在这里,我们谈论的是shell,而不是两个完全不同的程序的编辑器。说shell处于某种编辑器模式意味着什么?

PS:您可以在我了解shell是什么以及如何使用vim进行基本编辑的前提下得出答案。


这本身不是关于核心外壳功能的问题,而是关于行编辑(做错字并回过头来校正自己的操作)。
n。代词

Answers:


27

在“ vi”模式下,您可以像在vi编辑器中的一行一样在当前shell提示符下进行编辑/导航。您可以像单行文本文件一样查看它。类似地,在“ emacs”模式下,您可以使用(某些)Emacs快捷方式来编辑/导航当前命令行。

例如,在vi模式下,您可以执行以下操作(在bash中):

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

在Emacs模式下,你可以打如Ctrl+ A在行开始跳(VI:Ctrl+ [0ESC0)。您可以通过set -o emacs(在bash,ksh,zsh等中)打开emacs模式。

Readline

许多交互式命令行程序(包括bash)都使用readline库。因此,您可以在一处配置要使用的输入模式(vi或emacs)和其他选项,以使使用readline的每个程序都具有完全相同的编辑/导航界面。

例如,我的readline配置如下:

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

例如,据我所知,zsh / ksh不使用readline,但还支持非常类似于bash / readline一种的vi / emacs模式。

当然,命令行外壳程序中的vi / emacs模式只是完整编辑器功能集的一部分。并非所有功能都在命令行Shell中有意义,并且某些功能的支持比其他功能更复杂。

规范模式

在“发明”交互式命令行外壳的vi / emacs模式之前,您的外壳将仅使用终端的规范模式,该模式仅提供有限的一组编辑命令(例如Ctrl+ W删除最后一个单词)。


假设我不知道我处于哪种输入模式。我可以通过输入一些文字并按[Ctrl] + [A]来进行验证吗?如果光标移至其emacs开头,则其他vi?
limovala

2
@limovala,应该是一个很好的近似值。当然取决于您的外壳-如果CTL + A不起作用,另一种可能性是您的外壳不包含任何编辑模式。也许某些外壳还实现了其他编辑模式。但实际上,您的方法应该足够好。您还可以在此之后使用vi命令进行测试,以更加确定。在bash中,您也可以使用set -o | grep 'emacs\|vi'。在zsh(我有vi模式)下,这不起作用。
maxschlepzig

绑定-P还将很好地表明一个模式处于哪种状态
Paul

23

您会注意到,当您cat在终端上的shell提示符下运行时,cat应该将其从stdin中读取的内容写到stdout,然后按a,您会看到a终端驱动程序回显的内容,但cat没有写回去a(您看到了仅一个a,由终端驱动程序回显的一个)。

但是,如果键入a Backspace b Enter,则看不到cat输出a\010b\015,而是b\012b和换行符)。

这是因为在规范模式下,终端驱动程序(我们说的是内核中的软件,而不是终端仿真器中的软件xterm)实现了非常基本的行编辑器。可以像使用命令一样使用系统调用来配置终端驱动程序。例如,要退出规范模式,您可以这样做。如果您这样做:ioctl()sttystty -icanon

stty -icanon; cat

然后,您将同时看到echo(您可能已通过禁用了stty -echo)和cat输出。

该编辑器是行编辑器。也就是说,用户可以编辑一行文本,直到将其发送到按终端设备读取终端设备的应用程序为止Enter

该编辑的编辑功能非常有限。在大多数实现中,只有4个编辑键(实际上是字符)也可以使用stty以下命令配置:

  • 擦除(^H^?通常):擦除前一个字符
  • 杀死(^U通常):清空(杀死)到目前为止输入的行
  • werase(^W):删除前一个单词
  • lnext(^V):直接输入下一个字符(取消上述所有字符的特殊含义)

在过去,人们认为终端驱动程序行编辑器将以更高级的功能进行扩展。这就是为什么早期的Shell都没有命令行编辑功能的原因(您在shell提示符下获得的命令行编辑功能与cat上面的运行方式一样)。

但是,这实际上从未发生过,也许部分原因是由于不同终端的混乱导致在某些按键上没有发送相同的字符,这显然不应该在内核空间中实现。

因此,一些外壳程序开始删除终端驱动程序的规范模式,并实现自己的行编辑器。当时,emacsvi是最流行的视觉文本编辑器,具有完全不同的键绑定和操作模式。在中vi,您有一种输入文本的模式,以及一种用于编辑的模式。在中emacs,您始终处于文本模式,但是可以通过按组合键来完成编辑(例如^b向后移动字符)。

当时壳没有必要提出自己不同的键绑定。那将使人们不得不学习另一种方法而感到沮丧。但是,选择一种(emacs或一种vi)样式而不是另一种将是疏远另一种编辑器的用户的肯定方法。

根据https://www.usenix.org/legacy/publications/library/proceedings/vhll/full_papers/korn.ksh.a

ksh流行的内联编辑功能(vi和emacs模式)是由Bell Laboratories的软件开发人员创建的。Pat Sullivan的vi行编辑模式,Mike Veach的emacs行编辑模式。每个人都独立地修改了Bourne shell来添加这些功能,并且两个人都希望在ksh拥有各自的内联编辑器的情况下使用ksh。最初,拒绝将命令行编辑添加到ksh的想法是希望将命令行编辑转移到终端驱动程序中。但是,当很明显这不太可能很快发生时,这两种行编辑模式都集成到了ksh中,并成为可选的,因此可以在将编辑作为终端界面的一部分的系统上将其禁用。

因此,他们实现了两者和一个界面,供用户在两者之间进行选择。ksh最有可能是80年代初期的第一次(重复使用分别编写的代码以在Bourne shell中添加vi模式和emacs模式,如上所示),其次tcshtcsh最初仅具有emacs键绑定,vi后来添加了mode)和后来bashzsh在90年代初。

您可以在两种模式之间进行切换bashzshkshset -o viset -o emacs,与bindkey -ebindkey -vtcshzsh

POSIX实际上指定vi模式,而不是emacs模式sh(这个故事有理查德·斯托曼反对POSIX指定emacs模式sh)。

为默认模式bash,公共领域的变种ksh(pdksh程序,mksh,oksh),tcsh并且zsh是emacs模式(虽然zsh,这是vi如果你的$EDITORIS vi),而在AT&T ksh,这是愚蠢的模式,除非$EDITOR$VISUAL提及viemacs

ksh后来还增加了一种gmacs模式,以适应不同emacs处理方式的高斯林用户Ctrl+T

现在的处理^Wemacstcshemacs模式可能早于werase在终端行编辑字符,所以我们真的不能责怪他们是和我有关声明“出发......”可以被看作是误导。只是当我输入类似内容时emacstcshinfo与您输入的其他内容行为不同时,我会感到恼火Ctrl-W。您可以想像,当您键入某些应用程序开始关闭其窗口时,我会感到更加烦恼 Ctrl-W


1
pdksh还解析$EDITORvi与开关在启动模式; 我删除了它mksh(特别是因为我仍然只真正维护了Emacs模式)。
mirabilos 2014年

非常感谢您,尤其是在详细讨论各种shell的行为和历史时。作为经常需要使用我没有配置的shell在不同发行版中工作的人,这特别有用。
BryKKan

感谢您的出色历史背景。遗憾的是,当时没有将更复杂的嵌入式编辑功能添加到终端驱动程序中。程序无需包含诸如Readline之类的库。我还想知道为什么POSIX未指定Emacs-mode,所以链接到Rationale的方法很有趣。(我也与^W关闭窗口分享您的无奈)。
安东尼G-莫妮卡的正义

1
@AnthonyGeoghegan,我们仍然需要zle / readline之类的东西,因为诸如文件名/命令完成之类的事情实际上无法在终端驱动程序中完成。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.