1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 09:10:04 +08:00
SpaceVim/bundle/xmake.vim/autoload/xmake.vim
2023-03-28 12:14:51 +08:00

245 lines
7.2 KiB
VimL

"=============================================================================
" xmake.vim --- xmake support for spacevim
" Copyright (c) 2016-2023 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" Original Author: luzhlon
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
" This file is based on:
" https://github.com/luzhlon/xmake.vim/tree/5b20e97f5d0b063a97be23451c730d0278eef927
""
" @section Introduction, intro
" @library
" xmake.vim is a plugin for using xmake in vim and neovim.
" This plugin requires SpaceVim API and |job| support.
" load the spacevim APIs:
let s:JOB = SpaceVim#api#import('job')
let s:NOTI = SpaceVim#api#import('notify')
let s:job = 0 " subprocess of xmake
let s:xmake_need_to_run = 0 " run this command after building successfully
let s:target = '' " target to build, build ALL if empty
let s:cb_cexpr = {j,d,s->vim#cadde(join(d, "\n"))}
function! s:xmake_stdout(id, data, event) abort
endfunction
function! s:xmake_stderr(id, data, event) abort
endfunction
function! s:xmake_exit(id, data, event) abort
if a:data
" copen
" if build failed, we need to display the error message
call s:NOTI.notify('build failed', 'Error')
call s:NOTI.notify('xmake returned ' . a:data, 'Error')
else
call s:NOTI.notify('build success' . s:target, 'MoreMsg')
if s:xmake_need_to_run
let t = get(get(g:xmproj['targets'], s:target, {}), 'targetfile')
if empty(t)
call s:NOTI.notify('Target not exists:' . s:target, 'Error')
else
call SpaceVim#plugins#runner#open(empty(s:target) ? 'xmake run': t)
endif
endif
endif
endfunction
" Get the bufnr about a target's sourcefiles and headerfiles
func! s:targetbufs(target)
let nrs = {}
for i in a:target['sourcefiles'] + a:target['headerfiles']
let n = bufnr(i)
if n > 0 && getbufvar(n, '&mod')
let nrs[n] = 1
endif
endfor
return nrs
endfunction
" Get the bufnrs to save
fun! s:buf2save()
if empty(s:target)
" Save all target's file
let nrs = {}
for tf in values(g:xmproj['targets'])
call extend(nrs, s:targetbufs(tf))
endfor
else
" Save s:target's file
let nrs = s:targetbufs(g:xmproj['targets'][s:target])
endif
return keys(nrs)
endfunction
" Save the file before building
fun! s:savefiles()
let n = bufnr('%') " save current bufnr
let bufnrs = s:buf2save()
let xnr = bufnr('xmake.lua')
if xnr > 0
call add(bufnrs, xnr)
endif
for nr in bufnrs " traverse project's files, and save them
sil! exe nr . 'bufdo!' 'up'
endfor
" switch to original buffer
exe 'b!' n
endfunction
" If exists a xmake subprocess
fun! s:isRunning()
if !empty(s:job) && s:JOB.status(s:job) == 'run'
call s:NOTI.notify('a xmake task is running')
return 1
endif
endfunction
" If loaded the xmake's configuration
fun! s:notLoaded()
if exists('g:xmproj')
return 0
endif
call s:NOTI.notify('No xmake-project loaded')
return 1
endfunction
" Building by xmake
fun! xmake#buildrun(...)
if s:notLoaded() | return | endif
if s:isRunning() | return | endif
" call s:savefiles() " save files about the target to build
wall
let s:xmake_need_to_run = a:0 && a:1
let color = $COLORTERM
cexpr ''
let cmd = empty(s:target) ? 'xmake': ['xmake', 'build', s:target]
if has_key(g:xmproj, 'compiler')
exe 'compiler' g:xmproj['compiler']
endif
let s:job = s:JOB.start(cmd, {
\ 'on_stdout': function('s:xmake_stdout'),
\ 'on_stderr': function('s:xmake_stderr'),
\ 'on_exit': function('s:xmake_exit'),
\ 'env' : {'COLORTERM' : 'nocolor'}
\ })
endfunction
" Interpret XMake command
fun! xmake#xmake(...)
let argv = filter(copy(a:000), {i,v->v!=''})
let argc = len(argv)
if !argc " building all targets without running
let s:target = ''
call xmake#buildrun()
elseif argv[0] == 'run' || argv[0] == 'r' " building && running
if argc > 1 | let s:target = argv[1] | endif
call xmake#buildrun(1)
elseif argv[0] == 'build' " building specific target
if argc > 1 | let s:target = argv[1] | endif
call xmake#buildrun()
else " else xmake's commands
if s:isRunning() | return | endif
let s:job = s:JOB.start(['xmake'] + argv, {
\ 'on_stdout': function('s:xmake_stdout'),
\ 'on_stderr': function('s:xmake_stderr'),
\ 'on_exit': function('s:xmake_exit'),
\ 'env' : {'COLORTERM' : 'nocolor'}
\ })
endif
endfunction
fun! s:onload(...)
" Check the fields
for t in values(g:xmproj['targets'])
if empty(t.headerfiles)
let t.headerfiles = []
endif
if empty(t.sourcefiles)
let t.sourcefiles = []
endif
endfor
" Support SpaceVim's tabmanager
call s:NOTI.notify('XMake-Project loaded successfully', 'MoreMsg')
let config = g:xmproj.config
let t:_spacevim_tab_name = join(filter([g:xmproj['name'], get(config, 'mode', ''), get(config, 'arch', '')], '!empty(v:val)'), ' - ')
call xmake#log#info('change the project name to:' . t:_spacevim_tab_name)
" Find compiler
let cc = get(g:xmproj.config, 'cc', '')
let cxx = get(g:xmproj.config, 'cxx', '')
let compiler = ''
if !empty(cxx)
let compiler = cxx
elseif !empty(cc)
let compiler = cc
endif
if !empty(compiler)
let t = {'cl.exe': 'msvc', 'gcc': 'gcc'}
let g:xmproj.compiler = t[compiler]
endif
endfunction
augroup xmake_autoload
autocmd!
au User XMakeLoaded call <SID>onload()
augroup END
let s:path = expand('<sfile>:p:h')
let s:xmake_load_stdout_cache = []
let s:xmake_load_tempname = ''
function! s:xmake_load_stdout(id, data, event) abort
call add(s:xmake_load_stdout_cache, a:data)
endfunction
function! s:xmake_load_stderr(id, data, event) abort
for line in a:data
let s:NOTI.notify_max_width = max([strwidth(line) + 5, s:NOTI.notify_max_width])
call s:NOTI.notify(line, 'WarningMsg')
endfor
endfunction
function! s:xmake_load_exit(id, data, event) abort
call xmake#log#info('LoadXCfg entered.')
if a:data
call s:NOTI.notify('XMake-Project loaded unsuccessfully.')
call s:NOTI.notify('xmake returned ' . a:data)
else
let l = ''
try
let l = readfile(s:xmake_load_tempname)
let g:xmproj = json_decode(l[0])
do User XMakeLoaded
catch
call xmake#log#debug('xmake_load_tempname is: ' . s:xmake_load_tempname)
call xmake#log#debug('failed to paser s:xmake_load_tempname')
call xmake#log#debug(' exception: ' . v:exception)
call xmake#log#debug(' throwpoint: ' . v:throwpoint)
endtry
endif
endfunction
fun! xmake#load()
let s:xmake_load_stdout_cache = []
let s:xmake_load_tempname = tempname()
let cmdline = ['xmake', 'lua', s:path . '/spy.lua', '-o', s:xmake_load_tempname, 'project']
call xmake#log#info('cmdline is:' . string(cmdline))
let jobid = s:JOB.start(cmdline, {
\ 'on_stdout' : function('s:xmake_load_stdout'),
\ 'on_stderr' : function('s:xmake_load_stderr'),
\ 'on_exit' : function('s:xmake_load_exit')
\ }
\ )
endfunction
function! xmake#on_project_changed() abort
if filereadable('xmake.lua')
call xmake#load()
endif
endfunction
" vim:set et sw=2 cc=80: