diff options
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/core/which-key.lua | 6 | ||||
| -rw-r--r-- | lua/lsp/keybinds.lua | 67 | ||||
| -rw-r--r-- | lua/lsp/peek.lua | 140 | 
3 files changed, 147 insertions, 66 deletions
| diff --git a/lua/core/which-key.lua b/lua/core/which-key.lua index 595e076e..17995e87 100644 --- a/lua/core/which-key.lua +++ b/lua/core/which-key.lua @@ -152,6 +152,12 @@ M.config = function()            "<cmd>lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lvim.lsp.popup_border}})<cr>",            "Prev Diagnostic",          }, +        p = { +          name = "Peek", +          d = { "<cmd>lua require('lsp.peek').Peek('definition')<cr>", "Definition" }, +          t = { "<cmd>lua require('lsp.peek').Peek('typeDefinition')<cr>", "Type Definition" }, +          i = { "<cmd>lua require('lsp.peek').Peek('implementation')<cr>", "Implementation" }, +        },          q = { "<cmd>Telescope quickfix<cr>", "Quickfix" },          r = { "<cmd>lua vim.lsp.buf.rename()<cr>", "Rename" },          s = { "<cmd>Telescope lsp_document_symbols<cr>", "Document Symbols" }, diff --git a/lua/lsp/keybinds.lua b/lua/lsp/keybinds.lua index cc0d4ec9..21f29994 100644 --- a/lua/lsp/keybinds.lua +++ b/lua/lsp/keybinds.lua @@ -1,70 +1,5 @@  local M = {} --- Taken from https://www.reddit.com/r/neovim/comments/gyb077/nvimlsp_peek_defination_javascript_ttserver/ -function M.preview_location(location, context, before_context) -  -- location may be LocationLink or Location (more useful for the former) -  context = context or 15 -  before_context = before_context or 0 -  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 - before_context, -    range["end"].line + 1 + context, -    false -  ) -  local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype") -  return vim.lsp.util.open_floating_preview(contents, filetype, { border = lvim.lsp.popup_border }) -end - -function M.preview_location_callback(_, method, result) -  local context = 15 -  if result == nil or vim.tbl_isempty(result) then -    print("No location found: " .. method) -    return nil -  end -  if vim.tbl_islist(result) then -    M.floating_buf, M.floating_win = M.preview_location(result[1], context) -  else -    M.floating_buf, M.floating_win = M.preview_location(result, context) -  end -end - -function M.PeekDefinition() -  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then -    vim.api.nvim_set_current_win(M.floating_win) -  else -    local params = vim.lsp.util.make_position_params() -    return vim.lsp.buf_request(0, "textDocument/definition", params, M.preview_location_callback) -  end -end - -function M.PeekTypeDefinition() -  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then -    vim.api.nvim_set_current_win(M.floating_win) -  else -    local params = vim.lsp.util.make_position_params() -    return vim.lsp.buf_request(0, "textDocument/typeDefinition", params, M.preview_location_callback) -  end -end - -function M.PeekImplementation() -  if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then -    vim.api.nvim_set_current_win(M.floating_win) -  else -    local params = vim.lsp.util.make_position_params() -    return vim.lsp.buf_request(0, "textDocument/implementation", params, M.preview_location_callback) -  end -end -  function M.setup()    if lvim.lsp.default_keybinds then      vim.cmd "nnoremap <silent> gd <cmd>lua vim.lsp.buf.definition()<CR>" @@ -78,7 +13,7 @@ function M.setup()        { noremap = true, silent = true }      ) -    vim.cmd "nnoremap <silent> gp <cmd>lua require'lsp.keybinds'.PeekDefinition()<CR>" +    vim.cmd "nnoremap <silent> gp <cmd>lua require'lsp.peek'.Peek('definition')<CR>"      vim.cmd "nnoremap <silent> K :lua vim.lsp.buf.hover()<CR>"      vim.cmd "nnoremap <silent> <C-p> :lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lvim.lsp.popup_border}})<CR>"      vim.cmd "nnoremap <silent> <C-n> :lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lvim.lsp.popup_border}})<CR>" diff --git a/lua/lsp/peek.lua b/lua/lsp/peek.lua new file mode 100644 index 00000000..e512eee0 --- /dev/null +++ b/lua/lsp/peek.lua @@ -0,0 +1,140 @@ +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_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(_, method, result) +  if result == nil or vim.tbl_isempty(result) then +    print("peek: No location found: " .. method) +    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 + +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 floting 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('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 success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_location_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 | 
