First pass at optimizing ale to autoload (#80)

* First pass at optimizing ale to autoload

First off, the structure/function names should be revised a bit,
but I will wait for @w0rp's input before unifying the naming style.
Second off, the docs probably need some more work, I just did some
simple find-and-replace work.

With that said, this pull brings major performance gains for ale. On my
slowest system, fully loading ale and all its code takes around 150ms.

I have moved all of ale's autoload-able code to autoload/, and in
addition, implemented lazy-loading of linters. This brings load time on
that same system down to 5ms.

The only downside of lazy loading is that `g:ale_linters` cannot be
changed at runtime; however, it also speeds up performance at runtime by
simplfying the logic greatly.

Please let me know what you think!

Closes #59

* Address Travis/Vint errors

For some reason, ale isn't running vint for me...

* Incorporate feedback, make fixes

Lazy-loading logic is much improved.

* Add header comments; remove incorrect workaround

* Remove unneeded plugin guards

* Fix lazy-loading linter logic

Set the wrong variable....

* Fix capitialization
This commit is contained in:
Bjorn Neergaard
2016-10-10 13:51:29 -05:00
committed by w0rp
parent 0680f875fe
commit 7f0ce89d2b
44 changed files with 337 additions and 336 deletions

119
autoload/ale/cursor.vim Normal file
View File

@@ -0,0 +1,119 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Echoes lint message for the current line, if any
" Return a formatted message according to g:ale_echo_msg_format variable
function! s:GetMessage(linter, type, text) abort
let msg = g:ale_echo_msg_format
let type = a:type ==# 'E'
\ ? g:ale_echo_msg_error_str
\ : g:ale_echo_msg_warning_str
" Capitalize the 1st character
let text = toupper(a:text[0]) . a:text[1:-1]
" Replace handlers if they exist
for [k, v] in items({'linter': a:linter, 'severity': type})
let msg = substitute(msg, '\V%' . k . '%', v, '')
endfor
return printf(msg, text)
endfunction
" 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) abort
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) abort
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')
" We need to turn T for truncated messages on for shortmess,
" and then then we need to reset the option back to what it was.
let shortmess_options = getbufvar('%', '&shortmess')
try
" Echo the message truncated to fit without creating a prompt.
setlocal shortmess+=T
exec "norm :echomsg message\n"
finally
call setbufvar('%', '&shortmess', shortmess_options)
endtry
endfunction
function! ale#cursor#EchoCursorWarning(...) abort
" Only echo the warnings in normal mode, otherwise we will get problems.
if mode() !=# 'n'
return
endif
let buffer = bufnr('%')
if !has_key(g:ale_buffer_loclist_map, buffer)
return
endif
let loclist = g:ale_buffer_loclist_map[buffer]
let pos = getcurpos()
let index = s:BinarySearch(loclist, pos[1], pos[2])
if index >= 0
let l = loclist[index]
let msg = s:GetMessage(l.linter_name, l.type, l.text)
call ale#cursor#TruncatedEcho(msg)
else
echo
endif
endfunction
let s:cursor_timer = -1
function! ale#cursor#EchoCursorWarningWithDelay() abort
if s:cursor_timer != -1
call timer_stop(s:cursor_timer)
let s:cursor_timer = -1
endif
let s:cursor_timer = timer_start(10, function('ale#cursor#EchoCursorWarning'))
endfunction
if g:ale_has_required_features && g:ale_echo_cursor
augroup ALECursorGroup
autocmd!
autocmd CursorMoved,CursorHold * call ale#cursor#EchoCursorWarningWithDelay()
augroup END
endif