使用vim和unite.vim插件浏览大型项目

3
我已经听说过Shougo的“Unite”插件很长时间了,所以最近我终于决定试试看。如果你还不熟悉的话: 其中一个功能是能够通过递归搜索文件/文件夹查找某些内容。通常你会这样做: "Unite file_rec/async"。这通常会在当前工作目录(在我的情况下,就是我正在工作的文件所在的目录)开始搜索。我在一个非常庞大的代码库中工作,有近100万个文件散布在一个常常无意义的地方,有时候混杂着源代码、二进制文件和文本文件。这意味着使用默认的unite文件仅仅是太慢了,即使我使用vimproc插件异步运行也一样。我之前解决这个问题的方法(在unite之外)是运行一个每晚执行的脚本,该脚本会建立一个所有“cpp”和“h”文件的列表,将它们的绝对路径输出到一个巨大的文件中,然后我通过grep命令来在项目中快速跳转。这种方法看起来相当合理,但我想知道是否有更好的方法。
我觉得我只是挖掘了Unite提供的可能性表面,我认为一定有一些聪明的方法可以使用这个插件实现类似的功能。它已经支持引用vim的“:ol”命令,该命令列出你最近使用的文件,所以我想甚至只是直接引用我所有项目源/头文件的全局变量也是一个不错的开始。有没有Unite专家解决了这个问题?我甚至很乐意听听其他人在访问类似于我这样的大型项目中的所有可用源文件时的解决方案。我工作的大多数人都只是使用Visual-Studios,其中包含了".sln"文件,该文件包含了你需要的所有内容...也许我可以劫持/导入那个文件?
2个回答

5

这是我最终采用的方法

使用以下命令构建我的文件列表

 find "$(cygpath -aw "$PWD")" -iname *.cpp -o -iname *.h -o -name build -prune > filenamelist

注意,我在工作中使用的是Windows机器和Cygwin,因此必须将路径转换为适用于Windows的路径,以便在Cygwin shell之外引用文件(即从VIM内部)。 我还想排除某些目录,例如构建文件夹。
我创建了unite.vim\autoload\unite\sources\filelist.vim:
let s:unite_source = {
      \ 'name': 'filelist',
      \ }

function! s:unite_source.gather_candidates(args, context)
    let filelist_path = "filenamelist"
    let filenamelist = readfile(filelist_path)

    return map(filenamelist, '{
            \ "word": v:val,
            \ "source": "filelist",
            \ "kind": "filelist",
            \ }')
endfunction

function! unite#sources#filelist#define()
    return s:unite_source
endfunction

And unite.vim\autoload\unite\kinds\filelist.vim

let s:kind = {
      \ 'name': 'filelist',
      \ 'default_action': 'load',
      \ 'action_table': {},
      \ 'parents': [],
      \ }

let s:kind.action_table.load = {
      \ 'is_selectable': 1,
      \ }

function! s:kind.action_table.load.func(candidates)
  if len(a:candidates) != 1
    echo "candidates must be only one"
    return
  endif
  execute "open " a:candidates[0].word
endfunction

function! unite#kinds#filelist#define()
  return s:kind
endfunction

请注意,这只是一个快速实现,我将输入文件硬编码为“ filenamelist”,而实际上应该将输入文件列表设置为传入参数,并在我的 .vimrc 中设置它,以便根据我正在处理的项目进行切换;-)

之后,我只需创建一个简单的热键来调用 Unite 文件列表。它将加载分割窗口并让您搜索/选择要打开的文件,然后完全作为 unite 插件进行集成。


1
现在Unite已经有了这个功能的源代码(https://github.com/Shougo/unite.vim/commits/master/autoload/unite/sources/file_list.vim)! - idbrii
很棒的解决方案!每当您重命名文件或添加/删除文件时,您是否需要重新运行查找命令? - Niko Bellic

4
Vim是一个文本编辑器,而不是操作系统 :-). "Doesn't locate command just work?" 命令不能正常工作吗?否则请检查 "tree -i -f -P "*.cpp|*.h"" 命令。您可以使用shell脚本来进行缓存处理,以达到记忆化的效果,并将其源代码加载到Unite.vim中。如果不行,请尝试像FZF这样的递归搜索 https://github.com/junegunn/fzf 。主要思想是将巨大的操作保持在Vim之外。Vim不适用于此类异步任务。阻塞Vim进行此类活动将不是一种愉快的体验,因为它只是一个文本编辑器,目前缺少异步支持。实现这一点的真正Vim/Unix方式是与好的程序交互,找到结果并将其加载到Vim中。FZF/Selecta等都是不错的选择。我的博客上有一些基本提示:linuxesome.blogspot.com,但它有点过时。编辑:现在vim已经支持异步处理,需要Vim > 8.0版本。

3
+1 我使用 fzf 来处理非常大的项目,而且 fzfvim 中表现良好。 - Roman Kiselenko
1
是的。它非常适用于大型项目,并且与Vim完美集成。 - Nishant
FZF 在这方面似乎提供了与 Unite 相同的功能。使用 vimproc 和 Unite,只需启动一个预编译的二进制文件(在 vim 外部),它将处理搜索并返回结果,因此它是非阻塞(异步)操作。Locate 可以工作,但不是理想的选择,因为可能有多个分支具有相同的文件。我希望结果仅限于我的当前项目。我相信我可以限制 locate 的结果,但也必须有其他选项。理想情况下,我应该能够生成一个包含所有源/头文件的文件,并配置 Unite 引用该文件。 - Lucky Mike
@LuckyMy 当我在大型项目中使用异步时,我的UI确实被阻塞了。Shougo本人建议不要在超过10000个文件的大型项目中使用它。看看我编辑的tree命令,那也可能起作用。你的第一个关注点应该是这样一个大型项目。即使Linux只有45K个文件 :) - Nishant
1
我最终使用了find命令而不是tree命令,因为tree命令会将目录作为单独的行输出。 - Lucky Mike
1
我告诉过你,避免使用插件来处理繁重的工作 :-)。是的,find命令可能更强大,是一个很好的替代方案。我有过这样的情况,我发现简单的Unix工具确实做得更好。FZF是它的一个包装器,如果你想要模糊搜索和一个简单的Vim集成——比如打开文件、目录等——那么它就是你需要的。我的意思是,现在你得到的结果是在bash中的,将该结果以简单的方式集成到Vim中打开,这就是FZF的作用。它只是简单的标准输入输出,所以你可以决定要使用哪个vim命令或自定义函数来处理输出。请查看我的博客。 - Nishant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接