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
|
-- mod-version:4
local common = require "core.common"
local config = require "core.config"
local command = require "core.command"
local Doc = require "core.doc"
---@class config.plugins.trimwhitespace
---@field enabled boolean
---@field trim_empty_end_lines boolean
config.plugins.trimwhitespace = common.merge({
enabled = false,
trim_empty_end_lines = false,
config_spec = {
name = "Trim Whitespace",
{
label = "Enabled",
description = "Disable or enable the trimming of white spaces by default.",
path = "enabled",
type = "toggle",
default = false
},
{
label = "Trim Empty End Lines",
description = "Remove any empty new lines at the end of documents.",
path = "trim_empty_end_lines",
type = "toggle",
default = false
}
}
}, config.plugins.trimwhitespace)
---@class plugins.trimwhitespace
local trimwhitespace = {}
---Disable whitespace trimming for a specific document.
---@param doc core.doc
function trimwhitespace.disable(doc)
doc.disable_trim_whitespace = true
end
---Re-enable whitespace trimming if previously disabled.
---@param doc core.doc
function trimwhitespace.enable(doc)
doc.disable_trim_whitespace = nil
end
---Perform whitespace trimming in all lines of a document except the
---line where the caret is currently positioned.
---@param doc core.doc
function trimwhitespace.trim(doc)
local cline, ccol = doc:get_selection()
for i = 1, #doc.lines do
local old_text = doc:get_text(i, 1, i, math.huge)
local new_text = old_text:gsub("%s*$", "")
-- don't remove whitespace which would cause the caret to reposition
if cline == i and ccol > #new_text then
new_text = old_text:sub(1, ccol - 1)
end
if old_text ~= new_text then
doc:insert(i, 1, new_text)
doc:remove(i, #new_text + 1, i, math.huge)
end
end
end
---Removes all empty new lines at the end of the document.
---@param doc core.doc
---@param raw_remove? boolean Perform the removal not registering to undo stack
function trimwhitespace.trim_empty_end_lines(doc, raw_remove)
for _=#doc.lines, 1, -1 do
local l = #doc.lines
if l > 1 and doc.lines[l] == "\n" then
local current_line = doc:get_selection()
if current_line == l then
doc:set_selection(l-1, math.huge, l-1, math.huge)
end
if not raw_remove then
doc:remove(l-1, math.huge, l, math.huge)
else
table.remove(doc.lines, l)
end
else
break
end
end
end
command.add("core.docview", {
["trim-whitespace:trim-trailing-whitespace"] = function(dv)
trimwhitespace.trim(dv.doc)
end,
["trim-whitespace:trim-empty-end-lines"] = function(dv)
trimwhitespace.trim_empty_end_lines(dv.doc)
end,
})
local doc_save = Doc.save
Doc.save = function(self, ...)
if
config.plugins.trimwhitespace.enabled
and
not self.disable_trim_whitespace
then
trimwhitespace.trim(self)
if config.plugins.trimwhitespace.trim_empty_end_lines then
trimwhitespace.trim_empty_end_lines(self)
end
end
doc_save(self, ...)
end
return trimwhitespace
|