Below is some code to create a plugin for Vim that sets enviroment (better) for a C project. I have made this very modular so you can adopt this for different languanges or situations. This should work for simple makefile type projects as well as "out-of-source-build" projects like CMake.
To make this a plugin, place this in a file (assuming you set vim's `packpath` variable like I said above):
~/.vim/pack/plugins/start/cpp-devel-vim/plugin/cpp-devel-vim.vim
This code will:
1. When a file of ".c" is opened we search for a makefile (upwards from the current location).
If we do not find a makefile, we look for some common out-of-source-build-directories and make the assumption we're using CMake or Xmake.
2. Set vim's internal $PATH to that location.
3. Generate a "make-string" to call make with (-e.g. make -f <location we found>)
4. Create an override for the built in ":make" command (just some convinencies).
I have tried to add pleny of comments for you to follow along if necessary--and make this super cool(er).
I honeslty hope this helps you (or someone).
To make this a plugin, place this in a file (assuming you set vim's `packpath` variable like I said above):
~/.vim/pack/plugins/start/cpp-devel-vim/plugin/cpp-devel-vim.vim
This code will:
1. When a file of ".c" is opened we search for a makefile (upwards from the current location).
If we do not find a makefile, we look for some common out-of-source-build-directories and make the assumption we're using CMake or Xmake.
2. Set vim's internal $PATH to that location.
3. Generate a "make-string" to call make with (-e.g. make -f <location we found>)
4. Create an override for the built in ":make" command (just some convinencies).
I have tried to add pleny of comments for you to follow along if necessary--and make this super cool(er).
I honeslty hope this helps you (or someone).
Code:
" vim: sw=4 sts=4 et
"------------------------------------------------------------------------------
" Some `public' overrides for an end-user to change if they want.
let s:MakeProgram = 'make'
let s:MakeCmdLineArgs = ''
let s:MakefileName = 'Makefile'
" `common' build directory names to search for; this will determine
" `projectRoot'. Much of this script uses `projectRoot' so this is
" these directories are essential to this scripts functionality if a
" `makefile` is NOT found first.
"
" I imagine a directory structure something like the following:
" ProjectName
" |
" +-- bin
" |
" +-- doc
" |
" +-- src
" | |
" ...
let s:BuildDirectoriesToSearch = [ 'bin',
\ 'build',
\ 'binary',
\ 'Development',
\ 'Debug',
\ 'Release',
\ 'src'
\ ]
let s:BuildFilesToSearch = [ 'makefile',
\ 'Makefile',
\ s:MakefileName
\ ]
" --------------------------------------------------------------------
" SetCppCodingStyle()
" Sets the current style based functions, like textwidth, path, brace
" and paren settings.
" --------------------------------------------------------------------
function! SetCppCodingStyle() "{{{
" Don't include these in filename completions
set suffixes+=.lo,.o,.moc,.la,.closure,.loT
"--------------------------------------------------------------
" Path Stuff
" Set the current working path to the same location where make
" is set to run from.
exe "cd " . s:PathToRunMakeFrom
let &tags = s:AssumedProjectRoot . '/tags'
" Include the typical unix include directories in the
" `path` variable.
let s:TypicalUnixIncludeDirectories = '/usr/include,/usr/local/include'
let &path = s:TypicalUnixIncludeDirectories . ',' . s:AssumedProjectRoot . ',' . '**7/'
" Allow `path' to search 7 levels deep.
" End Path Stuff
"--------------------------------------------------------------
call s:CreateCommands()
" Misc stuff
set shiftwidth=2
set sts=4
set et
set tw=100
set listchars=tab:?\ ,trail:?
" mark 'misplaced' tab characters
set list
iab i i
set incsearch
set errorformat+=%f:%l:\ %m
" Set the error format for the Clang compiler.
if &syntax == 'cmake'
call SmartParensOff()
set sw=3
set ts=3
set et
set tw=0
return
endif
endfunction "}}}
" --------------------------------------------------------------------
" s:CreateVariables()
" Creates the following variables:
"
" s:AssumedProjectRoot
" s:BinDirectory
" s:FileLocation
" s:MakefileLocation
" s:PathToRunMakeFrom
" --------------------------------------------------------------------
function! s:CreateVariables() "{{{
" -Find the assumed project root. The assumption being that a
" `makefile` is kept in the project root folder.
let s:AssumedProjectRoot = fnamemodify(s:File_Search(s:BuildFilesToSearch, ['.;']), ':p:h')
" -Find a build directory. The assumption being that a
" `CMakeLists.txt` file is kept in the project root but cmake
" will need to be run from within this bin folder.
let s:BinDirectory = s:Directory_Search(s:BuildDirectoriesToSearch, ['.;'])
" -A variable storing the current file being edited.
let s:FileLocation = fnamemodify(expand(getcwd()), '%:p')
" -Establish the directory to run make from.
" -Run this search frist, because the makefile location search
" may result in a different location and if it does this
" variable will be reset.
let s:PathToRunMakeFrom = fnamemodify(s:File_Search(s:BuildFilesToSearch, ['.;']), ':p:h')
" -Search for a makefile.
let s:MakefileLocation = s:File_Search(s:BuildFilesToSearch, ['.;'])
" -If the search for a makefile resulted in "." assume we are
" using a different build system than Make (like cmake or
" xmake) so we need to check the BIN folder.
if s:MakefileLocation == '.'
let s:MakefileLocation = findfile(s:BinDirectory . s:MakefileName, ".;")
let s:PathToRunMakeFrom = s:BinDirectory
endif
endfunction "}}}
" --------------------------------------------------------------------
" s:CreateCommands()
" Creates the following commands:
"
" :make : Overrides built in make command
" --------------------------------------------------------------------
function! s:CreateCommands() "{{{
"=============================================================================
"~ W A R N I N G ~
"=============================================================================
"The following section is a command override for the make
"command
"-----------------------------------------------------------------------------
:command! -nargs=0 Make :call Make()
" Create a command for the Make() function.
:cabbrev make <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'Make' : 'make')<CR>
" Override the built-in `make' command to use ours instead.
"-----------------------------------------------------------------------------
endfunction "}}}
" --------------------------------------------------------------------
" s:Directory_Search(directories, path)
"
" directories : The directories to search for.
" path : The path to start looking from and
" direction to search (up/down/both)
" --------------------------------------------------------------------
function! s:Directory_Search(directories, path) "{{{
let s:path = get(a:path, 'path', ['.;'])
for $dir in a:directories
if finddir($dir, s:path) != ""
" return expand(finddir($dir, ".;"))
return fnamemodify(expand(finddir($dir, ".;")), ':p')
endif
endfor
return "."
endfunction "}}}
" --------------------------------------------------------------------
" s:File_Search(files, path)
"
" files : The files to search for.
" path : The path to start looking from and
" direction to search (up/down/both)
" --------------------------------------------------------------------
function! s:File_Search(files, path) "{{{
let s:path = get(a:path, 'path', ['.;'])
for $file in a:files
if findfile($file, s:path) != ""
" return expand(findfile($file, ".;"))
return fnamemodify(expand(findfile($file, ".;")), ':p')
endif
endfor
return "."
endfunction "}}}
" --------------------------------------------------------------------
" MakeSetup()
" Locate the makefile and set the makeprog string.
" --------------------------------------------------------------------
function! MakeSetup() "{{{
let s:MakeProgString = s:MakeProgram . ' --directory="' . s:PathToRunMakeFrom . '" ' . ' --makefile="' . s:MakefileLocation . '" ' .s:MakeCmdLineArgs
let &makeprg=s:MakeProgString
endfunction "}}}
" --------------------------------------------------------------------
" Make()
" Custom Make() command.
" --------------------------------------------------------------------
function! Make( ) "{{{
" close the issues window
exe ":cclose"
" update : write source file if necessary
exe ":update"
" issue `make`
make
" open the issues window
exe ":botright cwindow"
endfunction "}}}
" ================================
" Autogroup settings.
" ================================
augroup CPPProgramming
autocmd!
autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call s:CreateVariables()
autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call SetCppCodingStyle()
autocmd BufNewFile,BufRead,BufEnter *.c,*.cc,*.cpp,*.h,*.hpp call MakeSetup()
augroup END