This repository has been archived by the owner on Aug 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 798
/
formatting.lua
114 lines (93 loc) · 3.86 KB
/
formatting.lua
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
local log = require("null-ls.logger")
local methods = require("null-ls.methods")
local u = require("null-ls.utils")
local api = vim.api
local lsp = vim.lsp
local postprocess = function(edit, params)
edit.row = edit.row or 1
edit.col = edit.col or 1
edit.end_row = edit.end_row or #params.content + 1
edit.end_col = edit.end_col or 1
edit.range = u.range.to_lsp(edit)
-- strip trailing newline
edit.newText = edit.text:gsub("[\r\n]$", "")
end
local M = {}
M.handler = function(method, original_params, handler)
if not original_params.textDocument then
return
end
if method == methods.lsp.FORMATTING or method == methods.lsp.RANGE_FORMATTING then
local bufnr = vim.uri_to_bufnr(original_params.textDocument.uri)
-- copy content and options to temp buffer
local temp_bufnr = api.nvim_create_buf(false, true)
api.nvim_buf_set_option(temp_bufnr, "eol", api.nvim_buf_get_option(bufnr, "eol"))
api.nvim_buf_set_option(temp_bufnr, "fixeol", api.nvim_buf_get_option(bufnr, "fixeol"))
api.nvim_buf_set_option(temp_bufnr, "fileformat", api.nvim_buf_get_option(bufnr, "fileformat"))
api.nvim_buf_set_lines(temp_bufnr, 0, -1, false, api.nvim_buf_get_lines(bufnr, 0, -1, false))
local called_handler = false
local handler_wrapper = function(...)
-- don't call handler if buffer was unloaded, e.g. on :wq
if not api.nvim_buf_is_loaded(bufnr) then
return
end
-- calling handler twice breaks sync formatting
if called_handler then
return
end
-- schedule before calling handler in case handler throws
vim.schedule(function()
api.nvim_buf_delete(temp_bufnr, { force = true })
end)
handler(...)
called_handler = true
end
local handle_err = function(err)
log:warn("error in formatting handler: " .. err)
-- after error, call handler w/ empty response to prevent timeout
handler_wrapper()
end
local make_params = function()
local params = u.make_params(original_params, methods.map[method])
-- override actual content w/ temp buffer content
params.content = u.buf.content(temp_bufnr)
return params
end
local after_each = function(edits)
local ok, err =
pcall(lsp.util.apply_text_edits, edits, temp_bufnr, require("null-ls.client").get_offset_encoding())
api.nvim_buf_set_option(temp_bufnr, "buflisted", false) -- apply_text_edits sets buflisted to true
if not ok then
handle_err(err)
end
end
local callback = function()
local ok, err = pcall(function()
local edits = require("null-ls.diff").compute_diff(
u.buf.content(bufnr),
u.buf.content(temp_bufnr),
u.get_line_ending(bufnr)
)
local is_actual_edit = not (edits.newText == "" and edits.rangeLength == 0)
if is_actual_edit then
log:debug("received edits from generators")
log:trace(vim.inspect(edits))
end
handler_wrapper(is_actual_edit and { edits } or nil)
end)
if not ok then
handle_err(err)
end
end
require("null-ls.generators").run_registered_sequentially({
filetype = api.nvim_buf_get_option(bufnr, "filetype"),
method = methods.map[method],
make_params = make_params,
postprocess = postprocess,
after_each = after_each,
callback = callback,
})
original_params._null_ls_handled = true
end
end
return M