diff --git a/autoload/lsp/ui/vim/tooltip.vim b/autoload/lsp/ui/vim/tooltip.vim new file mode 100644 index 000000000..fb003102d --- /dev/null +++ b/autoload/lsp/ui/vim/tooltip.vim @@ -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 diff --git a/autoload/lsp/ui/vim/tooltip/float.vim b/autoload/lsp/ui/vim/tooltip/float.vim new file mode 100644 index 000000000..b15c695d9 --- /dev/null +++ b/autoload/lsp/ui/vim/tooltip/float.vim @@ -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 diff --git a/autoload/lsp/ui/vim/tooltip/popup.vim b/autoload/lsp/ui/vim/tooltip/popup.vim new file mode 100644 index 000000000..e69de29bb diff --git a/autoload/lsp/ui/vim/tooltip/preview.vim b/autoload/lsp/ui/vim/tooltip/preview.vim new file mode 100644 index 000000000..e69de29bb diff --git a/autoload/lsp/ui/vim/tooltip/utils.vim b/autoload/lsp/ui/vim/tooltip/utils.vim new file mode 100644 index 000000000..e69de29bb diff --git a/doc/tooltip-api.txt b/doc/tooltip-api.txt new file mode 100644 index 000000000..963c67c43 --- /dev/null +++ b/doc/tooltip-api.txt @@ -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