aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Harrison <adamdharrison@gmail.com>2021-06-05 00:32:02 -0400
committerAdam Harrison <adamdharrison@gmail.com>2021-06-05 00:32:02 -0400
commitf7410a21a711bcb1e5856189e791c8ddb5ef161f (patch)
treeea781351c437e6785f17a778ad6ca4ac7e0bb04f
parente9c69e44bfa260eb492ca519768fddb1b0c5417b (diff)
downloadlite-xl-plugins-f7410a21a711bcb1e5856189e791c8ddb5ef161f.tar.gz
lite-xl-plugins-f7410a21a711bcb1e5856189e791c8ddb5ef161f.zip
Added in regex replacement plugin. Allows for each preview of stuff.
-rw-r--r--plugins/regexreplacepreview.lua126
1 files changed, 126 insertions, 0 deletions
diff --git a/plugins/regexreplacepreview.lua b/plugins/regexreplacepreview.lua
new file mode 100644
index 0000000..926530b
--- /dev/null
+++ b/plugins/regexreplacepreview.lua
@@ -0,0 +1,126 @@
+-- mod-version:1 -- lite-xl 1.16
+local core = require "core"
+local keymap = require "core.keymap"
+local command = require "core.command"
+
+-- Takes the following pattern: /pattern/replace/
+-- Capture groupings can be replaced using \1 through \9
+local function regex_replace_file(view, pattern, old_lines, raw, start_line, end_line)
+ local doc = view.doc
+ local start_pattern, end_pattern, end_replacement, start_replacement = 2, 2;
+ repeat
+ end_pattern = string.find(pattern, "/", end_pattern)
+ until end_pattern == nil or pattern[end_pattern-1] ~= "\\"
+ if end_pattern == nil then
+ end_pattern = #pattern + 1
+ else
+ end_pattern = end_pattern - 1
+ start_replacement = end_pattern+2;
+ end_replacement = end_pattern+2;
+ repeat
+ end_replacement = string.find(pattern, "/", end_replacement)
+ until end_replacement == nil or pattern[end_replacement-1] ~= "\\"
+ end
+ end_replacement = end_replacement and (end_replacement - 1)
+
+ local re = start_pattern ~= end_pattern and regex.compile(pattern:sub(start_pattern, end_pattern))
+
+ local replacement = end_replacement and pattern:sub(start_replacement, end_replacement)
+ local replace_line = raw and function(line, new_text)
+ if line == #doc.lines then
+ doc:raw_remove(line, 1, line, #doc.lines[line], { idx = 1 }, 0)
+ else
+ doc:raw_remove(line, 1, line+1, 1, { idx = 1 }, 0)
+ end
+ doc:raw_insert(line, 1, new_text, { idx = 1 }, 0)
+ end or function(line, new_text)
+ if line == #doc.lines then
+ doc:remove(line, 1, line, #doc.lines[line])
+ else
+ doc:remove(line, 1, line+1, 1)
+ end
+ doc:insert(line, 1, new_text)
+ end
+
+ local line_scroll = nil
+ if re then
+ for i = (start_line or 1), (end_line or #doc.lines) do
+ local new_text, matches, rmatches
+ local old_text = old_lines[i] or doc.lines[i]
+ local old_length = #old_text
+ if replacement then
+ new_text, matches, rmatches = regex.gsub(re, old_text, replacement)
+ end
+ if matches and #matches > 0 then
+ old_lines[i] = old_text
+ replace_line(i, new_text)
+ if line_scroll == nil then
+ line_scroll = i
+ doc:set_selection(i, rmatches[1][1], i, rmatches[1][2])
+ end
+ elseif old_lines[i] then
+ replace_line(i, old_lines[i])
+ old_lines[i] = nil
+ end
+ if not replacement then
+ local s,e = regex.match(re, old_text)
+ if s then
+ line_scroll = i
+ doc:set_selection(i, s, i, e)
+ break
+ end
+ end
+ end
+ if line_scroll then
+ view:scroll_to_line(line_scroll, true)
+ end
+ end
+ if replacement == nil then
+ for k,v in pairs(old_lines) do
+ replace_line(k, v)
+ end
+ old_lines = {}
+ end
+ return old_lines, line_scroll ~= nil
+end
+
+command.add("core.docview", {
+ ["regex-replace-preview:find-replace-regex"] = function()
+ core.command_view:set_text("/")
+ local old_lines = {}
+ local view = core.active_view
+ local doc = view.doc
+ local original_selection = { doc:get_selection(true) }
+ local selection = doc:has_selection() and { doc:get_selection(true) } or {}
+ core.command_view:enter(
+ "Regex Replace (enter pattern as /old/new/)",
+ function(pattern)
+ regex_replace_file(view, pattern, {}, false, selection[1], selection[3])
+ end,
+ function(pattern)
+ local incremental, has_replacement = regex_replace_file(view, pattern, old_lines, true, selection[1], selection[3])
+ if incremental then
+ old_lines = incremental
+ end
+ if not has_replacement then
+ doc:set_selection(unpack(original_selection))
+ end
+ end,
+ function(pattern)
+ for k,v in pairs(old_lines) do
+ if v then
+ if k == #doc.lines then
+ doc:raw_remove(k, 1, k, #doc.lines[k], { idx = 1 }, 0)
+ else
+ doc:raw_remove(k, 1, k+1, 1, { idx = 1 }, 0)
+ end
+ doc:raw_insert(k, 1, v, { idx = 1 }, 0)
+ end
+ end
+ doc:set_selection(unpack(original_selection))
+ end
+ )
+ end
+})
+
+keymap.add { ["ctrl+shift+r"] = "regex-replace-preview:find-replace-regex" }