From 257d894d75bc583bb16f4dbe441907eb273d20ad Mon Sep 17 00:00:00 2001 From: Roberto Pommella Alegro Date: Sat, 25 Mar 2023 13:46:07 -0300 Subject: feat(lsp): render markdown in docs hover #22766 Problem: LSP docs hover (textDocument/hover) doesn't handle HTML escape seqs in markdown. Solution: Convert common HTML escape seqs to a nicer form, to display in the float. closees #22757 Signed-off-by: Kasama --- test/functional/plugin/lsp/utils_spec.lua | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 test/functional/plugin/lsp/utils_spec.lua (limited to 'test/functional/plugin/lsp/utils_spec.lua') diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua new file mode 100644 index 0000000000..3e53b6d574 --- /dev/null +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -0,0 +1,75 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local exec_lua = helpers.exec_lua + +describe('vim.lsp.util', function() + before_each(helpers.clear) + + describe('stylize_markdown', function() + local stylize_markdown = function(content, opts) + return exec_lua([[ + local bufnr = vim.uri_to_bufnr("file:///fake/uri") + vim.fn.bufload(bufnr) + + local args = { ... } + local content = args[1] + local opts = args[2] + local stripped_content = vim.lsp.util.stylize_markdown(bufnr, content, opts) + + return stripped_content + ]], content, opts) + end + + it('code fences', function() + local lines = { + "```lua", + "local hello = 'world'", + "```", + } + local expected = { + "local hello = 'world'", + } + local opts = {} + eq(expected, stylize_markdown(lines, opts)) + end) + + it('adds separator after code block', function() + local lines = { + "```lua", + "local hello = 'world'", + "```", + "", + "something", + } + local expected = { + "local hello = 'world'", + "─────────────────────", + "something", + } + local opts = { separator = true } + eq(expected, stylize_markdown(lines, opts)) + end) + + it('replaces supported HTML entities', function() + local lines = { + "1 < 2", + "3 > 2", + ""quoted"", + "'apos'", + "   ", + "&", + } + local expected = { + "1 < 2", + "3 > 2", + '"quoted"', + "'apos'", + " ", + "&", + } + local opts = {} + eq(expected, stylize_markdown(lines, opts)) + end) + end) +end) -- cgit From 251ca45ac94851c896db0d27685622fb78a73b3e Mon Sep 17 00:00:00 2001 From: Mike <10135646+mikesmithgh@users.noreply.github.com> Date: Sun, 16 Jul 2023 06:11:45 -0400 Subject: fix(lsp): markdown code fence should allow space before info string #24364 Problem: Bash language server returns "hover" markdown content that starts with a code fence and info string of `man` preceded by whitespace, which Nvim does not render properly. See https://github.com/bash-lsp/bash-language-server/blob/0ee73c53cebdc18311d4a4ad9367185ea4d98a03/server/src/server.ts#L821C15-L821C15 ```typescript function getMarkdownContent(documentation: string, language?: string): LSP.MarkupContent { return { value: language ? // eslint-disable-next-line prefer-template ['``` ' + language, documentation, '```'].join('\n') : documentation, kind: LSP.MarkupKind.Markdown, } } ``` For example, ``` ``` man NAME git - the stupid content tracker ``` ``` If I remove the white space, then it is properly formatted. ``` ```man instead of ``` man ``` Per CommonMark Spec https://spec.commonmark.org/0.30/#info-string whitespace is allowed before and after the `info string` which identifies the language in a codeblock. > The line with the opening code fence may optionally contain some text > following the code fence; this is trimmed of leading and trailing > spaces or tabs and called the [info > string](https://spec.commonmark.org/0.30/#info-string). If the [info > string](https://spec.commonmark.org/0.30/#info-string) comes after > a backtick fence, it may not contain any backtick characters. (The > reason for this restriction is that otherwise some inline code would > be incorrectly interpreted as the beginning of a fenced code block.) Solution: Adjust stylize_markdown() to allow whitespace before codeblock info. --- test/functional/plugin/lsp/utils_spec.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test/functional/plugin/lsp/utils_spec.lua') diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua index 3e53b6d574..c91fffa90f 100644 --- a/test/functional/plugin/lsp/utils_spec.lua +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -34,6 +34,19 @@ describe('vim.lsp.util', function() eq(expected, stylize_markdown(lines, opts)) end) + it('code fences with whitespace surrounded info string', function() + local lines = { + "``` lua ", + "local hello = 'world'", + "```", + } + local expected = { + "local hello = 'world'", + } + local opts = {} + eq(expected, stylize_markdown(lines, opts)) + end) + it('adds separator after code block', function() local lines = { "```lua", -- cgit From 5e3cf9fb4bc7f236c858f609ca83c57fb1779ab0 Mon Sep 17 00:00:00 2001 From: Grace Petryk Date: Sun, 10 Sep 2023 01:02:23 -0700 Subject: feat(lsp): improve control over placement of floating windows (#24494) --- test/functional/plugin/lsp/utils_spec.lua | 96 +++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'test/functional/plugin/lsp/utils_spec.lua') diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua index c91fffa90f..f544255d81 100644 --- a/test/functional/plugin/lsp/utils_spec.lua +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -1,4 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local feed = helpers.feed local eq = helpers.eq local exec_lua = helpers.exec_lua @@ -85,4 +87,98 @@ describe('vim.lsp.util', function() eq(expected, stylize_markdown(lines, opts)) end) end) + + describe("make_floating_popup_options", function () + + local function assert_anchor(anchor_bias, expected_anchor) + local opts = exec_lua([[ + local args = { ... } + local anchor_bias = args[1] + return vim.lsp.util.make_floating_popup_options(30, 10, { anchor_bias = anchor_bias }) + ]], anchor_bias) + + eq(expected_anchor, string.sub(opts.anchor, 1, 1)) + end + + local screen + before_each(function () + helpers.clear() + screen = Screen.new(80, 80) + screen:attach() + feed("79i") -- fill screen with empty lines + end) + + describe('when on the first line it places window below', function () + before_each(function () + feed('gg') + end) + + it('for anchor_bias = "auto"', function () + assert_anchor('auto', 'N') + end) + + it('for anchor_bias = "above"', function () + assert_anchor('above', 'N') + end) + + it('for anchor_bias = "below"', function () + assert_anchor('below', 'N') + end) + end) + + describe('when on the last line it places window above', function () + before_each(function () + feed('G') + end) + + it('for anchor_bias = "auto"', function () + assert_anchor('auto', 'S') + end) + + it('for anchor_bias = "above"', function () + assert_anchor('above', 'S') + end) + + it('for anchor_bias = "below"', function () + assert_anchor('below', 'S') + end) + end) + + describe('with 20 lines above, 59 lines below', function () + before_each(function () + feed('gg20j') + end) + + it('places window below for anchor_bias = "auto"', function () + assert_anchor('auto', 'N') + end) + + it('places window above for anchor_bias = "above"', function () + assert_anchor('above', 'S') + end) + + it('places window below for anchor_bias = "below"', function () + assert_anchor('below', 'N') + end) + end) + + describe('with 59 lines above, 20 lines below', function () + before_each(function () + feed('G20k') + end) + + it('places window above for anchor_bias = "auto"', function () + assert_anchor('auto', 'S') + end) + + it('places window above for anchor_bias = "above"', function () + assert_anchor('above', 'S') + end) + + it('places window below for anchor_bias = "below"', function () + assert_anchor('below', 'N') + end) + end) + end) + end) -- cgit From b2265bb72c268c95180dc92c129be11fd87f995d Mon Sep 17 00:00:00 2001 From: Maria José Solano Date: Tue, 19 Sep 2023 21:30:22 -0700 Subject: test(lsp): add normalize_markdown tests --- test/functional/plugin/lsp/utils_spec.lua | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'test/functional/plugin/lsp/utils_spec.lua') diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua index f544255d81..12763cfef5 100644 --- a/test/functional/plugin/lsp/utils_spec.lua +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -88,6 +88,40 @@ describe('vim.lsp.util', function() end) end) + describe('normalize_markdown', function () + it('collapses consecutive blank lines', function () + local result = exec_lua [[ + local lines = { + 'foo', + '', + '', + '', + 'bar', + '', + 'baz' + } + return vim.lsp.util._normalize_markdown(lines) + ]] + local expected = {'foo', '', 'bar', '', 'baz'} + eq(expected, result) + end) + + it('removes preceding and trailing empty lines', function () + local result = exec_lua [[ + local lines = { + '', + 'foo', + 'bar', + '', + '' + } + return vim.lsp.util._normalize_markdown(lines) + ]] + local expected = {'foo', 'bar'} + eq(expected, result) + end) + end) + describe("make_floating_popup_options", function () local function assert_anchor(anchor_bias, expected_anchor) -- cgit From 9abced6ad95f6300ae80cd8b8aa124ebcf511b50 Mon Sep 17 00:00:00 2001 From: LW Date: Sun, 8 Oct 2023 01:09:25 -0700 Subject: fix(lsp): account for border height in max floating popup height (#25539) --- test/functional/plugin/lsp/utils_spec.lua | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'test/functional/plugin/lsp/utils_spec.lua') diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua index 12763cfef5..804dc32f0d 100644 --- a/test/functional/plugin/lsp/utils_spec.lua +++ b/test/functional/plugin/lsp/utils_spec.lua @@ -212,6 +212,14 @@ describe('vim.lsp.util', function() it('places window below for anchor_bias = "below"', function () assert_anchor('below', 'N') end) + + it('bordered window truncates dimensions correctly', function () + local opts = exec_lua([[ + return vim.lsp.util.make_floating_popup_options(100, 100, { border = 'single' }) + ]]) + + eq(56, opts.height) + end) end) end) -- cgit