Navigating through a huge project with vim and unite.vim plugin

3.7k views Asked by At

I've been reading great things about Shougo's "Unite" plugin for Vim for a long time, so I finally decided to give it a try. If you're not already familiar:

One feature is the ability to recursively search through files/folders to search for something. Normally you would do something like this: "Unite file_rec/async". This will typically start the search in the current working directory (in my case, the directory where the current file I'm working on lives). I work in an extremely large codebase; almost 1 million files scattered in an often nonsensical, sometimes with source, binaries, and text files all mixed together. This means using the default unite file is just too slow, even if I'm running async with the vimproc plugin. My old solution to this problem (outside unite) was to run a nightly script which would build a list of every single ".cpp" and ".h" file, spit out their absolute path into a giant file, and then I'd grep that file to jump between things in the project. Seemed fairly reasonable, but I'm wondering if there's a better way.

I feel like I'm just scratching the surface with the possibilities Unite provides, and I'm thinking there must be some clever way to accomplish something similar using this plugin. It already supports referencing vim's ":ol" command which lists your most-recently-used files, so I suppose even just referencing my glob of all project source/header files directly with unite would be a good start. Are there any unite experts that have solved this problem? I'd even love to hear other people's solutions for quickly accessing all available source files in large projects similar to mine? Most people I work with just use Visual-Studios which has the ".sln" file containing everything you need... maybe I can just hijack/import that?

2

There are 2 answers

2
Lucky Mike On BEST ANSWER

Here's what I ultimately ended up doing

Build my filelist using this command

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

*Note that I'm stuck using a windows machine at work with Cygwin, so I have to convert the path to a windows-friendly path for actually referencing the file outside of a cygwin shell (ie. from within VIM). I also wanted to exclude certain directories, ie. the build folder

I created 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

*Note that this was just a quick implementation, I hardcoded the input file to be "filenamelist" when I should really be setting the input filelist as an incoming parameter and setting it in my .vimrc so i can toggle it based on the project I'm working on ;-)

After that, I just created a simple hotkey to call Unite filelist. It will load the split-window and let you search/select the file you want to open and then do the right thing fully integrated as a unite plugin.

6
Nishant On

Vim is a Text Editor and not an OS :-). Doesn't locate command just work?

Otherwise check tree -i -f -P "*.cpp|*.h". You could memoize the result using a shell script for the caching effect. It can be sourced it to Unite.vim I think.

If not try something like FZF https://github.com/junegunn/fzf for recursive search. The main idea is to keep giant operations outside of Vim. Vim is not meant for Asynchronous tasks like this. Blocking Vim for an activity like this will not be a nice experience because it is only a text editor and currently it lacks asynchronous support.

The real Vim/Unix way of achieving this is to interact with a good program that finds the result and load it into Vim. FZF/Selecta etc are good candidates. Few basic tips can be found at my blog: linuxesome.blogspot.com but it's a bit outdated.

Edit: Now vim has asynchronous support as of Vim > 8.0