Question/suggestion: "watch compilation" mode
I'd like to be able dispatch tsc -w (typescript compiler watch mode) in the background and get automatic updates in the quickfix window as new errors come and go.
Is it possible to achieve this using vim-dispatch? Perhaps with a little bit of extra scripting?
Thanks!
There are also other build tools with a watch mode, e.g. latexmk -pvc or watchman-make.
My current take on this is similar to vimtex:
Run :Make on save
A :w[rite] in vim usually triggers a tool with a watch mode. Since vim has the autocmd BufWritePost we can immediately fire :Make in vim without needing a watch mode.
Example: cpp project using cmake with my default compilation during development in _builds/debug:
❯ tree -L 2
.
├── CMakeLists.txt
├── _builds
│ ├── debug
│ └── release
├── src
│ ├── common
│ └── mytool
├── test
├── third-party
└── tools
└── cmake
The following vim setup runs :Make -j8 (4 cores with hyperthreading, hence 8 jobs) whenever I save a *.cpp or *.h file.
Using vim-projectionist heuristics to find my preferred Makefile to run
let g:projectionist_heuristics = {
\ "CMakeLists.txt&_builds/debug/Makefile": {
\ "*": {"make": "make -C {project}/_builds/debug -j8"}
\ }
\ }
It is important that make has the option -C to run make from the pwd of vim which does not agree with the build directory for cmake's out-of-source build directories (see also https://mesonbuild.com/).
Similar to vimtex, autocmd which fires :Make on save is not active by default. Only after pressing <leader>ll which also invokes a first run of :Make
augroup filetypes_makeonsave
autocmd!
autocmd Filetype cpp nnoremap <buffer> <silent> <localleader>ll :call ToggleMakeOnSaveForCurrentFT()<CR>
augroup END
function! ToggleMakeOnSaveForCurrentFT()
let l:augroupname = 'make_on_save_'.&ft
execute("if !exists('#".l:augroupname."#BufWritePost')")
call EnableMakeOnSaveForCurrentFT()
execute('Make')
else
execute("augroup ".l:augroupname)
autocmd!
redraw
echom "Make on BufWritePost for ".&ft." not active"
augroup END
endif
endfunction
function! EnableMakeOnSaveForCurrentFT()
let l:augroupname = 'make_on_save_'.&ft
execute("if !exists('#".l:augroupname."#BufWritePost')")
execute("augroup ".l:augroupname)
autocmd!
silent execute("au BufWritePost * if &ft ==# '".&ft."' | execute('Make') | endif")
redraw " required to avoid loosing the message
echom "Make on BufWritePost for ".&ft." active (makeprg=".&mp.")"
augroup END
endif
endfunction
If you want to go one step further, you could immediately activate the autocmd if the vim-projectionist heuristics worked out with
augroup myprojectionist
autocmd!
autocmd User ProjectionistActivate call s:activate()
augroup END
function! s:activate() abort
for [root, value] in projectionist#query('make')
if &ft ==# 'cpp'
call EnableMakeOnSaveForCurrentFT()
endif
break
endfor
endfunction
Btw one can replace vim-dispatch :Make with neomake :NeomakeProject (this does not open a window, offers support for feedback via the statusline).