我为 vim 添加了自动切换中英文输入法的功能,但是使用中有一些不在我的预期之内的行为。

如果能像调试别的语言编写的代码那样单步调试 vimrc 就好了。

原始方法

很多时候采用原始的方法就足以解决问题了:在代码的关键位置打印输出,根据输出判断代码是否有问题。

在需要打印输出的地方使用echom,如:

echom "Filetype: " . &filetype . " Previous IM: " . g:previous_im

echom "Switching to previous IM: " . g:previous_im

在 vim 中做一些操作触发相关的代码。

然后输入:messages即可看到在此之前打印出来的输出,如:

Filetype: cpp Previous IM: 2052
Switching to previous IM: 2052

Filetype: cpp Previous IM: 2052
Switching to previous IM: 2052

我是怎样将 vim 的命令输出拷贝到剪贴板的?见vim.9i2b.24.1220.1920

echoechom的区别是,:echo命令会打印输出,但是输出信息不会被记录下来;:echom打印的信息会保存下来,可以使用:messages命令再次查看输出信息。

Debug 调试

以调试模式启动 vim

在正常启动 vim 的命令中添加-D参数,如vim -D 或者 vim -D t.cpp

vim 会在配置文件第一行处中断。窗口下方会出现一个>提示符,如:

Entering Debug mode. Type "cont" to continue.
C:\Users\Aoyu\_vimrc
line 1: source C:\Users\Aoyu\myvim\_vimrc
>

一些可以使用的命令,类似 gdb:

step,vim 会执行当前行的代码,如果这一行是一个函数调用或加载另一个配置文件(source),会进入该函数调用内或进入被调用的配置文件,类似于“步入”、“逐语句”。由于这一行是导入了另一个配置文件source C:\Users\Aoyu\myvim\_vimrc,所以 vim 会跳到另一个配置文件,并在第一行处中断(如果第一行是注释,那就看第二行,以此类推,直到遇到一行有效指令)。

next,vim 会执行当前行的代码,执行完毕后跳到下一行,类似于“步过”、“逐过程”。

finish,跳出当前过程。如果是在函数调用内,会执行完函数内剩余的所有代码然后跳出,如果是在加载一个配置文件,会把该配置文件执行完毕,然后跳出。类似于“步出”、“跳出”。

cont,继续执行后续代码,直到遇到一个断点。

interrupt,停止当前过程。如果当前是在某个函数内部,会立即停止执行该函数的剩余部分,然后跳出。

在调试时打印变量、表达式等的值的方式:

# 打印变量值
echo g:previous_im

# 打印选项值
echo &filetype

# 打印函数值
echo has("win32")

打断点 和 移除断点 的方式:

# 语法相同,只是命令中一个是 add,一个是 del

# 打断点
breakadd func [lineNumber] functionName
breakadd file [lineNumber] fileName
breakadd here

# 移除断点
breakdel func [lineNumber] functionName
breakdel file [lineNumber] fileName
breakdel here

还有这些命令可以移除断点:

# 按照编号移除断点
breakdel {number}

# 移除全部断点
breakdel *

更多内容参考 :help debug

vim 启动后调试某个命令

例如我有一个函数InsertModeLeave(),当我离开插入模式(Insert)时会自动执行。

autocmd InsertLeave * call InsertModeLeave()

这个函数有问题,我想手动逐行运行这个函数看看问题在哪。相比上一节的内容,更简单的方式是在 vim 启动后进行调试。假如我想调试函数InsertModeLeave(),我可以这样:

  • 启动 vim(或 gvim)
  • 如果调用这个函数的前置条件有其他操作,先执行这些操作
  • 运行命令:debug call InsertModeLeave(),此时 vim 就会进入调试模式,窗口下方出现一个>提示符
  • 输入step,就进入了函数内部,程序在函数内第一行处暂停
  • 接下来就可以用本文上一节描述的命令进行调试了

命令:debug顾名思义就是用于调试的,它的一般用法是:

:debug CommandName

日志记录

把 vim 从头到尾进行的所有的操作记录到日志中,从日志中分析问题。

我暂时未用到这种调试方法,因此暂时留空。

零配置启动

如果遇到了某些玄学问题,不好定位问题在哪,可以把配置分到多个文件中,先以“零配置”的方式启动,然后逐个加载(source)这些配置文件,如果加载完某个配置文件后出问题了,那问题肯定出在这个配置文件内。

我暂时未用到这种调试方法,因此暂时留空。

结尾

是否掌握一项技能、一个工具,判断标准是:是否具备“将其搓扁捏圆,并且还能恢复原状”的能力。

如果不懂得 vim 脚本的调试,即便命令用得再熟,也很难讲用 vim 用得“明白”。

参考