From 17f7e3165dff7c600fc9dd93a955986a1e9492b5 Mon Sep 17 00:00:00 2001
From: "Kenneth Benzie (Benie)" <benie@infektor.net>
Date: Tue, 5 Jan 2021 21:13:25 +0000
Subject: [PATCH] Add :Build command to invoke ninja or make

The `:Build [<target> ...]` command utilises the `$BUILD_DIR` variable set
by `:BuildDir {directory}` to invoke `ninja` or `make` based on the
existence of `$BUILD_DIR/build.ninja` or `$BUILD_DIR/Makefile`
respectively. The following commands are invoked in a new `:terminal`
window.

* `ninja -C $BUILD_DIR [<target> ...]` when `$BUILD_DIR/build.ninja` exists
* `make -C $BUILD_DIR [<target> ...]` when `$BUILD_DIR/Makefile` exists

In the case of `ninja`, completion for the targets supplied to the
`:Build` command is made available by the `build#targets()` function.
The list of targets returned by `ninja -C $BUILD_DIR -t targets` is
processed to generate the list of targets. Support for `make` target
completion is less straight forwards so has been omitted for now.
---
 autoload/build.vim  | 20 ++++++++++++++++++++
 plugin/commands.vim |  1 +
 2 files changed, 21 insertions(+)

diff --git a/autoload/build.vim b/autoload/build.vim
index b7d7c8c..0ec9fb6 100644
--- a/autoload/build.vim
+++ b/autoload/build.vim
@@ -4,3 +4,23 @@ function! build#dir(dir) abort
   let g:ycm_clangd_args = ['--compile-commands-dir='.$BUILD_DIR]
   YcmRestartServer
 endfunction
+
+function! build#targets(ArgLead, CmdLine, CursorPos) abort
+  let l:targets = []
+  if filereadable($BUILD_DIR.'/build.ninja')
+    for l:target in split(system('ninja -C '.$BUILD_DIR.' -t targets'), '\n')
+      call add(l:targets, substitute(l:target, ':.*$', '', ''))
+    endfor
+  elseif filereadable($BUILD_DIR.'/Makefile')
+    " TODO: support make
+  endif
+  return join(l:targets, "\n")
+endfunction
+
+function! build#run(...) abort
+  if filereadable($BUILD_DIR.'/build.ninja')
+    execute 'terminal ninja -C '.$BUILD_DIR.' '.join(a:000, ' ')
+  elseif filereadable($BUILD_DIR.'/Makefile')
+    execute 'terminal make -C '.$BUILD_DIR.' '.join(a:000, ' ')
+  endif
+endfunction
diff --git a/plugin/commands.vim b/plugin/commands.vim
index 53e4561..ae009cc 100644
--- a/plugin/commands.vim
+++ b/plugin/commands.vim
@@ -32,3 +32,4 @@ command! TodoFile lvimgrep /todo/ %
 
 " Change build directory
 command! -nargs=1 -complete=dir BuildDir call build#dir(<f-args>)
+command! -nargs=* -complete=custom,build#targets Build call build#run(<f-args>)