Skip to content

Commit 63c70a9

Browse files
committed
feat(lsp): added custom formatters for lsp hover and made :help work in hover text
1 parent 345fccc commit 63c70a9

File tree

4 files changed

+96
-61
lines changed

4 files changed

+96
-61
lines changed

lua/noice/config/init.lua

+14
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ M.defaults = {
7878
hover = {
7979
enabled = false,
8080
view = "notify",
81+
opts = {
82+
lang = "markdown",
83+
replace = true,
84+
render = "plain",
85+
buf_options = { iskeyword = '!-~,^*,^|,^",192-255', keywordprg = ":help" },
86+
},
87+
},
88+
hl_patterns = {
89+
["|%S-|"] = "@text.reference",
90+
["@%S+"] = "@parameter",
91+
["^%s*(Parameters:)"] = "@text.title",
92+
["^%s*(Return:)"] = "@text.title",
93+
["^%s*(See also:)"] = "@text.title",
94+
["{%S-}"] = "@parameter",
8195
},
8296
},
8397
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.

lua/noice/config/routes.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function M.defaults()
108108
{
109109
view = Config.options.lsp.hover.view,
110110
filter = { event = "lsp", kind = "hover" },
111-
opts = { lang = "markdown", replace = true },
111+
opts = Config.options.lsp.hover.opts,
112112
},
113113
{
114114
view = Config.options.lsp.progress.view,

lua/noice/source/lsp/format.lua

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
local require = require("noice.util.lazy")
2+
3+
local Message = require("noice.message")
4+
local NoiceText = require("noice.text")
5+
local Config = require("noice.config")
6+
7+
local M = {}
8+
9+
---@alias MarkedString string | { language: string; value: string }
10+
---@alias MarkupContent { kind: ('plaintext' | 'markdown'), value: string}
11+
---@alias MarkupContents MarkedString | MarkedString[] | MarkupContent
12+
13+
---@param contents MarkupContents
14+
---@param kind LspKind
15+
function M.format(contents, kind)
16+
if type(contents) ~= "table" or not vim.tbl_islist(contents) then
17+
contents = { contents }
18+
end
19+
20+
local parts = {}
21+
22+
for _, content in ipairs(contents) do
23+
if type(content) == "string" then
24+
table.insert(parts, content)
25+
elseif content.language then
26+
table.insert(parts, ("```%s\n%s\n```"):format(content.language, content.value))
27+
elseif content.kind == "markdown" then
28+
table.insert(parts, content.value)
29+
elseif content.kind == "plaintext" then
30+
table.insert(parts, ("```\n%s\n```"):format(content.value))
31+
end
32+
end
33+
34+
local text = table.concat(parts, "\n")
35+
text = text:gsub("\n\n\n", "\n\n")
36+
text = text:gsub("\n%s*\n```", "\n```")
37+
text = text:gsub("```\n%s*\n", "```\n")
38+
39+
local lines = vim.split(text, "\n")
40+
41+
local width = 50
42+
for _, line in pairs(lines) do
43+
width = math.max(width, vim.api.nvim_strwidth(line))
44+
end
45+
46+
local message = Message(M.event, kind)
47+
message.once = true
48+
message.opts.title = kind
49+
50+
for _, line in ipairs(lines) do
51+
message:newline()
52+
-- Make the horizontal ruler extend the whole window width
53+
if line:find("^[%*%-_][%*%-_][%*%-_]+$") then
54+
message:append(NoiceText("", {
55+
virt_text_win_col = 0,
56+
virt_text = { { (""):rep(width), "@punctuation.special.markdown" } },
57+
priority = 100,
58+
}))
59+
else
60+
message:append(line)
61+
for pattern, hl_group in pairs(Config.options.lsp.hl_patterns) do
62+
local from, to, match = line:find(pattern)
63+
if match then
64+
from, to = line:find(match, from)
65+
end
66+
if from then
67+
message:append(NoiceText(" ", {
68+
hl_group = hl_group,
69+
col = from - 1,
70+
length = to - from + 1,
71+
}))
72+
end
73+
end
74+
end
75+
end
76+
return message
77+
end
78+
79+
return M

lua/noice/source/lsp/init.lua

+2-60
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
local require = require("noice.util.lazy")
22

3-
local Message = require("noice.message")
43
local Manager = require("noice.message.manager")
5-
local NoiceText = require("noice.text")
64
local Config = require("noice.config")
5+
local Format = require("noice.source.lsp.format")
76

87
local M = {}
98

@@ -16,63 +15,6 @@ M.kinds = {
1615
hover = "hover",
1716
}
1817

19-
---@alias MarkedString string | { language: string; value: string }
20-
---@alias MarkupContent { kind: ('plaintext' | 'markdown'), value: string}
21-
---@alias MarkupContents MarkedString | MarkedString[] | MarkupContent
22-
23-
---@param contents MarkupContents
24-
---@param kind LspKind
25-
function M.format(contents, kind)
26-
if type(contents) ~= "table" or not vim.tbl_islist(contents) then
27-
contents = { contents }
28-
end
29-
30-
local parts = {}
31-
32-
for _, content in ipairs(contents) do
33-
if type(content) == "string" then
34-
table.insert(parts, content)
35-
elseif content.language then
36-
table.insert(parts, ("```%s\n%s\n```"):format(content.language, content.value))
37-
elseif content.kind == "markdown" then
38-
table.insert(parts, content.value)
39-
elseif content.kind == "plaintext" then
40-
table.insert(parts, ("```\n%s\n```"):format(content.value))
41-
end
42-
end
43-
44-
local text = table.concat(parts, "\n")
45-
text = text:gsub("\n\n\n", "\n\n")
46-
text = text:gsub("\n%s*\n```", "\n```")
47-
text = text:gsub("```\n%s*\n", "```\n")
48-
49-
local lines = vim.split(text, "\n")
50-
51-
local width = 50
52-
for _, line in pairs(lines) do
53-
width = math.max(width, vim.api.nvim_strwidth(line))
54-
end
55-
56-
local message = Message(M.event, kind)
57-
message.once = true
58-
message.opts.title = kind
59-
60-
for _, line in ipairs(lines) do
61-
message:newline()
62-
-- Make the horizontal ruler extend the whole window width
63-
if line:find("^[%*%-_][%*%-_][%*%-_]+$") then
64-
message:append(NoiceText("", {
65-
virt_text_win_col = 0,
66-
virt_text = { { (""):rep(width), "@punctuation.special.markdown" } },
67-
priority = 100,
68-
}))
69-
else
70-
message:append(line)
71-
end
72-
end
73-
return message
74-
end
75-
7618
function M.setup()
7719
if Config.options.lsp.hover.enabled then
7820
vim.lsp.handlers["textDocument/hover"] = M.hover
@@ -103,7 +45,7 @@ function M.hover(_, result)
10345
return
10446
end
10547

106-
local message = M.format(result.contents, "hover")
48+
local message = Format.format(result.contents, "hover")
10749
M.close_on_move(message)
10850
Manager.add(message)
10951
end

0 commit comments

Comments
 (0)