Skip to main content

Switching between .cpp and .h in vim

Posted in

When navigating through source code it is really nice to be able to jump from your source file to its header and vice verse. I used to use Toggle_H_CPP function described in my earlier posts. I wrote this function because I could not find any vim plugin that could that for me, especially when source and header are in different directories. Today I found a.vim plugin which can do such things. It is here. It allows to set g:alternateSearchPath variable and a.vim will look for a corresponding header/source in those directories.
However, if you have a rather big project to work on, then you might face some troubles. It appears that a.vim search in all those specified directories is not recursive. We could just add every single directory in your source tree to the search path, but as soon as you press :A (which is jump to a corresponding header/source) vim will freeze for some time, because it has to scan all those directories. I know that it depends upon a project. There are about 400 directories containing source and header files in my project and it takes too much time to jump to another file.
Here is how I solved this problem:

~/.vim/ftplugin/c.vim:

  1. if !exists("saved_default_alternateSearchPath")
  2.     let saved_default_alternateSearchPath = 1
  3.  
  4.     let g:defaultAlternateSearchPath = g:alternateSearchPath
  5. endif                                                                 
  6.  
  7. let g:alternateSearchPath = g:defaultAlternateSearchPath
  8.  
  9. " get top dir
  10. let s:path = GetProjectForFile(expand("%:p"))
  11. if s:path == ""
  12.     let s:path = getcwd()
  13. endif
  14.  
  15. let s:fname = strpart(expand("%:t"), 0, stridx(expand("%:t"), '.'))
  16.  
  17. let s:dirs = system("find ".s:path." -iname '".s:fname."*' | xargs -l dirname | sort -u ")
  18. let s:dirlist = split(s:dirs, "\n")       
  19.  
  20. for dir in s:dirlist
  21.     if stridx(g:alternateSearchPath, dir) == -1
  22.         let g:alternateSearchPath = g:alternateSearchPath.",abs:".dir
  23.     endif
  24. endfor

The idea is as follows, since ftplugin/c.vim script is read every time a file is being opened and we know file name we are going to see (let it be myFile.c) then, if I decide to jump to the header, then 100% I want to jump to myFile.{h,hpp,H,hh}. So, I should modify the search path to contain only a directory that has myFile.* in it and no other directories are needed. Some other directories may be needed when I open another file, but in that case ftplugin/c.vim script will be reread and it will take care of a proper search path. So, to put it in a nutshell, here what we do when we open myFile.c:

  • Lines 1-7: Reset g:alternateSearchPath to its default value, because we don't want this search paths to contain too many directories.
  • Lines 10-13: Get the projects top directory or current working directory. More about GetProjectForFile is here
  • Lines 18-21: Find a directory that has myFile.* in it
  • Lines 23-27: Add those directories to g:alternateSearchPath if they were not added before

Wow, now it works lightning fast. Well, much better than it used to be. Toggle_H_CPP is not needed anymore.... gone.

Post new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
infra_tructur_: