Merge pull request #97 from neersighted/statusline-count

Implement a more efficient statusbar
This commit is contained in:
w0rp 2016-10-13 15:02:58 +01:00 committed by GitHub
commit 86ee54e271
7 changed files with 120 additions and 44 deletions

View File

@ -2,14 +2,18 @@
" Description: Utility functions related to cleaning state. " Description: Utility functions related to cleaning state.
function! ale#cleanup#Buffer(buffer) abort function! ale#cleanup#Buffer(buffer) abort
if has_key(g:ale_buffer_should_reset_map, a:buffer) if has_key(g:ale_buffer_count_map, a:buffer)
call remove(g:ale_buffer_should_reset_map, a:buffer) call remove(g:ale_buffer_count_map, a:buffer)
endif endif
if has_key(g:ale_buffer_loclist_map, a:buffer) if has_key(g:ale_buffer_loclist_map, a:buffer)
call remove(g:ale_buffer_loclist_map, a:buffer) call remove(g:ale_buffer_loclist_map, a:buffer)
endif endif
if has_key(g:ale_buffer_should_reset_map, a:buffer)
call remove(g:ale_buffer_should_reset_map, a:buffer)
endif
if has_key(g:ale_buffer_sign_dummy_map, a:buffer) if has_key(g:ale_buffer_sign_dummy_map, a:buffer)
call remove(g:ale_buffer_sign_dummy_map, a:buffer) call remove(g:ale_buffer_sign_dummy_map, a:buffer)
endif endif

View File

@ -98,7 +98,7 @@ function! s:HandleExit(job) abort
" Sort the loclist again. " Sort the loclist again.
" We need a sorted list so we can run a binary search against it " We need a sorted list so we can run a binary search against it
" for efficient lookup of the messages in the cursor handler. " for efficient lookup of the messages in the cursor handler.
call sort(g:ale_buffer_loclist_map[l:buffer], 'ale#util#LocItemCompare') call sort(g:ale_buffer_loclist_map[l:buffer], 's:LocItemCompare')
if g:ale_set_loclist if g:ale_set_loclist
call setloclist(0, g:ale_buffer_loclist_map[l:buffer]) call setloclist(0, g:ale_buffer_loclist_map[l:buffer])
@ -108,6 +108,11 @@ function! s:HandleExit(job) abort
call ale#sign#SetSigns(l:buffer, g:ale_buffer_loclist_map[l:buffer]) call ale#sign#SetSigns(l:buffer, g:ale_buffer_loclist_map[l:buffer])
endif endif
if exists('*ale#statusline#Update')
" Don't load/run if not already loaded.
call ale#statusline#Update(l:buffer, g:ale_buffer_loclist_map[l:buffer])
endif
" Mark line 200, column 17 with a squiggly line or something " Mark line 200, column 17 with a squiggly line or something
" matchadd('ALEError', '\%200l\%17v') " matchadd('ALEError', '\%200l\%17v')
endfunction endfunction
@ -136,6 +141,26 @@ function! s:FixLocList(buffer, loclist) abort
endfor endfor
endfunction endfunction
function! s:LocItemCompare(left, right) abort
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! ale#engine#Invoke(buffer, linter) abort function! ale#engine#Invoke(buffer, linter) abort
if has_key(a:linter, 'job') if has_key(a:linter, 'job')
" Stop previous jobs for the same linter. " Stop previous jobs for the same linter.

View File

@ -1,20 +1,12 @@
" Author: KabbAmine <amine.kabb@gmail.com> " Author: KabbAmine <amine.kabb@gmail.com>
" Description: Statusline related function(s) " Description: Statusline related function(s)
function! ale#statusline#Status() abort " Update the buffer error/warning count with data from loclist.
" Returns a formatted string that can be integrated in the function! ale#statusline#Update(buffer, loclist) abort
" statusline
let l:buffer = bufnr('%')
let l:loclist = g:ale_buffer_loclist_map
if !has_key(l:loclist, l:buffer)
return ''
endif
let l:errors = 0 let l:errors = 0
let l:warnings = 0 let l:warnings = 0
for l:entry in l:loclist[l:buffer]
for l:entry in a:loclist
if l:entry.type ==# 'E' if l:entry.type ==# 'E'
let l:errors += 1 let l:errors += 1
else else
@ -22,11 +14,36 @@ function! ale#statusline#Status() abort
endif endif
endfor endfor
let l:errors = l:errors ? printf(g:ale_statusline_format[0], l:errors) : '' let g:ale_buffer_count_map[a:buffer] = [l:errors, l:warnings]
let l:warnings = l:warnings ? printf(g:ale_statusline_format[1], l:warnings) : '' endfunction
" Returns a tuple of errors and warnings for use in third-party integrations.
function! ale#statusline#Count(buffer) abort
" Cache is cold, so manually ask for an update.
if !has_key(g:ale_buffer_count_map, a:buffer)
call ale#statusline#Update(a:buffer, get(g:ale_buffer_loclist_map, a:buffer, []))
endif
return g:ale_buffer_count_map[a:buffer]
endfunction
" Returns a formatted string that can be integrated in the statusline.
function! ale#statusline#Status() abort
let l:buffer = bufnr('%')
" Cache is cold, so manually ask for an update.
if !has_key(g:ale_buffer_count_map, l:buffer)
call ale#statusline#Update(l:buffer, get(g:ale_buffer_loclist_map, l:buffer, []))
endif
" Build strings based on user formatting preferences.
let l:errors = g:ale_buffer_count_map[l:buffer][0] ?
\ printf(g:ale_statusline_format[0], g:ale_buffer_count_map[l:buffer][0]) : ''
let l:warnings = g:ale_buffer_count_map[l:buffer][1] ?
\ printf(g:ale_statusline_format[1], g:ale_buffer_count_map[l:buffer][1]) : ''
let l:no_errors = g:ale_statusline_format[2] let l:no_errors = g:ale_statusline_format[2]
" Different formats if no errors or no warnings " Different formats based on the combination of errors and warnings.
if empty(l:errors) && empty(l:warnings) if empty(l:errors) && empty(l:warnings)
let l:res = l:no_errors let l:res = l:no_errors
elseif !empty(l:errors) && !empty(l:warnings) elseif !empty(l:errors) && !empty(l:warnings)

View File

@ -43,23 +43,3 @@ function! ale#util#GetFunction(string_or_ref) abort
return a:string_or_ref return a:string_or_ref
endfunction endfunction
function! ale#util#LocItemCompare(left, right) abort
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

View File

@ -24,6 +24,7 @@ endif
" Globals " Globals
let g:ale_buffer_count_map = {}
let g:ale_buffer_loclist_map = {} let g:ale_buffer_loclist_map = {}
let g:ale_buffer_should_reset_map = {} let g:ale_buffer_should_reset_map = {}
let g:ale_buffer_sign_dummy_map = {} let g:ale_buffer_sign_dummy_map = {}
@ -98,7 +99,8 @@ let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning') let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
" This flag can be set to 0 to disable echoing when the cursor moves. " This flag can be set to 0 to disable echoing when the cursor moves.
if get(g:, 'ale_echo_cursor', 1) let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
if g:ale_echo_cursor
augroup ALECursorGroup augroup ALECursorGroup
autocmd! autocmd!
autocmd CursorMoved,CursorHold * call ale#cursor#EchoCursorWarningWithDelay() autocmd CursorMoved,CursorHold * call ale#cursor#EchoCursorWarningWithDelay()
@ -120,10 +122,10 @@ let g:ale_warn_about_trailing_whitespace =
" Housekeeping " Housekeeping
augroup ALECleanup augroup ALECleanupGroup
autocmd! autocmd!
" Clean up buffers automatically when they are unloaded. " Clean up buffers automatically when they are unloaded.
autocmd BufUnload * call ale#cleanup#Buffer('<abuf>') autocmd BufUnload * call ale#cleanup#Buffer(expand('<abuf>'))
augroup END augroup END
" Backwards Compatibility " Backwards Compatibility

View File

@ -0,0 +1,50 @@
Before:
let g:ale_buffer_loclist_map = {}
Execute (Count should be 0 when data is empty):
AssertEqual ale#statusline#Count(bufnr('%')), [0, 0]
Before:
let g:ale_buffer_count_map = {'44': [1, 2]}
Execute (Count should read data from the cache):
AssertEqual ale#statusline#Count(44), [1, 2]
Execute (Update the cache with new data):
call ale#statusline#Update(44, [])
Then (The cache should reflect the new data):
AssertEqual ale#statusline#Count(44), [0, 0]
Before:
let g:ale_buffer_loclist_map = {'1': [{'lnum': 1, 'bufnr': 1, 'vcol': 0, 'linter_name': 'testlinter', 'nr': -1, 'type': 'E', 'col': 1, 'text': 'Test Error'}]}
Execute (Count should be match the loclist):
AssertEqual ale#statusline#Count(1), [1, 0]
Execute (Output should be empty for non-existant buffer):
AssertEqual ale#statusline#Count(9001), [0, 0]
Before:
let g:ale_statusline_format = ['%sE', '%sW', 'OKIE']
Execute (Given some errors):
call ale#statusline#Update(bufnr('%'), [{'type': 'E'}, {'type': 'E'}])
Then (Statusline is formatted to the users preference):
AssertEqual ale#statusline#Status(), "2E"
Execute (Given some warnings):
call ale#statusline#Update(bufnr('%'), [{'type': 'W'}, {'type': 'W'}, {'type': 'W'}])
Then (Statusline is formatted to the users preference):
AssertEqual ale#statusline#Status(), "3W"
Execute (Given some warnings, and errors.):
call ale#statusline#Update(bufnr('%'), [{'type': 'E'}, {'type': 'W'}, {'type': 'W'}])
Then (Statusline is formatted to the users preference):
AssertEqual ale#statusline#Status(), "1E 2W"
Execute (Given a lack of data):
call ale#statusline#Update(bufnr('%'), [])
Then (Statusline is formatted to the users preference):
AssertEqual ale#statusline#Status(), 'OKIE'

View File

@ -2,9 +2,7 @@
" Load builtin plugins " Load builtin plugins
" We need this because run_vim.sh sets -i NONE " We need this because run_vim.sh sets -i NONE
set runtimepath=/home/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,/testplugin set runtimepath=/home/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,/testplugin,/vader
set runtimepath+=/home/ale
set runtimepath+=/vader
" The following is just an example " The following is just an example
filetype plugin indent on filetype plugin indent on