---------------------------------- EXTENSIONS --------------------------------- -- Tries popen -- @param ... string: Chunks for popen -- @return boolean, string: Status and output of popen function io.try(...) local cmd = table.concat({...}, " ") .. " 2>&1" local handle = io.popen(cmd) local output = handle:read("*a") local status = (handle:close() ~= nil and true or false) return status, output end -- Gets OS short name -- It is just intented to know if it is Linux, macOS or Windows. -- Sorry -- @return string: "linux" or "bsd" or "macos" or "windows" function os.uname() local status, output = io.try("uname") if status then output = output:gsub(" .*", ""):lower() if output ~= "linux" and output:match("bsd") ~= nil then return "bsd" elseif out ~= "linux" then return "macos" end return "linux" end return "windows" end -- Checks if OS is windows -- @return boolean: Windows or not function os.iswin() return os.uname() == "windows" end -- Checks if OS is Unix -- @return boolean: Unix or not function os.isunix() return os.uname() ~= "windows" end -- Gets OS language -- @return string, string, string: Language, locale and encoding function os.lang() local lang = os.getenv("LANG") if lang ~= nil then return lang:match("(%w%w)_?(%w?%w?)%.?(.*)") end return "en", "US", "UTF-8" end -- Checks if string is empty -- @return boolean: Empty or not function string:isempty() return self == '' end -- Changes newlines so everything is in one line -- @return string: String with formatted newlines as literal "\n" function string:linearize() return self:gsub("\n", "\\n") end function string:indent(num, char) num = num or 2 char = char or " " char = string.rep(char, num) return char .. self:gsub("\n", "\n" .. char) end -- Removes spaces at the beginning of the string -- @return string: left stripped string function string:lstrip() return self:gsub("^%s+", "") end -- Removes spaces at the end of the string -- @return string: right stripped string function string:rstrip() return self:gsub("%s+$", "") end -- Removes spaces at the beginning and at the end of the string -- @return string: stripped string function string:strip() self = self:lstrip():rstrip() return self end -- Alias of strip function string:trim() return self:strip() end -- The following are heavily influenced by Python pathlib -- Check: https://docs.python.org/3/library/pathlib.html -- Checks if string is a file or a directory -- @return boolean: Exists or not function string:exists() return os.rename(self, self) ~= nil end -- Checks if string is a file -- @return boolean: File or not function string:isfile() if self:exists() then return io.open(self, "a+") ~= nil end return false end -- Checks if string is a directory -- @return boolean: Directory or not function string:isdir() if self:exists() then return io.open(self, "a+") == nil elseif self == "." or self == ".." then return true end return false end -- Reads file content -- @return string or nil: File content or nil function string:read_text() if self:exists() then return io.open(self):read("*a") end end -- Gets file without suffix -- @return string: File wihtout suffix function string:stem() return self:gsub("%.%a+$", "") end -- Gets file extensions -- @return table: list of file extensions function string:suffixes() local suffixes = {} for suffix in self:gmatch("%.%a+") do table.insert(suffixes, suffix) end return suffixes end -- Gets file final extension -- @return string: final file extension function string:suffix() local suffixes = self:suffixes() if suffixes[#suffixes] then return suffixes[#suffixes] end return "" end -- Requires Pandoc -- Check: https://pandoc.org/lua-filters.html#module-pandoc if pandoc ~= nil then -- Gets file extension namespace -- Check: https://pandoc.org/MANUAL.html#general-options -- If suffix is 'md' or empty, the default is markdown. -- For the rest, the format is the suffix. -- @param file string: File name -- @return string: File extension according to Pandoc format namespaces function pandoc.getext(file) local ext = file:suffix():gsub("^.", "") return ((ext == "md" or ext:isempty()) and "markdown" or ext) end -- Pandoc converter -- Converts input file name into output format name. -- If ofile is not nil, writes output file name. -- If iformat is nil, defaults to ifile extension name. -- @param ifile string: Input file name -- @param oformat string: Output format name -- @param ofile string or nil: Output file name -- @param iformat string or nil: Input format name -- @return string: Output file content function pandoc.convert(ifile, oformat, ofile, iformat) iformat = (iformat == nil and pandoc.getext(ifile) or iformat) local doc = pandoc.write(pandoc.read(ifile:read_text(), iformat), oformat) if ofile ~= nil then local eol = (os:isunix() and "\n" or "\r\n") io.open(ofile, "w"):write(doc, eol):close() end return doc end end