Skip to content

Commit c2f37ed

Browse files
committed
feat: added config.lsp.hover. Undocumented for now and disabled by default.
1 parent 42d771a commit c2f37ed

File tree

6 files changed

+159
-22
lines changed

6 files changed

+159
-22
lines changed

lua/noice/config/init.lua

+27-13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ M.defaults = {
1818
-- view: (default is cmdline view)
1919
-- opts: any options passed to the view
2020
-- icon_hl_group: optional hl_group for the icon
21+
-- title: set to anything or empty string to hide
2122
cmdline = { pattern = "^:", icon = "", lang = "vim" },
2223
search_down = { kind = "search", pattern = "^/", icon = " ", lang = "regex" },
2324
search_up = { kind = "search", pattern = "^%?", icon = " ", lang = "regex" },
@@ -62,16 +63,22 @@ M.defaults = {
6263
enabled = true,
6364
view = "notify",
6465
},
65-
lsp_progress = {
66-
enabled = true,
67-
-- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
68-
-- See the section on formatting for more details on how to customize.
69-
--- @type NoiceFormat|string
70-
format = "lsp_progress",
71-
--- @type NoiceFormat|string
72-
format_done = "lsp_progress_done",
73-
throttle = 1000 / 30, -- frequency to update lsp progress message
74-
view = "mini",
66+
lsp = {
67+
progress = {
68+
enabled = true,
69+
-- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
70+
-- See the section on formatting for more details on how to customize.
71+
--- @type NoiceFormat|string
72+
format = "lsp_progress",
73+
--- @type NoiceFormat|string
74+
format_done = "lsp_progress_done",
75+
throttle = 1000 / 30, -- frequency to update lsp progress message
76+
view = "mini",
77+
},
78+
hover = {
79+
enabled = false,
80+
view = "notify",
81+
},
7582
},
7683
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.
7784
---@type NoiceConfigViews
@@ -97,6 +104,8 @@ end
97104
function M.setup(options)
98105
options = options or {}
99106

107+
M.fix_legacy(options)
108+
100109
if options.popupmenu and options.popupmenu.kind_icons == true then
101110
options.popupmenu.kind_icons = nil
102111
end
@@ -125,10 +134,15 @@ function M.setup(options)
125134
end,
126135
})
127136

128-
if M.options.lsp_progress.enabled then
129-
require("noice.source.lsp.progress").setup()
130-
end
137+
require("noice.source.lsp").setup()
131138
M._running = true
132139
end
133140

141+
function M.fix_legacy(opts)
142+
if opts.lsp_progress then
143+
opts.lsp = opts.lsp or {}
144+
opts.lsp.progress = opts.lsp_progress
145+
end
146+
end
147+
134148
return M

lua/noice/config/routes.lua

+7-2
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,13 @@ function M.defaults()
106106
opts = { lang = "lua", replace = true, title = "Noice" },
107107
},
108108
{
109-
view = Config.options.lsp_progress.view,
110-
filter = { event = "lsp" },
109+
view = Config.options.lsp.hover.view,
110+
filter = { event = "lsp", kind = "hover" },
111+
opts = { lang = "markdown", replace = true },
112+
},
113+
{
114+
view = Config.options.lsp.progress.view,
115+
filter = { event = "lsp", kind = "progress" },
111116
},
112117
})
113118
end

lua/noice/source/lsp/init.lua

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
local require = require("noice.util.lazy")
2+
3+
local Message = require("noice.message")
4+
local Manager = require("noice.message.manager")
5+
local NoiceText = require("noice.text")
6+
local Config = require("noice.config")
7+
8+
local M = {}
9+
10+
---@alias LspEvent "lsp"
11+
M.event = "lsp"
12+
13+
---@enum LspKind
14+
M.kinds = {
15+
progress = "progress",
16+
hover = "hover",
17+
}
18+
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+
76+
function M.setup()
77+
if Config.options.lsp.hover.enabled then
78+
vim.lsp.handlers["textDocument/hover"] = M.hover
79+
end
80+
if Config.options.lsp.progress.enabled then
81+
require("noice.source.lsp.progress").setup()
82+
end
83+
end
84+
85+
---@param message NoiceMessage
86+
function M.close_on_move(message)
87+
local open = true
88+
message.opts.timeout = 100
89+
message.opts.keep = function()
90+
return open
91+
end
92+
vim.api.nvim_create_autocmd("CursorMoved", {
93+
callback = function()
94+
open = false
95+
end,
96+
once = true,
97+
})
98+
end
99+
100+
function M.hover(_, result)
101+
if not (result and result.contents) then
102+
vim.notify("No information available")
103+
return
104+
end
105+
106+
local message = M.format(result.contents, "hover")
107+
M.close_on_move(message)
108+
Manager.add(message)
109+
end
110+
111+
return M

lua/noice/source/lsp/progress.lua

+3-3
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ function M._update()
6767
if not vim.tbl_isempty(M._progress) then
6868
for _, message in pairs(M._progress) do
6969
if message.opts.progress.kind == "end" then
70-
Manager.add(Format.format(message, Config.options.lsp_progress.format_done))
70+
Manager.add(Format.format(message, Config.options.lsp.progress.format_done))
7171
else
72-
Manager.add(Format.format(message, Config.options.lsp_progress.format))
72+
Manager.add(Format.format(message, Config.options.lsp.progress.format))
7373
end
7474
end
7575
return
@@ -81,7 +81,7 @@ function M.update()
8181
end
8282

8383
function M.setup()
84-
M.update = Util.interval(Config.options.lsp_progress.throttle, M._update, {
84+
M.update = Util.interval(Config.options.lsp.progress.throttle, M._update, {
8585
enabled = function()
8686
return not vim.tbl_isempty(M._progress)
8787
end,

lua/noice/ui/init.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ local Util = require("noice.util")
55
local Router = require("noice.message.router")
66
local Manager = require("noice.message.manager")
77

8-
---@alias NoiceEvent MsgEvent|CmdlineEvent|NotifyEvent
9-
---@alias NoiceKind MsgKind|NotifyLevel
8+
---@alias NoiceEvent MsgEvent|CmdlineEvent|NotifyEvent|LspEvent
9+
---@alias NoiceKind MsgKind|NotifyLevel|LspKind
1010

1111
local M = {}
1212
M._attached = false

lua/noice/view/backend/mini.lua

+9-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ function MiniView:update_options()
3333
self._opts = vim.tbl_deep_extend("force", defaults, self._opts)
3434
end
3535

36-
function MiniView:can_hide()
36+
---@param message NoiceMessage
37+
function MiniView:can_hide(message)
38+
if message.opts.keep and message.opts.keep() then
39+
return false
40+
end
3741
return not Util.is_blocking()
3842
end
3943

@@ -42,7 +46,10 @@ function MiniView:autohide(id)
4246
self.timers[id] = vim.loop.new_timer()
4347
end
4448
self.timers[id]:start(self._opts.timeout, 0, function()
45-
if not self:can_hide() then
49+
if not self.active[id] then
50+
return
51+
end
52+
if not self:can_hide(self.active[id]) then
4653
return self:autohide(id)
4754
end
4855
self.active[id] = nil

0 commit comments

Comments
 (0)