diff --git a/.SpaceVim.d/tasks.toml b/.SpaceVim.d/tasks.toml index aed69eca5..8079d385e 100644 --- a/.SpaceVim.d/tasks.toml +++ b/.SpaceVim.d/tasks.toml @@ -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 diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 7ab8bee9c..568553dc7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -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 }} diff --git a/autoload/SpaceVim/layers/core.vim b/autoload/SpaceVim/layers/core.vim index 455b5ae5f..f5d52870a 100644 --- a/autoload/SpaceVim/layers/core.vim +++ b/autoload/SpaceVim/layers/core.vim @@ -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) diff --git a/autoload/SpaceVim/plugins/runner.vim b/autoload/SpaceVim/plugins/runner.vim index 99b8e48bf..d7ada9fec 100644 --- a/autoload/SpaceVim/plugins/runner.vim +++ b/autoload/SpaceVim/plugins/runner.vim @@ -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 call 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 diff --git a/autoload/SpaceVim/plugins/tasks.vim b/autoload/SpaceVim/plugins/tasks.vim index e248a1e09..0d30a21de 100644 --- a/autoload/SpaceVim/plugins/tasks.vim +++ b/autoload/SpaceVim/plugins/tasks.vim @@ -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 :call open_task() 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 diff --git a/docs/documentation.md b/docs/documentation.md index 4b7715114..c60f0694f 100644 --- a/docs/documentation.md +++ b/docs/documentation.md @@ -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 ```