2021-04-19 02:56:32 +00:00
|
|
|
local util = require "navigator.util"
|
|
|
|
local log = util.log
|
2021-05-21 11:39:46 +00:00
|
|
|
local trace = util.trace
|
2021-04-19 02:56:32 +00:00
|
|
|
local code_action = {}
|
|
|
|
local gui = require "navigator.gui"
|
2021-04-25 02:43:18 +00:00
|
|
|
local config = require("navigator").config_values()
|
2021-04-19 02:56:32 +00:00
|
|
|
local api = vim.api
|
2021-04-23 08:19:59 +00:00
|
|
|
function code_action.code_action_handler(err, _, actions, cid, bufnr, _, customSelectionHandler)
|
|
|
|
log(cid, bufnr)
|
2021-04-19 02:56:32 +00:00
|
|
|
if actions == nil or vim.tbl_isempty(actions) then
|
|
|
|
print("No code actions available")
|
|
|
|
return
|
|
|
|
end
|
2021-04-23 08:19:59 +00:00
|
|
|
local data = {" Auto Fix <C-o> Apply <C-e> Exit"}
|
2021-04-19 02:56:32 +00:00
|
|
|
for i, action in ipairs(actions) do
|
|
|
|
local title = action.title:gsub("\r\n", "\\r\\n")
|
|
|
|
title = title:gsub("\n", "\\n")
|
|
|
|
title = string.format("[%d] %s", i, title)
|
|
|
|
table.insert(data, title)
|
|
|
|
end
|
|
|
|
local width = 0
|
|
|
|
for _, str in ipairs(data) do
|
|
|
|
if #str > width then
|
|
|
|
width = #str
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function apply_action(idx)
|
|
|
|
local action_chosen = actions[idx - 1]
|
2021-04-25 11:49:47 +00:00
|
|
|
local switch = string.format("silent b %d", bufnr)
|
2021-04-19 02:56:32 +00:00
|
|
|
if action_chosen.edit or type(action_chosen.command) == "table" then
|
|
|
|
if action_chosen.edit then
|
|
|
|
vim.lsp.util.apply_workspace_edit(action_chosen.edit)
|
|
|
|
end
|
|
|
|
if type(action_chosen.command) == "table" then
|
2021-04-23 08:19:59 +00:00
|
|
|
-- switch buff
|
|
|
|
vim.cmd(switch)
|
2021-04-19 02:56:32 +00:00
|
|
|
vim.lsp.buf.execute_command(action_chosen.command)
|
|
|
|
end
|
|
|
|
else
|
2021-04-23 08:19:59 +00:00
|
|
|
vim.cmd(switch)
|
2021-04-19 02:56:32 +00:00
|
|
|
vim.lsp.buf.execute_command(action_chosen)
|
|
|
|
end
|
2021-04-23 08:19:59 +00:00
|
|
|
|
2021-05-21 11:39:46 +00:00
|
|
|
trace(action_chosen)
|
2021-04-19 02:56:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
gui.new_list_view {
|
|
|
|
items = data,
|
|
|
|
width = width + 4,
|
|
|
|
loc = "top_center",
|
|
|
|
relative = "cursor",
|
|
|
|
rawdata = true,
|
|
|
|
data = data,
|
|
|
|
on_confirm = function(pos)
|
|
|
|
if pos < 2 then
|
|
|
|
pos = 2
|
|
|
|
end
|
|
|
|
apply_action(pos)
|
|
|
|
end,
|
|
|
|
on_move = function(pos)
|
|
|
|
if pos < 2 then
|
|
|
|
pos = 2
|
|
|
|
end
|
|
|
|
local l = data[pos]
|
2021-04-22 23:39:24 +00:00
|
|
|
return l
|
2021-04-19 02:56:32 +00:00
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
-- https://github.com/glepnir/lspsaga.nvim/blob/main/lua/lspsaga/codeaction.lua
|
|
|
|
-- lspsaga has a clever design to inject code action indicator
|
|
|
|
local sign_group = "nvcodeaction"
|
|
|
|
local get_namespace = function()
|
|
|
|
return api.nvim_create_namespace(sign_group)
|
|
|
|
end
|
|
|
|
|
|
|
|
local get_current_winid = function()
|
|
|
|
return api.nvim_get_current_win()
|
|
|
|
end
|
|
|
|
|
|
|
|
local sign_name = "NavigatorLightBulb"
|
|
|
|
|
|
|
|
if vim.tbl_isempty(vim.fn.sign_getdefined(sign_name)) then
|
2021-06-15 20:46:04 +00:00
|
|
|
vim.fn.sign_define(sign_name, {text = config.icons.code_action_icon, texthl = "LspDiagnosticsSignHint"})
|
2021-04-19 02:56:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local function _update_virtual_text(line)
|
|
|
|
local namespace = get_namespace()
|
2021-04-23 04:21:22 +00:00
|
|
|
pcall(api.nvim_buf_clear_namespace, 0, namespace, 0, -1)
|
2021-04-19 02:56:32 +00:00
|
|
|
|
|
|
|
if line then
|
2021-06-15 20:46:04 +00:00
|
|
|
local icon_with_indent = " " .. config.icons.code_action_icon
|
2021-04-19 02:56:32 +00:00
|
|
|
|
2021-04-23 04:21:22 +00:00
|
|
|
pcall(
|
|
|
|
api.nvim_buf_set_extmark,
|
2021-04-19 02:56:32 +00:00
|
|
|
0,
|
|
|
|
namespace,
|
|
|
|
line,
|
|
|
|
-1,
|
|
|
|
{
|
|
|
|
virt_text = {{icon_with_indent, "LspDiagnosticsSignHint"}},
|
|
|
|
virt_text_pos = "overlay",
|
|
|
|
hl_mode = "combine"
|
|
|
|
}
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function _update_sign(line)
|
|
|
|
local winid = get_current_winid()
|
2021-04-25 11:49:47 +00:00
|
|
|
if code_action[winid] == nil then
|
|
|
|
code_action[winid] = {}
|
|
|
|
end
|
|
|
|
if code_action[winid].lightbulb_line ~= 0 then
|
2021-04-19 02:56:32 +00:00
|
|
|
vim.fn.sign_unplace(sign_group, {id = code_action[winid].lightbulb_line, buffer = "%"})
|
|
|
|
end
|
|
|
|
|
|
|
|
if line then
|
|
|
|
--log("updatasign", line, sign_group, sign_name)
|
|
|
|
vim.fn.sign_place(
|
|
|
|
line,
|
|
|
|
sign_group,
|
|
|
|
sign_name,
|
|
|
|
"%",
|
|
|
|
{lnum = line + 1, priority = config.code_action_prompt.sign_priority}
|
|
|
|
)
|
|
|
|
code_action[winid].lightbulb_line = line
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local need_check_diagnostic = {
|
|
|
|
["go"] = true,
|
|
|
|
["python"] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
function code_action:render_action_virtual_text(line, diagnostics)
|
|
|
|
return function(_, _, actions)
|
|
|
|
if actions == nil or type(actions) ~= "table" or vim.tbl_isempty(actions) then
|
|
|
|
if config.code_action_prompt.virtual_text then
|
|
|
|
_update_virtual_text(nil)
|
|
|
|
end
|
|
|
|
if config.code_action_prompt.sign then
|
|
|
|
_update_sign(nil)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if config.code_action_prompt.sign then
|
|
|
|
if need_check_diagnostic[vim.bo.filetype] then
|
|
|
|
if next(diagnostics) == nil then
|
|
|
|
_update_sign(nil)
|
|
|
|
else
|
|
|
|
_update_sign(line)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
_update_sign(line)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if config.code_action_prompt.virtual_text then
|
|
|
|
if need_check_diagnostic[vim.bo.filetype] then
|
|
|
|
if next(diagnostics) == nil then
|
|
|
|
_update_virtual_text(nil)
|
|
|
|
else
|
|
|
|
_update_virtual_text(line)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
_update_virtual_text(line)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local special_buffers = {
|
|
|
|
["LspSagaCodecode_action"] = true,
|
|
|
|
["lspsagafinder"] = true,
|
|
|
|
["NvimTree"] = true,
|
2021-04-23 04:21:22 +00:00
|
|
|
["vista"] = true,
|
|
|
|
["guihua"] = true,
|
2021-04-19 02:56:32 +00:00
|
|
|
["lspinfo"] = true,
|
|
|
|
["markdown"] = true,
|
|
|
|
["text"] = true
|
|
|
|
}
|
|
|
|
-- local action_call_back = function (_,_)
|
|
|
|
-- return Action:action_callback()
|
|
|
|
-- end
|
|
|
|
|
2021-04-23 04:21:22 +00:00
|
|
|
local action_vritual_call_back = function(line, diagnostics)
|
|
|
|
return code_action:render_action_virtual_text(line, diagnostics)
|
2021-04-19 02:56:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local code_action_req = function(_call_back_fn, diagnostics)
|
|
|
|
local context = {diagnostics = diagnostics}
|
|
|
|
local params = vim.lsp.util.make_range_params()
|
|
|
|
params.context = context
|
|
|
|
local line = params.range.start.line
|
|
|
|
local callback = _call_back_fn(line, diagnostics)
|
|
|
|
vim.lsp.buf_request(0, "textDocument/codeAction", params, callback)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- code_action.code_action = function()
|
|
|
|
-- local diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
|
|
|
|
-- code_action_req(action_call_back, diagnostics)
|
|
|
|
-- end
|
|
|
|
|
|
|
|
code_action.code_action_prompt = function()
|
|
|
|
if special_buffers[vim.bo.filetype] then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
|
|
|
|
local winid = get_current_winid()
|
|
|
|
code_action[winid] = code_action[winid] or {}
|
|
|
|
code_action[winid].lightbulb_line = code_action[winid].lightbulb_line or 0
|
|
|
|
code_action_req(action_vritual_call_back, diagnostics)
|
|
|
|
end
|
|
|
|
|
|
|
|
return code_action
|