aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco <francesco.bbt@gmail.com>2021-06-07 23:24:52 +0200
committerGitHub <noreply@github.com>2021-06-07 23:24:52 +0200
commit6b541da4c773eb7f44caab69c06f37b085bc6834 (patch)
treef5536f6c6caa0d8fbed3de15c2258ad7776277b6
parentebcc96175fb8d2c91edf1a0c2f06179996f607f2 (diff)
parent6e8fffb27aceeee1cf36b778b1bdd33817cbda8e (diff)
downloadlite-xl-plugins-6b541da4c773eb7f44caab69c06f37b085bc6834.tar.gz
lite-xl-plugins-6b541da4c773eb7f44caab69c06f37b085bc6834.zip
Merge pull request #25 from adamharrison/RegexReplacement
Regex Replacement Plugin
-rw-r--r--README.md1
-rw-r--r--plugins/regexreplacepreview.lua126
2 files changed, 127 insertions, 0 deletions
diff --git a/README.md b/README.md
index 4af61c0..48f9796 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,7 @@ Plugin | Description
~~[`projectmanager`](plugins/projectmanager.lua?raw=1)~~ | Integrated in lite-xl with improvements ~~Save projects and load/reload them quickly~~
[`rainbowparen`](plugins/rainbowparen.lua?raw=1) | Show nesting of parentheses with rainbow colours
[`restoretabs`](plugins/restoretabs.lua?raw=1) | Keep a list of recently closed tabs, and restore the tab in order on cntrl+shift+t.
+[`regexreplaceplugin`](plugins/regexreplaceplugin.lua?raw=1) | Allows for you to write a regex and its replacement in one go, and live preview the results.
*[`scale`](plugins/scale.lua?raw=1)* | Provides support for dynamically adjusting the scale of the code font / UI (`ctrl+-`, `ctrl+=`)
[`scalestatus`](plugins/scalestatus.lua?raw=1) | Displays current scale (zoom) in status view (depends on scale plugin)
[`selectionhighlight`](plugins/selectionhighlight.lua?raw=1) | Highlights regions of code that match the current selection *([screenshot](https://user-images.githubusercontent.com/3920290/80710883-5f597c80-8ae7-11ea-97f0-76dfacc08439.png))*
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" }