-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathhelpers.lua
More file actions
128 lines (112 loc) · 3.64 KB
/
helpers.lua
File metadata and controls
128 lines (112 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
local M = {}
local methods = require "null-ls.methods"
local c = require "null-ls.config"
local loop = require "null-ls.loop"
local code_action = methods.internal.CODE_ACTION
M.extract_struct_name = function(params)
local linenr = params.row
local line = params.content[linenr]
return line:match "^type (.*) struct"
end
M.prompt_tag_name = function()
return vim.fn.input "Enter struct tag: "
end
M.make_code_action = function(opts)
local name = opts.name
local filetypes = opts.filetypes or {}
local action_fn = opts.action_fn
local save_on_return = opts.save_on_return or true
return {
name = name,
method = code_action,
filetypes = filetypes,
generator = {
fn = function(params)
-- cli callback handler
local handler = function(_, output)
if not output then
return
end
-- patch params method
params.lsp_method = methods.lsp.FORMATTING
M.apply_edits({
{
row = 1,
col = 1,
end_row = vim.tbl_count(params.content) + 1,
end_col = 1,
text = output,
},
}, params)
if save_on_return then
vim.schedule(function()
vim.cmd(params.bufnr .. "bufdo! silent keepjumps noautocmd update")
end)
end
end
-- function to invoke cli
local invoke_cli = function(action)
local command = action.command
local args = action.args
local timeout = action.timeout or c.get().default_timeout
local stdin = action.stdin or false
assert(
vim.fn.executable(command) > 0,
string.format("command %s is not executable (make sure it's installed and on your $PATH)", command)
)
local client = vim.lsp.get_client_by_id(params.client_id)
local spawn_opts = {
cwd = client and client.config.root_dir or vim.fn.getcwd(),
input = command,
handler = handler,
timeout = timeout,
}
if stdin then
local content = table.concat(params.content, "\n")
spawn_opts["input"] = content
end
loop.spawn(command, args, spawn_opts)
end
local action_list = action_fn(params)
if not action_list then
return
end
local actions = {}
for _, action in pairs(action_list) do
table.insert(actions, {
title = action.title,
action = function()
if action.callback then
action.callback(invoke_cli)
else
invoke_cli(action)
end
end,
})
end
return actions
end,
},
}
end
M.apply_edits = function(edits, params)
local bufnr = params.bufnr
-- directly use handler, since formatting_sync uses a custom handler that won't work if called twice
-- formatting and rangeFormatting handlers should be identical
local handler = require("null-ls.client").resolve_handler(params.lsp_method)
local diffed_edits = {}
for _, edit in ipairs(edits) do
local split_text, line_ending = require("null-ls.utils").split_at_newline(bufnr, edit.text)
local diffed = require("null-ls.diff").compute_diff(params.content, split_text, line_ending)
-- check if the computed diff is an actual edit
if not (diffed.newText == "" and diffed.rangeLength == 0) then
table.insert(diffed_edits, diffed)
end
end
handler(nil, diffed_edits, {
method = params.lsp_method,
client_id = params.client_id,
bufnr = bufnr,
})
end
return M