125 lines
4.5 KiB
Lua
125 lines
4.5 KiB
Lua
--context is always -eq to the highest possible subfolder in the mods dir, this can be ether the mod or modpack root folder.
|
|
local DIR_DELIM = debug.getinfo(1, "S").source:match("[\\/]")
|
|
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or "context"
|
|
local cwdpath = minetest and (minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELIM .. "lua5_1") or debug.getinfo(1, "S").source:match("^(.+)[/\\]"):sub(2)
|
|
|
|
--setup lib env
|
|
local print = _G[context]["log"]
|
|
--some string function moved here, for more info see: string.lua
|
|
function string:trim()
|
|
return self:match("^%s*(.-)%s*$")
|
|
end
|
|
|
|
--[[
|
|
function string:split (p2Sep, p3Patern)
|
|
if p2Sep == nil then
|
|
p2Sep = "%s"
|
|
end
|
|
if p3Patern == nil then
|
|
p3Patern = table.concat({"([^", p2Sep, "]+)"}, "")
|
|
end
|
|
local returns = {}
|
|
for _ in string.gmatch(self, p3Patern) do
|
|
table.insert(returns, _)
|
|
end
|
|
return returns
|
|
end
|
|
--]]
|
|
|
|
function string:startsWith(p2Needle) -- self == haystack
|
|
return self:sub(1, #p2Needle) == p2Needle
|
|
end
|
|
|
|
function string:endsWith(p2Needle) -- self == haystack
|
|
return p2Needle == "" or self:sub(-#p2Needle) == p2Needle
|
|
end
|
|
|
|
function string:charCount(p2Char)
|
|
local count = 0
|
|
for _ in string.gmatch(self, p2Char) do
|
|
count = count + 1
|
|
end
|
|
return count
|
|
end
|
|
|
|
--end string.lua snipet
|
|
|
|
|
|
_G[context].colors ={
|
|
reset = "\27[0m",
|
|
red = "\27[31m",
|
|
green = "\27[32m",
|
|
yellow = "\27[33m",
|
|
blue = "\27[34m",
|
|
magenta = "\27[35m",
|
|
cyan = "\27[36m",
|
|
white= "\27[37m"
|
|
}
|
|
|
|
_G[context].forFileAsLines=function(filePath, funcHandle, ignoreReturn)
|
|
local file = io.open(filePath, "r")
|
|
--if file is context:open then
|
|
local returns = {}
|
|
if not file then error(_G[context].colors.red.."access error: reading non-existant file, @" .._G[context].colors.cyan ..filePath.._G[context].colors.reset) end
|
|
if file then
|
|
--itarate over each line and pass to funkyFunc
|
|
for line in file:lines() do
|
|
local linedata=line:trim()--:sub(1,-2) --remove spooky char at the end of a line. If file uses \r\n, it may require (1,-3)
|
|
linedata=funcHandle and (funcHandle(linedata)) or linedata --buggy:TODO
|
|
--this data subject to brakeages, test for errors here:
|
|
--print("<"..linedata..">")
|
|
if not ignoreReturn then --used for large files, to avoid memory bloat.
|
|
table.insert(returns, linedata)
|
|
end
|
|
end
|
|
file:close()
|
|
return returns
|
|
else
|
|
return {}
|
|
end
|
|
end
|
|
|
|
--
|
|
_G[context].forFileAsIniObj = function(filePath, ignoreHeaders)
|
|
local debug_print=false
|
|
local returns = {} --object to store data about ini file as a hashmap table
|
|
returns[""]={} --default object to store global values before a header tag('[' or ']') is found in the file stream
|
|
local rpointer = "" -- by default pointer set to "" by default
|
|
local _ = debug_print and print("<"..filePath..">")
|
|
local _ = _G[context].forFileAsLines(filePath, function (line)
|
|
--in ini, ';' may be used as a comment by default.
|
|
--in the future this may be abstracted into a larger function with more customization
|
|
if not line:startsWith(";") and string.charCount(line, " ") ~= #line and #line ~= 0 then --discard comments or empty lines
|
|
--if is header "[*]"
|
|
local _ = debug_print and print(line)
|
|
if line:match("^%[.*%]$") then
|
|
if not ignoreHeaders then
|
|
rpointer = line:sub(2,-2):trim() --remove [ and ] from the header and use as str:returnPointer
|
|
returns[rpointer]= returns[rpointer] or {}
|
|
end
|
|
--else if is key value pair "*=*"
|
|
elseif line:match("^.+=.+$") and line:charCount("=") == 1 then
|
|
local spointerarray = line:split("=")
|
|
spointerarray[1]=spointerarray[1]:trim()
|
|
spointerarray[2]=spointerarray[2]:trim()
|
|
--If parser fails due to missing '"', use raw string as a fall back.
|
|
--minetest.parse_json create an unmutable error with no way to prevent it,
|
|
--just return as string ill deal with this later. :(
|
|
--Upon reflection this function should always return a string,
|
|
--since it may be used in multiple use case and so should leave parsing decisions to the caller
|
|
--_G[context].parse(spointerarray[2]) or
|
|
returns[rpointer][spointerarray[1]] = spointerarray[2]
|
|
else --else is error
|
|
error(table.concat({"error reading: ", filePath, "@^", line, "$"},""))
|
|
end
|
|
end
|
|
end, true)
|
|
--if the global array table was never used, delete it.
|
|
if #returns[""] == 0 and true then
|
|
returns[""]=nil
|
|
end
|
|
return returns
|
|
end
|
|
--Why the fuck is "true" true in the context of a conditional, is lua just as bad as javascript?
|
|
assert(true == _G[context].parse(_G[context].forFileAsIniObj(cwdpath..DIR_DELIM.."test.ini", false)["testdata"]["success"]))
|
|
|