给下面的代码每一行行尾加入分号,有几种方法呢?

1
2
3
var foo = 'aotu'
var bar = 'is a team'
var foobar = foo + bar

方法一,使用点操作符

  1. $移动到行尾,a;<Esc>完成一行分号的输入;($a;<Esc>)
  2. j移动到下一行,重复步骤1再来一遍,完成第二行;(j$a;<Esc>)
  3. 重复步骤2,完成第三行。(j$a;<Esc>)

好累,还不如鼠标点呢,vim的哲学就是Don’t repeat yourself,我们要想办法减少一些重复。

在vim里,.命令是会重复上次修改,我们要构造可重复的修改,于是方法为:

  1. $移动到行尾,a;<Esc>完成一行分号的输入;($a;<Esc>)
  2. j移动到下一行,然后$.,完成第二行;(j$.)
  3. 重复步骤2,完成第三行。(j$.)

可以看到.命令非常有用,尽量让可以重复的操作变成可以用.来重复的操作。

回过头来,什么样的才是“修改”呢,x会删除光标下的字符;dd删除一行;>G从当前行到文档末尾缩进,都算得上修改,它们都是在普通模式中执行的命令。 插入模式的修改肯定也是修改啦,不过如何记录的呢?就是从进入插入模式的那一刻起(例如输入i),直到返回普通模式为止(也就是输入<Esc>或<Ctrl + [ >>,Vim会记录每一个按键操作。
复合命令A相当于$a在这里更显得有用了,因为它是可重复的修改:

  1. A到行尾,;<Esc>完成一行分号的输入;(A;<Esc>)
  2. j移动到下一行,然后.,完成第二行;(j.)
  3. 重复步骤2,完成第三行。(j.)

认识.命令的魅力,尽量使操作可重复。

方法二,使用列块模式

  1. <Ctrl + v>(如果macvim或者gvim则是<Ctrl + q>)进入列块可视模式,jj$先下移动两行然后跳到行尾;
  2. A;进入插入模式输入分号;
  3. <Esc>回到普通模式完成插入。

这个方法里用了可视模式里列块选择,<Ctrl + v>是进入列块选择,通过移动建立选取后,使用AI进入插入模式编辑文本,然后使用<Esc>退出插入模式,同时结束列块模式,这时插入的文本就会扩散到选区选中的行了。

有意思的是,可以进入列块选择后复制,然后把它贴出来,试试咯。

如果你多输入了一个字符怎么办呢?gv可以重新选择刚才的选区,再调整一下选中你想删除的字符,删除它。gv适用于可视模式哦。

方法三,使用EX

  1. 查看行号,假设是x到y,然后适用命令:x,ynormal A;

这个方法里用到了命令行模式,在命令行模式中执行的命令又被称为Ex命令。有时使用Ex命令,能比普通模式命令更快地完成同样的工作。

其中:是进入命令行模式,x,y就是开始行号x和结束行号y,两者中间加上逗号表示范围;除了行号,其实我们还可以使用正则,比如删除含aotu字符的行到含有labs的行,则可以使用:/aotu/ , /labs/ d,可以用-来表示匹配行的前一行,+表示匹配行的下一行,那么删除匹配行的下一行则应该是:/aotu/+ d

normal就是表示执行正常(noramal)模式下的命令,后面的A;就很好理解了,在行尾插入分号。如果是m(ove)移动行,d(elet)删除行,co(py)t复制行,是不用输入noraml的。如:1,5 co 100 复制1~5行并把它们粘贴到100行以下。

. 代表当前行;:.,/pattern/ d会删除当前行到包含pattern的行。

$ 代表文件的最后一行;:5, . m $会移动第5行到当前行移动到文件末尾。

% 代表文件的每一行,等同于1,$。全文替换到时候常常:%s/foo/bar/g

也许有人问,如果这个例子里的行是不联系的,怎么办呢?

你可以使用:x,y g/pattern/normal A;或者:x,y v/pattern/normal A;
这里的g就是globally,整个的意思就是x到y行之间匹配pattern的行normal模式执行A;,而v则是来自于conVerse的v,所以整个的意思就是x到y行之间不匹配pattern的行normal模式执行A;

方法四,使用宏

  1. 在第一行上qa,然后A;<Esc>,按q
  2. j到第二行上@a
  3. j到第三行上@@

宏记录就是说vim会记录你所操作的序列,然后你可以在记录完成后的任意时间(normal模式下)一键播放录制的操作序列(宏)。

上面的例子,在普通模式中qa中的q就是进入宏模式,a就是这个宏的名字叫做a,宏的名字可以是26个字母中的某一个,大小写都可以,然后可以看到vim状态栏上显示“recording @a”,这时你的所有操作都会被记录。直到你返回会普通模式,然后按q

@a就是播放名字为a的宏,而@@就是重复播放刚刚播放过的宏。

其实上面为了演示@@而没有让他们可重复起来,可重复应该是在第1步qaA;<Esc>jq,然后在第2步2@qa就直接添加了第2和第3行的分号了。

上面只是大概的四种方法,要细分可能还有一些方法。

最后话说VS code 的vim插件挺好用的,更新也很快。

参考资料:《vim实用技巧》