diff options
author | Francesco <francesco.bbt@gmail.com> | 2021-06-07 23:24:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-07 23:24:52 +0200 |
commit | 6b541da4c773eb7f44caab69c06f37b085bc6834 (patch) | |
tree | f5536f6c6caa0d8fbed3de15c2258ad7776277b6 | |
parent | ebcc96175fb8d2c91edf1a0c2f06179996f607f2 (diff) | |
parent | 6e8fffb27aceeee1cf36b778b1bdd33817cbda8e (diff) | |
download | lite-xl-plugins-6b541da4c773eb7f44caab69c06f37b085bc6834.tar.gz lite-xl-plugins-6b541da4c773eb7f44caab69c06f37b085bc6834.zip |
Merge pull request #25 from adamharrison/RegexReplacement
Regex Replacement Plugin
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | plugins/regexreplacepreview.lua | 126 |
2 files changed, 127 insertions, 0 deletions
@@ -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" } |