local index_module = "Module:index"
local error = error
local format = string.format
local sub = string.sub
local type = type
local function index_range(...)
index_range = require(index_module).range
return index_range(...)
end
--[==[Replaces the content of the string {str} between indices {i} and {j} with a new substring, which is specified by {repl}.
{repl} works in the same fashion as {string.gsub}:
* If it is a string or number, its value is used for the replacement.
* If it is a table, the existing substring between {i} and {j} is used as a lookup key for the replacement value (if any).
* If it is a function, the existing substring between {i} and {j} is given to it as a single argument, and the replacement value is the return value (if any).
If {j} is less than {i}, the substring to be replaced will be the empty string, which amounts to inserting the replacement value at the index {i}; in general, it is clearer (and more performant) to do this with ] (e.g. {replace("foo", 2, 1, "bar")} and {insert("foo", 2, "bar")} both return {"fbaroo"}, as they are exactly equivalent).]==]
return function(str, i, j, repl)
local str_len = #str
i, j = index_range(str_len, i, j, nil, true)
local repl_type = type(repl)
if not (repl_type == "string" or repl_type == "number") then
if repl_type == "table" then
repl = repl
elseif repl_type == "function" then
repl = repl(sub(str, i, j))
else
error(format("bad argument #4 to 'string/replace' (string/function/table expected, got %s)", repl_type))
end
-- If `repl` returned nothing, there's no substitution.
if repl == nil then
return str
end
repl_type = type(repl)
if not (repl_type == "string" or repl_type == "number") then
error(format("invalid replacement value (a %s)", repl_type))
end
end
return (i == 1 and "" or sub(str, 1, i - 1)) .. repl .. (j >= str_len and "" or sub(str, j + 1))
end