vim-dispatch icon indicating copy to clipboard operation
vim-dispatch copied to clipboard

Question/suggestion: "watch compilation" mode

Open artemave opened this issue 7 years ago • 1 comments

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!

artemave avatar Nov 30 '18 16:11 artemave

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).

kiryph avatar Jun 05 '19 10:06 kiryph