core: ported regex.gsub to faster native version (#1233)
* added regex.gmatch iterator and other fixes * fixed issues reported by Guldoman * push strings with fixed len just in case for binary safety * added limit to regex.gsub and use pushinteger * added description to regex.gsub limits param * replaced substitutions regex description for correctness * ignore negative limits on regex.gsub
This commit is contained in:
@@ -216,7 +216,7 @@ command.add("core.docview!", {
|
||||
return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil)
|
||||
end
|
||||
local result, matches = regex.gsub(regex.compile(old, "m"), text, new)
|
||||
return result, #matches
|
||||
return result, matches
|
||||
end)
|
||||
end,
|
||||
|
||||
|
||||
@@ -80,63 +80,3 @@ regex.find = function(pattern, str, offset, options)
|
||||
end
|
||||
return table.unpack(out)
|
||||
end
|
||||
|
||||
-- Will iterate back through any UTF-8 bytes so that we don't replace bits
|
||||
-- mid character.
|
||||
local function previous_character(str, index)
|
||||
local byte
|
||||
repeat
|
||||
index = index - 1
|
||||
byte = string.byte(str, index)
|
||||
until byte < 128 or byte >= 192
|
||||
return index
|
||||
end
|
||||
|
||||
-- Moves to the end of the identified character.
|
||||
local function end_character(str, index)
|
||||
local byte = string.byte(str, index + 1)
|
||||
while byte and byte >= 128 and byte < 192 do
|
||||
index = index + 1
|
||||
byte = string.byte(str, index + 1)
|
||||
end
|
||||
return index
|
||||
end
|
||||
|
||||
-- Build off matching. For now, only support basic replacements, but capture
|
||||
-- groupings should be doable. We can even have custom group replacements and
|
||||
-- transformations and stuff in lua. Currently, this takes group replacements
|
||||
-- as \1 - \9.
|
||||
-- Should work on UTF-8 text.
|
||||
regex.gsub = function(pattern_string, str, replacement)
|
||||
local pattern = type(pattern_string) == "table" and
|
||||
pattern_string or regex.compile(pattern_string)
|
||||
local result, indices = {}
|
||||
local matches, replacements = {}, {}
|
||||
local offset = 0
|
||||
repeat
|
||||
indices = { regex.cmatch(pattern, str, offset) }
|
||||
if #indices > 0 then
|
||||
table.insert(matches, indices)
|
||||
local currentReplacement = replacement
|
||||
if #indices > 2 then
|
||||
for i = 1, (#indices/2 - 1) do
|
||||
currentReplacement = string.gsub(
|
||||
currentReplacement,
|
||||
"\\" .. i,
|
||||
str:sub(indices[i*2+1], end_character(str,indices[i*2+2]-1))
|
||||
)
|
||||
end
|
||||
end
|
||||
currentReplacement = string.gsub(currentReplacement, "\\%d", "")
|
||||
table.insert(replacements, { indices[1], #currentReplacement+indices[1] })
|
||||
if indices[1] > 1 then
|
||||
table.insert(result, str:sub(offset, previous_character(str, indices[1])) .. currentReplacement)
|
||||
else
|
||||
table.insert(result, currentReplacement)
|
||||
end
|
||||
offset = indices[2]
|
||||
end
|
||||
until #indices == 0 or indices[1] == indices[2]
|
||||
return table.concat(result) .. str:sub(offset), matches, replacements
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user