VIM之魅

转载自:http://www.20ju.com/content/V190812.htm

Vim的方法

若是说 Vim的理念是“减”字诀,那么实现这些理念的方法即是“增”字诀: 增长模式种类、增长移动方式、增长操做对象、增长操做方式、增长定制方式。

1. 增长模式种类

前文提到引入 普通模式的重要意义,但 Vim并未就此止步,还提供了另外四种基本模式: 选择模式(select mode)、可视化模式、命令行模式和ex模式。
选择模式与可视化模式的目的均是选择文本以备后续操做。前者相似Windows下的选择模式, 在方便程度与威力上远不及后者,故略去不谈。
普通模式下,按下  v 、  V 、  Ctrl-V 将分别开启以字符、行或块为单位 的可视化模式,此后用户能够经过屡次使用 Vim的移动命令来选定所需文本。 例如,在 普通模式下输入  v/the 并回车后,从光标初始处到此后最近的  the以前都将被高亮。如发现并不是所求,继续按  n 将使选择区域扩大到下一处 的  the 以前,之后还可屡次用  j 或  k来延伸或压缩所选区域的行,或者 反复用  h 或  l 进行左右微调,用  w 或  b 来增减被选单词, 用  f 或  t 肯定字符,等等。 相比直接经过正常模式操做,可视化模式容许用户在对文本片断进行编辑 以前加以检视、调整和确认,于是更加直观、准确和安全,而且让所选文本成为 批处理的总体对象,增长了编辑效率,同时减小了操做的碎片化。 与用鼠标相比,如果操做短文本或规律明显的文本,速度多不及 普通模式下的操做; 如果操做文本较长且不太规律的文本,则每每不及可视化模式下的操做。 好比,要选中从当前行到倒数第二行的文本,若中间相距较远,用鼠标定然慢而不便。 性急如我者,一不留神就可能把鼠标拖出桌面以外。 使用可视化模式则异常轻松:  VGk ,完毕。
可视化模式不只支持行操做,还支持列操做,这也是比 普通模式更便利之处。 好比要交换文件中头两列的字符, 可键入  gg<Ctrl-V>Gdp 。
命令行模式与ex模式都可执行ex命令,只是后者在执行后不像前者那样 返回正常模式。 普通命令虽然丰富,但远远谈不上完备。好比,没法同时编辑多处文本片断, 没法在不离开当前编辑窗口的条件下操做其余文件,没法获取其余文件中的内容, 没法读取环境变量,没法执行外部命令,等等。 有了ex命令, Vim的潜能开始无限释放,一方面充分地利用了外部资源, 另外一方面大大减小了用户离开 Vim的几率,从而提升编辑效率。
ex命令源自Unix下的行编辑器(line editor)  ex , Vim将其扩充为  Vimscript语言,成为第三方开发插件的主要工具(也可用Perl、Python、Ruby等语言)。 因为在ex模式下可经过  :normal 执行 普通模式下的命令,故而实际上彻底涵盖了 后者。只是执行ex命令时前面须要冒号,后面须要回车,效率上有所不及。 根据我的须要,用户可自定义ex命令,也可把经常使用的ex命令经过  nmap 、  vmap 、  imap 等映射为其余模式下的命令,以期最大限度地减小键击次数。
命令行模式除用  : 开启以执行ex命令外,还可用  / 或  ? 来启动正向 或反向的模式搜索,可用  ! 进行文本过滤(filter) (即:将所选文本输入给外部程序,并替之以输出结果),大大加强了 Vim的 移动和编辑效率。
此外,在基本模式的基础上,还有六种衍生模式,暂略不提。 从以上能够看出,多种模式的并存令 Vim鱼与熊掌兼得——功能上强大而灵活, 使用上便利而快捷。

2. 增长移动方式

真正让 Vim有飞通常感受的是其快速多变的移动能力。可谓上天入地,无所不至,无至不速。 上文提到HJKL代替方向键的意义,但那只能让光标偏移最小单位,并不适宜频繁地单独使用。 不然,那便不是飞行,而是爬行。因为 Vim提供的移动命令过多,不免使人眼花缭乱, 为便于说明,特作以下分类,并列举一些典型但远非完备的实例。

行间移动:

行间移动是一种常见的需求, Vim提供了绝对行数和相对行数两种跳转方式。 这里有一个小窍门,为了便于肯定移动行数,可经过  :set number 显示绝对行号, 或  :set relativenumber 显示相对行号。建议定制一个功能键(如F6), 让行号随时能够在相对、绝对和隐藏之间循环切换。平时默认为相对行号或许更高效些, 一是相对行号比绝对行号小,一般键入更快;二是相对移动的  j 、  k 命令比绝对移动的  G 命令少用一个shift键。
H            ——移至屏首
L            ——移至屏末
M            ——移至屏中
5H           ——移至屏首起第5行
5L           ——移至屏末起倒数第5行
gg           ——移至页首
G            ——移至页末
50%          ——移至页中
20G          ——移至页首起第20行
20j          ——下移20行
20k          ——上移20行
5gj          ——下移5个显示行(与文件行不一样,显示行考虑折行)
5gk          ——上移5个显示行(同上注)

列间移动:

做为一种近距离微调,列间移动很是实用。除了跳至行首或行末之外,最有用的即是  f/F/t/T/;/, 系列命令了。惋惜中文是多字节的,没法享用此功能。
0            ——移至行首
$            ——移至行末
^            ——移至软行首(即忽略首空白)
g_           ——移至软行末(即忽略尾空白)
g0           ——移至屏幕行首(考虑折行)
gm           ——移至屏幕行中(同上注)
g$           ——移至屏幕行末(同上注)
20|          ——移至第20列
fx           ——移至本行下一个字符“x”处
Fx           ——移至本行上一个字符“x”处
tx           ——移至本行下一个字符“x”前
Tx           ——移至本行上一个字符“x”后
;            ——重复上次 f/F/t/T 命令
,            ——反向重复上次 f/F/t/T 命令

结构移动:

在用户眼中,文本不是单纯的字符集合,不只具备行列差异,更有结构差异。 常见的结构划分有:单词(word),句子(sentence),段落(paragraph) 和区块(section)等。 除了系统的默认设定外, Vim还容许用户自定义结构的界定方式。 有些遗憾的是,因为中文词与词之间没有分界,没法利用单词的跳转功能。
w            ——右移至最近词首
W            ——同上,但忽略非空白单词分隔符
b            ——左移至最近词首
B            ——同上,但忽略非空白单词分隔符
e            ——右移至最近词尾
E            ——同上,但忽略非空白单词分隔符
ge           ——左移至最近词尾
gE           ——同上,但忽略非空白单词分隔符
(            ——前移至最近句首
)            ——后移至最近句首
{            ——前移至最近段首
}            ——后移至最近段首
除基本的文本结构外,程序员还对语法结构感兴趣。  % 是一个方便的命令,它能让光标在匹配项之间来回游走。 除了  ( 与  ) 、  [ 与  ] 、  { 与  } 的括号匹配外, 还支持C风格的注释(  /* 与  */ )与宏(  #if 、  #ifdef 、 #else 、  #elif 、  #endif 等)匹配。  Vim更提供了matchit的插件(但并未默认安装),支持其余编程语言的匹配结构。 若仍嫌不满,用户也可自定义其余的匹配方式。 下面的命令是给程序员额外的福利——
[[           ——前移至最近区首(经常使用于跳至C类型的函数头)
]]           ——后移至最近区首(同上注)
[{           ——前移至最近代码区的首部(C类型语法)
]}           ——后移至最近代码区的尾部(同上注)
[m           ——前移至最近方法的首部(Java类型语法)
]m           ——后移至最近方法的首部(同上注)
[M           ——前移至最近方法的尾部(同上注)
]M           ——后移至最近方法的尾部(同上注)
gd           ——跳至当前变量的局部声明处
gD           ——跳至当前变量的全局声明处
Vim具备折叠功能,故而支持折叠结构的跳转。
[z           ——移至当前展开的折叠区的首部
]z           ——移至当前展开的折叠区的尾部
zj           ——移至下一折叠区的首部
zk           ——移至上一折叠区的尾部

屏幕移动:

在浏览文件时,用户每每更但愿调整的是屏幕而不是光标。
Ctrl+F       ——向下滚动一屏
Ctrl+B       ——向上滚动一屏
Ctrl+D       ——向下滚动一个单位(默认半屏)
Ctrl+U       ——向上滚动一个单位(默认半屏)
Ctrl+E       ——向下滚动一行
Ctrl+Y       ——向上滚动一行
zl           ——向右滚动一列(仅在禁用折行时有效)
zh           ——向左滚动一列(同上注)
zt           ——置当前行于屏首
zt           ——置当前行于屏末
zz           ——置当前行于屏中
10z.         ——置第10行于屏中
50z-         ——置第50行于屏末
鉴于滚屏操做十分经常使用而Ctrl键不便,建议用  nmap 将^f/^b/^d/^u/^e/^y 分别替换为空格键、Shift+空格键、Enter键、Backspace键、下方向键、上方向键。

搜索移动:

几乎全部的编辑器都有搜索功能,但不多有 Vim这般强大和方便。 强大致如今它不只支持最基本的正则表达式,还支持懒惰模式 (  lazy mode ), 甚至能够  跨行 匹配。方便则体如今搜索过程对用户友好,没有讨厌的弹出窗口, 支持高亮匹配,支持增量搜索(光标在关键词输入过程当中即开始运动,没必要等待回车键), 支持智能大小写判断,一键重复正向或反向搜索,等等。另外,特别推荐四个诱人的命令:
*            ——正向搜索光标所在的单词(精确匹配)
#            ——反向搜索光标所在的单词(精确匹配)
g*           ——正向搜索光标所在的单词(模糊匹配)
g#           ——反向搜索光标所在的单词(模糊匹配)
若是要在多个文件中搜索,能够用内部命令  vimgrep 或外部命令  grep 。 前者在正则表达式上更强大,也更通用(Windows下没有自带的grep),但速度不及后者。 我我的的选择是在配置中加上一行:  set grepprg=ack\ -a,以便让更好用的  ack 来取代grep。

定点移动

定点移动是 Vim又一特点,迅速而精确的远程移动让浏览和编辑变得史无前例的轻松。
Vim的标记(mark)至关于一种书签,用来记录用户关注的热点位置。 假设用户对当前光标所处位置感兴趣,可输入命令  mx (x能够是任何字母)。 之后只要输入  `x 便可 返回原标记处,或用  ‘x  返回原标记处所在的行首。 用做标记的字母有大小写之别。小写为局部标记,用于缓冲区内部跳转, 仅对当前编辑的文件有效,且在缓冲区关闭后失效。 大写为全局标记,可在不一样的文件之间跳转,不因缓冲区关闭而失效(需设定  viminfo )。
比用户标记更有用的是系统标记。 Vim贴心地在一些热点上留下暗记,以便用户回访。 例如,用户每次退出 Vim时的光标位置都会被保留,最近十个分别用数字0到9来命名。 下面是其余一些实用的标记跳转:
``           ——跳转至当前缓冲区最近跳转点(可实现两点之间的来回跳转)
''           ——同上,但仅精确到行
`.           ——跳转至当前缓冲区最近修改处
`[           ——跳转至上次改动或拷贝处的首部
`]           ——跳转至上次改动或拷贝处的尾部
`<           ——跳转至最近可视化选择区的首部
`>           ——跳转至最近可视化选择区的尾部
`"           ——跳转至上次退出当前缓冲区时光标的最后位置(在普通模式下)
`^           ——跳转至上次退出当前缓冲区时光标的最后位置(在插入模式下)
全部标记都可经过命令  :marks 来显示,以供查询。要得到更好的视觉效果, 不妨试试  ShowMarks 插件,它利用 Vim的sign功能将隐性标记显性化了。
除了标记列表外, Vim还维护了一张变化列表。 该表记录了用户每次修改文本的位置,运行命令  :changes 便可察看。 相应的跳转命令是:
g;           ——跳转至变化列表中的较旧处(支持数字前缀)
g,           ——跳转至变化列表中的较新处(支持数字前缀)
程序员在浏览代码时常常须要在不一样的源文件中跳转(好比察看某个函数的定义),  Vim为此提供了标签(tag)支持。 与标记不一样,标签须要依赖外部工具如  ctags 、  cscope 等来产生。 使用命令  :tag <tagname> 可实现标签跳转,不过更简便的仍是将光标置于 关键词之上,而后经过  Ctrl-] 转至其定义处,必要时可用  Ctrl-T  返回。 用鼠标亦可完成以上任务,但并不推荐。
最后,上述各类移动命令所产生的跳跃点均保存于跳转列表中(最多不超过100个), 可经过命令  :jumps 检视。这意味着用户能够在原来的轨迹上来回跃迁——
Ctrl-O       ——跳转至跳转列表中的较旧处(支持数字前缀)
Tab或Ctrl-I  ——跳转至跳转列表中的较新处(支持数字前缀)

其余移动

还有一些其余类型的移动,试列举一二:
gf           ——跳转至光标之上或以后的路径所对应的文件
gF           ——同上,但跳至文件后所指定的行数
]s           ——跳转至下个错误拼写处
[s           ——跳转至上个错误拼写处

3. 增长操做对象

Vim丰 富的移动方式让用户以最小的代价——包括手指、目光、时间和精力——把所感兴趣的 文本带入视线范围并将光标精肯定位。 这只是编辑的第一步,下一步是在当前位置进行文本操做。 通常编辑器修改文本多经过Backspace键、Delete键、方向键并结合鼠标完成,效率低下。 究其缘由,主要在于操做对象太过单一:要么是以字符为单位,粒度过小; 要么以高亮区域为单位,选定太慢。  Vim则不一样,提供了各类粒度的操做对象,供用户在不一样需求下选择,大大提升了编辑效率。
Vim的 编辑命令具备统一的形式:数字 + 操做符(operator) + 文本对象, 表示对某一文本对象进行指定次数的操做。其中,数字部分为可选项,默认为1; 有些操做符后不接对象,正如不及物动词后不接宾语。 一切彷佛都平淡无奇,直到文本对象与移动命令天然而奇妙地结合在一块儿,瞬时光芒四射。 具体地说,文本对象可由移动命令所扫过的字符片断来定义。 因而,有多少移动方式,便对应多少文本对象。 这已是咱们第二次看到移动命令的重用(reuse)了(前一次用于可视化模式下)。
举例来讲,操做符  d 表示删除,移动命令  w 表示前进到下一单词,则  dw 将删除从当前光标至下一单词以前的全部字符。 假设当前光标处于某单词的首部,  2dw 将删除该单词及其后一单词。 若是知道移动命令自己也可加数字前缀,则  2d3w 将删除6个单词,与  3d2w 、  6dw 、  d6w 的效果相同。 相似地,操做还能够句子、段落、语法结构为单位, 以行或列为单位,以屏幕为单位,以匹配模式为单位,或以定点为界限,等等。
进一步地, Vim在Vi的基础上新增了其余的文本对象,用于可视化模式下的选择 和 普通模式下的编辑。兹列几项以下——
aw           ——一个单词(支持数字前缀)
is           ——一个句子内部(支持数字前缀)
ap           ——一个段落(支持数字前缀)
a"           ——一个双引号区域
i}或i{或iB   ——一个“{}”块内部(支持数字前缀)
a>或a<       ——一个“<>”块(支持数字前缀)
at           ——一个标签块(支持数字前缀)
不妨看一个典型用例。假设有一段文字:
String name = "Shen Xin";
用户但愿将  Shen Xin 换成  Zhang Ming ,此时光标位于该行的头部。 Vi(不是 Vim)的常见作法是:  f" 到达第一个引号,  l 右移一个字符, 而后  ct" 清空人名并进入插入模式。 而在 Vim下,只要键入  ci" 便可达到一样效果,节省了一半键击。
再看一个HTML片断:
<tr>
    <td>
        ...
    </td>
    <td>
        ...
    </td>
    .
    .
    .
    <td>
        ...
    </td>
</tr>
假定光标位于某个  td 标签内部,要拷贝整个HTML行(即  tr 标签块),Vi的一种作法是:  ?<tr 并回车到达行首,  y 开启拷贝操做,  /\/tr>/e 指定行尾,再回车完成任务,共需十屡次 按键。 利用行数或段落移动可能会省一些键,但都不如 Vim来得惬意:  y2at 。
还不止于此, Vim甚至容许用户自定义文本对象。好比设置一个操做符待定模式 (opeator-pending mode, Vim的六种衍生模式之一)下的映射:  omap af :normal [[v%<CR> (af意指“a function”) ,便创建了一个C语言风格 的函数对象。若以为晦涩,不妨回顾一下,  :normal 表示执行 普通模式命令,  [[ 跳至函数头部的  { 处,  v开启可视化模式,  % 表示选择区的 末端为与  { 匹配的  } ,由此定义了一块函数区域,用  af 来命名。 一样地,用户可按缩进、折叠、语法或其余区域划分方式来定义文本对象。
除文本对象外,用鼠标或键盘产生的选择区域、用折叠命令隐藏的文本片断等皆可 做为总体的操做对象。
在命令行模式下,还可按行数范围或模式匹配来指定操做对象。 好比,  %s/x/y 将全部行(  % )中的第一个  x 换成  y ,  /第一章/+1,/第二章/-1d 将删除光标后“第一章”与“第二章”之间的全部文字,  .-5,.+5w a.txt 把以光标为中心的11行文字保存到名为  a.txt 的文件中。
经过增长文本对象, Vim使文本操做的粒度更加多样化,从而提升了批量处理的几率。 同时,因为文本对象更趋结构化与语义化,让思惟与文字之间的转换更加流畅天然, 从而减小了编辑失误的几率。

4. 增长操做方式

当用户把光标移至合适的位置,并选定合适的操做对象之后,剩下的就是执行具体操做了。

新增文本

最经常使用的操做是增长新文本。Vi在 普通模式下用  a 、  A 、  i 、  I 、  o 或  O 切换到插入模式。 Vim新增了  gI ,与  I 的区别是,它保证将 光标置于首列。此外 Vim还增长了  gi ,便于从上回退出缓冲区的插入点继续工做。 一个貌似简单的插入操做便有这么多的花样,目的很明确,那就是尽可能减小键击次数。 另外,恐怕不多人意识到以上命令均支持数字前缀。如在 普通模式下输入  100a , 而后插入一些文字,当用户再次回到 普通模式下时,方才输入的文字将自动重复一百次。 从这里再次印证两件事:一是 Vim为减小 按键可谓处心积虑——原本复制操做就支持数字前缀, 但仍为插入操做加此功能;二是插入模式的确被视为暂态,随时等待退出。
通常不建议在插入模式下使用命令,但  Ctrl-Y 与  Ctrl-E 有时仍是有用的。 它们分别在插入模式下重复光标上行或下行对应列的字符。 这么作并不省手,但省眼省心,符合 Vim的理念。
插入模式下另外一对命令  Ctrl-P 与  Ctrl-N 可实现文本的自动补全, 以  Ctrl-X 开启的子模式可产生更具体的完成提示,如后接  Ctrl-F 指 文件名匹配, 后接  Ctrl-K 指字典匹配,后接  Ctrl-S 指拼写建议, 后接  Ctrl-O指万能补全(omnicompletion)等。 不过经设置或安装插件,可尽可能经过Tab键或Shift-Tab来完成, 如此更符合减小手指移动的原则。
插入模式下的  Ctrl-R 能输入与寄存器(稍后将会介绍)相关的内容, 好比  Ctrl-R " 将输入最近一次的内部拷贝(即无名寄存器中的内容),  Ctrl-R + 将输入最近一次的外部拷贝(即系统剪贴板),  Ctrl-R . 将输入最近一次的插入文本,等等。 更特别地,  Ctrl-R = 后将输入表达式。例如  Ctrl-R =12*50将打出  600 ,至关于一个小计算器。

删除文本

与插入操做相对的是删除操做。最普通也是最低效的方式是在插入模式下使用删除键。 使用  x 或  X 一样可删除字符,但不需退出 普通模式,还支持数字前缀。  d 命令既可前接可视化区域,又可后接文本对象,是万能的删除方式。 做为频繁使用的行删除命令,  dd 被设计为叠字无疑是明智的,而用  D 命令 代替另外一经常使用的  d$ 也是省键之举。 除此以外,如前例所示,命令行下也能完成删除操做。

替换文本

替换操做的方式更加多样。最简单的是以字符为单位的  r (在可视化模式下也可批量替换), 如需连续替换可用  R进入替换模式,如需删除若干字符后进入插入模式,可用  s 。 与负责删除操做的  d 命令相对应的是负责改动操做的  c 命令:  {可视化模式}c 、  c + 文本对象 、  cc 与  C 。
文本编辑常常涉及大小写变换, Vim对此固然不会视而不见。  ~ 是大小写转换符,可将若干字符的大小写对换。如 6~ 做用于  aBcDeF 的结果是:  AbCdEf 。  g~ 更强大,后可接文本对象。因而前面的命令可用  g~e 代替,虽然多敲一字符,却没必要数字符,以手动换心动,效率只高不低。 利用可视化模式  ve~ 也可完成任务,但产生了可视化区域的反作用。 不出意料地,  g~~ 将当前行全部字母进行大小写转换。 若是但愿将目标字符固定为大写或小写,则用  gU 或  gu 命令。 相似地,  gUU 将当前行全部字母变成大写,  guu 将当前行全部字母变成小写。
对文本进行格式上的调整也是一项常规需求。  Vim提供了  J 与  gJ ,能将多行文字并为一行,极为实用。  < 、  >分别将文本左移或右移一个缩进单位 (在插入模式下用  Ctrl-T 或  Ctrl-D )。  = 命令能自动调节缩进,  gq 命令能格式化选定的文本。 按惯例,以上命令在应用于行时,均采用叠字:  << 、  >> 、  == 、  gqq 。 若需左、中、右对齐,则分别使用  :left 、  :center 、  :right 。
Ctrl-A 、  Ctrl-X 是一对不为人知但却很是有用的命令, 它们能分别 对光标之上或以后的数字进行增减运算,而且不只支持十进制,还默认支持八进制和十六进制。 假设光标后有一个字串  0x2a ,输入  2<Ctrl-X> 后它将变成 0x28 , 且光标也移至  8 处。适当设置后,此二命令甚至能对单字母进行增减。
在命令行模式下可执行更复杂的替换操做。 命令  :s 可充分利用正则表达式的威力进行文本替换, 若要重复上次替换,只需键入  & , 若要对全部行重复上次替换,只需键入  g& 。 前面还提到,经过  ! 能调用外部程序进行过滤操做。 好比  !apsort 将当前段落( 即  ap 对象)中的全部行按字母进行排序 (即  sort )。 因为过滤程序绝不受限,这便意味着用户能为所欲为地对文本进行任何替换。

复制、移动与粘贴

对于编辑器都支持的复制、移动、粘贴等功能, Vim也是花样百出。 通常编辑器的剪贴板只保存用户显式剪切或拷贝的文字,而 Vim把任何被改动、删除或 拷贝(yank)的文字都存于至关于剪贴板的寄存器中。 利用此特色,组合命令  xp 轻易实现了两个相邻字符的交换, 不只比输入模式下少一次 按键,并且手指不会因方向键而离开主键区。
更美好的是,用户可指定具体的寄存器。好比  "a5dd 将删除的5行存于名为  a 的寄存器中,之后可用  "ap 粘贴到其余地方。 指定寄存器虽增长了 按键次数,但也保证了重要的文本不被轻易覆盖。 另外一有趣的用法是,以大写字母命名的寄存器会将新内容追加(而不是覆盖)到 对应小写字母的寄存器中。好比继刚才的操做以后,用户在某处敲入  "A2yy , 则此时寄存器中将有7行文字。
Vim的寄存器不只不止一个,并且不止一种。 例如,最近的修改、删除或拷贝的文本存在  无名寄存器 (说是无名,实则有名:  " )中, 最近拷贝的存在  数字寄存器  0 中, 最近修改或删除的存在寄存器  1 至  9 中。 对于少于一行的删除(如  dw )还专门有个名为  - 的  微删除寄存器 。 若是不但愿改变寄存器内容,可以使用名为  _ 的  黑洞寄存器 。 为便于与 Vim的外部环境交流,  系统寄存器  * 与  + 对应系统剪贴板,寄存器  ~ 保存最近一次从外部程序(如Word)拖放(Drag-and-Drop)过来的文本。 此外,还有  只读寄存器  % 、  # 、  . 和  : , 以及记录最近搜索模式名为  / 的寄存器。 依然是惯例,  :registers 列出重要寄存器的名字及内容。
最后,若是用户不肯意移动光标或屏幕,也可在命令行模式下完成复制、移动与粘贴的任务。

重复

Vim让人以为重复再也不是一件使人乏味的事,有时甚至是一种享受。
命令  . 重复上次的变化,但不包括命令行命令。 若要重复上次的命令行命令,可用  @: 。 如同在unix shell中同样,在命令行模式下用  !! 重复上次的shell命令。 若要在必定范围内重复屡次命令,可用  范围:g/模式/Ex命令或  范围:g/模式/normal 普通命令 , 即在指定范围内对匹配某一模式的行重复执行给定的命令。 将其中的  g 换成  g! 或  v 则将命令做用于非匹配行。
复杂的重复可以使用 Vim的宏(macro)。好比用  qq 将记录接下来的 按键,用  q 结束。 之后可用  @q 重放,再后来可用  @@ 重放。 与简单的拷贝不一样,宏不只能复制插入模式下的 按键,还能记录 普通模式下的 按键。 举个稍微复杂的例子,假设光标所在行的文字是  (1) , 在 普通模式下依次键入  qqYp<Ctrl-A>q8@q ,便能产生从一到十的编号列表 (提示:  Y 表示行复制,  p 表示粘贴,  Ctrl-A 是前述的数字增长命令)。
即便更复杂的重复在 Vim下也是可能的,命令  :source 或  :runtime 可调用  Vimscript脚本,不过那主要是程序员们大展身手的地方了。

撤销与恢复

在撤销与恢复的操做方面, Vim再度显示其独到之处。
首先,在基本的撤销命令  u 与 恢复命令  Ctrl-R 以外,还有 行撤销命令  U ,即撤销对某行最近进行的全部修改。 其次,以上命令与其余普通命令同样,也支持数字前缀,便可一次性执行屡次 撤销或恢复。 更有特点的是, Vim的 撤销与恢复状态不是堆栈(stack)结构,而是树(tree)结构。 通俗地举例来讲,在通常编辑器中,若是在做出某种修改后发布撤销命令, 而后再做另外一种修改,再撤销。此时用户若执行恢复命令,将恢复第二次修改的内容, 而第一次修改的痕迹彻底被抹去。一旦用户意识到操做错误,极可能会后悔不迭。 为避免此类事件发生, Vim提供了撤销列表,保留了各个时刻的文本状态,用户随时 可经过命令  g- 和  g+ 来先后遍历,也可用命令 :earlier 或  :later 根据修改时间的范围来恢复状态,还可用命令  :undo 跳到状态树的某个分支 (此后再用  u与  Ctrl-R 先后遍历)。在此推荐插件 Gundo,它不只清晰地展现了撤销与恢复的树形结构,实现快速恢复,还能预览各个修改版本之间的差异。
通常编辑器在文件关闭后没法撤销或恢复上次的修改, Vim则否则。 用户只要略加设置,便能实现文件修改状态的持久化。

文件操做

Vim提升文件操做效率的关键在一个字——   ,即多分区、多缓冲区(buffer)、 多窗口、多标签页、多文件浏览、多文件读写与多类型文件处理。
多分区指经过文本折叠将一个文件分为多个折叠区,让文件的结构层次更加清晰, 而且减小了因文件过长而带来的频繁的手指移动和目光移动。  Vim中以  z 开头的折叠命令超过20个,足见其丰。
多缓冲区(buffer)指在一个窗口内可同时编辑多个文件。 缓冲区之间的切换方式不少,如用  :bn 或  :bp 进行缓冲区翻页, 用  Ctrl-^ 在两个缓冲区之间来回切换,用  :e #N 按缓冲区编号编辑, 用  :b 文件名 按缓冲区的文件名选择编辑对象 (文件名支持自动完成,且没必要输全,如  :b R 可转至文件README.txt)。 若是同时载入缓冲区的文件过多,还有大量优秀的管理缓冲区的插件可资利用, 好比  command-tFuzzyFinderbufexplorer等。
要想充分利用屏幕资源,减小缓冲区切换的代价,或但愿在多个文件之间进行对比编辑, 可利用 Vim的多窗口功能。 Vim可对窗口进行横向和纵向屡次切分, 还能调整窗口的大小、位置、焦点等。
当多缓冲区、多窗口仍不知足需求时,可开启多标签窗口(tabbed window), 以提升对多文件的处理能力。
大多用户习惯用文件浏览器来选择或管理文件,幸亏在 Vim中可不假他求,其内置的 netrw插件便具有此功能。不过,非内置的  NERD tree 插件 彷佛更受欢迎。
读取和写入文件是编辑器最基本的功能。 Vim的特色是能在不离开当前缓冲区的条件下, 读取其余文件的内容,或把缓冲区中的部分文本写入其余文件中。 如  :35r infile 将名为  infile 的文件内容插入到当前文件的第35行下, 1,7w outfile 把当前文件的头7行保存到名为  outfile 的文件中。
最后,为减小用户离开的机会, Vim能透明读写多种类型的远程文件、压缩文件和加密文件。 若是利用插件或其余第三方工具,还可对更多类型的文件进行读写操做。

自动操做

贴心的编辑器应当尽量地减小用户没必要要的操做。  Vim可根据用户设置,完成自动换行,自动缩进,自动将Tab换成空格、自动折叠、 自动读取、自动保存等任务。 不过真正“懒惰”的 Vim用户是不会知足于此的,他们会“辛勤”地端起终极武器  autocmd 。
简单地说,  autocmd 是一种事件驱动式(event-driven)的命令, 能在某些用户感兴趣的事件发生之时自动执行预先指定的命令。例如,  autocmd BufLeave,FocusLost * wa 将在用户离开当前缓冲区时自动保存当前文件, autocmd BufNewFile *.html 0r template.html 将在用户编辑一个全新的HTML文件 时自动加载模版文件 template.html ,  autocmd BufReadPost *.doc %!antiword % 可在打开Word文档后利用  Antiword 将其转化为文本格式,等等。 考虑到适用于autocmd的事件多达近80种,涵盖了与编辑相关的各个阶段和行为,用户 足以借此打造一个高度自动化的编辑平台。

其余操做

Vim的操做方式还有许多,好比经过一系列的  z 命令操做拼写列表; 经过  :help 或  K 显示在线帮助;经过  :sh开启一个shell; 经过  :redir 将命令行或shell的执行结果导入文件、寄存器或变量; 用命令  :hardcopy 和 :TOhtml 将所选文字分别以PostScript和HTML的形式输出; 用命令  ga  g8 或  :list 显示非打印字符; 用命令  gCtrl-G 显示行、列、字符、词等统计数据,等等。 此外,用户还能计算表达式、显示各类变量、设置和状态,并能实时改变各类设置或状态, 包括文件类型、界面格式、键盘映射、高亮设置、配色方案(colorscheme),等等。
最后, Vim虽 不推荐用鼠标,但仍在Vi之上增长了鼠标操做,而且提供了菜单和工具条。 一方面,这下降了学习难度,对初学者显得更加友好。 另外一方面,毋庸讳言,鼠标也有优于键盘的时候。 例如,在双手离开主键区时,用鼠标定位视线所及的区域每每更快捷; 在浏览长文件时,用鼠标滑轮先后滚屏一般更轻松。

5. 增长定制方式

窥一斑而知全豹。上述简介虽远未穷尽 Vim的功能,但其丰富与强大已经是彰显无遗。 难能难得的是, Vim的灵活性与可扩展性并不所以而稍减,这让用户拥有足够的控制权。

启动定制

启动 Vim须要一系列步骤,每步皆可由用户定制。以从命令行启动为例, 可供选择程序的就有:vi、 vim、g vim、view、gview、r vim、rg vim、e vim、eview、  vimdiff、g vimdiff等。其中,以g打头的是图形(graphic)模式;以e打头的是简易 (easy)模式,即与其余编辑器同样,只有输入模式(除非按  Ctrl-L 进入 普通模式); 以r打头的是限制(restricted)模式,该模式下没法启动shell命令; 以view结尾的是只读(read-only)模式;以diff结尾的是比较模式。 每一个程序又可接不一样的参数,进一步控制 Vim的行为。
Vim最重要的配置是 vimrc文件,实为一些ex命令的集合,在 Vim初始化时自动执行。 图形模式下的 Vim还会追加执行g vimrc文件中的命令。除了缺省的 . vimrc(Windows下是_ vimrc)和.g vimrc(Windows下是_g vimrc)外, 用户也可经过命令行参数来指定其余文件,或用特殊文件名  NONE 跳过初始化。
此外,除非在命令行参数中指明禁用插件, Vim启动时还会在运行时路径(runtimepath) 下寻找并执行插件,包括plugin目录下的  全局插件 与ftplugin目录下的  文件类型插件 。 所谓插件,无非是一些可重用的能完成某种特定功能的 Vim脚本。 用户能够本身编写,也可利用他人的成果。  Vim的  官方网站 有近4千种插件供人下载, 极大地扩展了 Vim的现有功能。
正常状况下, Vim启动时还会执行 viminfo文件中的命令。该文件保留了之前命令行历史、 搜索字符串历史、 搜索与替换模式、寄存器内容、标记、缓冲区列表、全局变量等等, 使得一些重要编辑历史不因退出而消失。
viminfo储存的是一些全局信息,若是但愿保留某一窗口的设置,能够利用view文件; 若是但愿保留全部窗口的设置,能够利用session文件;若是但愿保留撤销与恢复信息, 能够利用undo文件。这些文件均为自动生成,但用户也可手工修改。 它们在 Vim下次启动之时将被加载,以恢复原先的窗口、 标签页、折叠区域、光标位置、 标记位置、跳转位置以及其余设置。 毫无疑问,这种持久化(persistence)有效地减小了因关闭 Vim而带来的重复操做。
Vim最重要的定制均应在启动以前完成,如下略加展开。

命令定制

Vim尽管提供了足够多的命令,依然给予用户充分的定制空间。
一种定制方式是:用户为原有的命令赋予新的行为。 好比,对于缩进命令  = 和格式化命令  gq ,用户可分别经过定义  equalprg 或  formatprg 调用指定的外部程序, 也可分别经过定义  indentexpr 或  formatexpr 调用自定义的表达式。
另外一种定制方式是:经过  nmap 、  vmap 、  omap 等命令创建各类模式下的键盘映射。 用户借此可自定义各类实用的组合命令,定义新的文本对象(见前例),也可改变原命令的定义。 只要用户愿意,他甚至能够将原有的命令集合改得体无完肤,重建一套大相径庭的命令体系。
最强大的定制方式,固然是利用 VimScript或其余脚本语言及外部程序来定义全新的命令, 这也是许多插件所作的工做。

编辑定制

Vim能 根据文件的后缀或内容自动识别上百种文件类型,并据此选用相应的预处理机制、 语法高亮机制、文本宽度、缩进风格、折叠方式等。 在此基础上,用户可新增或修改文件类型、语法结构、处理机制以及各类格式选项。 经过这类定制,为用户创造良好的编辑环境,有利于提升编辑效率。
针对不一样类型的文件结构,用户可进一步量身定制,以期最大限度地减小 按键。 好比对于冗余度较高的XML、HTML类型的文件,可经过安装插件  xmledit 、  ZenCoding 或  sparkup 来减轻编辑负担。
一个经常使用节省键击的方式是经过  iabbrev 来定制输入模式下的缩写。 要想实现更高级的相似TextMate的片断(snippet)功能,可安装插件  snipMate 。
自动补全(autocomplete)能大大提升输入的效率和准确度。  Vim根据用户对  complete 选项的设置, 从当前缓冲区、其余窗口缓冲区、加载缓冲区、 字典(dictionary)、词典(thesaurus)、包含文件(included files)、 标签文件等中选择,也可经过设置  omnifunc 调用万能补全函数。
另外,要避免文本的拼写错误,用户可设置语种及其相应的拼写文件。 同理,要避免代码的语法错误,用户也可经过定制或安装插件来完成。

其余定制

Vim提 供给用户的选择还有不少。好比,用户可打造彻底个性化的界面,包括鼠标、 菜单、 工具栏、光标、状态栏、标签页、滚动条、提示框(tooltip)、字体、配色方案,等等; 可定制折叠方式(foldmethod)、折叠级别(foldlevel)、折叠文本(foldtext)等; 可定制搜索是否高亮匹配、增量移动、大小写敏感、智能判断、循环扫描等; 可定制交换(swap)文件以及备份(backup)文件的保存路径、后缀名以及是否禁用; 可定制错误格式(errorformat)以利用QuickFix来调试程序; 可定制文件的编码、格式(dos、unix或mac)、加密方法(zip或blowfish); 可定制我的的帮助文件、笔记乃至知识管理系统;如此等等,恕难一一列举。

结语

本文不是对 Vim功能简单的堆砌和罗列——那只会让初学者更加望而却步—— 而是试图总结它的设计理念和实现方法,以此来讲明其“编辑器之神”之誉既非过词, 亦非幸致。与之相应地,Emacs有“神之编辑器”的称号。假若是真如此,那说明 人类用户仍是选择 Vim为好——他们不是神,没法变出第三只手去hold住修饰键 (此为戏言,还请Emacs的拥趸勿恼)。
或许有人认为编辑器效率对工做效率的影响十分有限,毕竟人们大部分时间是花在思考上, 而不是花在编辑上。但不要忘记,用户的大部分思考须要参考不一样的文件以及同一文件的不一样 片断,有时还须要对文本进行必要的调整或修改,若是编辑器不能给予用户 “移动如飞、改动如电”的能力,必然频繁消耗用户的目光、手指和注意力,最终下降工做效率。 换言之,“快”的意义毫不仅仅在于节省的那些浏览或修改的时间,更重要的是 节省思惟与文字之间的转换开销,让思考活动与编辑行为尽量地交融无碍。
有种说法是“程序高手都用 Vim”,还有种说法是“用 Vim的都是程序高手”。 说实话,程序高手与是否用 Vim并没有必然联系。但有一点能够确定,优秀的程序员总会不断 追求更加高效的工做方式,就像不断追求更加高效的代码同样。 不管是开源的 Vim、 Emacs、Eclipse或NetBeans,仍是闭源的Visual Studio、Xcode、 SlickEdit或TextMate,各有其长,关键在于使用者可否作到“运用之妙,存乎一心”。 话说回来,见到那些声称只用Notepad来写代码的“高手”,心头仍是难免为之一紧: 这是怎样的自虐啊。
惯用 Vim者会发现它有一个反作用:一旦换到其余编辑器下,就像一个习惯奔跑的人 不得不停下来踱步同样,那种感觉直可用“兔心龟步”来形容。 不过仅仅用“快”来形容 Vim仍是不够的,还得加上一个“柔”字,即它具备高度的灵活性和 可扩展性。绝不夸张地说,正是 Vim的高可定制化让其本来已极其巨大的威力变得几无极限。 假如用户艳羡其余编辑器中的某项功能,大可利用 Vim的柔性复制过来。
Vim丰富的命令与灵活的定制为熟手津津乐道,也让生手视为畏途。 实际上,正如此前所指出的那样, Vim的多模式特征让其命令更有意义也更易记忆。 下面以 普通模式下的命令为例(注意箭头后的首字母):
a(A) => Append                       b(B) => Backward word
c(C) => Change                       d(D) => Delete
e(E) => End of word                  f(F) => Find
g(G) => Go                           H    => Home of window
i(I) => Insert                       J    => Join
K    => Keyword under the cursor     L    => Last line of window
m    => Mark                         M    => Middle line of window
n(N) => Next find                    o(O) => Open a new line
p    => Paste                        r(R) => Replace
s(S) => Substitue                    t(T) => Till
u(U) => Undo                         v(V) => Visual mode
w(W) => Word move                    y(Y) => Yank
由上可见,除了代替方向键的  hjkl 四小写字母外,剩下只有三对字母  Q(q) 、  z(Z) 和  x(X) 了。这三个均属最难组词的字母, 其中  x(X) 表明删除或剪切,与之前打字机删除字符相同,形状上也像剪刀;  z 主要用于折叠命令,能够理解为  Z ip(拉链),形状上也具折叠态。 其余如  | 表明列、  > 表明缩进、  ( 表明句首,  { 表明段首等 皆极具象征意义。至于命令行模式下的就更不用说,大多都是单词或词组的简写。
除了富有涵义的单词和隐喻以外, Vim的命令和选项的设计还到处透着一致性, 进一步减小了记忆的负担。事实上,这也是 Vim的  宗旨 之一。 好比,移动命令与文本对象相一致;相同字母的大小写 命令之间一般是对应的,且小写的更经常使用;相同首字母的命令中叠字者更经常使用, 且多表示行操做;表明方向的  hjkl 应用于折叠移动(  zj 、  zk)、 窗口移动(  Ctrl-W-J 、  Ctrl-W-K 、  Ctrl-W-H 、  Ctrl-W-L )、 插入模式下的移动(  Ctrl-G-J 、 Ctrl-G-K )等 以及ex命令中  ! 的用法,等等。
至于定制方面,网上有大量的 Vim配置可供参考。初学者可先行“拿来主义”, 挑一个合适本身的来用,之后慢慢学习领会,渐进改造直至趁心如意。
Vim虽以难著称,其实有一个宗旨:让新手尽快上路,而后在使用中逐步累积知识。 对于老手而言, Vim又是常学常新的。纵是在 Vim世界里浸淫十余年者,也随时可 享俯拾遗珠之乐。
人们经常强调 Vim陡峭的学习曲线,却忽略事情的另外一面,即它的效率曲线也是陡峭的。 固然 Vim的独特性决定了它永远成不了最流行的编辑器,但这实在不重要, 重要的是凡窥其门径者,无一不留恋难舍,大有“除却巫山不是云”之感。 好在即便离开了 Vim,手指依旧能够在别处弹奏着一样独特的韵律。 在许多编辑器或IDE下,均可使用Vi或 Vim的键盘绑定,其中包括:Emacs、 Eclipse、 NetBeans、IntelliJ、Visual Studio、SlickEdit、XCode、TextMate、Komodo等。 在非编辑器的环境中,一样有Vi( Vim)的身影。 在Firefox、Chrome、Safari等浏览器中都有类 Vim的插件, 在*nix的命令行终端下经配置也可以使用Vi, 在Mac下有一些软件能够为大多数应用程序(Cocoa Application)的文本框绑定Vi输入法。 全部这些的背后,都站着一大批受到 Vim魅力感召的人们。
回到本文开篇的问题: Vim的魅力何在?个人答案是:表面上在于快和柔, 本质上则在于对用户的最大尊重——尊重用户的体验与感觉,尊重用户的自由与智慧。  Vim以其独有的理念充分地发挥了用户的能动性与想象力,从而营造出一个空寂的世界, 在那里无按钮菜单之分神,无弹出窗口之聒噪,无鼠标之不便, 只有意念在键盘上静静而天然地流淌,让人沉浸其中而不肯自拔。 最后,请容许我用一段绝非刻意而为之的对比来重述本身的观点:
Vim最大的障碍不在于其自己,而在于用户的自我束缚。
Vim最大的魅力不在于其自己,而在于用户的自我解放。
(全文完)
附:本人的  Vim配置 。
相关文章
相关标签/搜索