Skip to content

[WIP] Refactor floats #510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions autoload/lsp/ui/vim/tooltip.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
" Generic functions for interacting with tooltip-type windows for hover,
" preview etc.

if !has('nvim') && has('patch-8.1.1517') && g:lsp_preview_float
let s:create_tooltip = function('lsp#ui#vim#tooltip#popup#create_tooltip')
elseif has('nvim') && exists('*nvim_open_win') && g:lsp_preview_float
let s:create_tooltip = function('lsp#ui#vim#tooltip#float#create_tooltip')
else
let s:create_tooltip = function('lsp#ui#vim#tooltip#preview#screate_tooltip')
endif

function! lsp#ui#vim#tooltip#show_cursor_tooltip(lines, filetype, synranges, options) abort
" ...
let winid = s:create_tooltip()
" ...
endfunction
5 changes: 5 additions & 0 deletions autoload/lsp/ui/vim/tooltip/float.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
" Implements backend-specific tooltip API using neovim floats (version 0.4.0)

function! lsp#ui#vim#tooltip#float#create_tooltip() abort
return 0
endfunction
Empty file.
Empty file.
Empty file.
173 changes: 173 additions & 0 deletions doc/tooltip-api.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
*tooltip-api.txt* generic API for handling tooltips

Vim-lsp offers a generic API that allows overlaying information on the main
buffer, e.g., for `hover` or `PeekDefinition`, here referred to as "tooltip" to
distinguish from vim's popups or neovim's floating windows (which this API is
meant to abstract).

The API is separated into
1. a `top-level API` for opening and updating tooltips to be called from
functions handling language server responses,
2. an `intermediate-level API` that is implemented separately for each backend
using the specific backend's low-level API.

Calling the intermediate-level API should be avoided since it is subject to
change in order to adapt to changes in low-level API or to add new backends.

==============================================================================
TOP-LEVEL API *top-level-api*

The top-level API offers generic functions for creating and updating tooltip
windows. It distinguishes two types of windows that behave differently:

1. `cursor tooltips` open near or relative to the cursor (e.g., for `hover`)
and are typically closed quickly,
2. `pum tooltips` open near or relative to the popup menu (e.g., for showing
documentation) and are typically updated rather than closed.

All the following functions take the same initial arguments:

- {lines}: A |list| of |String|s that represents the plain-text content of
the popup.
- {filetype}: The |'filetype'| of the popup buffer. This determines the
syntax highlighting of the entire buffer, which ftplugin is used, and so
on.
- {syn-ranges}: A |list| of |dict|s, each representing a highlight group
to be applied to the popup.

Can be used for displaying stripped `*bold*` in a bold font, or to apply
syntax highlighting to a region.
Example of an entry: >
{
'range': {
'start': {
'line': 5,
'character': 10
},
'end': {
'line': 5,
'character': 15
}
},
'group': 'markdownBold'
}
<
Pass an empty |list| `[]` for no additional highlighting (apart from
the syntax highlighting applied for the {filetype}).
- {options}: A |dict| controlling the behavior of the tooltip that can
contain the following keys:
- 'close': conditions when the tooltip should be closed. Possible
values: 'move', 'insert'.
- 'maxwidth': maximal width of the tooltip
- 'border': draw border around tooltip; default: |v:false|
- 'focus': focus tooltip; default: |v:false|
- 'firstline': ???
- 'cursor': {'align': , 'pos': } ???

TODO: add more options, bike-shed names, decide on defaults,
TODO: 'pos' in characters or bytes? 0- or 1-indexed?

Options not relevant to a function or a backend are ignored.

show_cursor_tooltip({lines}, {filetype}, {syn-ranges}, {options})

Shows a tooltip at the current cursor position, either above or below,
depending on where there is enough space.

The preview's content is set depending on {lines}, {syn-ranges} and
{filetype}, see above.

Returns the window ID of the created popup.

show_pum_tooltip({lines}, {filetype}, {syn-ranges}, {options})

Shows a tooltip associated with the currently selected item in the popup
menu. It can be either to the left/right of the item, depending on where
there is enough space. Settings from |'completepopup'| is taken into
account.

The preview's content is set depending on {lines}, {syn-ranges} and
{filetype}, see above.

Returns the window ID of the created popup.

update_pum_tooltip({winid}, {lines}, {filetype}, {syn-ranges}, {options})

Changes the content of the tooltip associated with the currently selected
item in the popup menu. {winid} must be the value returned by
`show_pum_tooltip`.


In addition, there are utility functions useful for interacting with floats:

parse_lsp_response({data})

Parses a LSP response (be it a String, MarkedString, Markdown segment,
MarkupContent, ...; from hereon just {data}) to

- a |list| of |String|s that represent the "stripped" content, e.g.
markdown `*bold*` strings will be converted to just `bold`, code
blocks will have the markers removed, etc. It's the "plain-text, no
colour" version of the {data};

- a |list| of |Dicts| that specifies the |syn-ranges|, i.e., of
character ranges and Vim syntax groups to apply to them.

Returns a tuple |[lines,syn-ranges]| .

TODO: move to `util.vim`?


==============================================================================
INTERMEDIATE-LEVEL API *intermediate-level-api*

These functions abstract the low-level backend-specific API for interacting
with tooltip-type windows. They have a common signature but are implemented
separately for each backend.

Currently, the following backends are implemented:

1. `popup` windows for vim 8.1.1517+
2. `floating windows` for neovim 0.4.0+
3. TODO: `preview` buffers as a fallback

create_tooltip()

Creates a hidden floating window, with undefined position, and an empty
buffer associated with it.

Returns the created window ID.


set_tooltip_contents({winid}, {lines})

Updates the contents of a given floating window, and unhides it. Also
retriggers size calculation.


set_tooltip_position({winid}, {options})

Sets the position of the given floating window, be it cursor-relative,
pum-relative, etc. Also retriggers size calculation.

TODO: Which {options}?


close_tooltip({winid})

Closes the tooltip with the ID {winid}.


In addition, there are common utility functions:

get_size_info({lines})

Get width and height needed to show the line-wrapped contents of a list
of strings.

Returns a tuple of |[lines,width]|

TODO: in characters or bytes?


vim:tw=78:ts=4:ft=help:et