Assuming you have the makeprg
set up correctly:
let &l:makeprg = 'cd build && make'
The &l:
syntax for let
sets local variables; you can also use setlocal
but then you need to use backslashes, which is annoying.
You can make a command or keybind which 1) runs :make
or :makel
, which either populates or clears the quickfix window or locallist, and 2) runs your program if the quickfix window and locallist are empty.
Personally I like my MM
mapping:
nnoremap <silent> MM :silent! :wa<CR>:echo &makeprg<CR>:silent make<CR>:redraw!<CR>
To extend that we can add a new b:run
variable which contains a shell command to run. You probably want to set this from an autocmd as the commands are probably different per-project, and then add something like this to the mapping:
:exe get(b:, 'run') isnot 0 && len(getqflist() + getloclist('')) is 0 ? '!' .. b:run : ''<CR>
getqflist()
gets the quickfix list, and getloclist('')
gets the location list for the current buffer. Only of both are empty and b:run
is set do we run the command.
Putting it all together:
augroup run
au!
au BufNewFile,BufReadPost /path/to/my/project/*.c
\ let &l:makeprg = 'cd build && make'
\ let b:run = './build/bin/run --args'
augroup end
nnoremap <silent> MM :silent! :wa<CR>:echo &makeprg<CR>:silent make<CR>:redraw!<CR>:exe get(b:, 'run') isnot 0 && len(getqflist() + getloclist('')) is 0 ? '!' .. b:run : ''<CR>
That mapping becomes a bit ... much, so you can also put it as a command + mapping, or function + mapping:
command -nargs=* Make
\ silent! :wa
\| echo &makeprg
\| silent make <args>
\| redraw!
\| exe get(b:, 'run') isnot 0 && len(getqflist() + getloclist('')) is 0 ? '!' .. b:run : ''
nnoremap <silent> MM :Make<CR>