bitmask
bitmask

Reputation: 34628

How to make vim pretend to have a flat source directory from a complex tree?

I often find myself working in projects with directory structures similar to this:

a/
  x/
    file1.h
  y/
    file2.h
  z/
    file3.h
b/
  u/
    file4.cpp
    file5.h
  v/
    file6.cpp
    file7.cpp
  w/

where source files are spread over all the directories.

I have a shortcut such that saying Ctrl+n opens a :tabnew prompt, but I still find it cumbersome to find the file I want myself by just typing/auto-completing the directories, as I have to remember where a particular file that I want to open lives.

Can I get vim to pretend the entire directory structure to be flat, or rather do a find and then open? I'd like to still have auto completion. Of course, there could be name clashes in theory, but for most cases you wont have files of the same name in separate directories even if you technically could.


So what I want is for the source directory to appear as if it looked like this:

    file1.h
    file2.h
    file3.h
    file4.cpp
    file5.h
    file6.cpp
    file7.cpp

Allowing me to type something like :magiccommand f<TAB>2<TAB> to open a/y/file2.h.

Upvotes: 1

Views: 96

Answers (3)

bitmask
bitmask

Reputation: 34628

I wound up using a solution inspired by dash-tom-bang's answer, which is essentially independent of the project and its tree structure.

map <C-b> :tabfind 
imap <C-b> <C-o><C-b>
set path=.,,**,/usr/include

The drawback is that I shouldn't use <C-b> in my home directory or a similarly full directory. But for that I recommend to fallback to:

map <C-n> :tabnew 
imap <C-n> <C-o><C-n>

Upvotes: 0

dash-tom-bang
dash-tom-bang

Reputation: 17853

:help 'path'

In your case, something like this:

:set path=/path/to/a/**,/path/to/b/**

Then :tabf file4.cpp. So change your shortcut to be :tabfind instead of :tabnew.

I'd also suggest that you look into using ctags, because then you can jump directly to symbols in any file in your project with :tag MyExcellentFunction (or :stag .. or :tab stag ...).

If you do end up using tags and drop your tags file in the project root, this'll help you out:

function! SetUpPath(filepath)
    setlocal path=
    for l:tagfile in tagfiles()
        let l:tagpath = fnamemodify(l:tagfile, ":h")
        execute "setlocal path+=" . fnameescape(l:tagpath) . '/**'
    endfor
    setlocal path-=.
    setlocal path-=
    setlocal path-=
endfunction

autocmd BufEnter * call SetUpPath(fnamemodify(expand("<afile>"), ":p"))

(This could also be modified to look for .git or .svn directories if that's your pleasure.)

Upvotes: 1

Luc Hermitte
Luc Hermitte

Reputation: 32926

There exists several fuzzyfinders that help to accomplish that -- I even wrote one a long time ago.

You can also stick to vanilla Vim and use starstar: :sp **/f*2<tab>.

If you set 'path' correctly, you could also type :find +sp f<tab> (it doesn't seem to work with :tabedit though).

Upvotes: 3

Related Questions