K wobsahej skočić

Modul:string/replace last

z Wikisłownika

local str = {}

local string_pattern_escape_module = "Module:string/patternEscape"
local string_replacement_escape_module = "Module:string/replacementEscape"

local ipairs = ipairs
local require = require
local sort = table.sort
local tonumber = tonumber
local ufind = mw.ustring.find
local ugsub = mw.ustring.gsub
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = mw.ustring.sub

local function pattern_escape(...)
	pattern_escape = require(string_pattern_escape_module)
	return pattern_escape(...)
end

local function replacement_escape(...)
	replacement_escape = require(string_replacement_escape_module)
	return replacement_escape(...)
end

local function _getParameters(frame_args, arg_list)
	local new_args, index, value = {}, 1
	
	for _, arg in ipairs(arg_list) do
		value = frame_args[arg]
		if value == nil then
			value = frame_args[index]
			index = index + 1
		end
		new_args[arg] = value
	end
	
	return new_args
end

function str.replace_last(source_str, pattern, replace, count, plain)
	if source_str == "" or pattern == "" or count <= 0 then
		return source_str
	end
	
	if plain then
		pattern, replace = pattern_escape(pattern), replacement_escape(replace)
	end
	
	local last_n_matches = {}
	local cycle = 1
	local matches_found = 0
	local i = nil
	
	while true do
		local mstart, mend = ufind(source_str, pattern, i)
		if mstart == nil then break end
		last_n_matches[cycle] = {mstart, mend}
		cycle = cycle + 1
		if cycle > count then cycle = 1 end
		if matches_found < count then matches_found = matches_found + 1 end
		i = mend + 1
	end
	
	-- reverse sort
	sort(last_n_matches, function(a, b) return a[1] > b[1] end)
	
	local result = source_str
	
	for _, pair in ipairs(last_n_matches) do
		local mstart, mend = unpack(pair)
		result = usub(result, 1, mstart - 1) .. ugsub(usub(result, mstart, mend), pattern, replace) .. usub(result, mend + 1)
	end
	
	return result
end

function str.invoke(frame)
	local new_args = _getParameters(frame.args, {"source", "pattern", "replace", "count", "plain"})
	local source_str = new_args["source"] or ""
	local pattern = new_args["pattern"] or ""
	local replace = new_args["replace"] or ""
	local count = tonumber(new_args["count"])
	local plain = new_args["plain"] or true
	
	-- plain = str._getBoolean(plain)
	plain = plain == "true"
	
	return str.replace_last(source_str, pattern, replace, count, plain)
end

return str