Module:gsub lookahead

From Wiktionary, the free dictionary
Jump to navigation Jump to search


-- Like mw.ustring.gsub, but the repl function is expected to return two values, a "prefix" and "suffix".
-- They are merged in the replacement, but the search continues at the suffix, not after the entire replacement.
-- Only matters if repl is a function, though.
--
-- Example of differences:
--   mw.ustring.gsub("aaaaaac", "a(.)", function (c) return "b" .. c end)  -> bababac (3)
--   gsub_lookahead("aaaaaac", "a(.)", function (c) return "b", c end)     -> bbbbbbc (6)
--

local m_str_utils = require("Module:string utilities")

local find = m_str_utils.find
local gsub = m_str_utils.gsub
local len = m_str_utils.len
local sub = m_str_utils.sub

local function find_wrapper ( s, pattern, n )
    local r = { find( s, pattern, n ) }
    return r[ 1 ], r[ 2 ], { select( 3, unpack( r ) ) }
end

return function ( s, pattern, repl, n )
    if type(repl) ~= "function" then return gsub( s, pattern, repl, n ) end
	n = n or 1

    local repls = 0
    
    while true do
        local i0, i1, groups = find_wrapper( s, pattern, n )
        if i0 == nil then break end

        local prefix, suffix = repl( unpack( groups ) )
        prefix = prefix or sub( s, i0, i1 )
        s = sub( s, 1, i0 - 1 ) .. prefix .. (suffix or "") .. sub( s, i1 + 1 )
        n = i0 + len( prefix )
        repls = repls + 1
    end

    return s, repls
end