#1889 Add support for automatically previewing messages based on the cursor position
This commit is contained in:
parent
f380d8508e
commit
43d7e8fde9
5 changed files with 116 additions and 39 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
61
doc/ale.txt
61
doc/ale.txt
|
@ -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.
|
||||||
|
|
|
@ -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'))
|
||||||
|
|
||||||
|
|
Reference in a new issue