Vim 技巧 —— 实现多行注释的几种方法

习惯问题,一直在用 Vim。之前装的几个插件,基本上覆盖了日常使用中的绝大部分场景。只是遇到需要多行注释的时候,一直没有一套比较直接的方法。
于是上网查了些资料,也实际测试了下效果。整理出一部分方法(不借助插件),以作备忘。

字符串替换

命令模式下可以使用 :s/old/new 替换当前文本行中的指定字符串。前面还可以加上数字等用来指定范围。如:

  • :n1,n2 s/old/new:从 n1 行开始,到 n2 行结束,将每一行中符合 old 模式的内容替换为 new
  • :% s/old/new:将整个文件中的 old 替换为 new

类似于 Vim 中内置了一个 sed 工具。

对于 Python 代码,注释代码块当然可以用双 ''',临时的注释我个人比较偏向行首加 #。借助字符串替换可以很方便的实现。命令如下:
:n1,n2 s/^/#
n1n2 行中的行首空白字符替换为 #,等同于在每一行行首插入 #

对于如下 Python 代码:

1
2
3
4
5
6
7
8
9
10
11
from datetime import datetime
import calendar
import os


current_time = datetime.now()
total_days = calendar.monthrange(current_time.year, current_time.month)
total_days = total_days[1]

for i in range(total_days):
os.mkdir(str(i + 1))

before replace

在 Vim 中运行 :1,3 s/^/#,后,效果如下:

1
2
3
4
5
6
7
8
9
10
11
# from datetime import datetime
# import calendar
# import os


current_time = datetime.now()
total_days = calendar.monthrange(current_time.year, current_time.month)
total_days = total_days[1]

for i in range(total_days):
os.mkdir(str(i + 1))

如果要取消注释,再运行如下命令即可:
:1,3 s/# /
将 1 - 3 行行首的 # 替换为空字符串(即移除行首的 #)

visual 模式下指定文本范围

如果不喜欢用数字行号指定施行替换的文本行,也可以在 Visual 模式下手动选择生效的文本范围。

Normal 模式下按键盘上的 v 键进入 visual 模式,然后就可以通过光标移动命令(如 hjkl{} 等)选中多行文本。

接着在命令模式下运行 :'<,'> s/^/# 即可在选中的文本上执行文本替换。
select & replace

其中 '<,'> 即代表 visual 模式下选中的文本行。一般情况下,选中文本以后再按 : 进入命令模式,'<,'> 部分内容会自动补全。

多行编辑

多行编辑指同时在多行文本中每一行的相同位置插入相同的内容。只需要编辑某一行文本,其他文本行就会自动进行同样的修改。

比如需要注释 Python 代码的前 3 行,就可以同时编辑这 3 行文本,在第一行行首插入 #,则前 3 行会同时被注释掉。

首先光标定位到第一行行首,按下键盘上的 ctrl + v 组合键(Windows 下可以用 ctrl + q)进入 Visual Block 模式,按两次 j 键下移光标,选中前三行的首字符。
再按下键盘上 I(大写)键进入插入模式,在第一行行首插入 # 字符。
按下 Esc 退出插入模式,则后两行行首也会自动插入 # 字符。

VISUAL BLOCK

before Esc

after Esc

录制 Macro

Vim 中的(Macro)即一系列编辑操作的合集。
在 Vim 中,可以把需要重复执行的多步编辑操作录制下来,绑定到某个按键上。之后就可以按下 @绑定的按键 重复执行录制好的步骤。
有点像定义和调用函数。

使用 q某按键 开始录制宏,执行某些编辑操作后,再按下 q 结束录制。随后按下 @某按键 调用录制好的宏。

如需要注释前 3 行 Python 代码,则可以录制包含如下步骤的宏:

  • 在当前行的行首开始插入文本(I
  • 输入注释符号(#
  • 退出插入模式(Esc
  • 移动到下一行(j)

上述宏中的操作步骤可以首尾相接,无限循环。即注释当前行,移动到下一行;注释当前行,移动到下一行。。。

具体的操作步骤如下:

  • 在 Normal 模式下,光标移动到首行,按下 qq 开始录制宏(录制结束后会绑定给 q
  • 按下 I 键(大写),进入行首插入模式
  • 输入 #
  • 按下 Esc 退出插入模式
  • 按下 j 移动光标到下一行文本
  • 按下 q 结束宏的录制

宏录制结束后,即可连按两次 @q 连续调用两次宏,分别注释第二行和第三行内容。

recording macro

. 命令

. 命令相当于一种简化了的宏。它表示重复应用上一步中对内容的更改。
. 命令无需录制,但只会重复对内容的编辑(如插入、替换等),不会重复其他操作。
比如前面的需要注释 Python 代码的前三行,可以执行如下操作:

  • 光标定位到首行,按 I(大写)在行首插入内容
  • 输入注释符号 #
  • 按下 Esc 退出插入模式
  • 按下 j 跳转到下一行,按 . 重复执行对上一行的编辑操作(行首插入 #
  • 重复上一步操作(j.),注释第三行

其他

在查阅资料的时候,还发现一个 norm 命令。
比如还是需要注释前 3 行,可以执行如下命令:
:1,3 norm I #

其中 1,3 表示只对 1 - 3 行应用后面的命令;
norm 表示从 Normal 模式下开始;
I # 表示进入插入模式(同时光标移动到行首),插入文本 #

参考资料

Vim: insert the same characters across multiple lines