Module:Utility functions

local util = {}

function util.table_print (tt, indent, done) done = done or {} indent = indent or 0 if type(tt) == "table" then local sb = {} for key, value in pairs (tt) do     table.insert(sb, string.rep (" ", indent)) -- indent it      if type (value) == "table" and not done [value] then done [value] = true if type(key) ~= "number" then table.insert(sb, string.format("%s = ", util.to_string (key) )) end table.insert(sb, "{\n"); table.insert(sb, util.table_print (value, indent + 2, done)) table.insert(sb, string.rep (" ", indent)) -- indent it       table.insert(sb, "}\n"); elseif "number" == type(key) then table.insert(sb, string.format("%s\n", util.to_string(value))) else table.insert(sb, string.format( "%s = \"%s\"\n", util.to_string (key), util.to_string(value))) end end return table.concat(sb) else return tt .. "\n" end end

function util.to_string( tbl ) if "nil"       == type( tbl ) then return tostring('nil') elseif "string" == type( tbl ) then return '"' .. tostring(tbl) .. '"' elseif "table" == type( tbl ) then return util.table_print(tbl) else return tostring(tbl) end end

function util.trim(s) -- from PiL2 20.4 return (s:gsub("^%s*(.-)%s*$", "%1")) end

local function __genOrderedIndex( t ) local orderedIndex = {} for key in pairs(t) do       table.insert( orderedIndex, key ) end table.sort( orderedIndex, function(left, right)       if type(left) == "table" then            left = left[1]        end        if type(right) == "table" then            right = right[1]        end        return left < right    end) return orderedIndex end

local function orderedNext(t, state) -- Equivalent of the next function, but returns the keys in the alphabetic -- order. We use a temporary ordered key table that is stored in the -- table being iterated.

--print("orderedNext: state = "..tostring(state) ) if state == nil then -- the first time, generate the index t.__orderedIndex = __genOrderedIndex( t ) key = t.__orderedIndex[1] return key, t[key] end -- fetch the next value key = nil for i = 1,table.getn(t.__orderedIndex) do       if t.__orderedIndex[i] == state then key = t.__orderedIndex[i+1] end end

if key then return key, t[key] end

-- no more value to return, cleanup t.__orderedIndex = nil return end

function util.orderedPairs(t) -- Equivalent of the pairs function on tables. Allows to iterate -- in order return orderedNext, t, nil end

local langnames = nil local code = function( title ) local subPage = ( title or mw.title.getCurrentTitle ).subpageText:lower if not langNames then langNames = mw.loadData( Module:Language/Names ) end if langNames[subPage] then return subPage end end function util.pageSuffix local langCode = code if langCode then return '/' .. langCode end return '/en' end

function util.compact(tab) local keys = {} local n = 0 for k,v in pairs(tab) do       n = n + 1 keys[n] = k   end local out = {} n = 0 for k,v in ipairs(keys) do       n = n + 1 out[n] = tab[v] end return out end

-- this is exactly as lua-users wiki defined it. Never mind the odd gsub argument. function util.interp(s, tab) return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end)) end

local function argOr(name, default) local frame = mw.getCurrentFrame if frame == nil then return default end return frame:getArgument(name) end

-- returns (true, module) or (false, message) function util.requireDataLocalised(name) -- So many ors because tilesheets somehow calls functions that call this *without a frame* local forceUntranslated = argOr('forceUntranslated', false) local moduleName = name if not forceUntranslated then moduleName = moduleName .. util.pageSuffix end local success, data = pcall(function       return mw.loadData(moduleName)    end)

if not success then success, data = pcall(function           return mw.loadData(name)        end) end return success, data end

function util.wrapForInvoke(func) return function(...) local first = ... local args = {} if first == mw:getCurrentFrame then for k,v in pairs(first.args) do              args[k] = v             end if first.args.fromParent then for k,v in pairs(first:getParent.args) do                   args[k] = v                                end end else args = { ... }       end return func(unpack(args)) end end

return util