diff options
-rw-r--r-- | manifest.json | 2 | ||||
-rw-r--r-- | plugins/lfautoinsert.lua | 70 |
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 |