Vim实用技巧 第2版(txt+pdf+epub+mobi电子书下载)


发布时间:2020-07-03 05:06:37

点击下载

作者:[英] Drew Neil 尼尔

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Vim实用技巧 第2版

Vim实用技巧 第2版试读:

前言

本书是为那些想提升自己的程序员写的。你一定听说过,对于Vim高手来说,Vim能以思考的速度编辑文本。阅读本书则是通往此途的必经之路。

本书是精通Vim的捷径。尽管它不会手把手教你,不过初学者可[1]以先运行随Vim发布的交互式课程——Vim向导来了解必备的知识。本书则在这一基础之上着重介绍核心概念,并为你讲解地道的用法。

Vim是高度可配置的,然而定制是一件很个性化的事情,因此我试图避免建议什么应该放进你的vimrc里,什么不应该。相反,本书关注的是Vim编辑器的核心功能。不管你是通过SSH登录远端服务器工作,还是在用本地安装了插件而增添了额外功能的GVim,这些功能都永远在那儿。精通了Vim的核心功能,你就获得了一个可移植的、强大的文本编辑工具。

本书如何组织

这是一本按技巧组织的书,它被设计成不必从头读到尾(没错!在下一章开头,我会建议你直接跳到正文)。每一章都是关于某一相关主题的技巧集合,而每个技巧都讲解一个特定的实用功能。有些技巧自成一体,而有些技巧则依赖本书中其他地方的内容,这些有依赖关系的技巧会以交叉引用的形式呈现给大家,因此你可以轻松找到所有内容。

虽然整本书的进度安排不是先从入门开始,然后再到高级,但是每个独立章节中的内容都是按循序渐进的方式来组织的。缺乏经验的Vim用户可能更愿意先浏览全书,只阅读每章的前几个技巧;而高级用户可能会重点看每章中比较靠后的技巧,或是根据需要查阅本书。

关于示例的说明

在Vim中,对一件给定的任务,总能找到不止一种解决办法。例如,第1章里的所有问题都围绕 . 命令进行设计,以便讲解 . 命令的应用,不过这些问题也都可以用 :substitute命令解决。

在阅读我的解决方法时,你自己也许会想:“难道用这种方法做不是更快吗?”可能你是对的!我的解决方法只是在讲解一种特定的技术,试图透过它们简单的外表,找出它与你日常所面临问题的相似之处,而这一点才是这些技巧可以帮你节省时间的地方。

先学会盲打,然后再学习Vim

如果你要低头看着键盘打字,那学习Vim的好处不会立竿见影地显现出来。要高效地使用Vim,必须学会盲打。

Vim的祖先要追溯到经典的Unix编辑器vi和ed,参见技巧27中的“Vim(及其家族)的词源”部分,它们比鼠标及所有点击界面出现得都早,因此根本没有这类接口,所有操作都通过键盘完成。Vim也是一样,Vim中的所有操作也都可以通过键盘完成。对盲打人员来说,这意味着用Vim做任何事都能更快些。

[1] http://vimhelp.appspot.com/usr_01.txt.html#vimtutor致谢

感谢Bram Moolenaar 创造了 Vim,也感谢所有对 Vim 的开发做出贡献的人。这是一个永恒的软件,我期盼自己能与它一同成长。

感谢Pragmatic Bookshelf 公司的每个人,正是你们的齐心协力才使这本书变得更好。特别感谢本书的项目编辑Kay Keppler,感谢他教导我成为一名作者,并促使本书成形,而不在乎经历了多少的成长之痛以及我偶尔使性子。同样要感谢本修订版的项目编辑Katharine Dvorak。我也想感谢David Kelly,感谢他对我与众不同的排版要求所做出的巧妙设计。

本书刚开始并没有打算按照技巧的方式组织章节,但Susannah Pfalzer 发现采用这种格式会更好。重写这么多内容的确很痛苦,但做完之后,我头一次写出了让自己满意的初稿。Susannah 知道什么是最好的,感谢她分享了这一见解。

感谢Dave Thomas 和 Andy Hunt 创办了Pragmatic Bookshelf 公司。我没想过让其他出版商出版本书,并且我很荣幸本书能和其他书一起列在他们的书目中。

如果没有技术审阅人员,本书不可能出版。每一位技术审阅人都为之贡献了力量,并帮助本书成形。在此我想感谢Adam McCrea、Alan Gardner、Alex Kahn、Ali Alwasity、Anders Janmyr、Andrew Donaldson、Angus Neil、Charlie Tanksley、Ches Martin、Daniel Bretoi、David Morris、Denis Gorin、Elyézer Mendes Rezende、Erik St. Martin、Federico Galassi、Felix Geisendörfer、Florian Vallen、Graeme Mathieson、Hans Hassel- berg、Henrik Nyh、Javier Collado、Jeff Holland、Josh Sullivan、Joshua Flanagan、Kana Natsuno、Kent Frazier、Luis Merino、Mathias Meyer、Matt Southerden、Mislav Marohnic、Mitch Guthrie、Morgan Prior、Paul Barry、Peter Aronoff、Peter Rihn、Philip Roberts、Robert Evans、Ryan Stenhouse、Steven、Ragnarök、Tibor Simic、Tim Chase、Tim Pope、Tim Tyrrell以及Tobias Sailer。

即便是有了技术审阅人员的审查,一些错误依然隐藏在书中。在此我想感谢为本书提交错误报告的所有人,是你们帮助我找到错误并修正它们。

Vim的内置文档是非常了不起的资源,本书中到处都在引用它。我想感谢Carlo Teubner把Vim文档在线发布到vimhelp.appspot.com,并持续更新。

本书第一版中有些技巧很糟糕,但我依然把它们加入书中,因为我觉得它们很重要。在本修订版中,我很高兴能够重写这几个糟糕的技巧。感谢Christian Brabandt实现了“改变玩法”的gn命令,让我能够重写技巧84。感谢Yeggapan Lakshmanan实现了cfdo命令(及其相关命令),让我能够重写技巧97。我也想感谢David Bürgin所提交的Vim补丁7.3.850,这一补丁终结了vimgrep命令带给我的小头疼。

另外,我想感谢整个 Vim 社区,感谢他们通过互联网分享见解。通过阅读StackOverflow 上 Vim 标签中的内容和订阅 vim_use 邮件列表,我学到了本书中的很多技巧。

Tim Pope的rails.vim插件对于说服我皈依 Vim 起了很大的作用,并且他开发的许多其他插件也都成为我的Vim设置中必不可少的组成部分。我也从Kana Natsuno的插件中领悟到很多东西,在我印象里,他的自定义文本对象是对Vim核心功能最好的扩展。感谢你们两位把Vim这把“锯子”磨得更加锋利,使我们大家从中获益。

感谢Joe Rozner 提供的 wakeup 源码,我使用它来介绍 :make 命令;感谢Oleg Efimov对nodeline缺陷的快速反馈,也感谢Ben Cormack对robots以及ninjas的解释。

2012 年 1 月,我们搬到了柏林,在这里的技术社区的启发下,我完成了本书。我想感谢Gregor Schmidt 成立了 Vim 柏林用户组,也感谢Schulz-Hofen 举办的招待我们的聚会。与 Vim 用户交谈的机会,真正帮我理清了思路,因此我感激每个参加 Vim 柏林会议的人。也感谢Daniel 及 Nina Holle 把自己的房子转租给我们,它既是居住的绝佳场所,也是工作的高效环境。

2011 年 3 月我住在埃及时,需要动手术清除肠道粘连。不幸的是,我离家很远;幸运的是,我妻子陪伴在身边。Hannah把我送到半岛南部医院,在那里我受到了很好的照顾。我想对那里的所有医务人员表示感谢,感谢他们对我的悉心照料,也感谢 Shawket Gerges 医生为我成功地进行了手术。

当我母亲知道我要动手术时,她抛下一切乘坐最早航班飞到埃及。要知道当时这个国家正在发生革命,她老人家需要多大的勇气才能做到这一切啊。我无法想象没有我母亲的支持与经验,我和Hannah 该如何度过这段困难时期。我为一生中拥有两个如此伟大的女人而感到幸福。写作体例说明

在本书中,我会通过图例进行演示,而不是描述它们,因为用书面语不太容易做到这一点。为了显示在交互式编辑会话中所采取的步骤,我采用了一种简单的标记方法,把按键操作及 Vim 缓冲区的内容排在一起进行说明。

如果你急于动手操作的话,现在可以直接跳过这一部分。这一部分主要描述本书沿用的体例,你会发现其中很多都不需要解释。或许在某个地方你会偶然发现一个符号,想搞清楚它究竟代表什么意思。当这种情况发生时,你可以回到这一部分来寻求答案。

了解Vim的内置文档

了解Vim文档的最好方式是花点时间阅读。我在书中给出了Vim文档入口的“超链接”,以方便读者找到相关文档。例如,这里有一个通往Vim向导的“超链接”::h vimtutor。

这个图标具有两个作用。第一,它起到指示牌的作用,把目光吸引到这些有用的参考信息上;第二,如果你在联网的电子设备上阅读本书的话,那么你可以单击这些图标,它会把你带到 Vim 在线文档的相应入口。从这个意义上讲,它的确是超链接。

但是,如果你正在阅读纸版书,那该怎么做?别担心,如果在你手边有可访问的 Vim程序,简单地输入图标前的命令即可。

例如,你可以输入 :h vimtutor(:h是 :help命令的简写)。你可以把它想成 vimtutor文档的唯一地址,即某种形式的URL。从这个意义上讲,此 help 引用也是一种指向 Vim 内置文档的超链接。

在书页中模拟Vim的标记

Vim 区分模式的界面把它同其他文本编辑器区别开来。以音乐作个比喻,让我们拿Qwerty 键盘与钢琴键盘进行比较。一个钢琴家可以每次只弹一个琴键来演奏主旋律,他也可以一次弹多个键来演奏和弦。对于多数文本编辑器,要触发一个键盘快捷键,需要先按住一个或多个修饰键,如控制键或命令键,然后再按另外一个键,在Qwerty键盘上的这种操作方式,等同于在钢琴键盘上演奏和弦。

某些Vim命令也由演奏和弦的方式触发。不过普通模式命令则被设计成输入一串按键。在Qwerty键盘上的这种操作方式,则等同于在钢琴键盘上演奏主旋律。

Ctrl-s 是用来表示组合键命令的惯用约定,意为“同时按控制键及 s 键”,但这种约定方式并不适合用来描述Vim区分模式的命令集。在本节,我们将结识贯穿于全书的标记,在讲解Vim的用法时会用到它们。

演奏主旋律

在普通模式中,我们按次序输入一个或多个键组成一条命令。这些命令看起来像下面这样:标记含义xx按一次 dw依次按 d、wdapd、a、p依次按

这些序列大多数包含两个或3个按键,但有的命令会更长。解读 Vim 普通模式命令序列的含义可能颇具挑战性,不过经过练习后你会做得更好。

演奏和弦

当你看到诸如 这样的键时,它的意思不是“先按 <,然后按 C,再按 -,等等”。 标记等同于Ctrl-p,意为“同时按 及 p”。

我不会无缘无故地选择这种标记方式的。首先,在Vim 的文档中使用了这种标记(:h key-notation),我们也用它定义自定义按键映射项。另外,某些 Vim 命令由组合键及其他键以一定的次序组合在一起,这种标记也可以很好地表达这些命令。请看下面这些例子。标记含义 和 n同时按 g按 g,然后同时按 和 ] 和 r,然后按 00同时按 和 w,然后同时按 和 =同时按

占位符

很多Vim命令需要以一定的次序按两个或多个按键。有些命令后面必须跟某种特定类型的按键,而其他命令后面则可以跟键盘上的任意键。我使用花括号表示一条命令后可以跟有效按键集合。下面是一些例子。标记含义f{char}f,后面跟任意字符按 `{a-z}`,后面跟任意小写字母按 m{a-zA-Z}按 m,后面跟任意小写或大写字母d{motion}d,后面跟任意动作命令按 {register} 和 r,后面跟一个寄存器地址同时按

显示特殊按键

有些特殊按键以其名字表示,下表节选了其中的一些。标记含义按退出键按回车键,也写作 按控制键按制表键按切换键同时按 按上光标键按下光标键␣按空格键

 注意,空格由␣ 表示。它和 f{char} 命令组合在一起时记为 f␣。

区分不同模式下的输入

在操作Vim时,经常会从普通模式切换到插入模式,然后再切换回普通模式。Vim中的每个键都可能具有不同的含义,这取决于当前哪个模式生效。我用了另一种样式表示在插入模式中输入的键,这可以让人很容易地把它们与普通模式下的按键区分开来。

看看这个例子 cwreplacement。普通模式命令 cw 会删除从光标位置到当前词结尾处的文本,并切换到插入模式。然后我们在插入模式中输入单词“replacement”,并按 键再切换回普通模式。

普通模式所用的样式也用于可视模式,而插入模式的样式也用来表示命令行模式及替换模式下输入的按键。你可以通过上下文清楚地知道当前处于哪个模式。

在命令行中操作

在有些技巧中,我们会在 shell或 Vim中执行一条命令行命令。下面是在 shell 中执行 grep 命令的格式。➾ $ grep -n Waldo *

下面是执行 Vim 内置的 :grep 命令的格式。➾ :grep Waldo *

在全书中,$符号表示在外部 shell 中执行一条命令行命令,: 提示符则表示这条命令在内部的命令行模式中执行。有时我们也会看到其他的提示符,包括:提示符含义$在外部 shell 中执行命令行命令:用命令行模式执行一条 Ex 命令/用命令行模式执行正向查找?用命令行模式执行反向查找=用命令行模式对一个 Vim 脚本表达式求值

无论你何时在文中见到一条 Ex 命令,比如 :write,都可以假设我们按了 键来执行该命令,否则该命令什么也不会做,因此可以认为 在 Ex 命令中是隐含的。

与之相反,Vim 的查找命令允许在按 前预览第一个匹配项(参见技巧82)。当你在文中见到一条查找命令时,比如 /pattern,你会看到 键被显式地标出来了;如果 被省略了,那是有意为之,也就是说你现在还不要按回车。

显示缓冲区内光标的位置

在显示缓冲区内容时,如果能指示当前光标位于何处,那会很有用。在下面的例子里,你可以看到光标位于单词“One”的第一个字母上。One two three

当我们执行一项包含若干步的修改时,缓冲区的内容会经历一些中间状态。为了讲解这一过程,我使用了一个表格,在其左栏中显示所执行的命令,在右栏中显示缓冲区的内容。下面是个简单的例子。按键操作缓冲区内容{start}One two threedwtwo three

在第2行,我们运行dw命令删除了光标下的单词。通过查看位于同一行的缓冲区内容,我们可以立刻看到这条命令执行完后缓冲区的状态。

高亮显示查找匹配项

在讲解 Vim 的查找命令时,如果能把缓冲区内出现的每个匹配项都高亮显示出来,那会很有帮助。在下例中,查找字符串“the”会让出现该模式的4处地方被高亮显示出来:按键操作缓冲区内容the problem with these new recruits is that they don't keep their {start}boots clean.the problem with these new recruits is that they don't keep their /theboots clean.

你可以跳到技巧81,了解如何激活 Vim 的查找高亮功能。

在可视模式中选择文本

可视模式允许在缓冲区内选择文本,然后在其上操作。在下例中,用it 文本对象选中 标签内的文本。按键操作缓冲区内容{start}href="http://pragprog.com/dnvim/">Practical Vimvit

注意,高亮显示可视选区的样式与高亮显示查找匹配项的样式相同。当你看到这种样式时,根据上下文就可以知道它究竟是代表一处查找匹配项,还是一个高亮选区。

下载本书中的示例

本书中的例子通常都先显示修改前的文件内容,并在示例文本中给出该文件所在的路径,如下所示:

macros/incremental.txtpartridge in a pear treeturtle dovesFrench henscalling birdsgolden rings

每当你看到以这种方式列出的文件路径时,都表示该例可被下载。我建议你在 Vim 中打开此文件,然后亲自试试这个例子。这是学习Vim的最好方式。

要照着书中的例子操作,你可以从Pragmatic Bookshelf的网站上[1]下载本书所有的示例和源代码。如果你在联网电子设备上阅读本书,也可以单击文件名来逐一获取每个文件。你可以用上面的例子试验一下。

使用Vim的出厂配置

Vim 是高度可配置的,如果你不喜欢其默认的行为,可以改变它们。这本是好事,但是,如果你用自定义的 Vim 跟着做本书中的例子,可能会感到迷惑,你也许会发现有些东西并不像书中描述的那样工作。如果你怀疑是自定义配置造成了干扰,那么你可以做一个快速的测试。试着先退出 Vim,然后再用下列选项启动它。➾ $ vim -u NONE -N

-u NONE 标志让 Vim 在启动时不加载你的vimrc,这样,你的定制项就不会生效,插件也会被禁用。当用不加载 vimrc 文件的方式启动时,Vim会切换到 vi 兼容模式,这将导致很多有用的功能被禁用,-N 标志则会使能 ‘nocompatible’ 选项,防止进入 vi 兼容模式。

对于本书中的大多数例子来说,用 vim -u NONE –N启动 Vim应该可以确保你获得与书中的描述相符的体验,不过也有几处例外。有些Vim的内置功能是由 Vim 脚本实现的,也就是说,只有在激活插件时,它们才会工作。下面的文件中包含了激活 Vim 内置插件的最小配置。

essential.vimset nocompatiblefiletype plugin on

在启动 Vim 时,可以执行如下命令,用该文件取代你的 vimrc。➾ $ vim -u code/essential.vim

在执行时,需要相应地调整 code/essential.vim 文件所在的路径。激活Vim内置的插件功能后,可以使用诸如 netrw(参见技巧44)、omni-completion(参见技巧119),以及很多其他的功能。我在本书中所说的Vim的出厂配置,指的就是激活了内置的插件功能,并且禁用了 vi 兼容模式时的配置。

需要留意技巧开头的名为“准备工作”的小节,要想跟着技巧中的步骤做,需要对Vim进行相应的配置。如果你由Vim的出厂配置开始,然后再动态应用这些定制项,就应该能重现技巧中的结果,不会遇到任何问题。

如果你仍遇到问题,请看后面的“关于Vim的版本”部分。

Vim 脚本所扮演的角色

Vim脚本让我们可以给Vim添加新的功能,或是改变其已有的功能。它是一种完整的脚本语言,并且这个主题本身就可以写一整本书。不过本书并不是这样一本书。

但我们不会完全避开此话题,Vim脚本一直隐身在幕后,时刻准备响应我们的召唤。在技巧16、技巧71、技巧95及技巧96中,我们将看到一些如何使用它们完成日常工作的例子。

本书展示了如何使用Vim的核心功能。换句话说,它假设我们不使用任何第三方插件。不过技巧87是个例外,visual-star.vim 插件添加的功能我认为是不可或缺的,并且它只需很少的代码——不超过10行。同时它也展示了扩充 Vim 的功能是多么容易。文中给出了 visual-star.vim的实现,但没有讲解。这应该能给你一些印象,了解Vim脚本是什么样的,以及你能用它干什么。如果它激起了你的兴趣,那就更好了。

关于 Vim 的版本

本书中的所有例子都在最新的 Vim版本中测试过,在写本书时是版本 7.4。就是说,大多数例子在任意 7.x 版本中都能够很好地工作,并且所讨论的很多功能在 6.x 中也同样适用。

有些Vim功能可以在编译期间被禁用。例如,在配置编译选项时,可以传入--with-features=tiny参数,这会禁用除最基本的功能外的其他所有功能(Vim的功能集还包括 small、normal、big和 huge)。可以查阅 :h +feature-list,浏览完整的功能列表。

如果你发现自己的Vim缺少本书所讨论的某个功能,那么你也许正在使用一个最小功能集的 Vim 发行版。可以用 :version命令检查此功能是否可用。➾ :version《 VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Oct 14 2015 18:41:08) Huge version without GUI. Features included (+) or not (-): +arabic +autocmd +balloon_eval +browse +builtin_terms +byte_offset +cindent +clientserver +clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments ...

在现代计算机上,没理由不用 Vim 的 huge 功能集!

用终端 Vim 还是图形化Vim?你自己定!

传统上,Vim在终端内运行,没有图形用户界面(GUI)。我们也可以说Vim具有TUI,即文本用户界面。如果你每天有大量时间花在命令行上,你会感觉这很自然。

如果你通常使用基于图形用户界面的文本编辑器,那么GVim(或OSX上的MacVim)可以给你提供一个通往Vim世界的有用桥梁(参见 :h gui)。GVim支持更多的字体以及更多的语法高亮颜色,也可以使用鼠标。它也遵从某些操作系统的约定,例如,在MacVim中,可以用Cmd-X 和Cmd-V与系统剪切板交互,也可以用 Cmd-S 保存文件,用 Cmd-W关闭一个窗口。如果你能接受的话,可以用这些命令,不过你应该已意识到,还有更好的方法完成这些。

对本书的目的而言,运行终端Vim还是GVim关系不大。我们将着重于介绍Vim的核心命令,这些功能在两者中都能很好地运行。我们要学习的重点是如何用Vim的方式来工作。

[1] http://pragprog.com/titles/dnvim/source_code第1章 Vim解决问题的方式

从本质上讲,我们的工作是重复性的。不论是在几个不同的地方做相同的小改动,还是在文档的相似结构间移动,我们都会重复很多操作。凡是可以简化重复性操作的方式,都会成倍地节省我们的时间。

Vim对重复性操作进行了优化。它之所以能高效地重复,是因为它会记录我们最近的操作,让我们用一次按键就能重复上次的修改。这听起来很强大,但是除非我们能够学会规划按键动作,使得在重复时能完成一项有用的工作,否则这没什么用。掌握这一理念是高效使用Vim的关键。

我们将以 . 命令作为开始。这个看似简单的命令是Vim中的瑞士军刀,掌握它的用法是精通Vim的第一步。我们将运行一些可由 . 命令快速完成的简单编辑任务,虽然每个任务彼此之间截然不同,但解决的方法却大同小异。我们将找到一种理想的编辑模式,即用一次按键移动,用另一次按键执行。技巧1 认识 . 命令. 命令可以让我们重复上次的修改,它是Vim中最为强大的多面手。

Vim文档只是简单地提到 . 命令会“重复上次修改”(参见 :h .),这听起来没什么特别,但在这个简单的说明里,我们会发现让Vim区分模式的编辑模型如此高效的核心原因。首先我们要问:“究竟什么是修改?”

要理解 . 命令的强大,我们需要意识到这一点:“上次修改”可以指很多东西,一次修改的单位可以是字符、整行,甚至是整个文件。

我们将使用下面这段文本进行说明。

the_vim_way/0_mechanics.txtLine oneLine twoLine threeLine four

x 命令会删除光标下的字符,在这种情况下使用 . 命令“重复上次修改”时,就会让Vim删除光标下的字符。按键操作缓冲区内容{start}ine oneL Line two Line three Line four×ine one Line two Line three Line four.e onen Line two Line three Line four..one Line two Line three Line four

我们可以输入几次 u 撤销上述修改,使文档恢复到初始状态。

dd 命令也做删除操作,但它会把整行一起删掉。如果在 dd 后使用 . 命令,那么“重复上次修改”会让Vim删除当前行。按键操作缓冲区内容{start}ine oneL Line two Line three Line fourddLine two Line three Line four.ine threeL Line four

最后,>G 命令会增加从当前行到文档末尾处的缩进层级。如果在此命令后使用 . 命令,那么“重复上次修改”会让Vim增加从当前行到文档末尾的缩进层级。在下例中,让光标从第二行开始,以便一目了然地看出差别。按键操作缓冲区内容{start}Line one Line two Line three Line four>GLine one Line two   Line three  Line fourjLine one  Line two Line three   Line four.Line one  Line two   Line three    Line fourj.Line one  Line two   Line three    Line four

x、dd以及 > 命令都是在普通模式中执行的命令,不过,每次进入插入模式时,也会形成一次修改。从进入插入模式的那一刻起(例如,输入 i),直到返回普通模式时为止(输入 ),Vim会记录每一个按键操作。做出这样一个修改后再用 . 命令的话,它将会重新执行所有这些按键操作(参见技巧8中的在插入模式中移动光标会重置修改状态部分中的补充说明)。

. 命令是一个微型的宏

在第11章“宏”中,我们将看到Vim可以录制任意数目的按键操作,然后在以后重复执行它们。这让我们可以把最常重复的工作流程录制下来,并用一个按键重放它们。可以把 . 命令当成一个很小的宏(macro)。

我们将在本章看到一些关于 . 命令的应用,另外还将在技巧9及技巧23中学到 . 命令的一些最佳应用技巧。技巧2 不要自我重复对于在行尾添加内容这样的常见操作,如添加分号,Vim提供了一个专门的命令,可以把两步操作合并为一步。

假设有如下的JavaScript程序片段。

the_vim_way/2_foo_bar.jsvar foo = 1var bar = 'a'var foobar = foo + bar

我们想在每行的结尾添加一个分号。要实现这一点,先得把光标移到行尾,然后切换到插入模式进行修改。$ 命令可以完成移动动作,接着就可以执行 a; 完成修改了。

要完成全部修改,也可以对下面两行做完全相同的操作,不过那样做会错过这里将要提到的小窍门。由于 . 命令可以重复上次的修改,因此不必重复之前的操作,而是执行两次 j$.。一个键(.)顶3个(a;),虽然每次省得并不多,不过在重复操作时,累积效应可不小。

不过让我们再仔细审视一下这个操作模式:j$.。j 命令使光标下移一行,而 $ 命令把光标移到行尾。我们用了两下按键,仅仅是为了把光标移到指定位置,以便可以用 . 命令。你觉得还有改进的余地吗?

减少无关的移动

a 命令在当前光标之后添加内容, A 命令则在当前行的结尾添加内容。不管光标当前处于什么位置,输入 A 都会进入插入模式,并把光标移到行尾。换句话说,它把 $a 封装成了一个按键操作。在本技巧后的一箭双雕部分中,我们将会看到Vim提供了不少这样的复合命令。

下面是对之前例子的改进。按键操作缓冲区内容{start}var foo = 1 var bar = 'a' var foobar = foo + barA;var foo = 1; var bar = 'a' var foobar = foo + barjvar foo = 1; a'var bar = ' var foobar = foo + bar.var foo = 1; var bar = 'a'; var foobar = foo + barj.var foo = 1; var bar = 'a'; ;var foobar = foo + bar

用 A 来代替 $a,大大提升了 . 命令的效率。不必再把光标移到行尾,只需保证它位于该行内就行了(可在任意位置)。现在可以重复执行足够多次的 j. ,完成对后续行的修改。

一键移动,另一键操作,真是太完美了!请留意这种应用模式,因为我们即将在更多的例子中看到它的身影。

虽然这一模式对这个简短的例子来说很好用,但它不是万能的。试想一下,如果我们不得不给连续50行添加分号,即便每个修改输一次 j. ,看起来也是一项很繁重的工作。跳到技巧30可以看到另外一种解决方法。一箭双雕我们可以这样说,A 命令把两个动作($a)合并成了一次按键。不过它不是唯一一个这样的命令,很多Vim的单键命令都可以被看成两个或多个其他命令的组合。下表列出了类似的一些例子,你能找出它们之间别的共同点吗?复合命令等效的长命令Cc$sclS^CI^iA$aoAOko如果你发觉自己正在输入 ko(或更糟糕,在用 k$a),马上打住!想想你在干什么,然后你就会意识到可以把它换成O 命令。你找出这些命令别的共同点了吗?它们全都会从普通模式切换到插入模式。仔细想想这一点,并想想这对 . 命令可能产生怎样的影响。技巧3 以退为进我们可以用一种常用的Vim操作习惯在一个字符前后各添加一个空格。乍一看,这种方法有点古怪,不过其好处是可重复,这将使我们可以事半功倍地完成工作。

假设有一行代码看起来是这样的:

the_vim_way/3_concat.jsvar foo = "method("+argument1+","+argument2+")";

在JavaScript里把字符串连接到一起从来都不美观,但可以像下面这样在 + 号前后各添加一个空格,让肉眼更容易识别。var foo = "method(" + argument1 + "," + argument2 + ")";

使修改可重复

下面的惯用方法可以解决这个问题。按键操作缓冲区内容{start}ar foo = "method("+argument1+","+argument2+")";v+argument1+","+argument2+")";var foo = "method("f+var foo = "method(" + argument1+","+argument2+")";s␣+␣;+","+argument2+")";var foo = "method(" + argument1.var foo = "method(" + argument1 + ","+argument2+")";;.var foo = "method(" + argument1 + "," + argument2+")";;.var foo = "method(" + argument1 + "," + argument2 + ")";

s 命令把两个操作合并为一个:它先删除光标下的字符,然后进入插入模式。在删除 + 号后,先输入␣+␣,然后退出插入模式。

先后退一步,然后前进三步,这是个奇怪的小花招,看起来可能不够直接。但这样做最大的好处是:我们可以用 . 命令重复这一修改。我们所要做的只是把光标移到下一个 + 号处,然后用 . 命令重复这一操作即可。

使移动可重复

本例中还有另外一个小窍门。f{char} 命令让Vim查找下一处指定字符出现的位置,如果找到了,就直接把光标移到那里(参见 :h f)。因此,输入 f+ 时,光标会直接移到下一个 + 号所在的位置。我们将会在技巧50里学到更多关于 f{char} 命令的知识。

完成第一处修改后,可以重复按 f+ 命令跳到下一个 + 号所在的位置。不过,还有一种更好的方法可以用。; 命令会重复查找上次 f 命令所查找的字符,因此不用输入4次 f+,而是只输入一次,后面跟着再用3次 ; 命令。

合而为一

; 命令带我们到下一个目标字符上, . 命令则重复上次的修改。因此,可以连续输入3次 ;. 来完成全部修改。看起来是不是很熟悉?

与其和Vim区分模式的编辑模型做斗争,倒不如与它一起协同工作。然后,你就会发现它能把特定任务变得多么的容易。技巧4 执行、重复、回退在面对重复性工作时,我们需要让移动动作和修改都能够重复,这样就可以达到最佳编辑模式。Vim对此的支持是:它会记住我们的操作,并使最常用的操作触手可及,所以可以很方便地重复执行它们。本节将介绍 Vim 可以重复执行的每个操作,并学习如何回退这些命令。

我们已经看到 . 命令会重复上次修改。由于很多操作都被当成一次修改,因此 . 命令已经证明了它的神通广大。但有些命令能以其他的方式重复。例如,@: 可以用来重复任意Ex命令(在技巧31中讨论),或者也可以输入 & (参见技巧93)来重复上次的 :substitute命令(它本身也是一条Ex命令)。

如果我们知道如何重复之前的操作,而无需每次都输入整条命令,那么就会获得更高的效率。可以先执行一次,随后只需重复即可。

然而,这么少的按键就可以完成这么多的事情,这也可能会带来麻烦。我们需要很小心地操作才行,不然就很容易出错。当一遍又一遍地连续按 j.j.j. 时,那种感觉就像是在敲鼓。可是,如果不小心在一行上敲了两次 j 键,会发生什么?或是更糟,敲了两次 . 键?

当Vim让一个操作或移动可以很方便地重复时,它总是会提供某种方式,让我们在不小心做过头时能回退回来。对 . 命令而言,我们永远可以按 u 键撤销上次的修改。如果在使用 f{char} 命令后,不小心按了太多次 ; 键,就会偏离我们的目标。不过可以再按 , 键跳回去,这个命令会反方向查找上次f{char}所查找的字符(参见技巧50)。

当不小心做过头时,知道怎么回退会很有帮助。表1-1总结了Vim中可重复执行的命令,以及相应的回退方式。在多数场景中,撤销(undo)都是我们想要使用的命令,难怪我键盘上的 u 键磨损得这么厉害!表1-1 可重复的操作及如何回退目的操作重复回退.{edit}u做出一个修改,;f{char}/t{char}在行内查找下一指定字符,;/T{char}F{char}在行内查找上一指定字符/patternn在文档中查找下一处匹配项N?patternn在文档中查找上一处匹配项Nu:s/target/replacement执行替换&uqx{changes}q@x执行一系列修改技巧5 查找并手动替换Vim提供了一个 :substitute 命令专门用于查找替换任务,不过用上面介绍的技术,也可以手动修改第一处地方,然后再一个个地查找替换其他匹配项。. 命令可以把我们从繁重的工作中解放出来,而即将登场的另一个有用的单键命令,则能够让我们方便地在匹配项间跳转。

在下面这段文本中,每一行都出现了单词“content”。

the_vim_way/1_copy_content.txt...We're waiting for content before the site can go live......If you are content with this, let's go ahead with it......We'll launch as soon as we have the content...

假设想用单词“copy”(意义同“copywriting”)来替代“content”。也许你会想,这太简单了,只要用替换命令就行了,像下面这样:

➾:%s/content/copy/g

但是,且慢!如果我们运行上面这条命令,就会出现“If you are ‘copy’ with this,”这样的句子,这很荒唐!

之所以会有这种问题,是因为“content”一词有两种含义,一个是“copy”的同义词(发音为'kon'tεnt),另一个是“happy”的同义词(发音为kən'tent)。用专业的话说,我们是在处理拼写相同,但含义和发音都不同的词。不过这不是我想说的重点,重点是我们一定要小心每一步操作。

我们不能想当然地用“copy”替换每一个“content”,而是要时刻留神,对每个地方都要问“这里要修改吗?”,然后回答“修改”或者“不改”。substitute 命令也能胜任这项工作,我们将在技巧90中学到该怎么做。不过现在,我们将寻求符合本章主题的另一种解决办法。

偷懒的办法:无需输入就可以进行查找

现在你可能已经猜到了,. 命令是我最喜爱的Vim单键命令,而排在第二位的是 命令,此命令可以查找当前光标下的单词(参见 `:h `)。

我们可以调出查找提示符,并输入完整的单词来查找“content”。

➾ /content

或者,可以简单地把光标移到这个单词上,然后按 * 键。以下面的操作为例。按键操作缓冲区内容{start}...We're waiting for content before the site can go live... ...If you are content with this, let's go ahead with it... ...We'll launch as soon as we have the content......We're waiting for content before the site can go live...* content with this, let's go ahead with it......If you are  content......We'll launch as soon as we have the copy...We're waiting for content before the site can go live...cw ...If you are content with this, let's go ahead with it... y......We'll launch as soon as we have the copncontent before the site can go live......We're waiting for  ...If you are content with this, let's go ahead with it... ...We'll launch as soon as we have the copy....y before the site can go live......We're waiting for cop ...If you are content with this, let's go ahead with it... ...We'll launch as soon as we have the copy...

刚开始,把光标移到单词“content”上,然后使用 * 命令对它进行查找,你也可以自己试一下。这会产生两个结果:一是光标跳到下一个匹配项上,二是所有出现这个词的地方都被高亮显示出来。如果你并没有看到高亮,试着运行一下 :set hls。要了解更多这方面的内容,请参见技巧81。

执行过一次查找“content”的命令后,现在只需按 n 键就可以跳到下一个匹配项。在本例中,按 *nn 会遍历完所有的匹配项,从而跳回到本次查找的起点。

使修改可重复

当光标位于“content”的开头时,就可以着手修改它。这包括两步操作:首先要删除单词“content”,然后输入替代的单词。cw 命令会删除从光标位置到单词结尾间的字符,并进入插入模式,接下来就可以输入单词“copy”了。Vim会把我们离开插入模式之前的全部按键操作都记录下来,因此整个 cwcopy 会被当成一个修改。也就是说,执行 . 命令会删除从光标到当前单词结尾间的字符,并把它修改为“copy”。

合而为一

万事俱备!每次按 n 键时,光标就会跳到下一个“content”单词所在之处,而按 . 键时,它就会把光标下的单词改为“copy”。

如果想替换所有地方,就可以不加思考地一直按 n.n.n. 以完成所有的修改(但是,这种情况下也可以用 :%s/content/copy/g 命令)。然而,由于我们需要留意不符合要求的匹配项,所以在按了 n 之后,要审视一下当前的匹配项,然后决定是否把它改为“copy”。如果需要修改的话,就按 . 命令,反之则不用。无论决定是什么,都可以再次按 n 移到下一个地方,如此循环往复,直到完成全部的修改。技巧6 认识 . 范式

到目前为止,我们介绍了3个简单的编辑任务。尽管每个问题都不一样,不过我们都找到了用 . 命令解决该问题的方法。在本节,我们将比较这些方案,并找出它们共有的模式——一个我称之为“ . 范式”的最佳编辑模式。

回顾前面3个 . 命令编辑任务

在技巧2中,我们想在一系列行的结尾添加分号。我们先用 A; 修改了第一行,做完这步准备后,就可以使用 . 命令对后续行重复此修改。我们使用了 j 命令在行间移动,要完成剩余的修改,只需简单地按足够多次 j. 就可以了。

在技巧3中,我们想为每个 + 号的前后各添加一个空格。先用 f+ 命令跳到目标字符上,然后用 s命令把一个字符替换成3个,做完这步准备后,就可以按若干次 ;. 完成此任务。

在技巧5中,我们想把每处出现单词“content”的地方都替换成“copy”。使用 * 命令来查找目标单词,然后用 cw 命令修改第一处地方。做完这步准备后,就可以用 n 键跳到下一匹配项,然后用 . 键做相同的修改。要完成这项任务,只需简单地按足够多次 n. 就行了。

理想模式:用一键移动,另一键执行

所有这些例子都利用 . 命令重复上次的修改,不过这不是它们唯一的共同点,另外的共同点是它们都只需要按一次键就能把光标移到下一个目标上。

用一次按键移动,另一次按键执行,再没有比这更好的了,不是吗?这就是我们的理想解决方案。我们将会一次又一次地看到这一编辑模式,所以为了方便起见,把它叫做“. 范式”。▶▶第一部分模式

Vim提供一个区分模式的用户界面,就是说在Vim中按键盘上的任意键所产生的结果可能会不一样,而这取决于当前处于哪种模式(mode)。知道当前正处于哪种模式,以及如何在各模式间切换,是极其重要的。在本书的这一部分,我们将学习每种模式的工作方式及其用途。第2章 普通模式

普通模式是Vim的自然放松状态,如果本章看起来出奇的短,那是因为几乎整本书都在讲如何利用普通模式,而本章只涉及其中的一些核心概念以及通用技巧。

其他文本编辑器大部分时间都处于类似Vim插入模式的状态中,因此对Vim新手来说,把普通模式(normal mode)当成默认状态看起来很奇怪。在技巧7中,我们将以一个画家的工作区作为类比,来解释其原因。

许多普通模式命令可以在执行时指定执行的次数,这样它们就可以被执行多次。在技巧10中,我们将结识一对用于加减数值的命令,并且会看到这两条命令如何与次数结合在一起,进行简单的算术运算。

指定执行的次数可以减少按键个数,但并不是说一定要为此目的而这样做。我们将会看到一些例子,在这些例子中,简单地重复执行一条命令,要比花时间去计算想要执行多少次更好。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载