From 926cd1a9533a816b0dbd7f6ca2ccbd2cd9cc2399 Mon Sep 17 00:00:00 2001 From: w0rp Date: Fri, 10 Feb 2017 19:34:44 +0000 Subject: [PATCH] Fix #283 Add an option for using ch_sendraw(), which can be better for some users --- autoload/ale/engine.vim | 31 ++++++++++--------- doc/ale.txt | 16 ++++++++++ plugin/ale.vim | 4 +++ test/smoke_test.vader | 68 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 test/smoke_test.vader diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 59c6de77..cd4c7b93 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -266,21 +266,22 @@ function! s:RunJob(options) abort let l:job_options.out_cb = function('s:GatherOutputVim') endif - if has('win32') - " job_start commands on Windows have to be run with cmd /c, - " othwerwise %PATHTEXT% will not be used to programs ending int - " .cmd, .bat, .exe, etc. - let l:command = 'cmd /c ' . l:command - else - " Execute the command with the shell, to fix escaping issues. - let l:command = split(&shell) + split(&shellcmdflag) + [l:command] + " The command will be executed in a subshell. This fixes a number of + " issues, including reading the PATH variables correctly, %PATHEXT% + " expansion on Windows, etc. + " + " NeoVim handles this issue automatically if the command is a String. + let l:command = has('win32') + \ ? 'cmd /c ' . l:command + \ : split(&shell) + split(&shellcmdflag) + [l:command] - if l:read_buffer - " On Unix machines, we can send the Vim buffer directly. - " This is faster than reading the lines ourselves. - let l:job_options.in_io = 'buffer' - let l:job_options.in_buf = l:buffer - endif + if l:read_buffer && !g:ale_use_ch_sendraw + " Send the buffer via internal Vim 8 mechanisms, rather than + " by reading and sending it ourselves. + " On Unix machines, we can send the Vim buffer directly. + " This is faster than reading the lines ourselves. + let l:job_options.in_io = 'buffer' + let l:job_options.in_buf = l:buffer endif " Vim 8 will read the stdin from the file's buffer. @@ -307,7 +308,7 @@ function! s:RunJob(options) abort call jobsend(l:job, l:input) call jobclose(l:job, 'stdin') - elseif has('win32') + elseif g:ale_use_ch_sendraw " On some Vim versions, we have to send the buffer data ourselves. let l:input = join(getbufline(l:buffer, 1, '$'), "\n") . "\n" let l:channel = job_getchannel(l:job) diff --git a/doc/ale.txt b/doc/ale.txt index a4d476c3..4a8f0ecb 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -395,6 +395,22 @@ g:ale_statusline_format *g:ale_statusline_format* - The 3rd element is for when no errors are detected +g:ale_use_ch_sendraw *g:ale_use_ch_sendraw* + + Type: |Number| + Default: `has('win32')` + + This option only applies to Vim, and is ignored when the plugin is run + in NeoVim. + + When this option is set to `1`, ALE will use |ch_sendraw()| for sending text + buffers to jobs, instead of setting the `in_io` option to `'buffer'` for + |job_start()|. See |in_io-buffer| for more information on this Vim option. + + Using |ch_sendraw()| instead may lead to better performance or stability in + some cases. Typically for Linux users, `in_io` seems to be a better option. + + g:ale_warn_about_trailing_whitespace *g:ale_warn_about_trailing_whitespace* Type: |Number| diff --git a/plugin/ale.vim b/plugin/ale.vim index d65a99cb..13c681a0 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -66,6 +66,10 @@ let g:ale_lint_on_save = get(g:, 'ale_lint_on_save', 0) " should be used instead. let g:ale_enabled = get(g:, 'ale_enabled', 1) +" This flag can be used to force ALE to send buffer data using ch_sendraw +" in Vim 8. This works better for some users. +let g:ale_use_ch_sendraw = get(g:, 'ale_use_ch_sendraw', has('win32')) + " These flags dictates if ale uses the quickfix or the loclist (loclist is the " default, quickfix overrides loclist). let g:ale_set_loclist = get(g:, 'ale_set_loclist', 1) diff --git a/test/smoke_test.vader b/test/smoke_test.vader new file mode 100644 index 00000000..9d0ea3f4 --- /dev/null +++ b/test/smoke_test.vader @@ -0,0 +1,68 @@ +Before: + function! TestCallback(buffer, output) + return [{ + \ 'bufnr': a:buffer, + \ 'lnum': 2, + \ 'vcol': 0, + \ 'col': 3, + \ 'text': a:output[0], + \ 'type': 'E', + \ 'nr': -1, + \}] + endfunction + + call ale#linter#Define('foobar', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': 'echo', + \ 'command': 'echo foo bar', + \}) + +After: + let g:ale_use_ch_sendraw = 0 + let g:ale_buffer_info = {} + delfunction TestCallback + call ale#linter#Reset() + +Given foobar (Some imaginary filetype): + foo + bar + baz + +Execute(Linters should run with the default options): + AssertEqual 'foobar', &filetype + + call ale#Lint() + call ale#engine#WaitForJobs(2000) + + AssertEqual [{ + \ 'bufnr': bufnr('%'), + \ 'lnum': 2, + \ 'vcol': 0, + \ 'col': 3, + \ 'text': 'foo bar', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \ }], getloclist(0) + +Execute(Linters should run with `let g:ale_use_ch_sendraw = 1`): + AssertEqual 'foobar', &filetype + + let g:ale_use_ch_sendraw = 1 + + call ale#Lint() + call ale#engine#WaitForJobs(2000) + + AssertEqual [{ + \ 'bufnr': bufnr('%'), + \ 'lnum': 2, + \ 'vcol': 0, + \ 'col': 3, + \ 'text': 'foo bar', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \ }], getloclist(0)