Add linting with eslint in NeoVim, with a few bugs.

This commit is contained in:
w0rp
2016-09-09 00:23:26 +01:00
commit 11c11e578f
8 changed files with 420 additions and 0 deletions

42
plugin/ale/aaflags.vim Normal file
View File

@@ -0,0 +1,42 @@
" This file sets up configuration settings for the ALE plugin.
" Flags can be set in vimrc files and so on to disable particular features,
" etc.
if exists('g:loaded_ale_flags')
finish
endif
let g:loaded_ale_flags = 1
" This flag can be set to 0 to disable linting when text is changed.
if !exists('g:ale_lint_on_text_changed')
let g:ale_lint_on_text_changed = 1
endif
" This flag can be set with a number of milliseconds for delaying the
" execution of a linter when text is changed. The timeout will be set and
" cleared each time text is changed, so repeated edits won't trigger the
" jobs for linting until enough time has passed after editing is done.
if !exists('g:ale_lint_delay')
let g:ale_lint_delay = 100
endif
" This flag can be set to 0 to disable linting when the buffer is entered.
if !exists('g:ale_lint_on_enter')
let g:ale_lint_on_enter = 1
endif
" This flag can be set to 0 to disable setting the loclist.
if !exists('g:ale_set_loclist')
let g:ale_set_loclist = 1
endif
" This flag can be set to 0 to disable setting signs.
if !exists('g:ale_set_signs')
let g:ale_set_signs = 1
endif
" This flag can be set to 0 to disable echoing when the cursor moves.
if !exists('g:ale_echo_cursor')
let g:ale_echo_cursor = 1
endif

72
plugin/ale/cursor.vim Normal file
View File

@@ -0,0 +1,72 @@
if exists('g:loaded_ale_cursor')
finish
endif
let g:loaded_ale_cursor = 1
" This function will perform a binary search to find a message from the
" loclist to echo when the cursor moves.
function! s:BinarySearch(loclist, line, column)
let min = 0
let max = len(a:loclist) - 1
let last_column_match = -1
while 1
if max < min
return last_column_match
endif
let mid = (min + max) / 2
let obj = a:loclist[mid]
" Binary search to get on the same line
if a:loclist[mid]['lnum'] < a:line
let min = mid + 1
elseif a:loclist[mid]['lnum'] > a:line
let max = mid - 1
else
let last_column_match = mid
" Binary search to get the same column, or near it
if a:loclist[mid]['col'] < a:column
let min = mid + 1
elseif a:loclist[mid]['col'] > a:column
let max = mid - 1
else
return mid
endif
endif
endwhile
endfunction
function! ale#cursor#TruncatedEcho(message)
let message = a:message
" Change tabs to spaces.
let message = substitute(message, "\t", ' ', 'g')
" Remove any newlines in the message.
let message = substitute(message, "\n", '', 'g')
let truncated_message = join(split(message, '\zs')[:&columns - 2], '')
" Echo the message truncated to fit without creating a prompt.
echo truncated_message
endfunction
function! ale#cursor#EchoCursorWarning()
let pos = getcurpos()
let index = s:BinarySearch(b:ale_loclist, pos[1], pos[2])
if index >= 0
call ale#cursor#TruncatedEcho(b:ale_loclist[index]['text'])
else
echo
endif
endfunction
if g:ale_echo_cursor
augroup ALECursorGroup
autocmd!
autocmd CursorMoved * call ale#cursor#EchoCursorWarning()
augroup END
endif

42
plugin/ale/sign.vim Normal file
View File

@@ -0,0 +1,42 @@
if exists('g:loaded_ale_sign')
finish
endif
let g:loaded_ale_sign = 1
if !hlexists('ALEErrorSign')
highlight link ALErrorSign error
endif
if !hlexists('ALEWarningSign')
highlight link ALEWarningSign todo
endif
if !hlexists('ALEError')
highlight link ALEError SpellBad
endif
if !hlexists('ALEWarning')
highlight link ALEWarning SpellCap
endif
" Signs show up on the left for error markers.
sign define ALEErrorSign text=>> texthl=ALEErrorSign
sign define ALEWarningSign text=-- texthl=ALEWarningSign
" This function will set the signs which show up on the left.
function! ale#sign#SetSigns(loclist)
sign unplace *
for i in range(0, len(a:loclist) - 1)
let obj = a:loclist[i]
let name = obj['type'] ==# 'W' ? 'ALEWarningSign' : 'ALEErrorSign'
let sign_line = 'sign place ' . (i + 1)
\. ' line=' . obj['lnum']
\. ' name=' . name
\. ' buffer=' . obj['bufnr']
exec sign_line
endfor
endfunction

182
plugin/ale/zmain.vim Normal file
View File

@@ -0,0 +1,182 @@
" Always set buffer variables for each buffer
let b:ale_should_reset_loclist = 0
let b:ale_loclist = []
if exists('g:loaded_ale_zmain')
finish
endif
let g:loaded_ale_zmain = 1
let s:lint_timer = -1
let s:linters = {}
let s:job_linter_map = {}
let s:job_output_map = {}
function! s:ClearJob(job)
if a:job != -1
let linter = s:job_linter_map[a:job]
call jobstop(a:job)
call remove(s:job_output_map, a:job)
call remove(s:job_linter_map, a:job)
let linter.job = -1
endif
endfunction
function! s:GatherOutput(job, data, event)
if !has_key(s:job_output_map, a:job)
return
endif
call extend(s:job_output_map[a:job], a:data)
endfunction
function! s:LocItemCompare(left, right)
if a:left['lnum'] < a:right['lnum']
return -1
endif
if a:left['lnum'] > a:right['lnum']
return 1
endif
if a:left['col'] < a:right['col']
return -1
endif
if a:left['col'] > a:right['col']
return 1
endif
return 0
endfunction
function! s:HandleExit(job, data, event)
if !has_key(s:job_linter_map, a:job)
return
endif
let linter = s:job_linter_map[a:job]
let output = s:job_output_map[a:job]
call s:ClearJob(a:job)
let linter_loclist = function(linter.callback)(output)
if b:ale_should_reset_loclist
let b:ale_should_reset_loclist = 0
let b:ale_loclist = []
endif
" Add the loclist items from the linter.
call extend(b:ale_loclist, linter_loclist)
" Sort the loclist again.
" We need a sorted list so we can run a binary search against it
" for efficient lookup of the messages in the cursor handler.
call sort(b:ale_loclist, 's:LocItemCompare')
if g:ale_set_loclist
call setloclist(0, b:ale_loclist)
endif
if g:ale_set_signs
call ale#sign#SetSigns(b:ale_loclist)
endif
" Mark line 200, column 17 with a squiggly line or something
" matchadd('ALEError', '\%200l\%17v')
endfunction
function! s:ApplyLinter(linter)
" Stop previous jobs for the same linter.
call s:ClearJob(a:linter.job)
let a:linter.job = jobstart(a:linter.command, {
\ 'on_stdout': 's:GatherOutput',
\ 'on_exit': 's:HandleExit',
\})
let s:job_linter_map[a:linter.job] = a:linter
let s:job_output_map[a:linter.job] = []
call jobsend(a:linter.job, join(getline(1, '$'), "\n") . "\n")
call jobclose(a:linter.job, 'stdin')
endfunction
function! s:TimerHandler()
let filetype = &filetype
let linters = ALEGetLinters(filetype)
" Set a variable telling us to clear the loclist later.
let b:ale_should_reset_loclist = 1
for linter in linters
call s:ApplyLinter(linter)
endfor
endfunction
function! ALEAddLinter(filetype, linter)
" Check if the linter program is executable before adding it.
if !executable(a:linter.executable)
return
endif
if !has_key(s:linters, a:filetype)
let s:linters[a:filetype] = []
endif
call add(s:linters[a:filetype], {
\ 'job': -1,
\ 'command': a:linter.command,
\ 'callback': a:linter.callback,
\})
endfunction
function! ALEGetLinters(filetype)
if !has_key(s:linters, a:filetype)
return []
endif
return s:linters[a:filetype]
endfunction
function! ALELint(delay)
let filetype = &filetype
let linters = ALEGetLinters(filetype)
if s:lint_timer != -1
call timer_stop(s:lint_timer)
let s:lint_timer = -1
endif
if len(linters) == 0
" There are no linters to lint with, so stop here.
return
endif
if a:delay > 0
let s:lint_timer = timer_start(a:delay, 's:TimerHandler')
else
call s:TimerHandler()
endif
endfunction
" Load all of the linters for each filetype.
runtime ale_linters/*/*.vim
if g:ale_lint_on_text_changed
augroup ALERunOnTextChangedGroup
autocmd!
autocmd TextChanged,TextChangedI * call ALELint(g:ale_lint_delay)
augroup END
endif
if g:ale_lint_on_enter
augroup ALERunOnEnterGroup
autocmd!
autocmd BufEnter * call ALELint(0)
augroup END
endif