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
129
130
131
132
133
134
135
136
137
138
|
-- mod-version:3
local core = require "core"
local command = require "core.command"
local common = require "core.common"
local config = require "core.config"
local keymap = require "core.keymap"
config.plugins.lfautoinsert = common.merge({ map = {
["{%s*\n"] = "}",
["%(%s*\n"] = ")",
["%f[[]%[%s*\n"] = "]",
["=%s*\n"] = false,
[":%s*\n"] = false,
["->%s*\n"] = false,
["^%s*<([^/!][^%s>]*)[^>]*>%s*\n"] = "</$TEXT>",
["^%s*{{#([^/][^%s}]*)[^}]*}}%s*\n"] = "{{/$TEXT}}",
["/%*%s*\n"] = "*/",
["c/c++"] = {
file_patterns = {
"%.c$", "%.h$", "%.inl$", "%.cpp$", "%.hpp$",
"%.cc$", "%.C$", "%.cxx$", "%.c++$", "%.hh$",
"%.H$", "%.hxx$", "%.h++$"
},
map = {
["^#if.*\n"] = "#endif",
["^#else.*\n"] = "#endif",
}
},
["lua"] = {
file_patterns = { "%.lua$", "%.nelua$" },
map = {
["%f[%w]do%s*\n"] = "end",
["%f[%w]then%s*\n"] = "end",
["%f[%w]else%s*\n"] = "end",
["%f[%w]repeat%s*\n"] = "until",
["%f[%w]function.*%)%s*\n"] = "end",
["%[%[%s*\n"] = "]]"
}
},
} }, config.plugins.lfautoinsert)
local function get_autoinsert_map(filename)
local map = {}
if not filename then return map end
for pattern, closing in pairs(config.plugins.lfautoinsert.map) do
if type(closing) == "table" then
if common.match_pattern(filename, closing.file_patterns) then
for p, e in pairs(closing.map) do
map[p] = e
end
end
else
map[pattern] = closing
end
end
return map
end
local function indent_size(doc, line)
local text = doc.lines[line] or ""
local s, e = text:find("^[\t ]*")
return e - s
end
command.add("core.docview!", {
["autoinsert:newline"] = function(dv)
local not_applied = { }
local fallback = true
local doc = dv.doc
local indent_type, soft_size = doc:get_indent_info()
local indent_string = indent_type == "hard" and "\t" or string.rep(" ", soft_size)
for idx, line, col, line2, col2 in doc:get_selections(true, true) do
-- We need to add `\n` to keep compatibility with the patterns
-- that expected a newline to be placed where the caret is.
local text = doc.lines[line]:sub(1, col - 1) .. '\n'
local remainder = doc.lines[line]:sub(col, -1)
local current_indent = text:match("^[\t ]*")
local pre, post
for ptn, close in pairs(get_autoinsert_map(doc.filename)) do
local s, _, str = text:find(ptn)
if s then
pre = string.format("\n%s%s", current_indent, indent_string)
if close
and col == #doc.lines[line]
and indent_size(doc, line + 1) <= indent_size(doc, line)
then
close = str and close:gsub("$TEXT", str) or close
-- Avoid inserting `close` if it's already present
if remainder:find("^"..close) then
close = ""
end
post = string.format("\n%s%s", current_indent, close)
elseif col < #doc.lines[line] then
post = string.format("\n%s", current_indent)
end
break
end
end
if pre or post then
fallback = false
doc:text_input(pre or "", idx)
local l, c, l2, c2 = doc:get_selection_idx(idx)
doc:text_input(post or "", idx)
doc:set_selections(idx, l, c, l2, c2)
else
table.insert(not_applied, {idx, current_indent})
end
end
-- Only call the fallback if no autoinsert was applied
if fallback then
command.perform("doc:newline")
else
for _,v in ipairs(not_applied) do
local idx, indent = table.unpack(v)
doc:text_input("\n"..indent, idx)
end
end
end
})
keymap.add {
["return"] = { "autoinsert:newline" }
}
return {
add = function(file_patterns, map)
table.insert(
config.plugins.lfautoinsert.map,
{ file_patterns = file_patterns, map=map }
)
end
}
|