The company where I work develops software in C ++ for Linux. For a long time, we used Qt Creator, with rare guys working from Emacs and Vim. When I myself tried to transfer to Vim, I realized that the situation with plug-ins for C ++ development is not very simple. After working a bit with CTags, I quickly realized that without a file, working in Vim would be very difficult.
Unfortunately, with the growing experience with Vim, the editor in Qt Creator in emulation mode suited me less and at some point I decided to spend some time and figure out how to make Vim a normal environment.
I outlined for myself four things that I would like from the development environment, and which I would have been enough in Vim to go completely into it:
1. autocompletion
2. Code Navigation
3. Debugging directly from the environment
4. Integration with Git (in particular, Blame right in the editor, and Git Grep)
Autocompletion in Vim is a solved problem, and the name of the solution is
YouCompleteMe . This is a very high-quality plugin that implements auto-completion for a large number of programming languages, in particular Python and C ++. Rumor has it that inside Google YouCompleteMe solves the second problem with code navigation, but uses Google’s internal tools for indexing.
')
Integration with Git is to some extent solved by
vim-fugitive . This is not as complex integration as Jet Brains, or in Visual Studio, but is comparable to what Qt Creator offers. Those two scenarios that I needed: blame and grep - work well.
Debugging and navigation were problems solved much worse. In this article I will talk about the plugin that we wrote to navigate through C ++ code. At the end of the article I will also talk about how we solved the problem with the integrated debugger for ourselves.
Of course, as I mentioned above, CTags could be used for navigation, but if you worked with CTags, then you know that it does not solve the problem. The C ++ parser is very weak, and often CTags find completely wrong parts of the code.
On the Internet as a few years ago, and now, the only thing that is on the topic of navigation on C ++ code is
this article . I set up this plugin, and it basically worked. But there were many complaints, of which two are the biggest:
1. The indexing process must be started by hand.
2. It is impossible to find a symbol by its name.
In the end, it all ended with the development of our own plugin for Vim, which allows you to navigate through C ++ code. It requires the
Compilation Database . If CMake is used in the project, it is enough to call it to get it.
cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
Otherwise, you can either use
Bear , or build it with your hands, the format is very simple.
The plugin is called
CtrlK , and allows you to do the following things:
1. Go to the definition of the character under the cursor.
2. Search for all occurrences of the character under the cursor.
3. Search for a symbol by its name (FuzzyFinder is used for this, but unfortunately, the search is not Fuzzy, but only by a substring). The search works for functions, methods, classes, global variables, macros, and even function arguments and local variables.
4. Displays the name of the function, inside which the cursor is located, in the status bar. Very handy when editing large functions when its ad is off screen.
In addition, there is an experimental ability to show a separate window in which the definition of the character under the cursor is constantly displayed. I saw this opportunity only in the Source Insight environment, and its usefulness seems debatable, but I find it very convenient.
The plugin uses libclang to parse the code and leveldb for the index.
Like YouCompleteMe, the plugin consists of a server part and a client. Here, the server part refers to a process that runs in parallel with Vim, and which communicates with Vim. For installation, we went a little different way than YCM. If YouCompleteMe asks you to run Make with your hands after installing via Vundle, we instead installed the server part via pip.
At first it seemed that it was possible to write the entire plugin in Python, and not to do the server part, but the speed of parsing a large number of files through the clang library for python is very low, and I had to write it in C ++, which requires taking this functionality to a separate process and complicates the installation.
As a result, the installation is reduced to the installation of the Python libraries clang, leveldb and the server part of ctrlk:
sudo pip install leveldb sudo pip install clang sudo pip install ctrlk
(If sudo pip install ctrlk did not work)Historically, the pip package for ctrlk does not belong to me. There are two flaws in the current package - the dependence on ez_setup is not specified, it can be resolved by hand
sudo pip install ez_setup
And there are no header files and clang libraries. This is more likely to result in a compilation error, because the standard installation of clang / llvm does not put them where the compiler would find them without a hint.
Both of these problems are resolved in the repository, but so far the pip package has not been updated. If sudo pip install ctrlk fell with a compilation error, you can simply install it with your hands
git clone https://github.com/SkidanovAlex/py-ctrlk.git cd py-ctrlk python setup.py build sudo python setup.py install
Installing the plugin (as well as L9 and FuzzyFinder, on which CtrlK depends). The easiest way to do this is to use
Vundle :
Plugin 'L9' Plugin 'FuzzyFinder' Plugin 'SkidanovAlex/CtrlK'
And small settings in vimrc
let g:ctrlk_clang_library_path="/home/user/llvm/lib" nmap <F3> :call GetCtrlKState()<CR> nmap <Ck> :call CtrlKNavigateSymbols()<CR> nmap <F2> :call CtrlKGoToDefinition()<CR> nmap <F12> :call CtrlKGetReferences()<CR>
Where g_ctrlk_clang_library_path should point to the path to libclang.so. It can be found, for example, by running
locate libclang.so
After that, vim, launched from the compilation database directory (or any of its subdirectories), will start indexing the files, and after a while you can navigate through them. F3 will show the current status of the parser, Ctrl + K opens FuzzyFinder where you can search for characters, F2 jumps to the definition of a character, and F12 shows all the places in the code where the character under the cursor is used.
If you want the status bar to show the name of the current function, you can configure it, for example, like this:
hi User1 ctermbg=darkgreen ctermfg=black guibg=darkgreen guifg=black hi User2 ctermbg=gray ctermfg=black guibg=gray guifg=black hi User3 ctermbg=darkgray ctermfg=gray guibg=darkgray guifg=gray set statusline=%1*\ %{CtrlKGetCurrentScope()}\ %2*\ %F%m%r%h\ %w\ \ %3*\ %r%{getcwd()}%h%=%l:%c set laststatus=2
Here are two examples of work. In the first example, we launch Vim from the project folder, press Ctrl + K, and go to the file. This is not a very good example, because you can go to a file simply by using Fuzzy Finder or CtrlP, but you can also go to any class or other symbol in CtrlK.

In the second example, we again use Ctrl + K to find the RestoreStartWorker function, position the cursor on the CodePrinter class in it, and find all references to this class in the code by pressing F12. If we had pressed F2, then Vim would immediately jump to class definition.

In this example, there is a slight delay in finding all occurrences. In fact, it works instantly, but after the first opening of any file, it takes 1-3 seconds to parse it, and before the parsing ends, the transition to the definition and search for entries does not work.
In conclusion, a little about debugging. There are several plugins for debugging, and they are all very bad. I spent a few days, and still managed to install
PyClewn and make it work. PyClewn allows you to set breakpoints, look at local variables, monitor the output of a program directly from Vim, and allow you to enter commands for GDB. This is much less convenient than integration with QtCreator, for example, or with any other fully-fledged development environment, but a little better than running GDB in a separate terminal. PyClewn generally solved the problem, but wanted more.
My colleague wrote a plugin for Vim that uses TMux to run GDB next to Vim on the same screen, and either manage it directly from Vim (for example, set breakpoints, watch the values of variables), or switch to the GDB window and just work with GDB . Local variables, or fields of objects, can be viewed as a tree in the nerd tree. Unfortunately, the plugin has no documentation, but its installation is quite simple. You need to install two plugins via Vundle, and then configure vimrc.
Plugin 'ManOfTeflon/exterminator' Plugin 'ManOfTeflon/nerdtree-json'
If the standard nerdtree is already used, then it should be removed. nerttree-json is a fork of nerdtree, which allows you to expand its capabilities, and do lazy-computing elements of the tree.
Then here is an example of setting the exterminator from the plugin author:
Hidden text function! s:get_range() " Why is this not a built-in Vim script function?! let [lnum1, col1] = getpos("'<")[1:2] let [lnum2, col2] = getpos("'>")[1:2] let lines = getline(lnum1, lnum2) let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)] let lines[0] = lines[0][col1 - 1:] return join(lines, "\n") endfunction nnoremap <silent> & :exec 'VimGrep ' . expand('<cword>')<cr> vnoremap <silent> & :exec 'VimGrep ' . s:get_range() comm! -nargs=0 -range GdbVEval exec 'GdbEval ' . s:get_range() nnoremap <silent> <F6> :exec "GdbEval " . expand("<cword>")<CR> vnoremap <silent> <F6> :GdbVEval<cr> nnoremap <silent> <F5> :GdbLocals<CR> nnoremap <silent> <F4> :GdbNoTrack<CR> nnoremap <silent> <Insert> :GdbContinue<cr> nnoremap <silent> <End> :GdbBacktrace<cr> nnoremap <silent> <Home> :GdbUntil<cr> nnoremap <silent> <S-Up> :GdbExec finish<cr> nnoremap <silent> <S-Down> :GdbExec step<cr> nnoremap <silent> <S-Right> :GdbExec next<cr> nnoremap <silent> <S-Left> :GdbToggle<cr> noremap <silent> <PageUp> :GdbExec up<cr> noremap <silent> <PageDown> :GdbExec down<cr> function! s:start_debugging(cmd) cd $PATH_TO_EXECUTABLE exec 'Dbg ' . a:cmd endfunction command! -nargs=1 DbgWrapper call s:start_debugging(<f-args>) nnoremap <silent> <leader>B :DbgWrapper ./executable<cr>
Where $ PATH_TO_EXECUTABLE and ./executable are the path to the debugging program and its name.
With this configuration, in Vim running from TMux, you can start debugging via \ B, as a result of which TMux splits the screen in two, and starts in the second GDB associated with Vim. In particular, when moving through frames in GDB, Vim will show the code in the current frame, and from Vim you can use the hot keys to move through the frames, set breakpoints, execute the program step by step, and show the values of variables in the nerdtree. In particular, F5 will show the values of all local variables, and F6 will show the variable under the cursor.
The plugin code for navigating through C ++ and its server part is open and available on GitHub under the MIT License:
https://github.com/SkidanovAlex/CtrlKhttps://github.com/SkidanovAlex/py-ctrlkThe debug code of the plug-in is also open, and is available under the WTFPL license:
https://github.com/ManOfTeflon/exterminator