Changes

no edit summary
Line 1: Line 1:     
local Utils = {}
 
local Utils = {}
 +
 +
-- * Function functions :V
 +
 +
function Utils.id(...)
 +
return ...
 +
end
 +
 +
function Utils.second(_, x)
 +
    return x
 +
end
 +
 +
-- * Number functions.
 +
 +
function Utils.round(x)
 +
return math.floor(x + 0.5)
 +
end
 +
 +
function Utils.divMod(x, y)
 +
return math.floor(x / y), x % y
 +
end
    
-- * Collection functions.
 
-- * Collection functions.
 +
 +
function Utils.isize(xs)
 +
local r = 0
 +
for _ in ipairs(xs) do
 +
r = r + 1
 +
end
 +
return r
 +
end
 +
 +
function Utils.size(xs)
 +
local r = 0
 +
for _ in pairs(xs) do
 +
r = r + 1
 +
end
 +
return r
 +
end
 +
 +
function Utils.removekey(xs, k)
 +
local e = xs[k]
 +
xs[k] = nil
 +
return e
 +
end
 +
 +
function Utils.isArray(xs)
 +
for k, _ in pairs(xs) do
 +
return k == 1
 +
end
 +
return true
 +
end
 +
 +
function Utils.findBy(xs, p)
 +
    if Utils.isArray(xs) then
 +
    for k, v in ipairs(xs) do
 +
            if p(v, k) then
 +
    return v, k
 +
    end
 +
        end
 +
    else
 +
    for k, v in pairs(xs) do
 +
    if p(v, k) then
 +
    return v, k
 +
    end
 +
        end
 +
    end
 +
return nil
 +
end
    
function Utils.find(tbl, v_, k_)
 
function Utils.find(tbl, v_, k_)
Line 8: Line 74:  
if k_ and v and v[k_] == v_ or not k_ and v == v_ then
 
if k_ and v and v[k_] == v_ or not k_ and v == v_ then
 
return v
 
return v
 +
end
 +
end
 +
return false
 +
end
 +
 +
function Utils.includes(tbl, v_, k_)
 +
for _, v in pairs(tbl) do
 +
if k_ and v and v[k_] == v_ or not k_ and v == v_ then
 +
return true
 
end
 
end
 
end
 
end
Line 35: Line 110:  
         return k, v
 
         return k, v
 
     end
 
     end
 +
end
 +
 +
function Utils.keys(tbl)
 +
local result = {}
 +
for k, _ in pairs(tbl) do
 +
table.insert(result, k)
 +
end
 +
return result
 +
end
 +
 +
function Utils.values(tbl)
 +
local result = {}
 +
for _, v in pairs(tbl) do
 +
table.insert(result, v)
 +
end
 +
return result
 
end
 
end
   Line 53: Line 144:  
end
 
end
 
return false
 
return false
 +
end
 +
 +
function Utils.imax(arr, def)
 +
    local maxValue
 +
    local maxIndex
 +
for i, v in ipairs(arr) do
 +
if not maxValue or v > maxValue then
 +
maxValue = v
 +
maxIndex = i
 +
end
 +
end
 +
return maxValue or def
 +
end
 +
 +
function Utils.imin(arr, def)
 +
    local minValue
 +
    local minIndex
 +
for i, v in ipairs(arr) do
 +
if not minValue or v < minValue then
 +
minValue = v
 +
minIndex = i
 +
end
 +
end
 +
return minValue or def
 
end
 
end
   Line 77: Line 192:  
         return k, v
 
         return k, v
 
     end
 
     end
 +
end
 +
 +
function Utils.ilast(arr)
 +
return arr[#arr]
 
end
 
end
   Line 90: Line 209:  
     end
 
     end
 
     return arr1
 
     return arr1
 +
end
 +
 +
Utils.join = table.concat
 +
 +
function Utils.ijoin(arr, sep)
 +
    sep = sep or ""
 +
    return table.concat(arr, sep)
 +
end
 +
 +
function Utils.joinLines(arr)
 +
  return table.concat(arr, "\n")
 
end
 
end
   Line 96: Line 226:  
end
 
end
   −
-- * String functions.
+
function Utils.sort(tbl, f)
 +
    table.sort(tbl, f)
 +
    return tbl
 +
end
 +
 
 +
function Utils.isort(arr, f)
 +
    local result = Utils.icopy(arr)
 +
    table.sort(result, f)
 +
    return result
 +
end
 +
 
 +
function Utils.isum(arr, result)
 +
    result = result or 0
 +
    for _, v in ipairs(arr) do
 +
        result = result + (v or 0)
 +
    end
 +
    return result
 +
end
 +
 
 +
-- * Number functions.
   −
function Utils.category(name)
+
function Utils.round(x)
     return "[[" .. "Category:" .. name .. "]]"
+
     return x % 2 ~= 0.5 and math.floor(x + 0.5) or x - 0.5
 
end
 
end
 +
 +
-- * String functions.
    
function Utils.pad(s, n, c)
 
function Utils.pad(s, n, c)
Line 122: Line 273:  
     s = s:gsub("^(%l)", function(a) return string.upper(a) end)
 
     s = s:gsub("^(%l)", function(a) return string.upper(a) end)
 
     return s
 
     return s
 +
end
 +
 +
-- * Wikitext/HTML functions.
 +
 +
function Utils.category(name)
 +
    return "[[" .. "Category:" .. name .. "]]"
 +
end
 +
 +
function Utils.red(s)
 +
    return Utils.format{[[<span style="color:red">${s}</span>]], s = s}
 
end
 
end
   Line 183: Line 344:  
     local success, data = pcall(function () return require(string.format("Module:%s", name)) end)
 
     local success, data = pcall(function () return require(string.format("Module:%s", name)) end)
 
     -- module without return (or empty, nil, false, true return) gives success = true, data = true
 
     -- module without return (or empty, nil, false, true return) gives success = true, data = true
 +
    if data == true then
 +
        return false, nil
 +
    else
 +
        return success, data
 +
    end
 +
end
 +
 +
function Utils.loadData(name)
 +
    local success, data = pcall(function () return mw.loadData(string.format("Module:%s", name)) end)
 +
    -- TODO: ???
 
     if data == true then
 
     if data == true then
 
         return false, nil
 
         return false, nil
Line 201: Line 372:  
             )
 
             )
 
             if type(v) == "table" then
 
             if type(v) == "table" then
                 debugPrint(v, i + 1)
+
                 Utils.debugPrint(v, i + 1)
 
             end
 
             end
 
         end
 
         end
Line 207: Line 378:  
         mw.log(tostring(x) .. " : " .. type(x))
 
         mw.log(tostring(x) .. " : " .. type(x))
 
     end
 
     end
 +
end
 +
 +
local function showValue(v)
 +
    return type(v) == "string" and string.format('"%s"', v) or type(v) == "function" and '"function"' or tostring(v)
 +
end
 +
 +
function Utils.js(x, i)
 +
    i = i or 0
 +
    local r = ""
 +
    if type(x) == "table" then
 +
        r = "{\n"
 +
        for k, v in pairs(x) do
 +
            if type(v) == "table" then
 +
                r = r .. string.rep("  ", i + 1) .. tostring(k) .. ": " .. Utils.js(v, i + 1)
 +
            else
 +
                r = r .. string.rep("  ", i + 1) .. tostring(k) .. ": " .. showValue(v) .. ",\n"
 +
            end
 +
        end
 +
        r = r .. string.rep("  ", i) .. (i == 0 and "}\n" or "},\n")
 +
    else
 +
        return showValue(x)
 +
    end
 +
    return r
 
end
 
end
   Line 225: Line 419:  
         end
 
         end
 
     end
 
     end
 +
end
 +
 +
function Utils.test(obj, desc, fn)
 +
    obj.test = function()
 +
        mw.log(desc)
 +
        fn(obj)
 +
        mw.log("ok")
 +
    end
 +
end
 +
 +
Utils.log = mw.log
 +
 +
function Utils.format(s, lookup)
 +
if not lookup then
 +
lookup = s
 +
s = lookup[1]
 +
table.remove(lookup, 1)
 +
end
 +
return (string.gsub(s, '${([^%.%!%:%}%[%]]+)%[?([^%.%!%:%}%]]*)%]?%.?([^%!%:%}]*)!?([^%:%}]?):?([^%}]*)}',
 +
function(name, element, attribute, conversion, format_spec)
 +
--local start_of_value, end_of_value, value = string.find(x, '^${(.-)[[.!:}]')
 +
--local start_of_access, end_of_access, access = string.find(x, '^${.-%[(.-)%][!:}]')
 +
--if not access then
 +
-- start_of_access, end_of_access, access = string.find(x, '^${[^:]-%.(.-)[!:}]')
 +
--end
 +
--local start_of_conversion, end_of_conversion, conversion = string.find(x, '^${.-!(.)[:}]')
 +
--local start_of_format_spec, end_of_format_spec, format_spec = string.find(x, ':(.*)}$')
 +
 +
local value = lookup[name]
 +
if string.len(element) > 0 then
 +
value = value[element]
 +
elseif string.len(attribute) > 0 then
 +
value = value[attribute]
 +
end
 +
 +
if string.len(conversion) > 0 then
 +
if conversion == 's' then
 +
value = tostring(value)
 +
end
 +
end
 +
 +
if string.len(format_spec) > 0 then
 +
local start_of_sign, end_of_sign, sign = string.find(format_spec, '([+%- ])')
 +
local start_of_width, end_of_width, width, comma, precision, option = string.find(format_spec, '(%d*)(,?)([.0-9]*)([bcdeEfFgGnosxX%%]?)$')
 +
precision = string.sub(precision, 2)
 +
local number = tonumber(value)
 +
if #width > 0 then
 +
if number then
 +
value = string.format(string.format(number % 1 ~= 0 and "%%0%s.%sf" or "%%0%sd", width, #precision > 0 and precision or 0), number)
 +
end
 +
value = string.format(string.format("%%0%ss", width), value)
 +
elseif #precision > 0 and number then
 +
value = string.format(string.format("%%0%s.%sf", width, precision), number)
 +
end
 +
if sign then
 +
if number and number > 0 then
 +
if sign == "+" then
 +
value = "+" .. value
 +
elseif sign == " " then
 +
value = " " .. value
 +
end
 +
end
 +
end
 +
end
 +
 +
return value
 +
end))
 +
end
 +
 +
function Utils.split(string, separator, max_split, plain)
 +
assert(separator ~= '')
 +
assert(max_split == nil or max_split >= 1)
 +
 +
local default_separator = false
 +
 +
local result = {}
 +
 +
if not separator or separator == '' then
 +
separator = '%s+'
 +
plain = false
 +
string = mw.text.trim(string)
 +
if string == '' then
 +
return result
 +
end
 +
end
 +
 +
max_split = max_split or -1
 +
 +
local item_index, start_index = 1, 1
 +
local separator_start, separator_end = mw.ustring.find(string, separator, start_index, plain)
 +
while separator_start and max_split ~= 0 do
 +
result[item_index] = mw.ustring.sub(string, start_index, separator_start - 1)
 +
item_index = item_index + 1
 +
start_index = separator_end + 1
 +
separator_start, separator_end = mw.ustring.find(string, separator, start_index, plain)
 +
max_split = max_split - 1
 +
end
 +
result[item_index] = mw.ustring.sub(string, start_index)
 +
 +
return result
 +
end
 +
 +
Utils.romanizable = {'zh-hans', 'zh-hant', 'zh-cn', 'zh-tw', 'zh-hk', 'zh-sg', 'zh-mo', 'zh-my', 'ja', 'ko', 'vi'}
 +
 +
Utils.normalization_table = {[' '] = ' ', ['~'] = '~', ['!'] = '!', ['?'] = '?'}
 +
 +
-- checks if string is set and if it's non-empty
 +
function Utils.isset(target)
 +
  return target ~= nil and target ~= ""
 +
end
 +
 +
--[[ simulates the (a ? b : c) notation of C/C++ and PHP languages.
 +
    Similar to {{#if:{{{a|}}}|{{{b|}}}|{{{c|}}}}} from parser functions. ]]
 +
function Utils.cv(a, b, c)
 +
  if a then return b else return c end
 +
end
 +
 +
--slices a table to return another table containing values within a certain range
 +
--source: http://snippets.luacode.org/snippets/Table_Slice_116
 +
function Utils.sliceTable (values,i1,i2)
 +
    local res = {}
 +
    local n = #values
 +
    -- default values for range
 +
    i1 = i1 or 1
 +
    i2 = i2 or n
 +
    if i2 < 0 then
 +
        i2 = n + i2 + 1
 +
    elseif i2 > n then
 +
        i2 = n
 +
    end
 +
    if i1 < 1 or i1 > n then
 +
        return {}
 +
    end
 +
    local k = 1
 +
    for i = i1,i2 do
 +
        res[k] = values[i]
 +
        k = k + 1
 +
    end
 +
    return res
 +
end
 +
 +
-- checks if a given page exists
 +
function Utils.exists(page)
 +
  if not Utils.isset(page) then return false end
 +
  return mw.getCurrentFrame():preprocess('{{#ifexist:' .. page .. '|1|0}}') == '1'
 +
end
 +
 +
--[[ Tries to get contents of a page with given name.
 +
    If the function fails it returns nil (page doesn't exist or can't be loaded)
 +
    On success it returns the contents of page (it can be be partially preprocessed, so watch out for parser markers). ]]
 +
function Utils.getPage(name)
 +
  if not Utils.isset(name) then return nil end
 +
 +
  local frame = mw.getCurrentFrame()
 +
 +
  -- do a safe call to catch possible errors, like "template doesn't exist"
 +
  local stat,page = pcall(frame.expandTemplate, frame, {title = ':' .. name})
 +
 +
  if not stat then
 +
    -- TODO: 'page' contains the error message. Do some debugging?
 +
    return nil
 +
  end
 +
 +
  return page
 +
end
 +
 +
function Utils.stripTags(text)
 +
  if Utils.isset(text) then
 +
    local tmp
 +
    repeat
 +
      tmp = text
 +
      -- a pair of tags, like <td style="">...</td>
 +
      text = string.gsub(text, '<%s*(%w+).->(.-)<%s*/%s*%1%s*>', '%2')
 +
      -- closed tag, like <br/>
 +
      text = string.gsub(text, '<%s*%w+%s*/%s*>', '')
 +
    until tmp == text
 +
  end
 +
  return text
 +
end
 +
 +
--[[ Sort table and remove repeating elements.
 +
    Since tbl is passed as reference, any changes in it will affect the passed table. ]]
 +
function Utils.trunkTable(tbl)
 +
  table.sort(tbl)
 +
  local last
 +
  local redo
 +
  repeat
 +
    redo = false
 +
    last = nil
 +
    for k,v in pairs(tbl) do
 +
      if v ~= last then
 +
        last = v
 +
      else
 +
        table.remove(tbl, k)
 +
        redo = true
 +
        break
 +
      end
 +
    end
 +
  until not redo
 +
end
 +
 +
--[[ Checks if a given value is among the elements of a table and returns its index.
 +
      Returns nil if it can't find it. ]]
 +
function Utils.isInTable(tbl, val)
 +
  for k,v in pairs(tbl) do
 +
    if v == val then return k end
 +
  end
 +
  return nil
 +
end
 +
 +
--[[ Compare 'n' elements in two tables, starting from 's1' in first table and 's2' in second table. ]]
 +
function Utils.partialTableCompare(t1, t2, s1, s2, n)
 +
  if n < 1 then return true end -- basically there's nothing to compare, so no differences were found
 +
 +
  for i = 0,(n-1) do
 +
    -- Note that nil values are also valid.
 +
    if t1[s1+i] ~= t2[s2+i] then return false end
 +
  end
 +
 +
  return true
 +
end
 +
 +
-- naming based on "Navbox" elements
 +
Utils.main_colors = {
 +
  game = {border = '#A88580', title = '#FFC9C2', above = '#FFD1CA', group = '#FFD9D2', subgroup = '#FFE1DA', dark = '#FFEEE8', background = '#FFF4EE'};
 +
  music = {border = '#A8A077', title = '#FFF3B4', above = '#FFF6C0', group = '#FFF7C8', subgroup = '#FFF8D0', dark = '#FFFBE4', background = '#FFFBEE'};
 +
  printwork = {border = '#9298A8', title = '#DDE6FF', above = '#E1E7FF', group = '#E6E9FF', subgroup = '#EAECFF', dark = '#EDF2FF', background = '#F4F9FF'};
 +
}
 +
 +
-- function for easy adding of styles to html tags
 +
function Utils.addStyle(tbl, val)
 +
  if Utils.isset(val) then
 +
    local av = tostring(val):gsub("^%s*(.-)%s*$", "%1")
 +
    if string.sub(av, -1) ~= ';' then av = av .. ';' end
 +
    tbl[#tbl+1] = av
 +
  end
 
end
 
end
    
return Utils
 
return Utils
cssedit, gkautomate
7,064

edits