mirror of https://github.com/dense-analysis/ale
Vim popup (#3817)
* implement vim popups for preview Details on implementation ------------------------- - we make use of the |popupwin| api - we split implementations (Nvim* vs. Vim* prefix) and call the right one based on has('nvim') - we follow a similar structure in each function, using the relevant API - popup_list, win_execute, popup_settext in VimShow - popup_create in VimCreate - popup_close in VimClose Some differences ---------------- - we DON'T have VimPrepareWindowContent because we use arguments to popup_create for borders, padding, etc., and it also takes care of buffer creation. - we follow the protocol of setting and using w:preview for information, but we only need the ID - InsertEnter is the only autocommand required, because of popup_create's moved argument. Any cursor movement with 'any' will close the popup. This in turns means VimClose is only called from InsertMode, so no mode-restoration necessary - we don't tweak too much in the buffer because vim's popup buffers already have most relevant settings and aren't editable without calling popup functions. - I enabled scrollbars, close buttons, dragging, and resizing - vim popups get as big as they need to by default, so no worrying about truncating/hiding/size Note: we might want to consider changing w:preview to w:ale_preview to avoid clashes if someone else tries to use the same variable * floating window: document that vim supports it * lint: fix indent/cont. lines
This commit is contained in:
parent
5ad4fdd583
commit
530b38de34
|
@ -930,6 +930,13 @@ make it look nicer.
|
||||||
let g:ale_floating_window_border = ['│', '─', '╭', '╮', '╯', '╰']
|
let g:ale_floating_window_border = ['│', '─', '╭', '╮', '╯', '╰']
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Since vim's default uses nice unicode characters when possible, you can trick
|
||||||
|
ale into using that default with
|
||||||
|
|
||||||
|
```vim
|
||||||
|
let g:ale_floating_window_border = repeat([''], 6)
|
||||||
|
```
|
||||||
|
|
||||||
<a name="faq-vim-lsp"></a>
|
<a name="faq-vim-lsp"></a>
|
||||||
|
|
||||||
### 5.xxii. How can I use ALE and vim-lsp together?
|
### 5.xxii. How can I use ALE and vim-lsp together?
|
||||||
|
|
|
@ -1,26 +1,35 @@
|
||||||
" Author: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch>
|
" Author: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch>
|
||||||
" Author: Kevin Clark <kevin.clark@gmail.com>
|
" Author: Kevin Clark <kevin.clark@gmail.com>
|
||||||
|
" Author: D. Ben Knoble <ben.knoble+github@gmail.com>
|
||||||
" Description: Floating preview window for showing whatever information in.
|
" Description: Floating preview window for showing whatever information in.
|
||||||
|
|
||||||
" Precondition: exists('*nvim_open_win')
|
" Precondition: exists('*nvim_open_win') || has('popupwin')
|
||||||
|
|
||||||
function! ale#floating_preview#Show(lines, ...) abort
|
function! ale#floating_preview#Show(lines, ...) abort
|
||||||
if !exists('*nvim_open_win')
|
if !exists('*nvim_open_win') && !has('popupwin')
|
||||||
execute 'echom ''Floating windows not supported in this vim instance.'''
|
execute 'echom ''Floating windows not supported in this vim instance.'''
|
||||||
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let l:options = get(a:000, 0, {})
|
||||||
|
|
||||||
|
if has('nvim')
|
||||||
|
call s:NvimShow(a:lines, l:options)
|
||||||
|
else
|
||||||
|
call s:VimShow(a:lines, l:options)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:NvimShow(lines, options) abort
|
||||||
" Remove the close autocmd so it doesn't happen mid update
|
" Remove the close autocmd so it doesn't happen mid update
|
||||||
augroup ale_floating_preview_window
|
augroup ale_floating_preview_window
|
||||||
autocmd!
|
autocmd!
|
||||||
augroup END
|
augroup END
|
||||||
|
|
||||||
let l:options = get(a:000, 0, {})
|
|
||||||
|
|
||||||
" Only create a new window if we need it
|
" Only create a new window if we need it
|
||||||
if !exists('w:preview') || index(nvim_list_wins(), w:preview['id']) is# -1
|
if !exists('w:preview') || index(nvim_list_wins(), w:preview['id']) is# -1
|
||||||
call s:Create(l:options)
|
call s:NvimCreate(a:options)
|
||||||
else
|
else
|
||||||
call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:true)
|
call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:true)
|
||||||
endif
|
endif
|
||||||
|
@ -30,7 +39,7 @@ function! ale#floating_preview#Show(lines, ...) abort
|
||||||
|
|
||||||
call nvim_set_current_win(w:preview['id'])
|
call nvim_set_current_win(w:preview['id'])
|
||||||
|
|
||||||
for l:command in get(l:options, 'commands', [])
|
for l:command in get(a:options, 'commands', [])
|
||||||
call execute(l:command)
|
call execute(l:command)
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
|
@ -41,13 +50,13 @@ function! ale#floating_preview#Show(lines, ...) abort
|
||||||
autocmd!
|
autocmd!
|
||||||
|
|
||||||
if g:ale_close_preview_on_insert
|
if g:ale_close_preview_on_insert
|
||||||
autocmd CursorMoved,TabLeave,WinLeave,InsertEnter <buffer> ++once call s:Close()
|
autocmd CursorMoved,TabLeave,WinLeave,InsertEnter <buffer> ++once call s:NvimClose()
|
||||||
else
|
else
|
||||||
autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:Close()
|
autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:NvimClose()
|
||||||
endif
|
endif
|
||||||
augroup END
|
augroup END
|
||||||
|
|
||||||
let [l:lines, l:width, l:height] = s:PrepareWindowContent(a:lines)
|
let [l:lines, l:width, l:height] = s:NvimPrepareWindowContent(a:lines)
|
||||||
|
|
||||||
call nvim_win_set_width(w:preview['id'], l:width)
|
call nvim_win_set_width(w:preview['id'], l:width)
|
||||||
call nvim_win_set_height(w:preview['id'], l:height)
|
call nvim_win_set_height(w:preview['id'], l:height)
|
||||||
|
@ -56,7 +65,33 @@ function! ale#floating_preview#Show(lines, ...) abort
|
||||||
call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:false)
|
call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:false)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:PrepareWindowContent(lines) abort
|
function! s:VimShow(lines, options) abort
|
||||||
|
if g:ale_close_preview_on_insert
|
||||||
|
" Remove the close autocmd so it doesn't happen mid update
|
||||||
|
silent! autocmd! ale_floating_preview_window
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Only create a new window if we need it
|
||||||
|
if !exists('w:preview') || index(popup_list(), w:preview['id']) is# -1
|
||||||
|
call s:VimCreate(a:options)
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Execute commands in window context
|
||||||
|
for l:command in get(a:options, 'commands', [])
|
||||||
|
call win_execute(w:preview['id'], l:command)
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call popup_settext(w:preview['id'], a:lines)
|
||||||
|
|
||||||
|
if g:ale_close_preview_on_insert
|
||||||
|
augroup ale_floating_preview_window
|
||||||
|
autocmd!
|
||||||
|
autocmd InsertEnter * ++once call s:VimClose()
|
||||||
|
augroup END
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:NvimPrepareWindowContent(lines) abort
|
||||||
let l:max_height = 10
|
let l:max_height = 10
|
||||||
|
|
||||||
let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)'))
|
let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)'))
|
||||||
|
@ -94,7 +129,7 @@ function! s:PrepareWindowContent(lines) abort
|
||||||
return [l:lines, l:width, l:height]
|
return [l:lines, l:width, l:height]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:Create(options) abort
|
function! s:NvimCreate(options) abort
|
||||||
let l:buffer = nvim_create_buf(v:false, v:false)
|
let l:buffer = nvim_create_buf(v:false, v:false)
|
||||||
let l:winid = nvim_open_win(l:buffer, v:false, {
|
let l:winid = nvim_open_win(l:buffer, v:false, {
|
||||||
\ 'relative': 'cursor',
|
\ 'relative': 'cursor',
|
||||||
|
@ -112,7 +147,32 @@ function! s:Create(options) abort
|
||||||
let w:preview = {'id': l:winid, 'buffer': l:buffer}
|
let w:preview = {'id': l:winid, 'buffer': l:buffer}
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:Close() abort
|
function! s:VimCreate(options) abort
|
||||||
|
let l:popup_id = popup_create([], {
|
||||||
|
\ 'line': 'cursor+1',
|
||||||
|
\ 'col': 'cursor',
|
||||||
|
\ 'drag': v:true,
|
||||||
|
\ 'resize': v:true,
|
||||||
|
\ 'close': 'button',
|
||||||
|
\ 'padding': [0, 1, 0, 1],
|
||||||
|
\ 'border': [],
|
||||||
|
\ 'borderchars': empty(g:ale_floating_window_border) ? [' '] : [
|
||||||
|
\ g:ale_floating_window_border[1],
|
||||||
|
\ g:ale_floating_window_border[0],
|
||||||
|
\ g:ale_floating_window_border[1],
|
||||||
|
\ g:ale_floating_window_border[0],
|
||||||
|
\ g:ale_floating_window_border[2],
|
||||||
|
\ g:ale_floating_window_border[3],
|
||||||
|
\ g:ale_floating_window_border[4],
|
||||||
|
\ g:ale_floating_window_border[5],
|
||||||
|
\ ],
|
||||||
|
\ 'moved': 'any',
|
||||||
|
\ })
|
||||||
|
call setbufvar(winbufnr(l:popup_id), '&filetype', get(a:options, 'filetype', 'ale-preview'))
|
||||||
|
let w:preview = {'id': l:popup_id}
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:NvimClose() abort
|
||||||
let l:mode = mode()
|
let l:mode = mode()
|
||||||
let l:restore_visual = l:mode is# 'v' || l:mode is# 'V' || l:mode is# "\<C-V>"
|
let l:restore_visual = l:mode is# 'v' || l:mode is# 'V' || l:mode is# "\<C-V>"
|
||||||
|
|
||||||
|
@ -132,3 +192,12 @@ function! s:Close() abort
|
||||||
normal! gv
|
normal! gv
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! s:VimClose() abort
|
||||||
|
if !exists('w:preview')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call popup_close(w:preview['id'])
|
||||||
|
unlet w:preview
|
||||||
|
endfunction
|
||||||
|
|
16
doc/ale.txt
16
doc/ale.txt
|
@ -651,9 +651,9 @@ problem will be displayed in a balloon instead of hover information.
|
||||||
Hover information can be displayed in the preview window instead by setting
|
Hover information can be displayed in the preview window instead by setting
|
||||||
|g:ale_hover_to_preview| to `1`.
|
|g:ale_hover_to_preview| to `1`.
|
||||||
|
|
||||||
When using Neovim, if |g:ale_hover_to_floating_preview| or |g:ale_floating_preview|
|
When using Neovim or Vim with |popupwin|, if |g:ale_hover_to_floating_preview|
|
||||||
is set to 1, the hover information will show in a floating window. And
|
or |g:ale_floating_preview| is set to 1, the hover information will show in a
|
||||||
|g:ale_floating_window_border| for the border setting.
|
floating window. And |g:ale_floating_window_border| for the border setting.
|
||||||
|
|
||||||
For Vim 8.1+ terminals, mouse hovering is disabled by default. Enabling
|
For Vim 8.1+ terminals, mouse hovering is disabled by default. Enabling
|
||||||
|balloonexpr| commands in terminals can cause scrolling issues in terminals,
|
|balloonexpr| commands in terminals can cause scrolling issues in terminals,
|
||||||
|
@ -968,8 +968,8 @@ g:ale_detail_to_floating_preview *g:ale_detail_to_floating_preview*
|
||||||
Type: |Number|
|
Type: |Number|
|
||||||
Default: `0`
|
Default: `0`
|
||||||
|
|
||||||
When this option is set to `1`, Neovim will use a floating window for
|
When this option is set to `1`, Neovim or Vim with |popupwin| will use a
|
||||||
ALEDetail output.
|
floating window for ALEDetail output.
|
||||||
|
|
||||||
|
|
||||||
g:ale_disable_lsp *g:ale_disable_lsp*
|
g:ale_disable_lsp *g:ale_disable_lsp*
|
||||||
|
@ -1200,7 +1200,8 @@ g:ale_floating_preview *g:ale_floating_preview*
|
||||||
Type: |Number|
|
Type: |Number|
|
||||||
Default: `0`
|
Default: `0`
|
||||||
|
|
||||||
When set to `1`, Neovim will use a floating window for ale's preview window.
|
When set to `1`, Neovim or Vim with |popupwin| will use a floating window
|
||||||
|
for ale's preview window.
|
||||||
This is equivalent to setting |g:ale_hover_to_floating_preview| and
|
This is equivalent to setting |g:ale_hover_to_floating_preview| and
|
||||||
|g:ale_detail_to_floating_preview| to `1`.
|
|g:ale_detail_to_floating_preview| to `1`.
|
||||||
|
|
||||||
|
@ -1281,7 +1282,8 @@ g:ale_hover_to_floating_preview *g:ale_hover_to_floating_preview*
|
||||||
Type: |Number|
|
Type: |Number|
|
||||||
Default: `0`
|
Default: `0`
|
||||||
|
|
||||||
If set to `1`, Neovim will use floating windows for hover messages.
|
If set to `1`, Neovim or Vim with |popupwin| will use floating windows for
|
||||||
|
hover messages.
|
||||||
|
|
||||||
|
|
||||||
g:ale_keep_list_window_open *g:ale_keep_list_window_open*
|
g:ale_keep_list_window_open *g:ale_keep_list_window_open*
|
||||||
|
|
Loading…
Reference in New Issue