summaryrefslogtreecommitdiff
path: root/lua/lvim/lsp/peek.lua
diff options
context:
space:
mode:
authorkylo252 <[email protected]>2021-10-10 21:07:41 +0200
committerGitHub <[email protected]>2021-10-10 21:07:41 +0200
commit52b74557415eb757ad4b7481b0aec8a3f98dd58d (patch)
tree9a05ec71a46c99fbdf8df0043be652b528c7c04e /lua/lvim/lsp/peek.lua
parente2c85df440564a62fd804555747b1652a6844a5e (diff)
feat: add an independent lvim namespace (#1699)
Diffstat (limited to 'lua/lvim/lsp/peek.lua')
-rw-r--r--lua/lvim/lsp/peek.lua152
1 files changed, 152 insertions, 0 deletions
diff --git a/lua/lvim/lsp/peek.lua b/lua/lvim/lsp/peek.lua
new file mode 100644
index 00000000..08345aff
--- /dev/null
+++ b/lua/lvim/lsp/peek.lua
@@ -0,0 +1,152 @@
+local M = {
+ floating_buf = nil,
+ floating_win = nil,
+ prev_result = nil,
+}
+
+local function create_floating_file(location, opts)
+ vim.validate {
+ location = { location, "t" },
+ opts = { opts, "t", true },
+ }
+
+ -- Set some defaults
+ opts = opts or {}
+ local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" }
+
+ -- location may be LocationLink or Location
+ local uri = location.targetUri or location.uri
+ if uri == nil then
+ return
+ end
+ local bufnr = vim.uri_to_bufnr(uri)
+ if not vim.api.nvim_buf_is_loaded(bufnr) then
+ vim.fn.bufload(bufnr)
+ end
+
+ local range = location.targetRange or location.range
+
+ local contents = vim.api.nvim_buf_get_lines(
+ bufnr,
+ range.start.line,
+ math.min(range["end"].line + 1 + (opts.context or 10), range.start.line + (opts.max_height or 15)), -- Don't let the window be more that 15 lines long(height)
+ false
+ )
+ local width, height = vim.lsp.util._make_floating_popup_size(contents, opts)
+ opts = vim.lsp.util.make_floating_popup_options(width, height, opts)
+ -- Don't make it minimal as it is meant to be fully featured
+ opts["style"] = nil
+
+ vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
+
+ local winnr = vim.api.nvim_open_win(bufnr, false, opts)
+ vim.api.nvim_win_set_option(winnr, "winblend", 0)
+
+ vim.api.nvim_win_set_cursor(winnr, { range.start.line + 1, range.start.character })
+ vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr)
+
+ -- Set some autocmds to close the window
+ vim.api.nvim_command(
+ "autocmd QuitPre <buffer> ++nested ++once lua pcall(vim.api.nvim_win_close, " .. winnr .. ", true)"
+ )
+ vim.lsp.util.close_preview_autocmd(close_events, winnr)
+
+ return bufnr, winnr
+end
+
+local function preview_location_callback(result)
+ if result == nil or vim.tbl_isempty(result) then
+ return nil
+ end
+
+ local opts = {
+ border = "rounded",
+ context = 10,
+ }
+
+ if vim.tbl_islist(result) then
+ M.prev_result = result[1]
+ M.floating_buf, M.floating_win = create_floating_file(result[1], opts)
+ else
+ M.prev_result = result
+ M.floating_buf, M.floating_win = create_floating_file(result, opts)
+ end
+end
+
+local function preview_location_callback_old_signature(_, _, result)
+ return preview_location_callback(result)
+end
+
+local function preview_location_callback_new_signature(_, result)
+ return preview_location_callback(result)
+end
+
+function M.open_file()
+ -- Get the file currently open in the floating window
+ local filepath = vim.fn.expand "%:."
+
+ if not filepath then
+ print "peek: Unable to open the file!"
+ return
+ end
+
+ -- Close the floating window
+ pcall(vim.api.nvim_win_close, M.floating_win, true)
+
+ -- Edit the file
+ vim.cmd("edit " .. filepath)
+
+ local winnr = vim.api.nvim_get_current_win()
+
+ -- Set the cursor at the right position
+ M.set_cursor_to_prev_pos(winnr)
+end
+
+function M.set_cursor_to_prev_pos(winnr)
+ -- Get position of the thing to peek at
+ local location = M.prev_result
+ local range = location.targetRange or location.range
+ local cursor_pos = { range.start.line + 1, range.start.character }
+
+ -- Set the winnr to the floating window if none was passed in
+ winnr = winnr or M.floating_win
+ -- Set the cursor at the correct position in the floating window
+ vim.api.nvim_win_set_cursor(winnr, cursor_pos)
+end
+
+function M.Peek(what)
+ -- If a window already exists, focus it at the right position!
+ if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then
+ local success_1, _ = pcall(vim.api.nvim_set_current_win, M.floating_win)
+ if not success_1 then
+ print "peek: You cannot edit the current file in a preview!"
+ return
+ end
+
+ -- Set the cursor at the correct position in the floating window
+ M.set_cursor_to_prev_pos()
+
+ vim.api.nvim_buf_set_keymap(
+ M.floating_buf,
+ "n",
+ "<CR>",
+ ":lua require('lvim.lsp.peek').open_file()<CR>",
+ { noremap = true, silent = true }
+ )
+ else
+ -- Make a new request and then create the new window in the callback
+ local params = vim.lsp.util.make_position_params()
+ local preview_callback = preview_location_callback_old_signature
+ if vim.fn.has "nvim-0.5.1" > 0 then
+ preview_callback = preview_location_callback_new_signature
+ end
+ local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_callback)
+ if not success then
+ print(
+ 'peek: Error calling LSP method "textDocument/' .. what .. '". The current language lsp might not support it.'
+ )
+ end
+ end
+end
+
+return M