Module:Y util

From Noita Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Y util/doc

--[[-- A variety of utility functions by Y&#x1F375 --]]--

local Y_util = {
  debug = {},
  string = {},
  table = {},
  xml = {},
};


function Y_util.string.isStrExist(str)
  return not(type(str)~="string" or string.len(string.gsub(str,"^%s*(.-)%s*$","%1"))==0);end
function Y_util.string.parseFloat(str)return (type(str)=="string" or type(str)=="number")
  and tonumber(string.match(str,"[%-%.]?%d+%.?%d*"))or nil; end
function Y_util.string.trim(str)
  return type(str)=="string" and string.match(str,"^%s*(.-)%s*$")or nil;end
function Y_util.string.split(str,delim) local t,d={},delim or ",";
  d="([^"..d.."]*)[%c"..d.."]*";for s in str:gmatch(d)do if(Y_util.string.isStrExist(s))then
    table.insert(t,s);end end return t;end
function Y_util.string.splitTrim(str,delim) local t,d={},delim or ",";
  d="([^"..d.."]*)[%c"..d.."%s]*";for s in str:gmatch(d)do if(Y_util.string.isStrExist(s))then
    table.insert(t,Y_util.string.trim(s));end end return t;end

function Y_util.table.insert_lazy(t,s) if(Y_util.string.isStrExist(s))then
  table.insert(t,s);return true else return false;end end
function Y_util.table.concatx(t,s,e,sep) local s,e=(s or ""),(e or "");
  local sep=e..(sep or "")..s;return s..table.concat(t,sep)..e;end

function Y_util.table.hasValue(t,v) for _,c in pairs(table) do
  if(v==c) then return true; end end return false;end
function Y_util.table.merge(ti,to) for k,v in pairs(ti)do
  if(type(k)=="number")then table.insert(to,v);else to[k]=v;end end return to;end
-- to are optional for ktov and vtok
function Y_util.table.ktov_m(ti,to) to=to or{};for k in pairs(ti)do
  table.insert(to,k);end table.sort(to);return to;end
function Y_util.table.vtok_m(ti,to) to=to or {};for _,v in pairs(ti)do
  if(type(v)=="string" or type(v)=="number")then to[v]=true;end end return to;end
function Y_util.table.getAllValStr( tabled, depth )
  local function sfloop( tabled, depth )
    local r = {};
    if( type(tabled)=="table" ) then
      for _,v in pairs(tabled) do
        if( type(v)=="table" ) then
          if( 0 < depth ) then
            Y_util.table.merge( sfloop( v, depth - 1 ), r );
          end
        elseif( type(v)=="string" or type(v)=="number" ) then
          table.insert( r, v );
        end
      end
    end
    return r;
  end
  local t=sfloop( tabled, math.min( (tonumber(depth) or 4), 10 ) );
  table.sort(t);return t;
end
function Y_util.table.deepclonev(t)
  local function sfloop(it) local rt={};
    for k,v in pairs(it) do
      if( type(v)=="table" )then rt[k]=sfloop(v);
      else rt[k]=v; end end return rt;
  end
  return sfloop(t);
end

function Y_util.xml.reindent( text )
  text = text:gsub( "%s*\n%s*", "" ) -- remove all newline and its surrounding whitespace
  :gsub( ">", ">\n" ) -- separate all tags to newlines
  :gsub( "(<[^/][^>]*>)\n(</)", "%1%2" ) --removes newline if innerHTML empty
  :gsub( "\n([^<])", "%1" ); -- removes newline if contains text
  local res,lvl = {},0;
  for line in text:gmatch( "(<[^\n]*)\n?" ) do -- line starts with '<'
    local startclose = ( ( line:find( "^</" ) ) and true or false );
    if( startclose ) then lvl = lvl - 1; end
    table.insert( res, (line:gsub( "^", string.rep("  ",lvl) )) );
    if( not(startclose)
    and not( line:find( "</[^>]*>$" ) ) ) then
      lvl = lvl + 1;
    end
  end
  return table.concat( res, "\n" );
end
function Y_util.xml.tagGen( e_tag, e_attr, contents )
  local res = nil;
  if( e_tag ~= nil ) then
    e_tag_s = e_tag;
    if( type(e_attr) == "table" ) then -- not nil
      for k,v in pairs(e_attr) do      -- tables are will auto concat'd to str
        if( type(k) == "string" ) then -- non-empty strings are passed
          local val = "";
          if( type(v) == "table" ) then val = table.concat(v," ");
          else val = v; end
          if( Y_util.string.isStrExist( val ) ) then
            e_tag_s = e_tag_s.." "..k.."=\""..val.."\"";
          end
        end
      end
    end
    if( type(contents) == "table" ) then
      contents = table.concat(contents);
    end
    res = "<"..e_tag_s..">"..contents.."</"..e_tag..">";
  end
  return res;
end

function Y_util.debug.e2json( elem, depth )
  local function sfloop( elem, depth )
    if( type(elem) ~= "table" ) then
      elem = { elem };
    end
    local data = {}; table.insert( data, "{ " );
    for k,v in pairs(elem) do
      local key  = "\""..k.."\": ";
      local test = type(v);
      local temp = nil;
      if( test == "table" and 0 < depth ) then
        temp = sfloop( v, depth - 1 );
      else
        if( test == "number" ) then
          temp = tostring(v);
        elseif( test == "string" ) then
          temp = "\""..string.gsub( v, "\"", "\\\"" ).."\"";
        else
          temp = "\"type("..test..")\"";
        end
      end
      if( type(temp) == "string" ) then
        if( #data > 1 ) then
          table.insert( data, ", " );
        end
        table.insert( data, key..temp );
      end
    end
    table.insert( data, " }" );
    return table.concat( data );
  end
  return sfloop( elem, math.min( (tonumber(depth) or 7), 10 ) );
end

return Y_util;