aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--manifest.json2
-rw-r--r--plugins/lfautoinsert.lua70
2 files changed, 50 insertions, 22 deletions
diff --git a/manifest.json b/manifest.json
index a999879..710d284 100644
--- a/manifest.json
+++ b/manifest.json
@@ -931,7 +931,7 @@
},
{
"description": "Automatically inserts indentation and closing bracket/text after newline",
- "version": "0.1",
+ "version": "0.2",
"path": "plugins/lfautoinsert.lua",
"id": "lfautoinsert",
"mod_version": "3"
diff --git a/plugins/lfautoinsert.lua b/plugins/lfautoinsert.lua
index 492f323..3e5302f 100644
--- a/plugins/lfautoinsert.lua
+++ b/plugins/lfautoinsert.lua
@@ -66,31 +66,59 @@ end
command.add("core.docview!", {
["autoinsert:newline"] = function(dv)
- command.perform("doc:newline")
-
+ local not_applied = { }
+ local fallback = true
local doc = dv.doc
- local line, col = doc:get_selection()
- local text = doc.lines[line - 1]
+ 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 ]*")
- for ptn, close in pairs(get_autoinsert_map(doc.filename)) do
- local s, _, str = text:find(ptn)
- if s then
- if close
- and col == #doc.lines[line]
- and indent_size(doc, line + 1) <= indent_size(doc, line - 1)
- then
- close = str and close:gsub("$TEXT", str) or close
- command.perform("doc:newline")
- core.active_view:on_text_input(close)
- command.perform("doc:move-to-previous-line")
- if doc.lines[line+1] == doc.lines[line+2] then
- doc:remove(line+1, 1, line+2, 1)
+ 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
- elseif col < #doc.lines[line] then
- command.perform("doc:newline")
- command.perform("doc:move-to-previous-line")
+ break
end
- command.perform("doc:indent")
+ 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