This repository was archived by the owner on Jan 3, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 156
/
Copy pathhover_actions.lua
141 lines (112 loc) · 3.41 KB
/
hover_actions.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
local rt = require("rust-tools")
local rt_utils = require("rust-tools.utils.utils")
local util = vim.lsp.util
local M = {}
local function get_params()
return util.make_position_params(0, nil)
end
M._state = { winnr = nil, commands = nil }
local function close_hover()
rt_utils.close_win(M._state.winnr)
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]
close_hover()
M.execute_rust_analyzer_command(action, ctx)
end
function M.execute_rust_analyzer_command(action, ctx)
local fn = vim.lsp.commands[action.command]
if fn then
fn(action, ctx)
end
end
function M._close_hover() 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
function M.handler(_, result, ctx)
if not (result and result.contents) then
-- return { 'No information available' }
return
end
local markdown_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
markdown_lines = vim.list_extend(l, markdown_lines)
end
markdown_lines = util.trim_empty_lines(markdown_lines)
if vim.tbl_isempty(markdown_lines) then
-- return { 'No information available' }
return
end
local bufnr, winnr = util.open_floating_preview(
markdown_lines,
"markdown",
vim.tbl_extend("keep", rt.config.options.tools.hover_actions, {
focusable = true,
focus_id = "rust-tools-hover-actions",
close_events = { "CursorMoved", "BufHidden", "InsertCharPre" },
})
)
if rt.config.options.tools.hover_actions.auto_focus then
vim.api.nvim_set_current_win(winnr)
end
if M._state.winnr ~= nil then
return
end
-- update the window number here so that we can map escape to close even
-- when there are no actions, update the rest of the state later
M._state.winnr = winnr
vim.keymap.set(
"n",
"<Esc>",
close_hover,
{ buffer = bufnr, noremap = true, silent = true }
)
vim.api.nvim_buf_attach(bufnr, false, {
on_detach = function()
M._state.winnr = nil
end,
})
--- stop here if there are no possible actions
if result.actions == 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(ctx)
end, { buffer = bufnr, noremap = true, silent = true })
end
-- Sends the request to rust-analyzer to get hover actions and handle it
function M.hover_actions()
rt_utils.request(0, "textDocument/hover", get_params(), M.handler)
end
return M