I would like to use vim as a c++ IDE. Is there a possibility to run "make" and see the "make" progression in a separate (newly opened) pane. Also, the consecutive execution of the binary would be nice.
3 Answers
Yes, Vim has the built in :make
command which executes make
by default, but you can set up other build systems by setting makeprg
. There’s no progress visualisation by default, but once :make
is done you can move through errors an earnings encountered with :cnext
and :cprev
. Calling :copen
will show you all of them.
One disadvantage though is that :make
is synchronous so your Vim instance will be blocked until compilation finish. There are plugins like Neomake that implement similar functionality using the asynchronous API.
There’s no default way to run your compiled program, but you can define a custom mapping or command to run it after compilation
-
2vim-makejob is another alternative for async
:make
. Commented Apr 13, 2020 at 4:37 -
2A further alternative would be vim-dispatch which provides an async
:Make
command. I have written an answer describing vim-dispatch for another question which might offer some bits for the OP as well: vi.stackexchange.com/a/22432/1292– HotschkeCommented Apr 13, 2020 at 5:37 -
1Or my build-tools-wrappers that does much more for C++ (e.g. it supports multiple build directories: debug, release, sanatize, whatever...). There are indeed many solutions. Commented Apr 13, 2020 at 10:12
You can make use of vim terminal
in vim 8.0 and later to handle asynchronous jobs.
Thus, to launch make
in a vertical split, you can do:
:vertical terminal make
I have a small function (with a command) to do exactly this:
command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
function! s:RunShellCommand(cmdline) abort
exe 'vert terminal '. a:cmdline
endfunction
So you can do :Shell any_command
to launch a command in a vertical split (i.e :Shell find /
).
For make
specifically, I use it in conjunction with those mappings:
nnoremap <leader>csm :Shell make<cr><cr>
nnoremap <leader>csr :Shell make re<cr><cr>
nnoremap <leader>cst :Shell make ex<cr><cr>
ex
is a rule in my Makefile that launches my tests.
One caveat is that make
rules auto-completion does not work.
Throw away make
make
is synchronous, that's it, just throw it away.
Async tool
One can use :h :terminal or :h term_start() to do async stuff in vim
.
We will use term_start
here as the basic async tool.
Goal
- Async make, update
quickfix
after it, user should see the making progress just like make in terminal. - Show
make successful
message if no error, no warning happens. - Show
found n qf entries
if there existsquickfix
entry with specific buffer number and line number. - Toggle making buffer if user request
make
again duringmaking
. - Spawn new make, delete last making buffer if user request
make
duringidle
.
Interface
nnoremap <f7> :Make<cr>
command -nargs=* Make call s:make(<q-args>)
Spawn async job
let s:making = 0
function s:make(args) abort
if s:making
if bufwinid(s:make_buf) == -1
" show making buffer
exe 'sbuffer' s:make_buf
wincmd p
else
" hide making buffer
exe printf('%d wincmd q', bufwinnr(s:make_buf))
endif
return
endif
" delete last result
if exists('s:make_buf') && bufexists(s:make_buf)
silent! exe 'bdelete' s:make_buf
endif
" spawn new make
let cmd = 'make'
if !empty(a:args)
let cmd .= ' ' . a:args
endif
let options = {'close_cb': function('s:make_callback'), 'term_rows': 16}
let s:make_buf = term_start(cmd, options)
let s:making = 1
wincmd p
endfunction
The subtle handler
func s:make_callback(channel)
" look, you can not get buffer content directly here.
call timer_start(10, function('s:make_callback_impl'))
endfunction
function s:make_callback_impl(timer) abort
exe 'cgetbuffer' s:make_buf
" consider entry with num zero bufnr and lnum an error or warning
let qfl = filter(getqflist(), {k,v -> v.bufnr != 0 && v.lnum != 0})
if empty(qfl)
echo "make successful"
else
echohl WarningMsg
echom printf('found %d qf entries', len(qfl))
echohl None
endif
let s:making = 0
endfunction
Be careful here, one might try to get buffer directly at s:make_callback
, that won't work, see
this question for detail.
-
2
-
@D.BenKnoble It's a small task, I prefer to do it by myself with built in async tool.– dedowsdiCommented Apr 13, 2020 at 23:01
term make
, if you needquickfix
, executecgetbuffer
from the terminal buffer later. To be honest, I prefer the colored rawmake
output. Thequickfix
formake
result ofc++
looks awful to me.