本文来自依云's Blog,转载请注明。
缘起
在一群文件里搜索特定的文本,第一个想到的工具是经典的 grep。自从知道 ag——The silver searcher 之后,我就只在命令行管道里用 grep 啦。
ag 的优势:
- 命令短
- 和 ack 以及 git grep 一样,默认会忽略掉你通常不想看的文本(二进制文件、被版本控制系统忽略掉的文件)
- C 编写的,比 ack 更快!
作者挺在乎程序的执行效率。这也很重要,因为文件多啊,几十上百兆的源码找起来可费时了。
不过在我这里,ag 取代掉的既不是 grep 也不是 ack。因为我之前用的是 cgvg,和 ack 一样也是 Perl 写的,但不一样的是,它包含两个命令:一个(cg)用来搜索,另一个(vg)用来在编辑器里打开!
不知道为什么其它工具的作者都没有想到这一点。匹配的地方找到了,大部分情况都需要用编辑器打开看看,也许再改改吧?cgvg 免去了复制路径到编辑器里并跳转到特定位置这一烦琐的步骤。
所以换用 ag 之后,我自然也希望能够很便利地使用编辑器查看匹配的地方了。为此,我做了三个工具。好吧,其实有一个是在 cgvg 时代就已经有了的。
搜索
实践一下。假设我要寻找 Vim 源码中涉及到p_enc
变量的地方。使用 agg 命令来搜索并使用翻页器 less 显示结果(截图时没有显示出 less 的存在):
agg 脚本更改了 ag 的显示样式,每一项开头都有一个序号,就和 cg 命令一样。同样地,agg 也把这个结果保存在主目录下的一个文件,以供 agv 命令使用。
注意,agg 并不能用来按文件名搜索。这种情况还是用 ag -g pattern
。
使用编辑器打开
agv 命令不给定参数,会显示上一次搜索的结果。如果给出一个编号,就会将结果在AGV_EDITOR
环境变量指定的编辑器里打开,并跳转到对应的地方。和 vg 不同的是,agg/agv 为每一个终端维护了一个结果列表,这样就可以在不同的终端里搜索不同的内容而不会相互干扰了。
比如我们要去第 14 号结果所在的地方,只要执行agv 14
,然后就到了:
我这里是在已有的 gVim 里打开的哦。因为我设置的AGV_EDITOR
的值是vv $file:$line:$col
。这是一句包含占位符的 shell 命令。$file
、$line
和$col
分别是结果所在的文件、行号、列号。而vv
,则是我写的另一个工具,用来在已经打开的 gVim 里打开文件,并且跳转到特定的地方。
vv 需要 Python easygui 库,以及 gVim(或者 Vim)的 +clientserver 支持。vv 不仅支持上述格式的参数,作为一名 Pythonista 所编写的工具,它也支持从 Python 报错时打印的 Traceback 的行中提取文件名和行号。比如:
vv 'File "/usr/lib/python3.4/sre_parse.py", line 358, in _parse_sub'
这里,不一定要复制一整行。包含必要的信息(文件名和行号)就可以了。
当然,手动复制粘贴比较累。所以配合我的 zsh 全局别名:
alias -g XS='"$(xsel)"'
我只需要选中那一行,然后执行
vv XS
就可以了。zsh 会帮我把XS
展开成我刚刚选择的文本。
ag.vim
ag.vim 是一个 ack.vim 的修改版,用于在 Vim 中调用 ag,就像 ack.vim 在 Vim 中调用 ack、grep.vim 在 Vim 中调用 grep 一样。
因为经常搜索在当前光标下的内容,我写了这么一条自定义命令:
command Agg exe 'Ag -Q ' . expand('<cword>')
Jul 19, 2014 10:00:32 AM
……你造轮子了……搜一下 sack 和 ctrlsf 吧……
Jul 19, 2014 11:44:30 AM
ctrlsf 我不太喜欢。我没有那么大的空间放它那个垂直分割的结果窗口。
至于 sack,那个 profiles 我不知道有什么用,特别是对于一个 autojump + zsh 用户。它在不同终端中不能使用不同的结果集。修改 $PATH 中的文件也不是什么好主意。它支持的编辑器也有限,并且无法跳转到结果所在的列。
所以如果要算造轮子的话,那也是造了一个更适合自己的轮子。
Jul 21, 2014 05:45:36 PM
有时 Traceback 显示的文件会是相对路径(比如直接 python a.py 的时候),可不可以让 vv 如果没有绝对路径时自动根据当前终端的工作路径来获取文件呢?
Jul 21, 2014 05:47:42 PM
对不起。。。。。
Jul 21, 2014 06:00:46 PM
原来是支持的。。。不过有点错误:
In [3]: vv.parseLineno('File "test.py", line 3')
Out[3]: ('+3', '/home/xxx/Documents/Programming/python/search-and-view/y')
Jul 21, 2014 07:05:45 PM
solved.
Jul 24, 2014 10:39:08 PM
太高端了,这是命令行的vim吗?我用了一下命令行的vim版本感觉自己简直无从下手。。
Jul 25, 2014 12:05:56 PM
前边那个截图是终端,后一个是 gvim。
Jul 25, 2014 12:06:44 PM
Vim 需要时间学习的。你可以在终端里执行 vimtutor 然后就有教程了。
Mar 20, 2015 04:04:30 PM
支持一下博主
May 31, 2015 03:57:11 PM
ctrlsf现在可以水平放置窗口,也可以调整大小了。
ctrlsf因为浏览可以使用预览模式,编辑也基本可以通过(最近新加的)编辑模式完成,90%的情况下不需要(在开着ctrlsf窗口的情况下)离开ctrlsf窗口,所以才把默认的体积设定得比较大。如果作为quickfix窗口的替代品来用的话可能确实不太好用。