mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(lsp): improve LSP doc hover rendering #30695
Problem: - Some servers like LuaLS add unwanted blank lines after multiline `@param` description. - List items do not wrap nicely. Solution: - When rendering the LSP doc hover, remove blank lines in each `@param` or `@return`. - But ensure exactly one empty line before each. - Set 'breakindent'.
This commit is contained in:
parent
5da2a171f7
commit
27f3750817
@ -99,9 +99,26 @@ local function get_border_size(opts)
|
||||
return { height = height, width = width }
|
||||
end
|
||||
|
||||
local function split_lines(value)
|
||||
value = string.gsub(value, '\r\n?', '\n')
|
||||
return split(value, '\n', { plain = true, trimempty = true })
|
||||
--- Splits string at newlines, optionally removing unwanted blank lines.
|
||||
---
|
||||
--- @param s string Multiline string
|
||||
--- @param no_blank boolean? Drop blank lines for each @param/@return (except one empty line
|
||||
--- separating each). Workaround for https://github.com/LuaLS/lua-language-server/issues/2333
|
||||
local function split_lines(s, no_blank)
|
||||
s = string.gsub(s, '\r\n?', '\n')
|
||||
local lines = {}
|
||||
local in_desc = true -- Main description block, before seeing any @foo.
|
||||
for line in vim.gsplit(s, '\n', { plain = true, trimempty = true }) do
|
||||
local start_annotation = not not line:find('^ ?%@.?[pr]')
|
||||
in_desc = (not start_annotation) and in_desc or false
|
||||
if start_annotation and no_blank and not (lines[#lines] or ''):find('^%s*$') then
|
||||
table.insert(lines, '') -- Separate each @foo with a blank line.
|
||||
end
|
||||
if in_desc or not no_blank or not line:find('^%s*$') then
|
||||
table.insert(lines, line)
|
||||
end
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
||||
local function create_window_without_focus()
|
||||
@ -116,7 +133,7 @@ end
|
||||
--- Convenience wrapper around vim.str_utfindex
|
||||
---@param line string line to be indexed
|
||||
---@param index integer|nil byte index (utf-8), or `nil` for length
|
||||
---@param encoding string|nil utf-8|utf-16|utf-32|nil defaults to utf-16
|
||||
---@param encoding 'utf-8'|'utf-16'|'utf-32'|nil defaults to utf-16
|
||||
---@return integer `encoding` index of `index` in `line`
|
||||
function M._str_utfindex_enc(line, index, encoding)
|
||||
local len32, len16 = vim.str_utfindex(line)
|
||||
@ -735,13 +752,13 @@ function M.convert_input_to_markdown_lines(input, contents)
|
||||
contents = contents or {}
|
||||
-- MarkedString variation 1
|
||||
if type(input) == 'string' then
|
||||
list_extend(contents, split_lines(input))
|
||||
list_extend(contents, split_lines(input, true))
|
||||
else
|
||||
assert(type(input) == 'table', 'Expected a table for LSP input')
|
||||
-- MarkupContent
|
||||
if input.kind then
|
||||
local value = input.value or ''
|
||||
list_extend(contents, split_lines(value))
|
||||
list_extend(contents, split_lines(value, true))
|
||||
-- MarkupString variation 2
|
||||
elseif input.language then
|
||||
table.insert(contents, '```' .. input.language)
|
||||
@ -1633,10 +1650,9 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
if do_stylize then
|
||||
vim.wo[floating_winnr].conceallevel = 2
|
||||
end
|
||||
-- disable folding
|
||||
vim.wo[floating_winnr].foldenable = false
|
||||
-- soft wrapping
|
||||
vim.wo[floating_winnr].wrap = opts.wrap
|
||||
vim.wo[floating_winnr].foldenable = false -- Disable folding.
|
||||
vim.wo[floating_winnr].wrap = opts.wrap -- Soft wrapping.
|
||||
vim.wo[floating_winnr].breakindent = true -- Slightly better list presentation.
|
||||
|
||||
vim.bo[floating_bufnr].modifiable = false
|
||||
vim.bo[floating_bufnr].bufhidden = 'wipe'
|
||||
|
@ -83,7 +83,62 @@ describe('vim.lsp.util', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('normalize_markdown', function()
|
||||
it('convert_input_to_markdown_lines', function()
|
||||
local r = exec_lua(function()
|
||||
local hover_data = {
|
||||
kind = 'markdown',
|
||||
value = '```lua\nfunction vim.api.nvim_buf_attach(buffer: integer, send_buffer: boolean, opts: vim.api.keyset.buf_attach)\n -> boolean\n```\n\n---\n\n Activates buffer-update events. Example:\n\n\n\n ```lua\n events = {}\n vim.api.nvim_buf_attach(0, false, {\n on_lines = function(...)\n table.insert(events, {...})\n end,\n })\n ```\n\n\n @see `nvim_buf_detach()`\n @see `api-buffer-updates-lua`\n@*param* `buffer` — Buffer handle, or 0 for current buffer\n\n\n\n@*param* `send_buffer` — True if whole buffer.\n Else the first notification will be `nvim_buf_changedtick_event`.\n\n\n@*param* `opts` — Optional parameters.\n\n - on_lines: Lua callback. Args:\n - the string "lines"\n - buffer handle\n - b:changedtick\n@*return* — False if foo;\n\n otherwise True.\n\n@see foo\n@see bar\n\n',
|
||||
}
|
||||
return vim.lsp.util.convert_input_to_markdown_lines(hover_data)
|
||||
end)
|
||||
local expected = {
|
||||
'```lua',
|
||||
'function vim.api.nvim_buf_attach(buffer: integer, send_buffer: boolean, opts: vim.api.keyset.buf_attach)',
|
||||
' -> boolean',
|
||||
'```',
|
||||
'',
|
||||
'---',
|
||||
'',
|
||||
' Activates buffer-update events. Example:',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
' ```lua',
|
||||
' events = {}',
|
||||
' vim.api.nvim_buf_attach(0, false, {',
|
||||
' on_lines = function(...)',
|
||||
' table.insert(events, {...})',
|
||||
' end,',
|
||||
' })',
|
||||
' ```',
|
||||
'',
|
||||
'',
|
||||
' @see `nvim_buf_detach()`',
|
||||
' @see `api-buffer-updates-lua`',
|
||||
'',
|
||||
-- For each @param/@return: #30695
|
||||
-- - Separate each by one empty line.
|
||||
-- - Remove all other blank lines.
|
||||
'@*param* `buffer` — Buffer handle, or 0 for current buffer',
|
||||
'',
|
||||
'@*param* `send_buffer` — True if whole buffer.',
|
||||
' Else the first notification will be `nvim_buf_changedtick_event`.',
|
||||
'',
|
||||
'@*param* `opts` — Optional parameters.',
|
||||
' - on_lines: Lua callback. Args:',
|
||||
' - the string "lines"',
|
||||
' - buffer handle',
|
||||
' - b:changedtick',
|
||||
'',
|
||||
'@*return* — False if foo;',
|
||||
' otherwise True.',
|
||||
'@see foo',
|
||||
'@see bar',
|
||||
}
|
||||
eq(expected, r)
|
||||
end)
|
||||
|
||||
describe('_normalize_markdown', function()
|
||||
it('collapses consecutive blank lines', function()
|
||||
local result = exec_lua(function()
|
||||
local lines = {
|
||||
|
Loading…
Reference in New Issue
Block a user