require "common.globals" require "api.logging" ---@class FileSys local FileSys = { __name = "FileSys", sep = "/" } setmetatable(FileSys, FileSys) ---Return a normalized absolutized version of `path` ---@param path string ---@return string function FileSys.abspath(path) return FileSys.normpath(FileSys.join(FileSys.getcwd(), path)) end ---Return the base name of `path` ---@param path string ---@return string function FileSys.basename(path) return string.sub(path, string.rfind(path, FileSys.sep, 1, true) + 1) end ---Return the directory name of `path` ---@param path string ---@return string function FileSys.dirname(path) return FileSys.split(path)[1] end ---Return true if `path` refers to an existing path ---@param path string ---@return boolean, string? function FileSys.exists(path) local ok, err, code = os.rename(path, path) if not ok then DetailedLog("err: "..err..", code: "..code, game.LOGGER_DEBUG) if code == 13 then -- Permission denied, but it exists return true end end return ok, err end ---Returns a path relative to the current working directory from a texture path ---@param path string # must be a path accepted by game.CreateSkinImage and such ---@return string function FileSys.fromTexturePath(path) --skins//textures/ local relpath = FileSys.join("skins", game.GetSkin(), "textures", FileSys.normpath(path)) if not FileSys.exists(FileSys.join(FileSys.getcwd(), relpath)) then DetailedLog("'"..relpath.."' does not exist", game.LOGGER_ERROR) end return relpath end ---Return a string representing the current working directory ---@return string function FileSys.getcwd() error(FileSys.__name .. ".getcwd() : Not Implemented") end ---Join one or more path components with the platform specific separator ---@param path string ---@param ... string ---@return string function FileSys.join(path, ...) local vargs = { select(1, ...) } local joinedpath = path for _, value in ipairs(vargs) do joinedpath = joinedpath .. FileSys.sep .. value end return joinedpath end ---Normalize `path`, collapse redundant separators and up references ---@param path string ---@param overrideSep? string ---@return string function FileSys.normpath(path, overrideSep) local sep = overrideSep or FileSys.sep --remove multiple slashes path = path:gsub("("..sep..")"..sep.."+", "%1") --remove './' path = path:gsub("%."..sep, "") --remove all up references local count = 0 local upRefPattern = "%w+"..sep.."%.%."..sep repeat path, count = path:gsub(upRefPattern, "") until count == 0 --remove last slash path = path:gsub("(.-)"..sep.."$", "%1") return path end ---Return a relative filepath to `path`, optionally relative to `relativeTo` ---@param path string ---@param relativeTo? string ---@return string function FileSys.relpath(path, relativeTo) relativeTo = relativeTo or FileSys.getcwd() path = path:sub(path:find(relativeTo, 1, true)[2] + 1) return path end ---Return a list of files and directory names in `path` ---@param path string ---@return string[] function FileSys.scandir(path) error(FileSys.__name .. ".scandir() : Not Implemented") end ---Split `path` to (head, tail), tail is the last component, head is everything else ---@param path string ---@return string, string function FileSys.split(path) local lastSep = path:rfind(FileSys.sep, 1, true) return path:sub(1, lastSep), path:sub(lastSep + 1) end ---Split `path` to (root, ext), such that `root + ext == path`, ext is either empty or starts with a '.' ---@param path string ---@return string, string function FileSys.splitext(path) local lastSep = path:rfind(".", 1, true) return path:sub(1, lastSep - 1), path:sub(lastSep) end return FileSys