vim.ui.select adapt native codeaction and codelens apply actions (#117)

* doc update for lsp-installer

* use vim.ui.select and guihua ui patch

* adjust null-ls sequence
neovim_0.6
rayx 2 years ago committed by GitHub
parent 4b1670423e
commit 941b3fc80f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -490,6 +490,17 @@ cmd = { "/Users/username/.local/share/nvim/lsp_servers/python/node_modules/.bin/
``` ```
The lsp servers installed by nvim-lsp-installer is in following dir
```lua
local path = require 'nvim-lsp-installer.path'
local install_root_dir = path.concat {vim.fn.stdpath 'data', 'lsp_servers'}
```
And you can setup binary full path to this: (e.g. with gopls)
`install_root_dir .. '/go/gopls'`
## Usage ## Usage
Please refer to lua/navigator/lspclient/mapping.lua on key mappings. Should be able to work out-of-box. Please refer to lua/navigator/lspclient/mapping.lua on key mappings. Should be able to work out-of-box.

@ -5,133 +5,14 @@ local code_action = {}
local gui = require "navigator.gui" local gui = require "navigator.gui"
local config = require("navigator").config_values() local config = require("navigator").config_values()
local api = vim.api local api = vim.api
-- trace = log trace = log
local sign_name = "NavigatorLightBulb" local sign_name = "NavigatorLightBulb"
--- `codeAction/resolve` --- `codeAction/resolve`
-- from neovim buf.lua, change vim.ui.select to gui -- from neovim buf.lua, change vim.ui.select to gui
local function on_code_action_results(results, ctx)
local trace = log
local action_tuples = {}
local data = {"  Auto Fix <C-o> Apply <C-e> Exit"}
for client_id, result in pairs(results) do
for i, action in pairs(result.result or {}) do
local title = 'apply action'
trace(action)
if action.edit and action.edit.title then
local edit = action.edit
title = edit.title:gsub("\r\n", "")
title = title:gsub("\n", "")
elseif action.title then
title = action.title:gsub("\r\n", "")
title = title:gsub("\n", "")
elseif action.command and action.command.title then
title = action.command.title:gsub("\n", "")
title = title:gsub("\n", "")
end
local edit = action.edit or {}
-- trace(edit.documentChanges)
if edit.documentChanges or edit.changes then
local changes = edit.documentChanges or edit.changes
-- trace(action.edit.documentChanges)
for _, change in pairs(changes or {}) do
-- trace(change)
if change.edits then
title = title .. " [newText:]"
for _, ed in pairs(change.edits) do
-- trace(ed)
if ed.newText and ed.newText ~= "" then
local newText = ed.newText:gsub("\n\t", "")
newText = newText:gsub("\n", "")
title = title .. " (" .. newText
if ed.range then
title = title .. " line: " .. tostring(ed.range.start.line) .. ")"
else
title = title .. ")"
end
end
end
elseif change.newText and change.newText ~= "" then
local newText = change.newText:gsub("\"\n\t\"", "")
newText = newText:gsub("\n", "")
title = title .. " (newText: " .. newText
if change.range then
title = title .. " line: " .. tostring(change.range.start.line) .. ")"
else
title = title .. ")"
end
end
end
end
title = string.format("[%d] %s", i, title)
table.insert(data, title)
table.insert(action_tuples, {client_id, action, title, i})
end
end
log(action_tuples)
log(data)
if #action_tuples == 0 then
vim.notify('No code actions available', vim.log.levels.INFO)
return
end
local width = 42
for _, str in ipairs(data) do
if #str > width then
width = #str
end
end
local divider = string.rep('', width + 2)
table.insert(data, 2, divider)
local listview = gui.new_list_view {
items = data,
width = width + 4,
loc = "top_center",
relative = "cursor",
rawdata = true,
data = data,
on_confirm = function(item)
trace(item)
local action_chosen = nil
for _, value in pairs(action_tuples) do
if value[3] == item then
action_chosen = value
return require('navigator.lspwrapper').on_user_choice(action_chosen, ctx)
end
end
end,
on_move = function(pos)
trace(pos)
return pos
end
}
log("new buffer", listview.bufnr)
vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1)
-- let move down 2 pos
ListViewCtrl:on_next()
ListViewCtrl:on_next()
end
local diagnostic = vim.diagnostic or vim.lsp.diagnostic local diagnostic = vim.diagnostic or vim.lsp.diagnostic
code_action.code_action_handler = util.mk_handler(function(err, results, ctx, cfg)
if err ~= nil then
log("code action err", err, results, ctx, cfg)
return
end
on_code_action_results(results, ctx)
end)
-- https://github.com/glepnir/lspsaga.nvim/blob/main/lua/lspsaga/codeaction.lua -- https://github.com/glepnir/lspsaga.nvim/blob/main/lua/lspsaga/codeaction.lua
-- lspsaga has a clever design to inject code action indicator -- lspsaga has a clever design to inject code action indicator
@ -254,21 +135,21 @@ local code_action_req = function(_call_back_fn, diagnostics)
vim.lsp.buf_request(0, "textDocument/codeAction", params, callback) vim.lsp.buf_request(0, "textDocument/codeAction", params, callback)
end end
local function code_action_request(params)
local bufnr = vim.api.nvim_get_current_buf()
local method = 'textDocument/codeAction'
vim.lsp.buf_request_all(bufnr, method, params, function(results)
on_code_action_results(results, {bufnr = bufnr, method = method, params = params})
end)
end
code_action.code_action = function() code_action.code_action = function()
local diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
local context = {diagnostics = diagnostics} local original_select = vim.ui.select
local params = vim.lsp.util.make_range_params() vim.ui.select = require("guihua.gui").select
params.context = context
-- vim.lsp.buf_request(0, "textDocument/codeAction", params, code_action.code_action_handler) log('codeaction')
code_action_request(params)
vim.lsp.buf.code_action()
vim.defer_fn(
function ()
vim.ui.select = original_select
end, 1000
)
end end
code_action.range_code_action = function(startpos, endpos) code_action.range_code_action = function(startpos, endpos)
@ -276,7 +157,17 @@ code_action.range_code_action = function(startpos, endpos)
context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics() context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
local params = util.make_given_range_params(startpos, endpos) local params = util.make_given_range_params(startpos, endpos)
params.context = context params.context = context
code_action_request(params)
local original_select = vim.ui.select
vim.ui.select = require("guihua.gui").select
vim.lsp.buf.range_code_action(context, startpos, endpos)
vim.defer_fn(
function ()
vim.ui.select = original_select
end, 1000
)
end end
code_action.code_action_prompt = function() code_action.code_action_prompt = function()
@ -301,3 +192,138 @@ code_action.code_action_prompt = function()
end end
return code_action return code_action
--[[
code_action.code_action_handler = util.mk_handler(function(err, results, ctx, cfg)
log(ctx)
if err ~= nil then
log("code action err", err, results, ctx, cfg)
return
end
on_code_action_results(results, ctx)
end)
local function code_action_request(params)
local bufnr = vim.api.nvim_get_current_buf()
local method = 'textDocument/codeAction'
vim.lsp.buf_request_all(bufnr, method, params, function(results)
on_code_action_results(results, {bufnr = bufnr, method = method, params = params})
end)
end
local function on_code_action_results(results, ctx, client)
local trace = log
local action_tuples = {}
local data = {"  Auto Fix <C-o> Apply <C-e> Exit"}
for client_id, result in pairs(results) do
for i, action in pairs(result.result or {}) do
local title = 'apply action'
trace(action)
if action.edit and action.edit.title then
local edit = action.edit
title = edit.title:gsub("\r\n", "")
title = title:gsub("\n", "")
elseif action.title then
title = action.title:gsub("\r\n", "")
title = title:gsub("\n", "")
elseif action.command and action.command.title then
title = action.command.title:gsub("\n", "")
title = title:gsub("\n", "")
end
local edit = action.edit or {}
-- trace(edit.documentChanges)
if edit.documentChanges or edit.changes then
local changes = edit.documentChanges or edit.changes
-- trace(action.edit.documentChanges)
for _, change in pairs(changes or {}) do
-- trace(change)
if change.edits then
title = title .. " [newText:]"
for _, ed in pairs(change.edits) do
-- trace(ed)
if ed.newText and ed.newText ~= "" then
local newText = ed.newText:gsub("\n\t", "")
newText = newText:gsub("\n", "")
title = title .. " (" .. newText
if ed.range then
title = title .. " line: " .. tostring(ed.range.start.line) .. ")"
else
title = title .. ")"
end
end
end
elseif change.newText and change.newText ~= "" then
local newText = change.newText:gsub("\"\n\t\"", "")
newText = newText:gsub("\n", "")
title = title .. " (newText: " .. newText
if change.range then
title = title .. " line: " .. tostring(change.range.start.line) .. ")"
else
title = title .. ")"
end
end
end
end
title = string.format("[%d] %s", i, title)
table.insert(data, title)
table.insert(action_tuples, {client_id, action, title, i})
end
end
log(action_tuples)
log(data)
if #action_tuples == 0 then
vim.notify('No code actions available', vim.log.levels.INFO)
return
end
local width = 42
for _, str in ipairs(data) do
if #str > width then
width = #str
end
end
local divider = string.rep('', width + 2)
table.insert(data, 2, divider)
local listview = gui.new_list_view {
items = data,
width = width + 4,
loc = "top_center",
relative = "cursor",
rawdata = true,
data = data,
on_confirm = function(item)
trace(item)
local action_chosen = nil
for _, value in pairs(action_tuples) do
if value[3] == item then
action_chosen = value
return require('navigator.lspwrapper').on_user_choice(action_chosen, ctx)
end
end
end,
on_move = function(pos)
trace(pos)
return pos
end
}
log("new buffer", listview.bufnr)
vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1)
-- let move down 2 pos
ListViewCtrl:on_next()
ListViewCtrl:on_next()
end
]]

@ -3,55 +3,62 @@
-- https://github.com/neovim/neovim/blob/master/runtime/lua/vim/lsp/codelens.lua -- https://github.com/neovim/neovim/blob/master/runtime/lua/vim/lsp/codelens.lua
local codelens = require('vim.lsp.codelens') local codelens = require('vim.lsp.codelens')
local log = require"navigator.util".log local log = require('navigator.util').log
local mk_handler = require"navigator.util".mk_handler local mk_handler = require('navigator.util').mk_handler
local nvim_0_6 = require"navigator.util".nvim_0_6 local nvim_0_6 = require('navigator.util').nvim_0_6
local trace = require"navigator.util".trace local trace = require('navigator.util').trace
local lsphelper = require "navigator.lspwrapper" local lsphelper = require('navigator.lspwrapper')
local api = vim.api local api = vim.api
local gui = require "navigator.gui" local gui = require('navigator.gui')
local M = {} local M = {}
local config = require("navigator").config_values() local config = require('navigator').config_values()
local sign_name = "NavigatorCodeLensLightBulb" local sign_name = 'NavigatorCodeLensLightBulb'
if vim.tbl_isempty(vim.fn.sign_getdefined(sign_name)) then if vim.tbl_isempty(vim.fn.sign_getdefined(sign_name)) then
vim.fn.sign_define(sign_name, vim.fn.sign_define(sign_name, { text = config.icons.code_lens_action_icon, texthl = 'LspDiagnosticsSignHint' })
{text = config.icons.code_lens_action_icon, texthl = "LspDiagnosticsSignHint"})
end end
local sign_group = "nvcodelensaction" local sign_group = 'nvcodelensaction'
local get_current_winid = require('navigator.util').get_current_winid local get_current_winid = require('navigator.util').get_current_winid
local is_enabled = true
local code_lens_action = {} local code_lens_action = {}
local function _update_sign(line) local function _update_sign(line)
trace("update sign at line ", line) trace('update sign at line ', line)
local winid = get_current_winid() local winid = get_current_winid()
if code_lens_action[winid] == nil then if code_lens_action[winid] == nil then
code_lens_action[winid] = {} code_lens_action[winid] = {}
end end
if code_lens_action[winid].lightbulb_line ~= 0 then if code_lens_action[winid].lightbulb_line ~= 0 then
vim.fn.sign_unplace(sign_group, {id = code_lens_action[winid].lightbulb_line, buffer = "%"}) vim.fn.sign_unplace(sign_group, { id = code_lens_action[winid].lightbulb_line, buffer = '%' })
end end
if line then if line then
-- log("updatasign", line, sign_group, sign_name) -- log("updatasign", line, sign_group, sign_name)
vim.fn.sign_place(line, sign_group, sign_name, "%", vim.fn.sign_place(
{lnum = line + 1, priority = config.lsp.code_lens_action.sign_priority}) line,
sign_group,
sign_name,
'%',
{ lnum = line + 1, priority = config.lsp.code_lens_action.sign_priority }
)
code_lens_action[winid].lightbulb_line = line code_lens_action[winid].lightbulb_line = line
end end
end end
local codelens_hdlr = mk_handler(function(err, result, ctx, cfg) local codelens_hdlr = mk_handler(function(err, result, ctx, cfg)
log(ctx, result)
M.codelens_ctx = ctx
if err or result == nil then if err or result == nil then
if err then if err then
log("lsp code lens", vim.inspect(err), ctx, cfg) log('lsp code lens', vim.inspect(err), ctx, cfg)
end end
return return
end end
trace("codelenes result", result) trace('codelenes result', result)
for _, v in pairs(result) do for _, v in pairs(result) do
_update_sign(v.range.start.line) _update_sign(v.range.start.line)
end end
@ -65,120 +72,58 @@ function M.setup()
vim.cmd('augroup navigator.codelenses') vim.cmd('augroup navigator.codelenses')
vim.cmd(' autocmd!') vim.cmd(' autocmd!')
vim.cmd( vim.cmd("autocmd BufEnter,CursorHold,InsertLeave <buffer> lua require('navigator.codelens').refresh()")
"autocmd BufEnter,CursorHold,InsertLeave <buffer> lua require('navigator.codelens').refresh()")
vim.cmd('augroup end') vim.cmd('augroup end')
local on_codelens = vim.lsp.handlers["textDocument/codeLens"] local on_codelens = vim.lsp.handlers['textDocument/codeLens']
vim.lsp.handlers["textDocument/codeLens"] = mk_handler( vim.lsp.handlers['textDocument/codeLens'] = mk_handler(function(err, result, ctx, cfg)
function(err, result, ctx, cfg) -- trace(err, result, ctx.client_id, ctx.bufnr, cfg or {})
-- trace(err, result, ctx.client_id, ctx.bufnr, cfg or {}) cfg = cfg or {}
cfg = cfg or {} ctx = ctx or { bufnr = vim.api.nvim_get_current_buf() }
ctx = ctx or {bufnr = vim.api.nvim_get_current_buf()} if nvim_0_6() then
if nvim_0_6() then on_codelens(err, result, ctx, cfg)
on_codelens(err, result, ctx, cfg) codelens_hdlr(err, result, ctx, cfg)
codelens_hdlr(err, result, ctx, cfg) else
else on_codelens(err, ctx.method, result, ctx.client_id, ctx.bufnr)
on_codelens(err, ctx.method, result, ctx.client_id, ctx.bufnr) codelens_hdlr(err, nil, result, ctx.client_id or 0, ctx.bufnr or 0)
codelens_hdlr(err, _, result, ctx.client_id or 0, ctx.bufnr or 0) end
end end)
end)
end end
M.lsp_clients = {} M.lsp_clients = {}
function M.refresh() function M.refresh()
if #vim.lsp.buf_get_clients() < 1 then if #vim.lsp.buf_get_clients() < 1 then
log("Must have a client running to use lsp code action") log('Must have a client running to use lsp code action')
return return
end end
if not lsphelper.check_capabilities("code_lens") then if not lsphelper.check_capabilities('code_lens') then
return return
end end
vim.lsp.codelens.refresh() vim.lsp.codelens.refresh()
end end
function M.run_action() local virtual_types_ns = api.nvim_create_namespace('ng_virtual_types')
log("run code len action")
assert(#vim.lsp.buf_get_clients() > 0, "Must have a client running to use lsp code action") function M.disable()
if not lsphelper.check_capabilities("code_lens") then local bufnr = vim.api.nvim_get_current_buf()
return vim.api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1)
end is_enabled = false
end
local line = api.nvim_win_get_cursor(0)[1]
local bufnr = api.nvim_get_current_buf()
local lenses = codelens.get(bufnr)
log(lenses)
if lenses == nil or #lenses == 0 then
return
end
local width = 40
local data = {
" " .. _NgConfigValues.icons.code_lens_action_icon .. " CodeLens Action <C-o> Apply <C-e> Exit"
}
local idx = 1
for i, lens in pairs(lenses) do
if lens.range.start.line == (line - 1) then
local title = lens.command.title:gsub("\r\n", "\\r\\n")
title = title:gsub("\n", "\\n")
title = string.format("[%d] %s", idx, title)
table.insert(data, title)
lenses[i].display_title = title
width = math.max(width, #lens.command.title)
idx = idx + 1
end
end
local apply = require('navigator.lspwrapper').apply_action
local function apply_action(action)
local action_chosen = nil
for key, value in pairs(lenses) do
if value.display_title == action then
action_chosen = value
end
end
if action_chosen == nil then
log("no match for ", action, lenses)
return
end
apply(action_chosen)
end
local divider = string.rep('', width + 2)
table.insert(data, 2, divider)
if #data > 2 then
local lv = gui.new_list_view {
items = data,
width = width + 4,
loc = "top_center",
relative = "cursor",
rawdata = true,
data = data,
on_confirm = function(pos)
log(pos)
apply_action(pos)
end,
on_move = function(pos)
log(pos)
return pos
end
}
vim.api.nvim_buf_add_highlight(lv.bufnr, -1, 'Title', 0, 0, -1) function M.run_action()
else local original_select = vim.ui.select
print('no codelense in current line') vim.ui.select = require("guihua.gui").select
end log('codeaction')
end
local virtual_types_ns = api.nvim_create_namespace("ng_virtual_types"); codelens.run()
vim.defer_fn(
function ()
vim.ui.select = original_select
end, 1000
)
function M.disable()
local bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1)
is_enabled = false
end end
M.inline = function() M.inline = function()
@ -195,7 +140,7 @@ M.inline = function()
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
local parameter = lsp.util.make_position_params() local parameter = lsp.util.make_position_params()
local response = lsp.buf_request_sync(bufnr, "textDocument/codeLens", parameter) local response = lsp.buf_request_sync(bufnr, 'textDocument/codeLens', parameter)
-- Clear previous highlighting -- Clear previous highlighting
api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1) api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1)
@ -222,16 +167,93 @@ M.inline = function()
log(msg) log(msg)
api.nvim_buf_set_extmark(bufnr, virtual_types_ns, start_line, -1, { api.nvim_buf_set_extmark(bufnr, virtual_types_ns, start_line, -1, {
virt_text = {{msg, "LspCodeLensText"}}, virt_text = { { msg, 'LspCodeLensText' } },
virt_text_pos = 'overlay', virt_text_pos = 'overlay',
hl_mode = 'combine' hl_mode = 'combine',
}) })
end end
end end
-- else -- else
-- api.nvim_command("echohl WarningMsg | echo 'VirtualTypes: No response' | echohl None") -- api.nvim_command("echohl WarningMsg | echo 'VirtualTypes: No response' | echohl None")
end end
end end
return M return M
-- function M.run_action()
-- log('run code len action')
--
-- assert(#vim.lsp.buf_get_clients() > 0, 'Must have a client running to use lsp code action')
-- if not lsphelper.check_capabilities('code_lens') then
-- return
-- end
--
-- local line = api.nvim_win_get_cursor(0)[1]
-- local bufnr = api.nvim_get_current_buf()
--
-- local lenses = codelens.get(bufnr)
-- log(lenses)
-- if lenses == nil or #lenses == 0 then
-- return
-- end
-- local width = 40
--
-- local data = {
-- ' ' .. _NgConfigValues.icons.code_lens_action_icon .. ' CodeLens Action <C-o> Apply <C-e> Exit',
-- }
-- local idx = 1
-- for i, lens in pairs(lenses) do
-- if lens.range.start.line == (line - 1) then
-- local title = lens.command.title:gsub('\r\n', '\\r\\n')
-- title = title:gsub('\n', '\\n')
-- title = string.format('[%d] %s', idx, title)
-- table.insert(data, title)
-- lenses[i].display_title = title
-- width = math.max(width, #lens.command.title)
-- idx = idx + 1
-- end
-- end
-- local apply = require('navigator.lspwrapper').apply_action
-- local function apply_action(action)
-- local action_chosen = nil
-- for key, value in pairs(lenses) do
-- if value.display_title == action then
-- action_chosen = value
-- end
-- end
-- if action_chosen == nil then
-- log('no match for ', action, lenses)
-- return
-- end
-- apply(action_chosen, M.codelens_ctx)
-- end
--
-- local divider = string.rep('─', width + 2)
--
-- table.insert(data, 2, divider)
-- if #data > 2 then
-- local lv = gui.new_list_view({
-- items = data,
-- width = width + 4,
-- loc = 'top_center',
-- relative = 'cursor',
-- rawdata = true,
-- data = data,
-- on_confirm = function(pos)
-- log(pos)
-- apply_action(pos)
-- end,
-- on_move = function(pos)
-- log(pos)
-- return pos
-- end,
-- })
--
-- vim.api.nvim_buf_add_highlight(lv.bufnr, -1, 'Title', 0, 0, -1)
-- else
-- print('no codelense in current line')
-- end
-- end
--

@ -38,6 +38,10 @@ function M.new_list_view(opts)
return require('guihua.gui').new_list_view(opts) return require('guihua.gui').new_list_view(opts)
end end
function M.select(items, opts, on_choice)
return
end
return M return M
-- Doc -- Doc

@ -554,7 +554,12 @@ local function lsp_startup(ft, retry, user_lsp_opts)
if nulls_cfg then if nulls_cfg then
local cfg = {} local cfg = {}
cfg = vim.tbl_deep_extend('keep', cfg, nulls_cfg) cfg = vim.tbl_deep_extend('keep', cfg, nulls_cfg)
lspconfig['null-ls'].setup(cfg) vim.defer_fn(
function ()
lspconfig['null-ls'].setup(cfg) -- adjust null_ls startup timing
end,
1000
)
log('null-ls loading') log('null-ls loading')
_NG_Loaded['null-ls'] = true _NG_Loaded['null-ls'] = true
configs['null-ls'] = cfg configs['null-ls'] = cfg

@ -241,7 +241,7 @@ function M.setup(user_opts)
end end
vim.lsp.handlers["textDocument/references"] = require"navigator.reference".reference_handler vim.lsp.handlers["textDocument/references"] = require"navigator.reference".reference_handler
vim.lsp.handlers["textDocument/codeAction"] = require"navigator.codeAction".code_action_handler -- vim.lsp.handlers["textDocument/codeAction"] = require"navigator.codeAction".code_action_handler
vim.lsp.handlers["textDocument/definition"] = require"navigator.definition".definition_handler vim.lsp.handlers["textDocument/definition"] = require"navigator.definition".definition_handler
if cap.declaration then if cap.declaration then

@ -417,82 +417,6 @@ function M.locations_to_items(locations, max_items)
return items, width + 24, second_part -- TODO handle long line? return items, width + 24, second_part -- TODO handle long line?
end end
function M.apply_action(action, ctx, client)
if client == nil then
client = vim.lsp.get_client_by_id(ctx.client_id or 1)
end
assert(action ~= nil, 'action must not be nil')
if action.edit then
vim.lsp.util.apply_workspace_edit(action.edit)
end
if action.command then
local command = type(action.command) == 'table' and action.command or action
local fn = client.commands[command.command] or (vim.lsp.commands and vim.lsp.commands[command.command])
if fn then
local enriched_ctx = vim.deepcopy(ctx)
enriched_ctx.client_id = client.id
fn(command, enriched_ctx)
else
M.execute_command(command)
end
end
log(action)
end
local function apply_action(action, client, ctx)
log(action, client)
if action.edit then
require('vim.lsp.util').apply_workspace_edit(action.edit)
end
if action.command then
local command = type(action.command) == 'table' and action.command or action
local fn = vim.lsp.commands and vim.lsp.commands[command.command]
if fn then
local enriched_ctx = vim.deepcopy(ctx)
enriched_ctx.client_id = client.id
fn(command, ctx)
else
require('vim.lsp.buf').execute_command(command)
end
end
end
function M.on_user_choice(action_tuple, ctx)
if not action_tuple then
return
end
log(action_tuple)
-- textDocument/codeAction can return either Command[] or CodeAction[]
--
-- CodeAction
-- ...
-- edit?: WorkspaceEdit -- <- must be applied before command
-- command?: Command
--
-- Command:
-- title: string
-- command: string
-- arguments?: any[]
--
local client = vim.lsp.get_client_by_id(action_tuple[1])
local action = action_tuple[2]
if
not action.edit
and client
and type(client.resolved_capabilities.code_action) == 'table'
and client.resolved_capabilities.code_action.resolveProvider
then
client.request('codeAction/resolve', action, function(err, resolved_action)
if err then
vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
return
end
apply_action(resolved_action, client, ctx)
end)
else
apply_action(action, client, ctx)
end
end
function M.symbol_to_items(locations) function M.symbol_to_items(locations)
if not locations or vim.tbl_isempty(locations) then if not locations or vim.tbl_isempty(locations) then
@ -536,3 +460,85 @@ function M.request(method, hdlr) -- e.g textDocument/reference
end end
return M return M
-- local function apply_action(action, client)
-- -- local client = vim.lsp.get_client_by_id(ctx.client_id)
-- log(action)
--
-- assert(action ~= nil, 'action must not be nil')
-- if action.edit then
-- require('vim.lsp.util').apply_workspace_edit(action.edit)
-- end
-- if action.command then
-- local command = type(action.command) == 'table' and action.command or action
-- local fn = vim.lsp.commands and vim.lsp.commands[command.command]
-- if fn then
-- local enriched_ctx = vim.deepcopy(ctx)
-- enriched_ctx.client_id = client.id
-- fn(command, ctx)
-- else
-- require('vim.lsp.buf').execute_command(command)
-- end
-- end
-- end
--
-- M.apply_action = apply_action
--
-- function M.on_user_choice(action_tuple, ctx)
-- log(ctx)
-- if not action_tuple then
-- return
-- end
-- log(action_tuple)
-- -- textDocument/codeAction can return either Command[] or CodeAction[]
-- --
-- -- CodeAction
-- -- ...
-- -- edit?: WorkspaceEdit -- <- must be applied before command
-- -- command?: Command
-- --
-- -- Command:
-- -- title: string
-- -- command: string
-- -- arguments?: any[]
-- --
-- local function apply_code_action(action, client)
-- if action.edit then
-- util.apply_workspace_edit(action.edit)
-- end
-- if action.command then
-- local command = type(action.command) == 'table' and action.command or action
-- local fn = client.commands[command.command] or vim.lsp.commands[command.command]
-- if fn then
-- local enriched_ctx = vim.deepcopy(ctx)
-- enriched_ctx.client_id = client.id
-- fn(command, enriched_ctx)
-- else
-- M.execute_command(command)
-- end
-- end
-- end
--
-- if action_tuple[1] ~= nil then
-- ctx.client_id = action_tuple[1]
-- end
-- local client = vim.lsp.get_client_by_id(ctx.client_id)
-- local action = action_tuple[2]
-- if
-- not action.edit
-- and client
-- and type(client.resolved_capabilities.code_action) == 'table'
-- and client.resolved_capabilities.code_action.resolveProvider
-- then
-- client.request('codeAction/resolve', action, function(err, resolved_action, c)
-- log(resolved_action, c)
-- if err then
-- vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
-- return
-- end
-- apply_code_action(resolved_action, client)
-- end)
-- else
-- apply_action(action, client)
-- end
-- end

@ -1,44 +1,16 @@
-- https://github.com/lukas-reineke/dotfiles/blob/master/vim/lua/lsp/rename.lua -- https://github.com/lukas-reineke/dotfiles/blob/master/vim/lua/lsp/rename.lua
local M = {} local M = {}
local util = require "navigator.util" local util = require('navigator.util')
local rename_prompt = "Rename -> " -- local rename_prompt = 'Rename -> '
M.rename = function() M.rename = function()
local current_name = vim.fn.expand("<cword>") local input = vim.ui.input
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_option(bufnr, "buftype", "prompt")
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
vim.api.nvim_buf_add_highlight(bufnr, -1, "NGPreviewTitle", 0, 0, #rename_prompt)
vim.fn.prompt_setprompt(bufnr, rename_prompt)
local width = #current_name + #rename_prompt + 10
local winnr = vim.api.nvim_open_win(bufnr, true, {
relative = "cursor",
width = width,
height = 1,
row = -3,
col = 1,
style = "minimal",
border = "single"
})
vim.api.nvim_win_set_option(winnr, "winhl", "Normal:Floating")
vim.api.nvim_buf_set_option(bufnr, "filetype", "guihua")
util.map("n", "<ESC>", "<cmd>bd!<CR>", {silent = true, buffer = true})
util.map({"n", "i"}, "<CR>", "<cmd>lua require('navigator.rename').callback()<CR>",
{silent = true, buffer = true})
util.map({"n", "i"}, "<BS>", [[<ESC>"_cl]], {silent = true, buffer = true})
vim.cmd(string.format("normal i%s", current_name))
end
M.callback = function() vim.ui.input = require('guihua.floating').input
local new_name = vim.trim(vim.fn.getline("."):sub(#rename_prompt + 1, -1)) vim.lsp.buf.rename()
vim.cmd [[stopinsert]] vim.defer_fn(function()
vim.cmd [[bd!]] vim.ui.input = input
if #new_name == 0 or new_name == vim.fn.expand("<cword>") then end, 1000)
return
end
local params = vim.lsp.util.make_position_params()
params.newName = new_name
vim.lsp.buf_request(0, "textDocument/rename", params)
end end
-- M.callback()
return M return M

Loading…
Cancel
Save