lewis6991 / lewis6991/hover.nvim
Proposal: Allow provider to mess with the hover buffer/window
Nobody has claimed this yet.
- Dominant language
- Lua
- Stars
- 744
- Forks
- 58
- PR merge metrics
- No merged PRs in 30d
Description
Some hover providers (like rust-analyzer) allow clients to have certain actions embedded in the hover, which would need providers to be able to modify the buffer and window (set keymaps, change window options) etc. So, I think allowing providers the ability to do that is a good idea.
Proposed Change
Allow providers to define a on_render function which is called when the hover is rendered.
Example Implementation
diff --git a/lua/hover/actions.lua b/lua/hover/actions.lua
index 65d8cc5..321c269 100644
--- a/lua/hover/actions.lua
+++ b/lua/hover/actions.lua
@@ -66,11 +66,13 @@ local function focus_or_close_hover()
end
local function show_hover(provider_id, config, result, opts)
- local _, winnr = util.open_floating_preview(result.lines, result.filetype, opts)
+ local bufnr, winnr = util.open_floating_preview(result.lines, result.filetype, opts)
if config.title then
add_title(winnr, provider_id)
end
+
+ return bufnr, winnr
end
-- Must be called in async context
@@ -89,7 +91,10 @@ local function run_provider(provider)
local result = provider.execute()
if result then
async.scheduler()
- show_hover(provider.id, config, result, opts)
+ local bufnr, winnr = show_hover(provider.id, config, result, opts)
+ if provider.on_render then
+ provider.on_render(bufnr, winnr)
+ end
return true
end
Example provider implementation (rust-tools hover actions)
---@diagnostic disable: missing-parameter, param-type-mismatch
local M = {}
M._state = { commands = nil }
local function execute_rust_analyzer_command(action, ctx)
local fn = vim.lsp.commands[action.command]
if fn then
fn(action, ctx)
end
end
-- run the command under the cursor, if the thing under the cursor is not the
-- command then do nothing
local function run_command(ctx)
local winnr = vim.api.nvim_get_current_win()
local line = vim.api.nvim_win_get_cursor(winnr)[1]
if line > #M._state.commands then
return
end
local action = M._state.commands[line]
vim.api.nvim_win_close(winnr, true)
execute_rust_analyzer_command(action, ctx)
end
local function parse_commands()
local prompt = {}
for i, value in ipairs(M._state.commands) do
if value.command == "rust-analyzer.gotoLocation" then
table.insert(
prompt,
string.format("%d. Go to %s (%s)", i, value.title, value.tooltip)
)
elseif value.command == "rust-analyzer.showReferences" then
table.insert(prompt, string.format("%d. %s", i, "Go to " .. value.title))
else
table.insert(prompt, string.format("%d. %s", i, value.title))
end
end
return prompt
end
require("hover").register({
name = "Rust Hover Actions",
enabled = function()
return true
end,
execute = function(done)
local util = require("vim.lsp.util")
local params = util.make_position_params()
vim.lsp.buf_request(
0,
"textDocument/hover",
params,
function(_, result, ctx)
if not result or not result.contents then
done()
return
end
M._state.commands = nil
local lines = util.convert_input_to_markdown_lines(result.contents)
if result.actions then
M._state.commands = result.actions[1].commands
local prompt = parse_commands()
local l = {}
for _, value in ipairs(prompt) do
table.insert(l, value)
end
lines = vim.list_extend(l, lines)
end
lines = util.trim_empty_lines(lines)
M._state.ctx = ctx
if vim.tbl_isempty(lines) then
done()
return
end
done({ lines = lines, filetype = "markdown" })
end
)
end,
on_render = function(bufnr, winnr)
if M._state.commands == nil then
return
end
-- makes more sense in a dropdown-ish ui
vim.api.nvim_win_set_option(winnr, "cursorline", true)
-- run the command under the cursor
vim.keymap.set("n", "<CR>", function()
run_command(M._state.ctx)
end, { buffer = bufnr, noremap = true, silent = true })
end,
})
return M
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lua/hover/actions.lua, especially show_hover and run_provider, and compare the proposed callback flow with the example provider's on_render function. Check how the rendered buffer and window are returned and passed to providers. Done means providers can receive those handles after rendering and use them for buffer and window customization.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- lua
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100