#1889 Add support for automatically previewing messages based on the cursor position

This commit is contained in:
w0rp 2018-09-14 12:42:26 +01:00
parent f380d8508e
commit 43d7e8fde9
No known key found for this signature in database
GPG key ID: 0FC1ECAA8C81CD83
5 changed files with 116 additions and 39 deletions

View file

@ -1,4 +1,6 @@
scriptencoding utf-8
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Author: João Paulo S. de Souza <joao.paulo.silvasouza@hotmail.com>
" Description: Echoes lint message for the current line, if any " Description: Echoes lint message for the current line, if any
" Controls the milliseconds delay before echoing a message. " Controls the milliseconds delay before echoing a message.
@ -37,12 +39,11 @@ function! ale#cursor#TruncatedEcho(original_message) abort
endtry endtry
endfunction endfunction
function! s:FindItemAtCursor() abort function! s:FindItemAtCursor(buffer) abort
let l:buf = bufnr('') let l:info = get(g:ale_buffer_info, a:buffer, {})
let l:info = get(g:ale_buffer_info, l:buf, {})
let l:loclist = get(l:info, 'loclist', []) let l:loclist = get(l:info, 'loclist', [])
let l:pos = getcurpos() let l:pos = getcurpos()
let l:index = ale#util#BinarySearch(l:loclist, l:buf, l:pos[1], l:pos[2]) let l:index = ale#util#BinarySearch(l:loclist, a:buffer, l:pos[1], l:pos[2])
let l:loc = l:index >= 0 ? l:loclist[l:index] : {} let l:loc = l:index >= 0 ? l:loclist[l:index] : {}
return [l:info, l:loc] return [l:info, l:loc]
@ -56,7 +57,9 @@ function! s:StopCursorTimer() abort
endfunction endfunction
function! ale#cursor#EchoCursorWarning(...) abort function! ale#cursor#EchoCursorWarning(...) abort
if !g:ale_echo_cursor let l:buffer = bufnr('')
if !g:ale_echo_cursor && !g:ale_cursor_detail
return return
endif endif
@ -65,28 +68,39 @@ function! ale#cursor#EchoCursorWarning(...) abort
return return
endif endif
if ale#ShouldDoNothing(bufnr('')) if ale#ShouldDoNothing(l:buffer)
return return
endif endif
let l:buffer = bufnr('') let [l:info, l:loc] = s:FindItemAtCursor(l:buffer)
let [l:info, l:loc] = s:FindItemAtCursor()
if !empty(l:loc) if g:ale_echo_cursor
let l:format = ale#Var(l:buffer, 'echo_msg_format') if !empty(l:loc)
let l:msg = ale#GetLocItemMessage(l:loc, l:format) let l:format = ale#Var(l:buffer, 'echo_msg_format')
call ale#cursor#TruncatedEcho(l:msg) let l:msg = ale#GetLocItemMessage(l:loc, l:format)
let l:info.echoed = 1 call ale#cursor#TruncatedEcho(l:msg)
elseif get(l:info, 'echoed') let l:info.echoed = 1
" We'll only clear the echoed message when moving off errors once, elseif get(l:info, 'echoed')
" so we don't continually clear the echo line. " We'll only clear the echoed message when moving off errors once,
execute 'echo' " so we don't continually clear the echo line.
let l:info.echoed = 0 execute 'echo'
let l:info.echoed = 0
endif
endif
if g:ale_cursor_detail
if !empty(l:loc)
call s:ShowCursorDetailForItem(l:loc, {'stay_here': 1})
else
call ale#preview#CloseIfTypeMatches('ale-preview')
endif
endif endif
endfunction endfunction
function! ale#cursor#EchoCursorWarningWithDelay() abort function! ale#cursor#EchoCursorWarningWithDelay() abort
if !g:ale_echo_cursor let l:buffer = bufnr('')
if !g:ale_echo_cursor && !g:ale_cursor_detail
return return
endif endif
@ -104,7 +118,7 @@ function! ale#cursor#EchoCursorWarningWithDelay() abort
" we should echo something. Otherwise we can end up doing processing " we should echo something. Otherwise we can end up doing processing
" the echo message far too frequently. " the echo message far too frequently.
if l:pos != s:last_pos if l:pos != s:last_pos
let l:delay = ale#Var(bufnr(''), 'echo_delay') let l:delay = ale#Var(l:buffer, 'echo_delay')
let s:last_pos = l:pos let s:last_pos = l:pos
let s:cursor_timer = timer_start( let s:cursor_timer = timer_start(
@ -114,24 +128,37 @@ function! ale#cursor#EchoCursorWarningWithDelay() abort
endif endif
endfunction endfunction
function! s:ShowCursorDetailForItem(loc, options) abort
let l:stay_here = get(a:options, 'stay_here', 0)
let s:last_detailed_line = line('.')
let l:message = get(a:loc, 'detail', a:loc.text)
let l:lines = split(l:message, "\n")
call ale#preview#Show(l:lines, {'stay_here': l:stay_here})
" Clear the echo message if we manually displayed details.
if !l:stay_here
execute 'echo'
endif
endfunction
function! ale#cursor#ShowCursorDetail() abort function! ale#cursor#ShowCursorDetail() abort
let l:buffer = bufnr('')
" Only echo the warnings in normal mode, otherwise we will get problems. " Only echo the warnings in normal mode, otherwise we will get problems.
if mode() isnot# 'n' if mode() isnot# 'n'
return return
endif endif
if ale#ShouldDoNothing(bufnr('')) if ale#ShouldDoNothing(l:buffer)
return return
endif endif
call s:StopCursorTimer() call s:StopCursorTimer()
let [l:info, l:loc] = s:FindItemAtCursor() let [l:info, l:loc] = s:FindItemAtCursor(l:buffer)
if !empty(l:loc) if !empty(l:loc)
let l:message = get(l:loc, 'detail', l:loc.text) call s:ShowCursorDetailForItem(l:loc, {'stay_here': 0})
call ale#preview#Show(split(l:message, "\n"))
execute 'echo'
endif endif
endfunction endfunction

View file

@ -131,13 +131,17 @@ function! ale#events#Init() abort
autocmd InsertLeave * call ale#Queue(0) autocmd InsertLeave * call ale#Queue(0)
endif endif
if g:ale_echo_cursor if g:ale_echo_cursor || g:ale_cursor_detail
autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarningWithDelay() | endif autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarningWithDelay() | endif
" Look for a warning to echo as soon as we leave Insert mode. " Look for a warning to echo as soon as we leave Insert mode.
" The script's position variable used when moving the cursor will " The script's position variable used when moving the cursor will
" not be changed here. " not be changed here.
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif
endif endif
if g:ale_close_preview_on_insert
autocmd InsertEnter * if exists('*ale#preview#CloseIfTypeMatches') | call ale#preview#CloseIfTypeMatches('ale-preview') | endif
endif
endif endif
augroup END augroup END
endfunction endfunction

View file

@ -15,13 +15,13 @@ function! ale#preview#Show(lines, ...) abort
setlocal modifiable setlocal modifiable
setlocal noreadonly setlocal noreadonly
setlocal nobuflisted setlocal nobuflisted
let &l:filetype = get(l:options, 'filetype', 'ale-preview')
setlocal buftype=nofile setlocal buftype=nofile
setlocal bufhidden=wipe setlocal bufhidden=wipe
:%d :%d
call setline(1, a:lines) call setline(1, a:lines)
setlocal nomodifiable setlocal nomodifiable
setlocal readonly setlocal readonly
let &l:filetype = get(l:options, 'filetype', 'ale-preview')
if get(l:options, 'stay_here') if get(l:options, 'stay_here')
wincmd p wincmd p

View file

@ -527,12 +527,13 @@ circumstances.
ALE will report problems with your code in the following ways, listed with ALE will report problems with your code in the following ways, listed with
their relevant options. their relevant options.
* By updating loclist. (On by default) - |g:ale_set_loclist| * By updating loclist. (On by default) - |g:ale_set_loclist|
* By updating quickfix. (Off by default) - |g:ale_set_quickfix| * By updating quickfix. (Off by default) - |g:ale_set_quickfix|
* By setting error highlights. - |g:ale_set_highlights| * By setting error highlights. - |g:ale_set_highlights|
* By creating signs in the sign column. - |g:ale_set_signs| * By creating signs in the sign column. - |g:ale_set_signs|
* By echoing messages based on your cursor. - |g:ale_echo_cursor| * By echoing messages based on your cursor. - |g:ale_echo_cursor|
* By showing balloons for your mouse cursor - |g:ale_set_balloons| * By displaying the preview based on your cursor. - |g:ale_cursor_detail|
* By showing balloons for your mouse cursor - |g:ale_set_balloons|
Please consult the documentation for each option, which can reveal some other Please consult the documentation for each option, which can reveal some other
ways of tweaking the behaviour of each way of displaying problems. You can ways of tweaking the behaviour of each way of displaying problems. You can
@ -805,6 +806,20 @@ g:ale_change_sign_column_color *g:ale_change_sign_column_color*
windows. windows.
g:ale_close_preview_on_insert *g:ale_close_preview_on_insert*
Type: |Number|
Default: `0`
When this option is set to `1`, ALE's |preview-window| will be automatically
closed upon entering Insert Mode. This option can be used in combination
with |g:ale_cursor_detail| for automatically displaying the preview window
on problem lines, and automatically closing it again when editing text.
This setting must be set to `1` before ALE is loaded for this behavior
to be enabled. See |ale-lint-settings-on-startup|.
g:ale_command_wrapper *g:ale_command_wrapper* g:ale_command_wrapper *g:ale_command_wrapper*
*b:ale_command_wrapper* *b:ale_command_wrapper*
Type: |String| Type: |String|
@ -893,6 +908,27 @@ g:ale_completion_max_suggestions *g:ale_completion_max_suggestions*
Adjust this option as needed, depending on the complexity of your codebase Adjust this option as needed, depending on the complexity of your codebase
and your available processing power. and your available processing power.
g:ale_cursor_detail *g:ale_cursor_detail*
Type: |Number|
Default: `0`
When this option is set to `1`, ALE's |preview-window| will be automatically
opened when the cursor moves onto lines with problems. ALE will search for
problems using the same logic that |g:ale_echo_cursor| uses. The preview
window will be closed automatically when you move away from the line.
Messages are only displayed after a short delay. See |g:ale_echo_delay|.
The preview window is opened without stealing focus, which means your cursor
will stay in the same buffer as it currently is.
The preview window can be closed automatically upon entering Insert mode
by setting |g:ale_close_preview_on_insert| to `1`.
Either this setting or |g:ale_echo_cursor| must be set to `1` before ALE is
loaded for messages to be displayed. See |ale-lint-settings-on-startup|.
g:ale_echo_cursor *g:ale_echo_cursor* g:ale_echo_cursor *g:ale_echo_cursor*
@ -903,11 +939,14 @@ g:ale_echo_cursor *g:ale_echo_cursor*
cursor is near a warning or error. ALE will attempt to find the warning or cursor is near a warning or error. ALE will attempt to find the warning or
error at a column nearest to the cursor when the cursor is resting on a line error at a column nearest to the cursor when the cursor is resting on a line
which contains a warning or error. This option can be set to `0` to disable which contains a warning or error. This option can be set to `0` to disable
this behaviour. this behavior.
The format of the message can be customizable in |g:ale_echo_msg_format|.
You should set this setting once before ALE is loaded, and restart Vim if Messages are only displayed after a short delay. See |g:ale_echo_delay|.
you want to change your preferences. See |ale-lint-settings-on-startup|.
The format of the message can be customized with |g:ale_echo_msg_format|.
Either this setting or |g:ale_cursor_detail| must be set to `1` before ALE
is loaded for messages to be displayed. See |ale-lint-settings-on-startup|.
g:ale_echo_delay *g:ale_echo_delay* g:ale_echo_delay *g:ale_echo_delay*
@ -916,7 +955,7 @@ g:ale_echo_delay *g:ale_echo_delay*
Default: `10` Default: `10`
Given any integer, this option controls the number of milliseconds before Given any integer, this option controls the number of milliseconds before
ALE will echo a message for a problem near the cursor. ALE will echo or preview a message for a problem near the cursor.
The value can be increased to decrease the amount of processing ALE will do The value can be increased to decrease the amount of processing ALE will do
for files displaying a large number of problems. for files displaying a large number of problems.

View file

@ -109,6 +109,13 @@ let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax'))
" 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.
let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1) let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
" This flag can be set to 1 to automatically show errors in the preview window.
let g:ale_cursor_detail = get(g:, 'ale_cursor_detail', 0)
" This flag can be set to 1 to automatically close the preview window upon
" entering Insert Mode.
let g:ale_close_preview_on_insert = get(g:, 'ale_close_preview_on_insert', 0)
" This flag can be set to 0 to disable balloon support. " This flag can be set to 0 to disable balloon support.
let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running')) let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running'))