mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 06:30:03 +08:00
161 lines
4.5 KiB
Lua
161 lines
4.5 KiB
Lua
--
|
|
--------------------------------------------------------------------------------
|
|
-- File: hover.lua
|
|
--------------------------------------------------------------------------------
|
|
--
|
|
|
|
local vim = vim
|
|
local api = vim.api
|
|
local feature = 'textDocument/hover'
|
|
local default_response_handler = vim.lsp.handlers[feature]
|
|
|
|
local hover_initialise = {
|
|
buffer_changes = 0,
|
|
complete_item = nil,
|
|
complete_item_index = -1,
|
|
insert_mode = false,
|
|
window = nil
|
|
}
|
|
|
|
local hover = hover_initialise
|
|
local util = require 'util'
|
|
|
|
local complete_visible = function()
|
|
return vim.fn.pumvisible() ~= 0
|
|
end
|
|
|
|
local get_markdown_lines = function(result)
|
|
local markdown_lines = vim.lsp.util.convert_input_to_markdown_lines(result.contents)
|
|
|
|
return vim.lsp.util.trim_empty_lines(markdown_lines)
|
|
end
|
|
|
|
local get_window_alignment = function(complete_columns, screen_columns)
|
|
if complete_columns < screen_columns / 2 then
|
|
alignment = 'right'
|
|
else
|
|
alignment = 'left'
|
|
end
|
|
|
|
return alignment
|
|
end
|
|
|
|
local create_window = function(method, result)
|
|
return util.focusable_float(method, function()
|
|
local markdown_lines = get_markdown_lines(result)
|
|
if vim.tbl_isempty(markdown_lines) then return end
|
|
|
|
local complete_display_info = vim.fn.pum_getpos()
|
|
local alignment = get_window_alignment(complete_display_info['col'], api.nvim_get_option('columns'))
|
|
|
|
local hover_buffer, hover_window
|
|
|
|
hover_buffer, hover_window = util.fancy_floating_markdown(markdown_lines, {
|
|
pad_left = 1; pad_right = 1;
|
|
col = complete_display_info['col']; width = complete_display_info['width']; row = vim.fn.winline();
|
|
align = alignment;
|
|
})
|
|
|
|
hover.window = hover_window
|
|
|
|
if hover_window ~= nil and api.nvim_win_is_valid(hover_window) then
|
|
vim.lsp.util.close_preview_autocmd({"CursorMoved", "BufHidden", "InsertCharPre"}, hover_window)
|
|
end
|
|
|
|
return hover_buffer, hover_window
|
|
end)
|
|
end
|
|
|
|
local handle_response = function(_, method, result)
|
|
if complete_visible() == false then return default_response_handler(_, method, result, _) end
|
|
if not (result and result.contents) then return end
|
|
|
|
return create_window(method, result)
|
|
end
|
|
|
|
local set_response_handler = function()
|
|
for _, client in pairs(vim.lsp.buf_get_clients(0)) do
|
|
local current_response_handler = client.config.handlers[feature] or default_response_handler
|
|
if current_response_handler == handle_response then return end
|
|
|
|
client.config.handlers[feature] = handle_response
|
|
end
|
|
end
|
|
|
|
local decode_user_data = function(user_data)
|
|
if user_data == nil or (user_data ~= nil and #user_data == 0) then return end
|
|
|
|
return vim.fn.json_decode(user_data)
|
|
end
|
|
|
|
local client_with_hover = function()
|
|
for _, value in pairs(vim.lsp.buf_get_clients(0)) do
|
|
if value.resolved_capabilities.hover == false then return false end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
local buffer_changed = function()
|
|
buffer_changes = api.nvim_buf_get_changedtick(0)
|
|
if hover.buffer_changes == buffer_changes then return false end
|
|
|
|
hover.buffer_changes = buffer_changes
|
|
|
|
return hover.buffer_changes
|
|
end
|
|
|
|
local close_window = function()
|
|
if hover.window == nil or not api.nvim_win_is_valid(hover.window) then return end
|
|
|
|
api.nvim_win_close(hover.window, true)
|
|
end
|
|
|
|
local get_complete_item = function()
|
|
local complete_info = api.nvim_call_function('complete_info', {{ 'eval', 'selected', 'items', 'user_data' }})
|
|
if complete_info['selected'] == -1 or complete_info['selected'] == hover.complete_item_index then return false end
|
|
|
|
hover.complete_item_index = complete_info['selected']
|
|
|
|
return complete_info['items'][hover.complete_item_index + 1]
|
|
end
|
|
|
|
local request_hover = function()
|
|
local complete_item = get_complete_item()
|
|
if not complete_visible() or not buffer_changed() or not complete_item then return end
|
|
|
|
close_window()
|
|
|
|
if not client_with_hover() then return end
|
|
|
|
local decoded_user_data = decode_user_data(complete_item['user_data'])
|
|
if decoded_user_data == nil then return end
|
|
|
|
set_response_handler()
|
|
|
|
return vim.lsp.buf_request(api.nvim_get_current_buf(), 'textDocument/hover', util.make_position_params())
|
|
end
|
|
|
|
local insert_enter_handler = function()
|
|
hover.insert_mode = true
|
|
local timer = vim.loop.new_timer()
|
|
|
|
timer:start(100, 80, vim.schedule_wrap(function()
|
|
request_hover()
|
|
|
|
if hover.insert_mode == false and timer:is_closing() == false then
|
|
timer:stop()
|
|
timer:close()
|
|
end
|
|
end))
|
|
end
|
|
|
|
local insert_leave_handler = function()
|
|
hover.insert_mode = false
|
|
end
|
|
|
|
return {
|
|
insert_enter_handler = insert_enter_handler,
|
|
insert_leave_handler = insert_leave_handler
|
|
}
|