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

Add task problem matcher (#4127)

This commit is contained in:
Wang Shidong 2021-03-14 15:12:00 +08:00 committed by GitHub
parent c69e3af7af
commit 1ca32fce79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 139 additions and 15 deletions

View File

@ -3,3 +3,20 @@
isBackground = false
[file-run.options]
cwd = '${workspaceFolder}bin/'
[test_problemMatcher]
command = "echo"
args = ['.SpaceVim.d/tasks.toml:6:1 test error message']
isBackground = true
[test_problemMatcher.problemMatcher]
errorformat = '%f:%l:%c\ %m'
[test_regexp]
command = "echo"
args = ['.SpaceVim.d/tasks.toml:12:1 test error message']
isBackground = true
[test_regexp.problemMatcher.pattern]
regexp = '\(.*\):\(\d\+\):\(\d\+\)\s\(\S.*\)'
file = 1
line = 2
column = 3
#severity = 4
message = 4

View File

@ -92,7 +92,7 @@ if exists('*nvim_create_buf')
else
function! s:self.create_buf(listed, scratch) abort
let bufnr = self.bufadd('')
" in vim, a:listed must be number, what the fuck!
" in vim, a:listed must be number
" why can not use v:true and v:false
call setbufvar(bufnr, '&buflisted', a:listed ? 1 : 0)
if a:scratch

View File

@ -158,7 +158,7 @@ function! s:open_default_shell(open_with_file_cwd) abort
if getwinvar(window, '&buftype') ==# 'terminal'
exe window . 'wincmd w'
if getbufvar(winbufnr(window), '_spacevim_shell_cwd') ==# l:path
" fuck gvim bug, startinsert do not work in gvim
" startinsert do not work in gvim
if has('nvim')
startinsert
else

View File

@ -217,7 +217,8 @@ function! SpaceVim#mapping#close_term_buffer(...) abort
if bufexists(abuf)
exe 'bd!' . abuf
endif
" fuck the terminal windows
" can not close the terminal windows
" close again
if get(w:, 'shell_layer_win', 0) == 1
close
endif

View File

@ -84,7 +84,8 @@ function! SpaceVim#plugins#iedit#start(...) abort
let curpos = getcurpos()
let argv = get(a:000, 0, '')
let save_reg_k = @k
" what the fuck, why register " is cleared.
" the register " is cleared
" save the register context before run following command
let save_reg_default = @"
let use_expr = 0
if !empty(argv) && type(argv) == 4

View File

@ -34,6 +34,10 @@ let s:status = {
\ 'exit_code' : 0
\ }
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
return
@ -78,7 +82,7 @@ function! s:async_run(runner, ...) abort
catch
let cmd = a:runner
endtry
call SpaceVim#logger#info(' cmd:' . string(cmd))
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
let s:start_time = reltime()
@ -156,7 +160,7 @@ function! s:async_run(runner, ...) abort
else
let cmd = exe + a:runner.opt + [get(s:, 'selected_file', bufname('%'))]
endif
call SpaceVim#logger#info(' cmd:' . string(cmd))
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
let s:start_time = reltime()
@ -342,8 +346,8 @@ function! SpaceVim#plugins#runner#select_file() abort
let runner = get(a:000, 0, get(s:runners, &filetype, ''))
let s:selected_language = &filetype
if !empty(runner)
call SpaceVim#logger#info('Code runner startting:')
call SpaceVim#logger#info('selected file :' . s:selected_file)
call s:LOGGER.info('Code runner startting:')
call s:LOGGER.info('selected file :' . s:selected_file)
call s:open_win()
call s:async_run(runner)
call s:update_statusline()
@ -392,16 +396,76 @@ function! SpaceVim#plugins#runner#run_task(task) abort
if !empty(opts) && has_key(opts, 'env') && !empty(opts.env)
call extend(opt, {'env' : opts.env})
endif
let problemMatcher = get(a:task, 'problemMatcher', {})
if isBackground
call s:run_backgroud(cmd, opt)
call s:run_backgroud(cmd, opt, problemMatcher)
else
call SpaceVim#plugins#runner#open(cmd, opt)
call SpaceVim#plugins#runner#open(cmd, opt, problemMatcher)
endif
endif
endfunction
function! s:match_problems(output, matcher) abort
if has_key(a:matcher, 'pattern')
let pattern = a:matcher.pattern
let items = []
for line in a:output
let rst = matchlist(line, pattern.regexp)
let file = get(rst, get(pattern, 'file', 1), '')
let line = get(rst, get(pattern, 'line', 2), 1)
let column = get(rst, get(pattern, 'column', 3), 1)
let message = get(rst, get(pattern, 'message', 4), '')
if !empty(file)
call add(items, {
\ 'filename' : file,
\ 'lnum' : line,
\ 'col' : column,
\ 'text' : message,
\ })
endif
endfor
call setqflist([], 'r', {'title' : ' task output',
\ 'items' : items,
\ })
copen
copen
else
try
let olderrformat = &errorformat
if has_key(a:matcher, 'errorformat')
let &errorformat = a:matcher.errorformat
let cmd = 'noautocmd cexpr a:output'
exe cmd
call setqflist([], 'a', {'title' : ' task output'})
copen
endif
finally
let &errorformat = olderrformat
endtry
endif
endfunction
function! s:on_backgroud_stdout(job_id, data, event) abort
let data = get(s:task_stdout, 'task' . a:job_id, []) + a:data
let s:task_stdout['task' . a:job_id] = data
endfunction
function! s:on_backgroud_stderr(job_id, data, event) abort
let data = get(s:task_stderr, 'task' . a:job_id, []) + a:data
let s:task_stderr['task' . a:job_id] = data
endfunction
function! s:on_backgroud_exit(job_id, data, event) abort
let s:end_time = reltime(s: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, [])
else
let output = get(s:task_stderr, 'task' . a:job_id, [])
endif
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'
endfunction
@ -410,7 +474,13 @@ function! s:run_backgroud(cmd, ...) abort
echo 'task running'
let opts = get(a:000, 0, {})
let s:start_time = reltime()
call s:JOB.start(a:cmd,extend({
let problemMatcher = get(a:000, 1, {})
if !has_key(problemMatcher, 'errorformat') && !has_key(problemMatcher, 'regexp')
call extend(problemMatcher, {'errorformat' : &errorformat})
endif
let task_id = s:JOB.start(a:cmd,extend({
\ 'on_stdout' : function('s:on_backgroud_stdout'),
\ 'on_exit' : function('s:on_backgroud_exit'),
\ }, opts))
call extend(s:task_problem_matcher, {'task' . task_id : problemMatcher})
endfunction

View File

@ -98,8 +98,7 @@ endfunction
" :w -- BufWriteCmd
" <C-w>p -- WinLeave
" :wq -- QuitPre -> BufWriteCmd -> WinLeave
" fuck when run `:wq` the commit window will not be closed
" @fixme what the fuck
" when run `:wq` the commit window will not be closed
" :q -- QuitPre -> WinLeave
function! s:BufWriteCmd() abort
let commit_file = '.git\COMMIT_EDITMSG'

View File

@ -68,8 +68,7 @@ endfunction
" :w -- BufWriteCmd
" <C-w>p -- WinLeave
" :wq -- QuitPre -> BufWriteCmd -> WinLeave
" fuck when run `:wq` the commit window will not be closed
" @fixme what the fuck
" when run `:wq` the commit window will not be closed
" :q -- QuitPre -> WinLeave
function! s:BufWriteCmd() abort
let commit_file = '.git\COMMIT_EDITMSG'

View File

@ -84,6 +84,7 @@ description: "General documentation about how to using SpaceVim, including the q
- [Bookmarks management](#bookmarks-management)
- [Tasks](#tasks)
- [Custom tasks](#custom-tasks)
- [Task Problems Matcher](#task-problems-matcher)
- [Task auto-detection](#task-auto-detection)
- [Task provider](#task-provider)
- [Replace text with iedit](#replace-text-with-iedit)
@ -2074,6 +2075,7 @@ The task's properties have the following semantic:
- **isBackground**: `true` or `false`, specifies whether background running is required,
by default, it is `false`.
- **description**: short description of the task
- **problemMatcher**: problems matcher of the task
When start a new task, it will kill the previous task. If you want to keep the task
run in background, set `isBackground` to `true`.
@ -2109,6 +2111,41 @@ So you will have the following values for each variable:
- **\${fileExtname}**: - `.ext`
- **\${lineNumber}**: - line number of the cursor
#### Task Problems Matcher
Problem matcher is used to capture the message in the task output
and show a corresponding problem in quickfix windows.
`problemMatcher` supports `errorformat` and `pattern` property.
If `errorformat` property is not defined, `&errorformat` option
will be used.
```toml
[tesk_errorformat]
command = "echo"
args = ['.SpaceVim.d/tasks.toml:6:1 test error message']
isBackground = true
[tesk_errorformat.problemMatcher]
errorformat = '%f:%l:%c\ %m'
```
If `pattern` is defined, the `errorformat` option will be ignored.
Here is an example:
```toml
[test_regexp]
command = "echo"
args = ['.SpaceVim.d/tasks.toml:12:1 test error message']
isBackground = true
[test_regexp.problemMatcher.pattern]
regexp = '\(.*\):\(\d\+\):\(\d\+\)\s\(\S.*\)'
file = 1
line = 2
column = 3
message = 4
```
#### Task auto-detection
Currently, SpaceVim can auto-detect tasks for npm.