vim 的 grep 插件`Leaderf rg`: grep 和模糊匹配的完美结合 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Yggdroot
V2EX    Vim

vim 的 grep 插件`Leaderf rg`: grep 和模糊匹配的完美结合

  •  1
     
  •   Yggdroot 2019-01-14 22:13:08 +08:00 5740 次点击
    这是一个创建于 2466 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    vim 有很多著名的 grep 插件,我使用过的有 ack.vim ,ag.vim 和 ctrlsf.vim ,它们应该也是目前用户最多的几个了。

    1. ack.vim
      起步比较早,早期后端 grep 工具是 ack,后来也支持 ag(the_silver_searcher),pt(the_platium_searcher),rg(ripgrep)等工具了。它是一个比较传统的 grep 插件,不支持异步,要等到 grep 结束后才能显示结果,在大的项目中 grep 会卡好一阵子。它貌似也不再维护,我 N 久前提交的 pull request 还挂在那,它最近的代码更新在 11 个月前。
    2. ag.vim
      它其实是抄袭 ack.vim ,没错,是抄袭。在早期 ack.vim 还不支持 ag 时,它的作者在 ack.vim 代码的基础上稍微改了改,支持了 ag。后来被 ack.vim 的作者给怼了,就放弃了对 ag.vim 的维护。目前功能上小于 ack.vim 。
    3. ctrlsf.vim
      这是国人开发的一个插件, 后端 grep 工具支持 ack/ag/pt/rg,同时也支持异步,不过需要 Vim 8.0.1039+或者 NeoVim 才支持异步。这个插件很好用,在我开发Leaderf rg之前一直使用的是它。

    Leaderf rg顾名思义,后端基于 rg,由于是LeaderF的子功能,基因上就决定它完美支持异步。同时 LeaderF 又是一个非著名的模糊查找插件,这使它可以在 grep 结果的基础上再通过模糊匹配的方式进行二次过滤,来帮助用户更快地锁定目标,这是目前上面提到的插件所不具备的。

    为什么选择 rg(ripgrep)

    快速 grep 工具目前有 ag, rg, pt, sift, ucg 等。
    我选择 rg 有以下几点原因:

    1. 速度比较快,rg 的 README 上有作者的对比,我实测也是 rg 快点。
    2. Windows 上 bug 少( bug 到目前还没发现),ag 和 pt 都遇到过 bug。
    3. 作者很活跃,提的 issue 能很快得到回复。
    4. rg 功能相对多些,可以从rg --help 看出来。

    Leaderf rg 使用介绍

    Leaderf rg的使用也比较简单,只要Leaderf[!] + rg 命令和选项(同命令行上一样)就可以了。 具体使用方法可以用:Leaderf rg -h来查看。

    usage: Leaderf[!] rg [-h] [-e <PATTERN>...] [-F] [-i] [-L] [-P] [-S] [-s] [-v] [-w] [-x] [--hidden] [--no-config] [--no-ignore] [--no-ignore-global] [--no-ignore-parent] [--no-ignore-vcs] [--no-pcre2-unicode] [-E <ENCODING>] [-M <NUM>] [-m <NUM>] [--max-depth <NUM>] [--max-filesize <NUM+SUFFIX?>] [--path-separator <SEPARATOR>] [--sort <SORTBY>] [--sortr <SORTBY>] [-f <PATTERNFILE>...] [-g <GLOB>...] [--iglob <GLOB>...] [--ignore-file <PATH>...] [--type-add <TYPE_SPEC>...] [-t <TYPE>...] [-T <TYPE>...] [--current-buffer | --all-buffers] [--recall] [--append] [--reverse] [--stayOpen] [--input <INPUT> | --cword] [--top | --bottom | --left | --right | --belowright | --aboveleft | --fullScreen] [--nameOnly | --fullPath | --fuzzy | --regexMode] [--nowrap] [<PATH> [<PATH> ...]] optional arguments: -h, --help show this help message and exit specific arguments: -e <PATTERN>..., --regexp <PATTERN>... A pattern to search for. This option can be provided multiple times, where all patterns given are searched. -F, --fixed-strings Treat the pattern as a literal string instead of a regular expression. -i, --ignore-case Searches case insensitively. -L, --follow Follow symbolic links while traversing directories. -P, --pcre2 When this flag is present, rg will use the PCRE2 regex engine instead of its default regex engine. -S, --smart-case Searches case insensitively if the pattern is all lowercase, case sensitively otherwise. -s, --case-sensitive Searches case sensitively. -v, --invert-match Invert matching. Show lines that do not match the given patterns. -w, --word-regexp Only show matches surrounded by word boundaries. This is roughly equivalent to putting \b before and after all of the search patterns. -x, --line-regexp Only show matches surrounded by line boundaries. --hidden Search hidden files and directories. By default, hidden files and directories are skipped. --no-config Never read configuration files. When this flag is present, rg will not respect the RIPGREP_CONFIG_PATH environment variable. --no-ignore Don't respect ignore files (.gitignore, .ignore, etc.). This implies --no-ignore-parent and --no-ignore-vcs. --no-ignore-global Don't respect ignore files that come from 'global' sources such as git's `core.excludesFile` configuration option (which defaults to `$HOME/.config/git/ignore`). --no-ignore-parent Don't respect ignore files (.gitignore, .ignore, etc.) in parent directories. --no-ignore-vcs Don't respect version control ignore files (.gitignore, etc.). --no-pcre2-unicode When PCRE2 matching is enabled, this flag will disable Unicode mode, which is otherwise enabled by default. -E <ENCODING>, --encoding <ENCODING> Specify the text encoding that rg will use on all files searched. -M <NUM>, --max-columns <NUM> Don't print lines longer than this limit in bytes. -m <NUM>, --max-count <NUM> Limit the number of matching lines per file searched to NUM. --max-depth <NUM> Limit the depth of directory traversal to NUM levels beyond the paths given. --max-filesize <NUM+SUFFIX?> Ignore files larger than NUM in size. This does not apply to directories. --path-separator <SEPARATOR> Set the path separator to use when printing file paths. --sort <SORTBY> This flag enables sorting of results in ascending order. --sortr <SORTBY> This flag enables sorting of results in descending order. -f <PATTERNFILE>..., --file <PATTERNFILE>... Search for patterns from the given file, with one pattern per line. (This option can be provided multiple times.) -g <GLOB>..., --glob <GLOB>... Include or exclude files and directories for searching that match the given glob.(This option can be provided multiple times.) --iglob <GLOB>... Include or exclude files and directories for searching that match the given glob. Globs are matched case insensitively.(This option can be provided multiple times.) --ignore-file <PATH>... Specifies a path to one or more .gitignore format rules files. --type-add <TYPE_SPEC>... Add a new glob for a particular file type. -t <TYPE>..., --type <TYPE>... Only search files matching TYPE. Multiple type flags may be provided. -T <TYPE>..., --type-not <TYPE>... Do not search files matching TYPE. Multiple type-not flags may be provided. <PATH> A file or directory to search. Directories are searched recursively. Paths specified on the command line override glob and ignore rules. --current-buffer Searches in current buffer. --all-buffers Searches in all listed buffers. --recall Recall last search. If the result window is closed, reopen it. --append Append to the previous search results. common arguments: --reverse show results in bottom-up order --stayOpen don't quit LeaderF after accepting an entry --input <INPUT> specifies INPUT as the pattern inputted in advance --cword current word under cursor is inputted in advance --top the LeaderF window is at the top of the screen --bottom the LeaderF window is at the bottom of the screen --left the LeaderF window is at the left of the screen --right the LeaderF window is at the right of the screen --belowright the LeaderF window is at the belowright of the screen --aboveleft the LeaderF window is at the aboveleft of the screen --fullScreen the LeaderF window takes up the full screen --nameOnly LeaderF is in NameOnly mode by default --fullPath LeaderF is in FullPath mode by default --fuzzy LeaderF is in Fuzzy mode by default --regexMode LeaderF is in Regex mode by default --nowrap long lines in the LeaderF window won't wrap If [!] is given, enter normal mode directly. 

    注意:如果:Leaderf后面有感叹号,会直接进入 normal 模式;如果没有感叹号,则是输入模式,此时可以输入字符来进行模糊匹配过滤。可以用 tab 键在两个模式间来回切换。

    Leaderf rg基本支持 rg 所有的必要选项,用户如果对 rg 命令比较熟悉,可以在 vim 命令行内输入:Leaderf, 然后手敲 rg 命令,命令选项还可以通过 tab 来补全。 当然,更聪明的做法是定义一些快捷键。例如:

    " search word under cursor, the pattern is treated as regex, and enter normal mode directly noremap <C-F> :<C-U><C-R>=printf("Leaderf! rg -e %s ", expand("<cword>"))<CR> " search word under cursor, the pattern is treated as regex, " append the result to previous search results. noremap <C-G> :<C-U><C-R>=printf("Leaderf! rg --append -e %s ", expand("<cword>"))<CR> " search word under cursor literally only in current buffer noremap <C-B> :<C-U><C-R>=printf("Leaderf! rg -F --current-buffer -e %s ", expand("<cword>"))<CR> " search word under cursor literally in all listed buffers noremap <C-D> :<C-U><C-R>=printf("Leaderf! rg -F --all-buffers -e %s ", expand("<cword>"))<CR> " search visually selected text literally, don't quit LeaderF after accepting an entry xnoremap gf :<C-U><C-R>=printf("Leaderf! rg -F --stayOpen -e %s ", leaderf#Rg#visual())<CR> " recall last search. If the result window is closed, reopen it. noremap go :<C-U>Leaderf! rg --recall<CR> " search word under cursor in *.h and *.cpp files. noremap <Leader>a :<C-U><C-R>=printf("Leaderf! rg -e %s -g *.h -g *.cpp", expand("<cword>"))<CR> " the same as above noremap <Leader>a :<C-U><C-R>=printf("Leaderf! rg -e %s -g *.{h,cpp}", expand("<cword>"))<CR> " search word under cursor in cpp and java files. noremap <Leader>b :<C-U><C-R>=printf("Leaderf! rg -e %s -t cpp -t java", expand("<cword>"))<CR> " search word under cursor in cpp files, exclude the *.hpp files noremap <Leader>c :<C-U><C-R>=printf("Leaderf! rg -e %s -t cpp -g !*.hpp", expand("<cword>"))<CR> 

    参考:rg 的glob 语法

    顺便说一下,直接在 vim 命令行敲:Leaderf rg,就会有传说中的"grep on the fly"的功能哦,同时支持 fuzzy 和 regex 两种模式。

    会不会支持 ag 等其他 grep 工具

    不会。
    首先,ripgrep 已经足够强大,基本不存在别的工具有而 ripgrep 没有的功能。其次,ripgrep 有编译好的 Windows、Linux 和 MacOS 上的binary,可以在这些平台上很容易安装。再者,由于作者比较懒,不想再实现重复的功能。

    15 条回复    2019-02-26 21:39:17 +08:00
    iam070
        1
    iam070  
       2019-01-14 22:16:56 +08:00
    插件作者都来发帖了,必须支持。
    我记得 WIN 上的 GVIM 好像还需要 python 支持,就没有安装了:)
    xiaotianhu
        2
    xiaotianhu  
       2019-01-14 23:33:12 +08:00 via iPhone
    好东西 有空试试
    jdhao
        3
    jdhao  
       2019-01-15 00:08:09 +08:00
    为啥有 LeaderF 了还要再开发 LeaderF rg 呢。。
    Yggdroot
        4
    Yggdroot  
    OP
       2019-01-15 09:19:35 +08:00 via Android
    @jdhao Leaderf rg 只是 LeaderF 的一个功能。
    skyzone
        5
    skyzone  
       2019-01-18 08:59:21 +08:00
    LeaderF 确实好用,最近一直在用,赞一个

    我是 win7 远程 linux 用,有一点不太友好,就是查询输入只能手打
    常常 window 下复制了,粘贴不进去~只能粘贴进第一个字符
    还有输入时虽然支持 Ctrl-V,使用系统粘贴板,但是我的 linux 没有桌面,不能用粘贴板,Ctrl-V 也没用
    后面就把代码中 @*改成用 @0 了,就可以用 Ctrl-V 了,
    顺便写了个插件,使用 @0 时,远程同步 windows 系统下的粘贴板,才方便从 window 上直接复制粘贴内容
    hanxiV2EX
        6
    hanxiV2EX  
       2019-01-23 08:01:53 +08:00 via Android
    支持,我已经放弃 greper 插件,改用 rg 这个了,二次过滤太强大了。
    hanxiV2EX
        7
    hanxiV2EX  
       2019-01-23 08:07:29 +08:00 via Android
    @skyzone 你需要 lemonade 配合 neovim 使用,无缝共享粘贴板。

    https://github.com/lemonade-command/lemonade

    你可以参加我的配置,windows 下启动 lemonade server,linux 里配好 client,neovim 会自动检测出来,也可以像我这样配置。

    https://github.com/hanxi/dotfiles
    dangoron
        8
    dangoron  
       2019-01-23 14:20:44 +08:00
    跟 fzf 的 Rg 对比有什么优势呢?
    https://github.com/junegunn/fzf.vim#advanced-customization
    Yggdroot
        9
    Yggdroot  
    OP
       2019-01-23 15:51:53 +08:00   1
    @dangoron 我没有深入使用过 fzf 的 Rg,做一下评论,如果不对请纠正。
    fzf rg 有以下不足:
    1. 没有 normal mode,查看结果不是很方便。
    2. 不支持只在当前 buffer 以及所有打开的 buffer 中搜索。
    3. 如果已经搜索一个串'abc',按回车跳到 buffer 中去后,无法再打开上一次的搜索结果,需要重新搜索'abc'; Leaderf rg 可以用文章中提到的`Leaderf! rg --recall`来打开上一次的搜索结果。
    4. 不支持把当前搜索结果追加到上一次的搜索结果上。
    5. 不支持跳到某个搜索位置后仍保持搜索窗口打开状态,就像 quickfix 窗口一样。Leaderf rg 有`--stayOpen`
    6. Leaderf rg 可以像使用 rg 命令一样来用,比如某一次搜索只想搜索 aaa 和 bbb 目录,可以用`Leaderf rg -e xxx aaa bbb`; 某一次不想搜索 src 目录,可以用`Leaderf rg -e xxx -g=!src/`; 而 fzf rg 做不到这么方便,它需要每一种情况都要定义一个命令。
    dangoron
        10
    dangoron  
       2019-01-23 16:06:17 +08:00
    @Yggdroot 可能目前还没有这么复杂的需求,只在当前打开的 buffer 中搜索这个倒是很不错,谢谢你的回复
    skywind3000
        11
    skywind3000  
       2019-01-23 22:44:44 +08:00
    @Yggdroot 对了,Leaderf rg 搜索当前项目目录怎么弄? root marker 那个。
    pony279
        12
    pony279  
       2019-01-24 00:55:31 +08:00
    暂时还没有时间研究搜索插件,我现在对 FZF 的 complain 主要有两点:

    1. 每次使用后,vim 的 buffer number 就会递增, 后面开的 buffer number 很容易增长到几十甚至上百
    2. :FZF 启动后在 terminal 里面 on the fly filter, 这意味着 vim 无法记住我上一次 filter 用的关键字,每次需要重新输入,效率略低
    Yggdroot
        13
    Yggdroot  
    OP
       2019-01-24 07:43:00 +08:00 via Android
    @skywind3000 那个只是给 Leaderf file 用的,默认是在 cwd 开始搜索,还没有 root marker 那个功能。
    Yggdroot
        14
    Yggdroot  
    OP
       2019-01-24 10:20:45 +08:00
    @pony279 第二条与我上面说的第三条类似,这对于 fzf 来说确实很难实现。
    Yggdroot
        15
    Yggdroot  
    OP
       2019-02-26 21:39:17 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     913 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 19:59 PVG 03:59 LAX 12:59 JFK 15:59
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86