Skip to main content

Vim as IDE

Posted in

I like vim very much and I often(nearly all the time) use it for development. But vim as it is just a text editor lacks some functionality, that is needed for development. It has completion through Ctrl+p, but It completes with proper words found in the given file and/or within the included headers. To make it more IDE-alike we will need the following plugins:

  • taglist
  • OmniCppComplete
  • NERD Tree
  • cscope vim mappings
  • cvim - *optional*

We will also need exuberant ctags installed.
Note: on Linux this is ctags, on FreeBSD this is exctags and *NOT* ctags.

NERDTree

This plugin will be used for working with filesystem without closing vim and without keeping a separate terminal running.

OmniCppComplete

Provides smart completion for both, 3rd party libraries and for the project you are working on.

cscope and taglist

These two are very useful to for navigation within your project. Expecially handy when you have to do a lot of code reading and investigation.

cvim

This plugin offers quick insertion of C/C++ statements, comments, idioms and file headers. To tell the truth I haven't used it for a long time.

In order to install these plugins, just follow the instructions of each plugin.

So, the plugins are installed, but that is not enough.

I want Shift+Alt+F9 to open/close theNEDTree and I want to be able to jump to it from any vim window(I mean split window) I have opened by pressing `. I add these two mapping to my .vimrc.

map <S-A-F9> :NERDTreeToggle<CR>
map ` :NERDTreeFind<CR>

One more thing to setup for NERDTree is files to ignore. I bet you will not want to edit object files, tilda files, shared and static libs and so on.

let NERDTreeIgnore=['.*\.o$']
let NERDTreeIgnore+=['.*\~$']
let NERDTreeIgnore+=['.*\.out$']
let NERDTreeIgnore+=['.*\.so$', '.*\.a$']

We are done with NERDTree. Taglist is coming next.
I want Shift+Alt+F10 to open/close the taglist.

map <S-A-F10> :TlistToggle<CR>:TlistAddFilesRecursive . *.{cpp,c,C,h,hpp,cc,cxx}<CR>

That's enough for taglist customization.

Now we need to make OmniCppComplete to work with tags that we will generate now.

map tags :!exctags -R --c++-kinds=+p --fields=+iaS --extra=+q . <CR>
set tags+=~/.vim/dev_tags/qt4.ctags
set tags+=~/.vim/dev_tags/gtk.ctags
set tags+=~/.vim/dev_tags/gtkmm.ctags
set tags+=./tags

Now we need to generate these tags. For example, for Qt 4 we will run

exctags -R --c++-kinds=+p --fields=+iaS --extra=+q /usr/local/qt.4.6.1/

and so on. Don't forget to run ctags for your project!

I have also defined the following function for easy cscope setup.

" Cscope plugin
function! CscopeSetup()
    let s:name=getcwd()
    let s:used_shell=$SHELL
 
    execute "!find . -name '*.cpp' -o -name '*.c' -o -name '*.C' -o -name '*.cc' -o -name '*.h' > cscope.files"
    execute '!cscope -q -b'
    " if [t]csh
    if stridx(s:used_shell, 'csh') >= 0
        execute '!setenv CSCOPE_DB '.s:name.'/cscope.out'
    else
        execute '!export CSCOPE_DB='.s:name.'/cscope.out'
    endif
 
    return
endfunction

Besides, I'm so lazy that I need a shortcut to switch between source and header.

map <S-F4> :execute Toggle_H_CPP()<CR>
 
function! Toggle_H_CPP()
    let l:ext=tolower(expand("%:e"))
 
    echo l:ext
 
    let l:new_ext = ""
    if l:ext == "c" || l:ext == "cpp" || l:ext == "cxx"
        let l:new_ext="h"
    elseif l:ext == "h" || l:ext == "hpp"
        let l:new_ext="c"
    else
        return
    endif
 
    let l:list=system("find . -name '".expand("%:t:r").".*' | grep -v \"~\" | grep -i \"\\.".l:new_ext."\" | grep -v \".svn/\" | perl -ne 'print \"$.\\t$_\"'")
    let l:num=strlen(substitute(l:list, "[^\n]", "", "g"))
    if l:num < 1
        echo "'".a:name."' not found"
        return
    endif
 
    if l:num != 1
        echo l:list
        let l:input=input("Which ? (CR=nothing)\n")
        if strlen(l:input)==0
            return
        endif
        if strlen(substitute(l:input, "[0-9]", "", "g"))>0
            echo "Not a number"
            return
        endif
        if l:input<1 || l:input>l:num
            echo "Out of range"
return
        endif
        let l:line=matchstr("\n".l:list, "\n".l:input."\t[^\n]*")
    else
        let l:line=l:list
    endif
 
    let l:line=substitute(l:line, "^[^\t]*\t./", "", "")
 
    """sf %:t:r.c
    execute "find ".l:line
endfunction

Wow, pretty big function...

We are now ready to start.

Whatever the directory structure of my project is I always run vim from the project's root directory. Even if the directory structure is huge, NERDTree will make it eaiser to navigate through it.

1.Start vim as 'vim .'
2.:execute CscopeSetup()
3.In normal mode type 'ctags', in case you haven't done this already.
4.Develop

Cscope with absoluthe pathnames in VIM

Hi, I wonder whether you has used such a thing. I'll be trying to build the Qt4 cscope database (in Windows), however when loading it in my project folder (in a different location), the database doesn't load properly, so I cannot navigate with cscope. I've tried with some workarounds, but none of them has succeded. Hope you can lead me toward a solution. Thanks =)

Re: Cscope with absoluthe pathnames in VIM

Hi. I prefer using cscope for the project I'm working on. As for the libraries that I use then ctags will be enough. So I used ctags for generating tags for Qt4. In general, this might be true for your case, unless you are developing Qt4 :)

The reasons I don't use cscope for 3rd party libraries:
1. The information that ctags provides, which includes function signatures, jumping to declaration are just enough for me as a user of some library, and I don't need to know which function calls this or that function and so on.

2. As far as I know (though I may be wrong) the way I tell which cscope database to use (through CSCOPE_DB variable) makes it possible to use only one db. At the same time, several tags files generated from ctags can be easily used.

But I'll try to setup cscope for your case.

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.
      o            OooOoo  OooOOo.    .oOOOo.    .oOOOo.  
O o O O O `O .O o .O o
o O o o o O o o
o o o O O .o o O
.oOoO OooOOo o oOooOO' o O .oOOo
o O O O o O o. O
O o o O o O `o .o O. oO
`OoO'o O `OooOO' o' `OoooO' `OooO'

Enter the code depicted in ASCII art style.