Module:Common

From Noita Wiki
Jump to navigation Jump to search

This module provides commonly required Lua functions, which are not provided by the standard library. It is intended to be used by other Lua modules on the wiki.

Functions

Function Return type Parameter1 Parameter2 Parameter3 Description
isEmpty bool any type Return true if the value is null, or when the type is string and the value is empty.
string.parseInt number string Get the first integer number from a string.
string.parseFloat number string Get the first floating point number from a string.
string.split table string:input string:delimeter (optional) The input string is split into a table when any of the delimeter characters are met. The default delimeter is ,%c, the string is split at comma or control characters (tabs, new lines, etc.).
string.trim string string Trim away leading and trailing whitespace from string.
table.merge table table:to table:from bool:append_ipairs (optional) Replace matching key value pairs in table:to with items from table:from. When bool:append_ipairs is set to true, number indexed pairs are appended into table:to. By default number indexed pairs are replaced.
table.mergeDeep table table:to table:from bool:append_ipairs (optional) Same as table.merge, except with this function all child tables are recursively merged as well, instead of replaced.
table.removeEmpty table table Remove all null or empty key value pairs from the table.
table.trimTable table table Trim all strings in the table.
formatNum string number number_k (optional) number_M (optional) number_k (Default value 4) and number_M (Default value 6) determine how many digits are required before appending the 'k' and 'M' prefixes.
With a value of 4 for number_k the 'k' prefix is not used with 4 digit numbers, since it would take more screen space to show a less accurate number (1234 vs 1.23k)




-- A set of commonly needed Lua functions with sane defaults for optional arguments

local p = {
	string = {},
	table = {}
}

function p.isEmpty(value)
	return value == nil or (type(value) == "string" and string.len(value) == 0)
end

function p.string.parseInt(str)
	return tonumber(string.match(str, "%-?%d+")) or nil
end

function p.string.parseFloat(str) -- Supports scientific notation
	local i, _, e, d = string.match(str, "(%-?%d*%.?%d+)(%.?)([Ee]?)([+-]?%d*)")
	local r = (e ~= nil and string.len(e) ~= 0) and
		(d ~= nil and string.len(d) ~= 0) and i..e..d or i
	if (r ~= nil) then -- remove trailing dot and/or zeroes
		r = string.gsub(tonumber(r), "(%d*)%.?0*$", "%1")
	end
	return tonumber(r)
end

--[[--
-- test for parseFloat
for _,v in pairs({
	"8.", "1.50", "-.1", "2.e3", ".0e3", "", "-.", " -e5e.3e", " e.4.e.3e", "e-.8e+2e"
}) do
	local t = p.string.parseFloat(v) or "nil"
	print( "\""..v.."\" \t; \""..t.."\" \t; "..(tonumber(t) or "nil").." ;" )
end
--]]--

function p.string.split(str, str_delimeter)
	local t = {}
	local d = "[^"..(str_delimeter or ",%c").."]*"
	for s in string.gmatch(str, d) do
		table.insert(t, s)
	end
	return t
end

function p.string.trim(str)
	return string.match(str, "^%s*(.-)%s*$")
end

function p.table.merge(tbl_to, tbl_from, b_append_ipairs)
	for k, v in pairs(tbl_from) do
		if (b_append_ipairs and type(k) == "number") then
			table.insert(tbl_to, v)
		else
			tbl_to[k] = v
		end
	end
	return tbl_to
end

function p.table.mergeDeep(tbl_to, tbl_from, b_append_ipairs)
	local function re(tbl_t, tbl_f)
		for k, v in pairs(tbl_f) do
			if (b_append_ipairs and type(k) == "number") then
				table.insert(tbl_t, v)
			elseif (type(tbl_t[k]) == "table" and type(tbl_f[k]) == "table") then
				re(tbl_t[k], tbl_f[k])
			else
				tbl_t[k] = v
			end
		end
		return tbl_t
	end
	return re(tbl_to, tbl_from)
end

function p.table.removeEmpty(tbl)
	for k, v in pairs(tbl) do
		if (p.string.isEmpty(v)) then
			table.remove(tbl, k)
			--tbl[k] = nil
		end
	end
	return tbl
end

function p.table.trimTable(tbl)
	for k, v in pairs(tbl) do
		if (type(v) == "string") then
			tbl[k] = p.string.trim(v)
		end
	end
	return tbl
end

function p.formatNum(num, nk, nm) -- Large number rounding and prefixing function
-- For inputs 1.2222... 11.2222..., 111.2222..., etc, produce following results
-- 1.22, 11.2, 111, 1111, 11.1k, 111k, 1.11M, 11.1M, 111M, 1111M, 11111M
	local s, _, d = string.match(tostring(tonumber(num)), "(%d+)(%.?)(%d*)")
	if (p.isEmpty(s)) then
		return nil
	end
	local l = string.len(s)
	if (not p.isEmpty(d)) then
		s = s..d
	end
	local f = ''
	-- 4 is intentional, format to 1234 and not 1.23k for better space usage
	if (l > (nk or 4)) then
		if (l > (nm or 6)) then
			l = l - 6
			f = 'M'
		else
			l = l - 3
			f = 'k'
		end
	end
	local x = math.max(0, 3 - l)
	local r = string.sub(s, 0, l)
	if (x ~= 0) then
		local t = string.sub(s, l + 1, l + x)
		if (not p.isEmpty(t)) then
			r = r..'.'..t
		end
	end
	return p.string.parseFloat(r)..f
end

return p