Использование Vim в качестве C/C++ IDE

Привет, Хабрахабр. Меня зовут Алексей и я занимаюсь тем, что разрабатываю встраиваемые операционные системы.

Сегодня я хочу рассказать, как я использую Vim в качестве IDE для C/C++ проектов.

Несмотря на то, что я использую Vim для C/C++, многие из рекоммендаций довольно общие и могут использоваться в любом проекте.

Первый шаг


Для начала, мы хотим иметь место, где можно будет сохранять настройки для своего проекта. Глобальный .vimrc нам не подходит, так как проектов много и они разные, а значит, каждый из них имеет свои специфические настройки.

В Vim есть подходящая для нас опция — exrc. Она говорит vim'у искать дополнительный .vimrc в текущей рабочей директории. Таким образом, мы можем иметь один файлик в корне каждого проекта с его специфическими настройками.

Так как vim будет подключать .vimrc из любой директории, из которой вы его запустите, желательно предпринять некоторые меры защиты и установить опцию secure. В основном, она запрещает внешним .vimrc писать что-то в файлы, выполнять комманды шелла и отображает маппинги, которые создаются.

В общем, нам нужно добавить следующие две строчки в наш главный .vimrc:
set exrc
set secure

Настройки конкретного проекта


После того, как мы получили возможность сохранять опции для каждого проекта в отдельности, почему бы нам этим не заняться.

У всех проектов есть какие-то свои правила касательно тех же отступов, так что просто пеместите нужные настройки в .vimrc в корне вашего проекта:
set tabstop=4
set softtabstop=4
set shiftwidth=4
set noexpandtab


Кроме этого, я стараюсь держать свои строки в пределах 110 символов. Но так как это очень специфично и сильно зависит от контекста, я не могу доверить такое важное дело как разбиение строк какому-либо редактору (даже vim). Но vim может помочь мне просто подсветив нужный столбец.
set colorcolumn=110
highlight ColorColumn ctermbg=darkgray

Определений типов файлов


По умолчанию, Vim предпологает, что все .h файлы это C++. Однако, часть моих проектов написаны на чистом C. Поэтому я хочу, чтобы тип файла был C. Кроме того, в моих проектах используется doxygen, так что я не против включить очень клевую подсветку doxygen в vim.

Для того, нужно добавить пару строк в локальный .vimrc:
augroup project
    autocmd!
    autocmd BufRead,BufNewFile *.h,*.c set filetype=c.doxygen
augroup END


Установка переменной path


В vim есть чудесная комманда gf (и родственные к ней), которая открывает файл, чье имя находится под курсором. Это неимоверно полезно при навигации по заголовочным файлам.

По умолчанию, vim смотрит файлы в текущей папке, а так же в /usr/include. Однако почти все проекты имеют заголовочные файлы, которые хранятся в других папках. Поэтому, нужно установить переменную path, которая содержит список папок для поиска, разделенный запятыми.
let &path.="src/include,/usr/include/AL,"

Заметка

Джавистам следует обратить внимание на опцию includeexpr. Она содержит выражение, которое будет использовано для преобразования строки в имя файла. Следующая строка заменяет все точки на слеши для gf. Таким образом, можно прыгать по import'ам.
set includeexpr=substitute(v:fname,'\\.','/','g')

Автодополнение


Лучший(Устарело. Сейчас я использую YouCompleteMe. Обратитесь к моему посту за деталями) Хороший плагин для автодополнения C/C++ кода, который я нашел, это clang_complete (инструкции для установки смотри на страничке плагина).

Он использует clang для того, чтобы сгенерировать список дополнений. И работает отлично для C и C++ (а так же еще пары языков).

Для того, чтобы clang знал о ваших папках с заголовочными файлами, нужно добавить -I и -D флаги в файл .clang_complete в корне вашего проекта. После этого, clang_complete будет автоматически вызываться при нажатии "." или "->".

Подсказка

Если path опция уже заполнена, то можно легко вставить список I-флагов с помощью следующей нехитрой комбинации клавиш
"='-I'.substitute(&path, ',', '\n-I', 'g')<CR>p


Другие clang плагины


Clang не просто компилятор, а еще и набор полезных библиотек для анализа и манипуляций с кодом. Таким образом, это очень хорошая основа для разнообразных плагинов. Так что в ближайшем будующем можно ожидать множество основаных на нем плагинов.

Навигатор


Для того чтобы отображать дерево проекта можно воспользоваться либо отдельными плагинами (NERD Tree например), либо встроеным netrw.

Я не использую ни один из способов, так как мне вполне комфортно выбирать файлы прямо из коммандного режима vim. (если установить wildmode в longest:list,full, то vim показывает подходящие файлы как нормальный шелл)

Настройка системы сборки


После того, как мы разобрались с редактированием и навигацией по файлам, можно собирать проект. В vim есть комманда make. По умолчанию, она запускает make в текущей директории и парсит вывод на наличие ошибок.

Фактическая комманда для выполнения хранится в makeprg. Если проект собирается в другой папке, использует другие параметры make или вообще использует другую систему сборки, нужно просто изменить makeprg чтобы отобразить это:
set makeprg=make\ -C\ ../build\ -j9


После этого, можно собирать проект просто напечатав :make.
Но так как нам этого мало, можно повесить эту комманду на одну из ненужных кнопок. Например:
nnoremap <F4> :make!<cr>

("!" предотвращает от прыгания на первую ошибку)

Настройки системы запуска


После того, как проект собран, вполне логично запустить его. Vim может запускать любую программу, для этого всего лишь нужно добавить восклицательный знак перед ее именем в коммандном режиме. Так, чтобы запустить мою супер-пупер программу, нужно набрать :!./my_great_program.

Конечно, это тоже нужно упростить!
nnoremap  :!./my_great_program<cr>


Система контроля версий


Так как vim предоставляет прямой доступ к коммандной строке, я не использую какой-либо специальный плагин для этих задач и просто управляю своим git-деревом прямо из шелла.

Но я должен отметить, что есть множество отличных vim плагинов для работы с разными системами контроля версий.
Например, fugitive. Если вы работаете с git, вы абсолютно должны посмотреть вимкасты fugitive.

Забытый пункт: отладка


Так как я чувствую себя комфортно в command-line gdb, да и специфика операционных систем делает почти невозможным отладку их отладчиками, за прошедший год я запускал gdb лишь однажды. В основном, все мои проекты я отлаживаю обычными print'ами и капелькой мозгов. Так что в моем vim нет ничего, чтобы напоминало отладчик.

Однако, я должен сказать, что существуют несколько плагинов для интеграции gdb и vim. Например, clewn, gdbvim.

Итог


После серии несложных оперций, vim превратился в вполне себе сносную IDE. Буду рад услышать о дополнительных настройках, которые облегчили вашу жизнь в vim и позволили лучше интегрировать его с окружающими инструментами.
Share post

Similar posts

Comments 16

    0
    ctags помогает переходить по функциям.
      0
      YouCompleteMe тоже это делает. И вроде как должен делать лучше, так как учитывает контекст (не могу утверждать, так как не юзаю эту фичу).

      Из не-clang альтернатив довольно хорошо работает cscope. Использовал его, чтобы копаться в исходниках Линукса.
        0
        YCM учитывает контекст только в текущем компилируемом юните. Т.е. он может найти определение во включенном хедере, но не перейдет от одной имплементации к другой.
          0
          С макросами он вроде тоже не очень дружит.
      +17
      Признайтесь честно, вы просто не знаете как из него выйти? :)
        +1
        В бородатые 90е, попался мне диск с FreeBSD одной из первых версий, с mc все было понятно, но редактор по-умолчанию там был vim. И единственный известный мне способ выйти из него был — кнопка reset :)
          0
          Я так когда-то выходил из редактора Turbo Pascal 3.0 :) А правильно было — Ctrl-K D.
        0
        У меня тоже сборка в Vim через make. Висит примерно на такой функции:

        function! MakeProject()
          execute "silent update"
          execute 'echo system("cd ..\\PROJECT_DIR && nmake")'
        endfunction
        


        При этом вывод make'а идет в том же окне, где код, таким же образом, как если, например, набрать :ls
        Мне кажется, удобно, потому что смотришь в код и не теряешь контекст.
        Upd. Это под Windows.

          0
          :make не просто компилирует проект, он еще и парсит вывод на ошибки компиляции и добавляет их в quickfix и можно прыгать по ним обычными :cnext и :cpre.

          Кроме того, по сравнению с этим решением, экран не блокируется до того, как сборка полностью закончится, а плавно выплевывает весь вывод по ходу его поступления.

          Ну и в моей системе, вывод потом всё равно разростается на весь экран и полностью закрывает собой код.

          Хорошой альтернативой обычному make вижу только всякие background-make'и.
            0
            И еще одно. Для константных строк execute это то же самое, что и просто написать комманду.

            То есть, эта функция эквивалентна вашей.
            function! MakeProject()
              silent update
              echo system("cd ..\\PROJECT_DIR && nmake")
            endfunction
            
            0
            А, понятно, в случае C и С++, наверное, удобнее как у вас. У меня просто другая ситуация — сборка обычно очень быстрая, вывод make'а короткий и содержит в основном информацию либо «Скомпилировалось ОК», либо «Ошибка на такой-то строке».
              0
              Вы можете попробовать настроить опцию errorformat и научить Vim прыгать прямо на место с ошибкой.
              0
              спс, вспомним былое.
              ЗЫ: месяц как вернулся на vim в основном frontend
                0
                Пишу на C/C++ в Vim уже года 3. Другого уже и не надо. Добавлю свои пять копеек:

                1. Попытки пересесть на Sublime привнесли в мой конфиг отличный плагин CtrlP (kien/ctrlp.vim)
                2. Индексация ctags + vim-scripts/indexer.tar.gz (спасибо хабраюзеру dimonomid)
                3. Частенько приходится работать через ssh, с помощью vim-scripts/CSApprox разница между gvim и vim почти полностью пропадает (главное не забыть выставить 'export TERM=xterm-256color'). А screen позволяет остановиться и продолжить с того же места в следующий раз.
                4. Следуя за модной тенденцией vimrc можно разбить на отдельные части и сложить в директорию vimrcd, подгружая все содержимое с помощью:
                :runtime! vimrc.d/*.vimrc

                5. После поста Пора завязывать использовать пробелы вместо табуляции в коде хабраюзера TheShock Сделал себе такую штуку и забыл о проблеме пробелы\табуляция:
                set list listchars=tab:>-,trail:.,extends:>,precedes:<

                6. cmake/make и vim: все мои проекты на cmake, поэтому процесс разработки начинается так:
                mkdir build
                cd build
                cmake ../
                gvim ../*

                Сборка из vim'а делается командой :mak, при этом если будут ошибки, vim встанет на нужную строчку. Переход к следующей выполняется командой :cnext
                7. Раньше пользовался такой штукой как :mks для сохранения текущего состояния, но потом перешел на ssh и уже упомянутый screen.
                  0
                  3. Я в течении этого года отказался от gvim полностью, хотя раньше довольно яро отстаивал его использование. Причина довольно проста, наличие полноценного терминала под рукой перевешивает все плюсы gvim'а (из gvim не запустишь ncurses приложения и не сделаешь Ctrl-Z).

                  По поводу самого CSApprox. Я использую небезизвестную тему solarized, которая отлично ведет себя в консоле.

                  6. У меня тоже имеется парочка проектов на cmake, но эти шаги одноразовые при настройке проекта. После этого, вышеуказанной коммандой я говорю vim собирать из папки, где cmake создал makefile и всё работает просто чудестно.
                    0
                    Запустишь, есть ConqueTerm :)

                Only users with full accounts can post comments. Log in, please.