Vim quickfix 模式的妙用
公司里有一批祖传脚本,代码写得又长又臭,领导让你重构。既然要重构,就难免要修改代码中的变量和函数,但是Shell语言目前并没有IDE之类的工具,没办法进行代码智能重构,所以我们在重构变量/函数的时候不能自动地把相关的引用代码一起修改掉,怎么办呢?
这时候就轮到编辑器之神Vim出场了,我们可以活用Vim的quickfix模式来修改所有与重构相关联的代码,而且只需三个步骤。
第一步是定位。Vim需要quickfix列表来确定哪些位置需要fix,这里有两个问题,第一个是我们如何找到需要修改的位置,第二个是如何输出符合格式的quickfix列表。对于前者,我们可以用grep命令来解决,对于后者,在grep的输出中添加位置信息即可,完整的命令为:grep --recursive --line-number 'regexp' /path/to/grep
。
第二步是传参。有了quickfix列表后,我们还需要用vim -q file
命令来激活quickfix模式,看到这里,你可能会以为我们需要把第一步得到的grep输出存到一个文件里提供给Vim,但这里我们可以利用Bash的Process Substitution功能,直接把grep命令的输出当成文件传给Vim,命令的形式为vim -q <(grep 命令)
。
第三步是编辑。激活了quickfix模式后,就是我们用Vim大展身手的时刻了。quickfix模式下我们可以用 :cn[ext]
/ :cp[revious]
命令来跳转到下一个/上一个需要编辑的位置,然后逐个进行修改。但是,只是这样操作的话,哪里对得起Vim编辑器之神的名号?所以这次我们来一波“执行→重复→回退”的Vim套路:使用了quickfix命令后,上一次执行的命令会保存在:
寄存器里,我们可以用@:
命令调用:
寄存器里的命令,然后再用@@
命令重复执行上一次@{寄存器}
命令。这样我们就能用@@
命令快速遍历quickfix列表,而不用一遍遍地敲:cn[ext]
/ :cp[revious]
命令了。要是想再进阶一点的话,我们还能组合一下录制寄存器的功能,把两个quickfix命令分别录制到不同的有名寄存器里,然后@{寄存器}
命令进行快速调用,这里就不展开细讲了。
总结一下上面的三个步骤,其实就是下面的一条命令和一张状态图。
vim -q(1) <((2) grep –recursive –line-number(3) ‘regexp’ /path/to/grep)
- -q 选项激活quickfix模式
- 用Bash的Process Substitution功能将grep的输出当成文件传给Vim
- –line-number选项调整grep输出格式
digraph G {
rankdir=LR
empty[label="寄存器 :|" shape=record]
copied[label="寄存器 :| :cnext" shape=record]
history[label="@@记录| :cnext" shape=record]
empty -> copied [label="执行:cnext命令"]
copied -> history [label="执行@:命令"]
history -> history [label="执行@@命令"]
}
从上面的总结我们可以看到,Vim的强大之处在于它丰富的模式和命令,以及可以组合各种编辑操作的灵活性。这些优点让我们几乎总是能制定高效的Vim方案来满足我们的编辑需求。希望大家以后能多探索一下Vim中没使用过的模式和命令,并尝试一下组合这些操作,说不定以后你也能找到自己的Vim妙招呢。