vim/autoload/build.vim
Kenneth Benzie (Benie) eabec4e9b6 Add build#dir() popup_menu() fallback
When `popup_menu()` is not available, i.e. neovim or old version of vim,
fallback to using `inputlist()` instead.
2021-07-13 21:00:48 +01:00

97 lines
3.1 KiB
VimL

function! build#dir(...) abort
if a:0 == 0
" No arguments, find build directories.
let s:dirs = split(substitute(globpath('.', 'build*'), '\.\/', '', 'g'), '\n')
let l:len = len(s:dirs)
if l:len == 0
echoerr 'no build directories found'
elseif l:len == 1
" One build directory found, use it.
let l:dir = s:dirs[0]
unlet s:dirs
else
" Multiple build directories found, select one.
if exists('*popup_menu')
" Create popup menu to select the build directory. Callback to this
" function on completion, handled in the else branch below.
call popup_menu(s:dirs, #{
\ filter: 'popup_filter_menu',
\ callback: 'build#dir',
\ })
else
" Fallback to inputlist when popup_menu is not available.
let l:choices = []
let l:index = 1
for l:dir in s:dirs
call add(l:choices, string(l:index).': '.l:dir)
let l:index += 1
endfor
let l:index = inputlist(l:choices)
let l:dir = s:dirs[l:index - 1]
endif
endif
else
if a:0 == 1
" Single argument, invoked by :BuildDir.
let l:dir = a:1
elseif a:0 == 2
" Two arguments, called back by popup_menu().
let l:dirs = s:dirs
unlet s:dirs
if a:2 == -1
" Selection in popup_menu() was cancelled.
return
endif
let l:dir = l:dirs[a:2 - 1]
else
echoerr 'build#dir called with too many arguments'
endif
endif
if exists('l:dir')
" Set build directory and restart YouCompleteMe.
let $BUILD_DIR = getcwd().'/'.substitute(l:dir, '\/$', '', '')
let l:coc_settings = {}
if isdirectory('.vim')
let l:coc_settings = json_decode(join(readfile('.vim/coc-settings.json'), ''))
else
call mkdir('.vim')
endif
let l:coc_settings['clangd.compilationDatabasePath'] = $BUILD_DIR
let l:coc_settings['cmake.lsp.buildDirectory'] = $BUILD_DIR
call writefile([json_encode(l:coc_settings)], '.vim/coc-settings.json')
CocRestart
endif
endfunction
function! build#targets(ArgLead, CmdLine, CursorPos) abort
if !exists('$BUILD_DIR')
echoerr 'build directory not set'
return ''
endif
let l:targets = []
if filereadable($BUILD_DIR.'/build.ninja')
" Ask ninja for the list of targets and prepare for returning.
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, it's much less straight forwards than ninja.
endif
return join(l:targets, "\n")
endfunction
function! build#run(...) abort
if !exists('$BUILD_DIR')
call echo#error('build directory not set')
return
endif
let l:build_dir = $BUILD_DIR
if filereadable($BUILD_DIR.'/build.ninja')
" Execute ninja in a terminal window.
execute 'terminal ninja -C '.l:build_dir.' '.join(a:000, ' ')
elseif filereadable($BUILD_DIR.'/Makefile')
" Execute make in a terminal window.
execute 'terminal make -C '.l:build_dir.' '.join(a:000, ' ')
endif
endfunction