1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-02 23:40:06 +08:00

Add multiple tasks support (#4150)

This commit is contained in:
Wang Shidong 2021-03-31 19:47:05 +08:00 committed by GitHub
parent c684e62045
commit 4407b7c8af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 108 additions and 83 deletions

View File

@ -1,6 +1,6 @@
[file-run]
command = "dir"
isBackground = false
command = "cat"
isBackground = true
[file-run.options]
cwd = '${workspaceFolder}bin/'
[test_problemMatcher]
@ -8,11 +8,14 @@
args = ['.SpaceVim.d/tasks.toml:6:1 test error message']
isBackground = true
[test_problemMatcher.problemMatcher]
useStdout = true
errorformat = '%f:%l:%c\ %m'
[test_regexp]
command = "echo"
args = ['.SpaceVim.d/tasks.toml:12:1 test error message']
isBackground = true
[test_regexp.problemMatcher]
useStdout = true
[test_regexp.problemMatcher.pattern]
regexp = '\(.*\):\(\d\+\):\(\d\+\)\s\(\S.*\)'
file = 1

View File

@ -24,7 +24,7 @@ jobs:
# - vimbin: nvim
# vimtag: v0.4.4
# vimtag: ["v0.4.3", "v0.4.3", "v0.4.3", "v0.4.2", "v0.3.8", "v0.3.7", "v0.3.5", "v0.3.4", "v0.3.3", "v0.3.2", "v0.3.1", "v0.3.0"]
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
env:
VIM_BIN: ${{ matrix.vimbin }}
VIM_TAG: ${{ matrix.vimtag }}

View File

@ -276,6 +276,7 @@ function! SpaceVim#layers#core#config() abort
let g:_spacevim_mappings_space.p.t = {'name' : '+Tasks'}
call SpaceVim#mapping#space#def('nnoremap', ['p', 't', 'e'], 'call SpaceVim#plugins#tasks#edit()', 'edit-project-task', 1)
call SpaceVim#mapping#space#def('nnoremap', ['p', 't', 'l'], 'call SpaceVim#plugins#tasks#list()', 'list-tasks', 1)
call SpaceVim#mapping#space#def('nnoremap', ['p', 't', 'c'], 'call SpaceVim#plugins#runner#clear_tasks()', 'clear-tasks', 1)
call SpaceVim#mapping#space#def('nnoremap', ['p', 't', 'r'],
\ 'call SpaceVim#plugins#runner#run_task(SpaceVim#plugins#tasks#get())', 'pick-task-to-run', 1)
call SpaceVim#mapping#space#def('nnoremap', ['p', 'k'], 'call SpaceVim#plugins#projectmanager#kill_project()', 'kill-all-project-buffers', 1)

View File

@ -22,24 +22,27 @@ let s:LOGGER =SpaceVim#logger#derive('runner')
"
"
let s:bufnr = 0
" the buffer number of code runner
let s:code_runner_bufnr = 0
" @fixme win_getid requires vim 7.4.1557
let s:winid = -1
let s:target = ''
let s:lines = 0
let s:runner_lines = 0
let s:runner_jobid = 0
let s:status = {
let s:runner_status = {
\ 'is_running' : 0,
\ 'has_errors' : 0,
\ 'exit_code' : 0
\ }
let s:task_status = {}
let s:task_stdout = {}
let s:task_stderr = {}
let s:task_problem_matcher = {}
function! s:open_win() abort
if s:bufnr !=# 0 && bufexists(s:bufnr) && index(tabpagebuflist(), s:bufnr) !=# -1
if s:code_runner_bufnr !=# 0 && bufexists(s:code_runner_bufnr) && index(tabpagebuflist(), s:code_runner_bufnr) !=# -1
return
endif
botright split __runner__
@ -54,7 +57,7 @@ function! s:open_win() abort
autocmd!
autocmd BufWipeout <buffer> call <SID>stop_runner()
augroup END
let s:bufnr = bufnr('%')
let s:code_runner_bufnr = bufnr('%')
if exists('*win_getid')
let s:winid = win_getid(winnr())
endif
@ -64,16 +67,13 @@ endfunction
function! s:insert() abort
call inputsave()
let input = input('input >')
if !empty(input) && s:status.is_running == 1
if !empty(input) && s:runner_status.is_running == 1
call s:JOB.send(s:runner_jobid, input)
endif
normal! :
call inputrestore()
endfunction
let s:running_cmd = ''
function! s:async_run(runner, ...) abort
if type(a:runner) == type('')
" the runner is a string, the %s will be replaced as a file name.
@ -83,8 +83,8 @@ function! s:async_run(runner, ...) abort
let cmd = a:runner
endtry
call s:LOGGER.info(' cmd:' . string(cmd))
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , -1, 0, ['[Running] ' . cmd, '', repeat('-', 20)])
let s:lines += 3
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , -1, 0, ['[Running] ' . cmd, '', repeat('-', 20)])
let s:runner_lines += 3
let s:start_time = reltime()
let opts = get(a:000, 0, {})
let s:runner_jobid = s:JOB.start(cmd,extend({
@ -123,12 +123,12 @@ function! s:async_run(runner, ...) abort
else
let compile_cmd_info = compile_cmd . (usestdin ? ' STDIN' : '')
endif
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , -1, 0, [
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , -1, 0, [
\ '[Compile] ' . compile_cmd_info,
\ '[Running] ' . s:target,
\ '',
\ repeat('-', 20)])
let s:lines += 4
let s:runner_lines += 4
let s:start_time = reltime()
let s:runner_jobid = s:JOB.start(compile_cmd,{
\ 'on_stdout' : function('s:on_stdout'),
@ -161,8 +161,8 @@ function! s:async_run(runner, ...) abort
let cmd = exe + a:runner.opt + [get(s:, 'selected_file', bufname('%'))]
endif
call s:LOGGER.info(' cmd:' . string(cmd))
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , -1, 0, ['[Running] ' . join(cmd) . (usestdin ? ' STDIN' : ''), '', repeat('-', 20)])
let s:lines += 3
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , -1, 0, ['[Running] ' . join(cmd) . (usestdin ? ' STDIN' : ''), '', repeat('-', 20)])
let s:runner_lines += 3
let s:start_time = reltime()
let s:runner_jobid = s:JOB.start(cmd,{
\ 'on_stdout' : function('s:on_stdout'),
@ -176,7 +176,7 @@ function! s:async_run(runner, ...) abort
endif
endif
if s:runner_jobid > 0
let s:status = {
let s:runner_status = {
\ 'is_running' : 1,
\ 'has_errors' : 0,
\ 'exit_code' : 0
@ -184,9 +184,6 @@ function! s:async_run(runner, ...) abort
endif
endfunction
" @vimlint(EVL103, 1, a:id)
" @vimlint(EVL103, 1, a:data)
" @vimlint(EVL103, 1, a:event)
function! s:on_compile_exit(id, data, event) abort
if a:id !=# s:runner_jobid
" make sure the compile exit callback is for current compile command.
@ -199,7 +196,7 @@ function! s:on_compile_exit(id, data, event) abort
\ 'on_exit' : function('s:on_exit'),
\ })
if s:runner_jobid > 0
let s:status = {
let s:runner_status = {
\ 'is_running' : 1,
\ 'has_errors' : 0,
\ 'exit_code' : 0
@ -207,16 +204,13 @@ function! s:on_compile_exit(id, data, event) abort
endif
else
let s:end_time = reltime(s:start_time)
let s:status.is_running = 0
let s:status.exit_code = a:data
let s:runner_status.is_running = 0
let s:runner_status.exit_code = a:data
let done = ['', '[Done] exited with code=' . a:data . ' in ' . s:STRING.trim(reltimestr(s:end_time)) . ' seconds']
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , s:lines + 1, 0, done)
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , s:runner_lines + 1, 0, done)
endif
call s:update_statusline()
endfunction
" @vimlint(EVL103, 0, a:id)
" @vimlint(EVL103, 0, a:data)
" @vimlint(EVL103, 0, a:event)
function! s:update_statusline() abort
redrawstatus!
@ -238,8 +232,8 @@ endfunction
function! SpaceVim#plugins#runner#open(...) abort
call s:stop_runner()
let s:runner_jobid = 0
let s:lines = 0
let s:status = {
let s:runner_lines = 0
let s:runner_status = {
\ 'is_running' : 0,
\ 'has_errors' : 0,
\ 'exit_code' : 0
@ -265,12 +259,12 @@ function! s:on_stdout(job_id, data, event) abort
" this is previous runner exit_callback
return
endif
if bufexists(s:bufnr)
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , s:lines + 1, 0, a:data)
if bufexists(s:code_runner_bufnr)
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , s:runner_lines + 1, 0, a:data)
endif
let s:lines += len(a:data)
let s:runner_lines += len(a:data)
if s:winid >= 0
call s:VIM.win_set_cursor(s:winid, [s:VIM.buf_line_count(s:bufnr), 1])
call s:VIM.win_set_cursor(s:winid, [s:VIM.buf_line_count(s:code_runner_bufnr), 1])
endif
call s:update_statusline()
endfunction
@ -281,13 +275,13 @@ function! s:on_stderr(job_id, data, event) abort
" this is previous runner exit_callback
return
endif
let s:status.has_errors = 1
if bufexists(s:bufnr)
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , s:lines + 1, 0, a:data)
let s:runner_status.has_errors = 1
if bufexists(s:code_runner_bufnr)
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , s:runner_lines + 1, 0, a:data)
endif
let s:lines += len(a:data)
let s:runner_lines += len(a:data)
if s:winid >= 0
call s:VIM.win_set_cursor(s:winid, [s:VIM.buf_line_count(s:bufnr), 1])
call s:VIM.win_set_cursor(s:winid, [s:VIM.buf_line_count(s:code_runner_bufnr), 1])
endif
call s:update_statusline()
endfunction
@ -299,12 +293,12 @@ function! s:on_exit(job_id, data, event) abort
return
endif
let s:end_time = reltime(s:start_time)
let s:status.is_running = 0
let s:status.exit_code = a:data
let s:runner_status.is_running = 0
let s:runner_status.exit_code = a:data
let done = ['', '[Done] exited with code=' . a:data . ' in ' . s:STRING.trim(reltimestr(s:end_time)) . ' seconds']
if bufexists(s:bufnr)
call s:BUFFER.buf_set_lines(s:bufnr, s:lines , s:lines + 1, 0, done)
call s:VIM.win_set_cursor(s:winid, [s:VIM.buf_line_count(s:bufnr), 1])
if bufexists(s:code_runner_bufnr)
call s:BUFFER.buf_set_lines(s:code_runner_bufnr, s:runner_lines , s:runner_lines + 1, 0, done)
call s:VIM.win_set_cursor(s:winid, [s:VIM.buf_line_count(s:code_runner_bufnr), 1])
call s:update_statusline()
endif
endfunction
@ -312,31 +306,29 @@ endfunction
" @vimlint(EVL103, 0, a:data)
" @vimlint(EVL103, 0, a:event)
function! SpaceVim#plugins#runner#status() abort
if s:status.is_running == 0 && exists('s:end_time')
return 'exit code : ' . s:status.exit_code
\ . ' time: ' . s:STRING.trim(reltimestr(s:end_time))
\ . ' language: ' . get(s:, 'selected_language', &ft)
endif
return ''
let running_nr = len(filter(values(s:task_status), 'v:val.is_running')) + s:runner_status.is_running
let running_done = len(filter(values(s:task_status), '!v:val.is_running'))
return printf(' %s running, %s done', running_nr, running_done)
endfunction
function! s:close() abort
call s:stop_runner()
if s:bufnr != 0 && bufexists(s:bufnr)
exe 'bd ' s:bufnr
if s:code_runner_bufnr != 0 && bufexists(s:code_runner_bufnr)
exe 'bd ' s:code_runner_bufnr
endif
endfunction
function! s:stop_runner() abort
if s:status.is_running == 1
if s:runner_status.is_running == 1
call s:JOB.stop(s:runner_jobid)
endif
endfunction
function! SpaceVim#plugins#runner#select_file() abort
let s:lines = 0
let s:status = {
let s:runner_lines = 0
let s:runner_status = {
\ 'is_running' : 0,
\ 'is_exit' : 0,
\ 'has_errors' : 0,
@ -456,7 +448,13 @@ function! s:on_backgroud_stderr(job_id, data, event) abort
endfunction
function! s:on_backgroud_exit(job_id, data, event) abort
let s:end_time = reltime(s:start_time)
let task_status = get(s:task_status, 'task' . a:job_id, {
\ 'is_running' : 0,
\ 'has_errors' : 0,
\ 'start_time' : 0,
\ 'exit_code' : 0
\ })
let end_time = reltime(task_status.start_time)
let task_problem_matcher = get(s:task_problem_matcher, 'task' . a:job_id, {})
if get(task_problem_matcher, 'useStdout', 0)
let output = get(s:task_stdout, 'task' . a:job_id, [])
@ -466,14 +464,20 @@ function! s:on_backgroud_exit(job_id, data, event) abort
if !empty(task_problem_matcher) && !empty(output)
call s:match_problems(output, task_problem_matcher)
endif
let exit_code = a:data
echo 'task finished with code=' . a:data . ' in ' . s:STRING.trim(reltimestr(s:end_time)) . ' seconds'
echo 'task finished with code=' . a:data . ' in ' . s:STRING.trim(reltimestr(end_time)) . ' seconds'
endfunction
function! s:run_backgroud(cmd, ...) abort
echo 'task running'
" how many tasks are running?
"
" echo 'tasks: 1 running, 2 done'
let running_nr = len(filter(values(s:task_status), 'v:val.is_running')) + 1
let running_done = len(filter(values(s:task_status), '!v:val.is_running'))
echo printf('tasks: %s running, %s done', running_nr, running_done)
let opts = get(a:000, 0, {})
" this line can not be removed.
let s:start_time = reltime()
let start_time = reltime()
let problemMatcher = get(a:000, 1, {})
if !has_key(problemMatcher, 'errorformat') && !has_key(problemMatcher, 'regexp')
call extend(problemMatcher, {'errorformat' : &errorformat})
@ -483,4 +487,18 @@ function! s:run_backgroud(cmd, ...) abort
\ 'on_exit' : function('s:on_backgroud_exit'),
\ }, opts))
call extend(s:task_problem_matcher, {'task' . task_id : problemMatcher})
call extend(s:task_status, {'task' . task_id : {
\ 'is_running' : 1,
\ 'has_errors' : 0,
\ 'start_time' : start_time,
\ 'exit_code' : 0
\ }})
endfunction
function! SpaceVim#plugins#runner#clear_tasks() abort
for taskid in keys(s:task_status)
if s:task_status[taskid].is_running ==# 1
call remove(s:task_status, taskid)
endif
endfor
endfunction

View File

@ -25,10 +25,9 @@ let s:BUF = SpaceVim#api#import('vim#buffer')
" task object
let s:self = {}
let s:select_task = {}
let s:conf = []
let s:bufnr = -1
let s:task_config = []
let s:task_viewer_bufnr = -1
let s:variables = {}
let s:providers = []
@ -44,7 +43,7 @@ function! s:load() abort
if filereadable('.SpaceVim.d/tasks.toml')
let local_conf = s:TOML.parse_file('.SpaceVim.d/tasks.toml')
endif
let s:conf = extend(global_conf, local_conf)
let s:task_config = extend(global_conf, local_conf)
endfunction
function! s:init_variables() abort
@ -63,17 +62,17 @@ function! s:init_variables() abort
endfunction
function! s:select_task(taskName) abort
let s:select_task = s:conf[a:taskName]
let s:select_task = s:task_config[a:taskName]
endfunction
function! s:pick() abort
let s:select_task = {}
let ques = []
for key in keys(s:conf)
if has_key(s:conf[key], 'isGlobal') && s:conf[key].isGlobal
for key in keys(s:task_config)
if has_key(s:task_config[key], 'isGlobal') && s:task_config[key].isGlobal
let task_name = key . '(global)'
elseif has_key(s:conf[key], 'isDetected') && s:conf[key].isDetected
let task_name = s:conf[key].detectedName . key . '(detected)'
elseif has_key(s:task_config[key], 'isDetected') && s:task_config[key].isDetected
let task_name = s:task_config[key].detectedName . key . '(detected)'
else
let task_name = key
endif
@ -117,7 +116,7 @@ endfunction
function! SpaceVim#plugins#tasks#get() abort
call s:load()
for Provider in s:providers
call extend(s:conf, call(Provider, []))
call extend(s:task_config, call(Provider, []))
endfor
call s:init_variables()
let task = s:expand_task(s:pick())
@ -132,7 +131,7 @@ endfunction
function! SpaceVim#plugins#tasks#list() abort
call s:load()
for Provider in s:providers
call extend(s:conf, call(Provider, []))
call extend(s:task_config, call(Provider, []))
endfor
call s:init_variables()
call s:open_tasks_list_win()
@ -148,8 +147,8 @@ endfunction
function! s:open_tasks_list_win() abort
if s:bufnr != 0 && bufexists(s:bufnr)
exe 'bd ' . s:bufnr
if s:task_viewer_bufnr != 0 && bufexists(s:task_viewer_bufnr)
exe 'bd ' . s:task_viewer_bufnr
endif
botright split __tasks_info__
let lines = &lines * 30 / 100
@ -164,7 +163,7 @@ function! s:open_tasks_list_win() abort
\ winfixheight
\ nomodifiable
set filetype=SpaceVimTasksInfo
let s:bufnr = bufnr('%')
let s:task_viewer_bufnr = bufnr('%')
nnoremap <buffer><silent> <Enter> :call <SID>open_task()<cr>
endfunction
@ -175,7 +174,7 @@ function! s:open_task() abort
if line =~# '^\[.*\]\s\+detected'
let task = split(task, ':')[1]
endif
let task = s:expand_task(s:conf[task])
let task = s:expand_task(s:task_config[task])
call SpaceVim#mapping#SmartClose()
call SpaceVim#plugins#runner#run_task(task)
else
@ -185,21 +184,21 @@ endfunction
function! s:update_tasks_win_context() abort
let lines = ['Task Type Description']
for task in keys(s:conf)
if has_key(s:conf[task], 'isGlobal') && s:conf[task].isGlobal ==# 1
for task in keys(s:task_config)
if has_key(s:task_config[task], 'isGlobal') && s:task_config[task].isGlobal ==# 1
let line = '[' . task . ']' . repeat(' ', 22 - strlen(task))
let line .= 'global '
elseif has_key(s:conf[task], 'isDetected') && s:conf[task].isDetected ==# 1
let line = '[' . s:conf[task].detectedName . task . ']' . repeat(' ', 22 - strlen(task . s:conf[task].detectedName))
elseif has_key(s:task_config[task], 'isDetected') && s:task_config[task].isDetected ==# 1
let line = '[' . s:task_config[task].detectedName . task . ']' . repeat(' ', 22 - strlen(task . s:task_config[task].detectedName))
let line .= 'detected '
else
let line = '[' . task . ']' . repeat(' ', 22 - strlen(task))
let line .= 'local '
endif
let line .= get(s:conf[task], 'description', s:conf[task].command . ' ' . join(get(s:conf[task], 'args', []), ' '))
let line .= get(s:task_config[task], 'description', s:task_config[task].command . ' ' . join(get(s:task_config[task], 'args', []), ' '))
call add(lines, line)
endfor
call s:BUF.buf_set_lines(s:bufnr, 0, -1, 0, sort(lines))
call s:BUF.buf_set_lines(s:task_viewer_bufnr, 0, -1, 0, sort(lines))
endfunction
function! SpaceVim#plugins#tasks#edit(...) abort

View File

@ -2122,11 +2122,12 @@ If `errorformat` property is not defined, `&errorformat` option
will be used.
```toml
[tesk_errorformat]
[test_problemMatcher]
command = "echo"
args = ['.SpaceVim.d/tasks.toml:6:1 test error message']
isBackground = true
[tesk_errorformat.problemMatcher]
[test_problemMatcher.problemMatcher]
useStdout = true
errorformat = '%f:%l:%c\ %m'
```
@ -2138,11 +2139,14 @@ Here is an example:
command = "echo"
args = ['.SpaceVim.d/tasks.toml:12:1 test error message']
isBackground = true
[test_regexp.problemMatcher]
useStdout = true
[test_regexp.problemMatcher.pattern]
regexp = '\(.*\):\(\d\+\):\(\d\+\)\s\(\S.*\)'
file = 1
line = 2
column = 3
#severity = 4
message = 4
```