More error analysis; refactoring of lit.puts
This commit is contained in:
parent
e353f5125f
commit
781a7920f6
|
@ -6,7 +6,7 @@ process of creating works of literature][1]".
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- [Pandoc]
|
- [Pandoc] v3
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
|
|
@ -6302,10 +6302,14 @@ function os.isunix()
|
||||||
return os.uname() ~= "windows"
|
return os.uname() ~= "windows"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Changes newlines so everything is in one line
|
-- Gets OS language
|
||||||
-- @return string: String with formatted newlines as literal "\n"
|
-- @return string, string, string: Language, locale and encoding
|
||||||
function string:linearize()
|
function os.lang()
|
||||||
return self:gsub("\n", "\\\\n")
|
local lang = os.getenv("LANG")
|
||||||
|
if lang ~= nil then
|
||||||
|
return lang:match("(%w%w)_?(%w?%w?)%.?(.*)")
|
||||||
|
end
|
||||||
|
return "en", "US", "UTF-8"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Checks if string is empty
|
-- Checks if string is empty
|
||||||
|
@ -6314,22 +6318,47 @@ function string:isempty()
|
||||||
return self == ''
|
return self == ''
|
||||||
end
|
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()
|
function string:lstrip()
|
||||||
return self:gsub("^%s+", "")
|
return self:gsub("^%s+", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Removes spaces at the end of the string
|
||||||
|
-- @return string: right stripped string
|
||||||
function string:rstrip()
|
function string:rstrip()
|
||||||
return self:gsub("%s+$", "")
|
return self:gsub("%s+$", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Removes spaces at the beginning and at the end of the string
|
||||||
|
-- @return string: stripped string
|
||||||
function string:strip()
|
function string:strip()
|
||||||
return self:lstrip():rstrip()
|
self = self:lstrip():rstrip()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Alias of strip
|
||||||
|
function string:trim()
|
||||||
|
return self:strip()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The following are heavily influenced by Python pathlib
|
-- The following are heavily influenced by Python pathlib
|
||||||
-- Check: https://docs.python.org/3/library/pathlib.html
|
-- Check: https://docs.python.org/3/library/pathlib.html
|
||||||
|
|
||||||
-- Checks if string is a file or directory
|
-- Checks if string is a file or a directory
|
||||||
-- @return boolean: Exists or not
|
-- @return boolean: Exists or not
|
||||||
function string:exists()
|
function string:exists()
|
||||||
return os.rename(self, self) ~= nil
|
return os.rename(self, self) ~= nil
|
||||||
|
@ -6363,6 +6392,8 @@ function string:read_text()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Gets file without suffix
|
||||||
|
-- @return string: File wihtout suffix
|
||||||
function string:stem()
|
function string:stem()
|
||||||
return self:gsub("%.%a+$", "")
|
return self:gsub("%.%a+$", "")
|
||||||
end
|
end
|
||||||
|
@ -6394,6 +6425,8 @@ if pandoc ~= nil then
|
||||||
|
|
||||||
-- Gets file extension namespace
|
-- Gets file extension namespace
|
||||||
-- Check: https://pandoc.org/MANUAL.html#general-options
|
-- 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
|
-- @param file string: File name
|
||||||
-- @return string: File extension according to Pandoc format namespaces
|
-- @return string: File extension according to Pandoc format namespaces
|
||||||
function pandoc.getext(file)
|
function pandoc.getext(file)
|
||||||
|
@ -6403,22 +6436,21 @@ if pandoc ~= nil then
|
||||||
|
|
||||||
-- Pandoc converter
|
-- Pandoc converter
|
||||||
-- Converts input file name into output format name.
|
-- Converts input file name into output format name.
|
||||||
-- If ofile is not nil, writes output file name instead of returning content.
|
-- If ofile is not nil, writes output file name.
|
||||||
-- If iformat is nil, defaults to ifile extension name.
|
-- If iformat is nil, defaults to ifile extension name.
|
||||||
-- @param ifile string: Input file name
|
-- @param ifile string: Input file name
|
||||||
-- @param oformat string: Output format name
|
-- @param oformat string: Output format name
|
||||||
-- @param ofile string or nil: Output file name
|
-- @param ofile string or nil: Output file name
|
||||||
-- @param iformat string or nil: Input format name
|
-- @param iformat string or nil: Input format name
|
||||||
-- @return string or nil: Output file content
|
-- @return string: Output file content
|
||||||
function pandoc.convert(ifile, oformat, ofile, iformat)
|
function pandoc.convert(ifile, oformat, ofile, iformat)
|
||||||
iformat = (iformat == nil and pandoc.getext(ifile) or iformat)
|
iformat = (iformat == nil and pandoc.getext(ifile) or iformat)
|
||||||
local doc = pandoc.write(pandoc.read(ifile:read_text(), iformat), oformat)
|
local doc = pandoc.write(pandoc.read(ifile:read_text(), iformat), oformat)
|
||||||
if ofile == nil then
|
if ofile ~= nil then
|
||||||
return doc
|
|
||||||
else
|
|
||||||
local eol = (os:isunix() and "\n" or "\r\n")
|
local eol = (os:isunix() and "\n" or "\r\n")
|
||||||
io.open(ofile, "w"):write(doc, eol):close()
|
io.open(ofile, "w"):write(doc, eol):close()
|
||||||
end
|
end
|
||||||
|
return doc
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -6459,6 +6491,94 @@ lit.metastruct = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Messages for the user
|
||||||
|
lit.msg = {
|
||||||
|
["INFO"] = {
|
||||||
|
["parsing"] = {
|
||||||
|
["en"] = "Parsing:\n#1",
|
||||||
|
["es"] = "Realizando análisis sintáctico:\n#1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["WARNING"] = {
|
||||||
|
|
||||||
|
},
|
||||||
|
["ERROR"] = {
|
||||||
|
["invalid_key"] = {
|
||||||
|
["en"] = "Invalid key '#1' with value '#2'",
|
||||||
|
["es"] = "Clave '#1' inválida con valor '#2'",
|
||||||
|
},
|
||||||
|
["invalid_path"] = {
|
||||||
|
["en"] = "Invalid path '#1' in key '#2'",
|
||||||
|
["es"] = "Ruta '#1' inválida en clave '#2'",
|
||||||
|
},
|
||||||
|
["invalid_type"] = {
|
||||||
|
["en"] = "Invalid type '#1' in key '#2'",
|
||||||
|
["es"] = "Tipo '#1' inválido en clave '#2'",
|
||||||
|
},
|
||||||
|
["invalid_value"] = {
|
||||||
|
["en"] = "Invalid value '#1' in key '#2'",
|
||||||
|
["es"] = "Valor '#1' inválido en clave '#2'",
|
||||||
|
},
|
||||||
|
["no_key"] = {
|
||||||
|
["en"] = "Key '#1' not found",
|
||||||
|
["es"] = "Clave '#1' no encontrada",
|
||||||
|
},
|
||||||
|
["aborted"] = {
|
||||||
|
["en"] = "Aborted due previous errors",
|
||||||
|
["es"] = "Abortado debido a previos errores",
|
||||||
|
},
|
||||||
|
["yaml_empty"] = {
|
||||||
|
["en"] = "Empty YAML",
|
||||||
|
["es"] = "YAML vacío",
|
||||||
|
},
|
||||||
|
["yaml_invalid"] = {
|
||||||
|
["en"] = "Invalid YAML",
|
||||||
|
["es"] = "YAML inválido",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function lit.debuglevel(str)
|
||||||
|
if str == "ERROR" then
|
||||||
|
lit.status = false
|
||||||
|
return 2
|
||||||
|
elseif str == "WARNING" then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function lit.setmsg(msg, ...)
|
||||||
|
local lang = os.lang()
|
||||||
|
msg = (msg[lang] ~= nil and msg[lang] or msg)
|
||||||
|
for i, str in ipairs({...}) do
|
||||||
|
msg = msg:gsub("#" .. i, str)
|
||||||
|
end
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
|
function lit.getmsg(key, ...)
|
||||||
|
local levelname = "INFO"
|
||||||
|
local level = 0
|
||||||
|
for mtype, msgs in pairs(lit.msg) do
|
||||||
|
if msgs[key] ~= nil then
|
||||||
|
key = lit.setmsg(msgs[key], ...)
|
||||||
|
levelname, level = mtype, lit.debuglevel(mtype)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return key, levelname, level
|
||||||
|
end
|
||||||
|
|
||||||
|
function lit.puts(key, ...)
|
||||||
|
local verbosity = lit.debuglevel(PANDOC_STATE.verbosity)
|
||||||
|
local msg, levelname, level = lit.getmsg(key, ...)
|
||||||
|
if level >= verbosity then
|
||||||
|
print("[" .. levelname .. "] [LIT] " .. msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function lit.getmetaval(meta, key)
|
function lit.getmetaval(meta, key)
|
||||||
local mtype = pandoc.utils.type(meta[key])
|
local mtype = pandoc.utils.type(meta[key])
|
||||||
local mval = meta[key]
|
local mval = meta[key]
|
||||||
|
@ -6469,40 +6589,44 @@ function lit.getmetaval(meta, key)
|
||||||
return mval, mtype
|
return mval, mtype
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function lit.checkmetaextra(meta)
|
||||||
|
for key, val in pairs(meta) do
|
||||||
|
local missing1 = lit.metastruct["mandatory"][key] == nil
|
||||||
|
local missing2 = lit.metastruct["optional"][key] == nil
|
||||||
|
local mval = lit.getmetaval(meta, key)
|
||||||
|
if missing1 and missing2 then
|
||||||
|
lit.puts("invalid_key", key, mval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function lit.checkmetatype(type, meta, key)
|
function lit.checkmetatype(type, meta, key)
|
||||||
local mval, mtype = lit.getmetaval(meta, key)
|
local mval, mtype = lit.getmetaval(meta, key)
|
||||||
local err = ""
|
|
||||||
if type ~= mtype then
|
if type ~= mtype then
|
||||||
if type == "path" then
|
if type == "path" then
|
||||||
if not(pandoc.path.directory(mval):isdir()) then
|
if not(pandoc.path.directory(mval):isdir()) then
|
||||||
err = "Invalid path '" .. mval .. "' in key '" .. key .. "'"
|
lit.puts("invalid_path", mval, key)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
err = "Invalid type '" .. mtype .. "' in key '" .. key .. "'"
|
lit.puts("invalid_type", mtype, key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not(err:isempty()) then lit.puts(err, "ERROR") end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.checkmetatable(table, meta, key)
|
function lit.checkmetatable(table, meta, key)
|
||||||
local mval = lit.getmetaval(meta, key)
|
local mval = lit.getmetaval(meta, key)
|
||||||
local err = ""
|
|
||||||
for _, pattern in pairs(table) do
|
for _, pattern in pairs(table) do
|
||||||
if mval:match("^" .. pattern .. "$") then
|
if mval:match("^" .. pattern .. "$") == nil then
|
||||||
err = ""
|
lit.puts("invalid_value", mval, key)
|
||||||
break
|
|
||||||
else
|
|
||||||
err = "Invalid value '" .. mval .. "' in key '" .. key .. "'"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not(err:isempty()) then lit.puts(err, "ERROR") end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.checkmeta(meta, kind)
|
function lit.checkmeta(meta, kind)
|
||||||
for key, val in pairs(lit.metastruct[kind]) do
|
for key, val in pairs(lit.metastruct[kind]) do
|
||||||
if meta[key] == nil then
|
if meta[key] == nil then
|
||||||
if kind == "mandatory" then
|
if kind == "mandatory" then
|
||||||
lit.puts("Key '" .. key .. "' not found", "ERROR")
|
lit.puts("no_key", key)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if type(val) == "table" then
|
if type(val) == "table" then
|
||||||
|
@ -6517,7 +6641,8 @@ end
|
||||||
function lit.setmeta(meta)
|
function lit.setmeta(meta)
|
||||||
lit.checkmeta(meta, "mandatory")
|
lit.checkmeta(meta, "mandatory")
|
||||||
lit.checkmeta(meta, "optional")
|
lit.checkmeta(meta, "optional")
|
||||||
-- TODO checks for 1) extra keys and 2) duplicates
|
lit.checkmetaextra(meta)
|
||||||
|
-- TODO checks for 2) duplicates
|
||||||
-- Set defaults if lit.status = true
|
-- Set defaults if lit.status = true
|
||||||
return meta
|
return meta
|
||||||
end
|
end
|
||||||
|
@ -6562,51 +6687,32 @@ function lit.eval(code)
|
||||||
end
|
end
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
-- TODO
|
||||||
function lit.assert(e, status)
|
function lit.assert(e, status)
|
||||||
if status == false then
|
if status == false then
|
||||||
lit.puts("Aborted due previous errors", "ERROR")
|
lit.puts("aborted")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
return e
|
return e
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.debuglevel(str)
|
|
||||||
if str == "ERROR" then
|
|
||||||
lit.status = false
|
|
||||||
return 2
|
|
||||||
elseif str == "WARNING" then
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function lit.puts(msg, kind)
|
|
||||||
local kind = kind or "INFO"
|
|
||||||
local verbosity = lit.debuglevel(PANDOC_STATE.verbosity)
|
|
||||||
level = lit.debuglevel(kind)
|
|
||||||
if level >= verbosity then
|
|
||||||
print("[" .. kind .. "] [LIT] " .. msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function lit.parseyaml(rawyaml)
|
function lit.parseyaml(rawyaml)
|
||||||
local yaml = io.popen("pandoc -t json <<<\"" .. rawyaml .. "\" 2>&1")
|
local yaml = io.popen("pandoc -t json <<<\"" .. rawyaml .. "\" 2>&1")
|
||||||
if yaml:read("*l"):sub(1, 1) == "{" then
|
if yaml:read("*l"):sub(1, 1) == "{" then
|
||||||
yaml = pandoc.read(rawyaml).meta
|
yaml = pandoc.read(rawyaml).meta
|
||||||
if pandoc.utils.stringify(yaml):isempty() then
|
if pandoc.utils.stringify(yaml):isempty() then
|
||||||
lit.puts("Empty YAML", "ERROR")
|
lit.puts("yaml_empty")
|
||||||
else
|
else
|
||||||
return lit.setmeta(yaml)
|
return lit.setmeta(yaml)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
lit.puts("Invalid YAML", "ERROR")
|
lit.puts("yaml_invalid")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.parseblock(parsed)
|
function lit.parseblock(parsed)
|
||||||
lit.puts("Parsing " .. table.concat(parsed, "\n"):linearize())
|
lit.puts("parsing", table.concat(parsed, ""):indent())
|
||||||
local yaml = lit.parseyaml(parsed[1])
|
local yaml = lit.parseyaml(parsed[1])
|
||||||
-- TODO: parsecode
|
-- TODO: parsecode
|
||||||
return "TODO"
|
return "TODO"
|
||||||
|
|
|
@ -41,10 +41,14 @@ function os.isunix()
|
||||||
return os.uname() ~= "windows"
|
return os.uname() ~= "windows"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Changes newlines so everything is in one line
|
-- Gets OS language
|
||||||
-- @return string: String with formatted newlines as literal "\n"
|
-- @return string, string, string: Language, locale and encoding
|
||||||
function string:linearize()
|
function os.lang()
|
||||||
return self:gsub("\n", "\\\\n")
|
local lang = os.getenv("LANG")
|
||||||
|
if lang ~= nil then
|
||||||
|
return lang:match("(%w%w)_?(%w?%w?)%.?(.*)")
|
||||||
|
end
|
||||||
|
return "en", "US", "UTF-8"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Checks if string is empty
|
-- Checks if string is empty
|
||||||
|
@ -53,22 +57,47 @@ function string:isempty()
|
||||||
return self == ''
|
return self == ''
|
||||||
end
|
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()
|
function string:lstrip()
|
||||||
return self:gsub("^%s+", "")
|
return self:gsub("^%s+", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Removes spaces at the end of the string
|
||||||
|
-- @return string: right stripped string
|
||||||
function string:rstrip()
|
function string:rstrip()
|
||||||
return self:gsub("%s+$", "")
|
return self:gsub("%s+$", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Removes spaces at the beginning and at the end of the string
|
||||||
|
-- @return string: stripped string
|
||||||
function string:strip()
|
function string:strip()
|
||||||
return self:lstrip():rstrip()
|
self = self:lstrip():rstrip()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Alias of strip
|
||||||
|
function string:trim()
|
||||||
|
return self:strip()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The following are heavily influenced by Python pathlib
|
-- The following are heavily influenced by Python pathlib
|
||||||
-- Check: https://docs.python.org/3/library/pathlib.html
|
-- Check: https://docs.python.org/3/library/pathlib.html
|
||||||
|
|
||||||
-- Checks if string is a file or directory
|
-- Checks if string is a file or a directory
|
||||||
-- @return boolean: Exists or not
|
-- @return boolean: Exists or not
|
||||||
function string:exists()
|
function string:exists()
|
||||||
return os.rename(self, self) ~= nil
|
return os.rename(self, self) ~= nil
|
||||||
|
@ -102,6 +131,8 @@ function string:read_text()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Gets file without suffix
|
||||||
|
-- @return string: File wihtout suffix
|
||||||
function string:stem()
|
function string:stem()
|
||||||
return self:gsub("%.%a+$", "")
|
return self:gsub("%.%a+$", "")
|
||||||
end
|
end
|
||||||
|
@ -133,6 +164,8 @@ if pandoc ~= nil then
|
||||||
|
|
||||||
-- Gets file extension namespace
|
-- Gets file extension namespace
|
||||||
-- Check: https://pandoc.org/MANUAL.html#general-options
|
-- 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
|
-- @param file string: File name
|
||||||
-- @return string: File extension according to Pandoc format namespaces
|
-- @return string: File extension according to Pandoc format namespaces
|
||||||
function pandoc.getext(file)
|
function pandoc.getext(file)
|
||||||
|
@ -142,22 +175,21 @@ if pandoc ~= nil then
|
||||||
|
|
||||||
-- Pandoc converter
|
-- Pandoc converter
|
||||||
-- Converts input file name into output format name.
|
-- Converts input file name into output format name.
|
||||||
-- If ofile is not nil, writes output file name instead of returning content.
|
-- If ofile is not nil, writes output file name.
|
||||||
-- If iformat is nil, defaults to ifile extension name.
|
-- If iformat is nil, defaults to ifile extension name.
|
||||||
-- @param ifile string: Input file name
|
-- @param ifile string: Input file name
|
||||||
-- @param oformat string: Output format name
|
-- @param oformat string: Output format name
|
||||||
-- @param ofile string or nil: Output file name
|
-- @param ofile string or nil: Output file name
|
||||||
-- @param iformat string or nil: Input format name
|
-- @param iformat string or nil: Input format name
|
||||||
-- @return string or nil: Output file content
|
-- @return string: Output file content
|
||||||
function pandoc.convert(ifile, oformat, ofile, iformat)
|
function pandoc.convert(ifile, oformat, ofile, iformat)
|
||||||
iformat = (iformat == nil and pandoc.getext(ifile) or iformat)
|
iformat = (iformat == nil and pandoc.getext(ifile) or iformat)
|
||||||
local doc = pandoc.write(pandoc.read(ifile:read_text(), iformat), oformat)
|
local doc = pandoc.write(pandoc.read(ifile:read_text(), iformat), oformat)
|
||||||
if ofile == nil then
|
if ofile ~= nil then
|
||||||
return doc
|
|
||||||
else
|
|
||||||
local eol = (os:isunix() and "\n" or "\r\n")
|
local eol = (os:isunix() and "\n" or "\r\n")
|
||||||
io.open(ofile, "w"):write(doc, eol):close()
|
io.open(ofile, "w"):write(doc, eol):close()
|
||||||
end
|
end
|
||||||
|
return doc
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
148
src/literate.lua
148
src/literate.lua
|
@ -28,6 +28,94 @@ lit.metastruct = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Messages for the user
|
||||||
|
lit.msg = {
|
||||||
|
["INFO"] = {
|
||||||
|
["parsing"] = {
|
||||||
|
["en"] = "Parsing:\n#1",
|
||||||
|
["es"] = "Realizando análisis sintáctico:\n#1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["WARNING"] = {
|
||||||
|
|
||||||
|
},
|
||||||
|
["ERROR"] = {
|
||||||
|
["invalid_key"] = {
|
||||||
|
["en"] = "Invalid key '#1' with value '#2'",
|
||||||
|
["es"] = "Clave '#1' inválida con valor '#2'",
|
||||||
|
},
|
||||||
|
["invalid_path"] = {
|
||||||
|
["en"] = "Invalid path '#1' in key '#2'",
|
||||||
|
["es"] = "Ruta '#1' inválida en clave '#2'",
|
||||||
|
},
|
||||||
|
["invalid_type"] = {
|
||||||
|
["en"] = "Invalid type '#1' in key '#2'",
|
||||||
|
["es"] = "Tipo '#1' inválido en clave '#2'",
|
||||||
|
},
|
||||||
|
["invalid_value"] = {
|
||||||
|
["en"] = "Invalid value '#1' in key '#2'",
|
||||||
|
["es"] = "Valor '#1' inválido en clave '#2'",
|
||||||
|
},
|
||||||
|
["no_key"] = {
|
||||||
|
["en"] = "Key '#1' not found",
|
||||||
|
["es"] = "Clave '#1' no encontrada",
|
||||||
|
},
|
||||||
|
["aborted"] = {
|
||||||
|
["en"] = "Aborted due previous errors",
|
||||||
|
["es"] = "Abortado debido a previos errores",
|
||||||
|
},
|
||||||
|
["yaml_empty"] = {
|
||||||
|
["en"] = "Empty YAML",
|
||||||
|
["es"] = "YAML vacío",
|
||||||
|
},
|
||||||
|
["yaml_invalid"] = {
|
||||||
|
["en"] = "Invalid YAML",
|
||||||
|
["es"] = "YAML inválido",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function lit.debuglevel(str)
|
||||||
|
if str == "ERROR" then
|
||||||
|
lit.status = false
|
||||||
|
return 2
|
||||||
|
elseif str == "WARNING" then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function lit.setmsg(msg, ...)
|
||||||
|
local lang = os.lang()
|
||||||
|
msg = (msg[lang] ~= nil and msg[lang] or msg)
|
||||||
|
for i, str in ipairs({...}) do
|
||||||
|
msg = msg:gsub("#" .. i, str)
|
||||||
|
end
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
|
function lit.getmsg(key, ...)
|
||||||
|
local levelname = "INFO"
|
||||||
|
local level = 0
|
||||||
|
for mtype, msgs in pairs(lit.msg) do
|
||||||
|
if msgs[key] ~= nil then
|
||||||
|
key = lit.setmsg(msgs[key], ...)
|
||||||
|
levelname, level = mtype, lit.debuglevel(mtype)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return key, levelname, level
|
||||||
|
end
|
||||||
|
|
||||||
|
function lit.puts(key, ...)
|
||||||
|
local verbosity = lit.debuglevel(PANDOC_STATE.verbosity)
|
||||||
|
local msg, levelname, level = lit.getmsg(key, ...)
|
||||||
|
if level >= verbosity then
|
||||||
|
print("[" .. levelname .. "] [LIT] " .. msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function lit.getmetaval(meta, key)
|
function lit.getmetaval(meta, key)
|
||||||
local mtype = pandoc.utils.type(meta[key])
|
local mtype = pandoc.utils.type(meta[key])
|
||||||
local mval = meta[key]
|
local mval = meta[key]
|
||||||
|
@ -38,40 +126,44 @@ function lit.getmetaval(meta, key)
|
||||||
return mval, mtype
|
return mval, mtype
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function lit.checkmetaextra(meta)
|
||||||
|
for key, val in pairs(meta) do
|
||||||
|
local missing1 = lit.metastruct["mandatory"][key] == nil
|
||||||
|
local missing2 = lit.metastruct["optional"][key] == nil
|
||||||
|
local mval = lit.getmetaval(meta, key)
|
||||||
|
if missing1 and missing2 then
|
||||||
|
lit.puts("invalid_key", key, mval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function lit.checkmetatype(type, meta, key)
|
function lit.checkmetatype(type, meta, key)
|
||||||
local mval, mtype = lit.getmetaval(meta, key)
|
local mval, mtype = lit.getmetaval(meta, key)
|
||||||
local err = ""
|
|
||||||
if type ~= mtype then
|
if type ~= mtype then
|
||||||
if type == "path" then
|
if type == "path" then
|
||||||
if not(pandoc.path.directory(mval):isdir()) then
|
if not(pandoc.path.directory(mval):isdir()) then
|
||||||
err = "Invalid path '" .. mval .. "' in key '" .. key .. "'"
|
lit.puts("invalid_path", mval, key)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
err = "Invalid type '" .. mtype .. "' in key '" .. key .. "'"
|
lit.puts("invalid_type", mtype, key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not(err:isempty()) then lit.puts(err, "ERROR") end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.checkmetatable(table, meta, key)
|
function lit.checkmetatable(table, meta, key)
|
||||||
local mval = lit.getmetaval(meta, key)
|
local mval = lit.getmetaval(meta, key)
|
||||||
local err = ""
|
|
||||||
for _, pattern in pairs(table) do
|
for _, pattern in pairs(table) do
|
||||||
if mval:match("^" .. pattern .. "$") then
|
if mval:match("^" .. pattern .. "$") == nil then
|
||||||
err = ""
|
lit.puts("invalid_value", mval, key)
|
||||||
break
|
|
||||||
else
|
|
||||||
err = "Invalid value '" .. mval .. "' in key '" .. key .. "'"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not(err:isempty()) then lit.puts(err, "ERROR") end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.checkmeta(meta, kind)
|
function lit.checkmeta(meta, kind)
|
||||||
for key, val in pairs(lit.metastruct[kind]) do
|
for key, val in pairs(lit.metastruct[kind]) do
|
||||||
if meta[key] == nil then
|
if meta[key] == nil then
|
||||||
if kind == "mandatory" then
|
if kind == "mandatory" then
|
||||||
lit.puts("Key '" .. key .. "' not found", "ERROR")
|
lit.puts("no_key", key)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if type(val) == "table" then
|
if type(val) == "table" then
|
||||||
|
@ -86,7 +178,8 @@ end
|
||||||
function lit.setmeta(meta)
|
function lit.setmeta(meta)
|
||||||
lit.checkmeta(meta, "mandatory")
|
lit.checkmeta(meta, "mandatory")
|
||||||
lit.checkmeta(meta, "optional")
|
lit.checkmeta(meta, "optional")
|
||||||
-- TODO checks for 1) extra keys and 2) duplicates
|
lit.checkmetaextra(meta)
|
||||||
|
-- TODO checks for 2) duplicates
|
||||||
-- Set defaults if lit.status = true
|
-- Set defaults if lit.status = true
|
||||||
return meta
|
return meta
|
||||||
end
|
end
|
||||||
|
@ -131,51 +224,32 @@ function lit.eval(code)
|
||||||
end
|
end
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
-- TODO
|
||||||
function lit.assert(e, status)
|
function lit.assert(e, status)
|
||||||
if status == false then
|
if status == false then
|
||||||
lit.puts("Aborted due previous errors", "ERROR")
|
lit.puts("aborted")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
return e
|
return e
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.debuglevel(str)
|
|
||||||
if str == "ERROR" then
|
|
||||||
lit.status = false
|
|
||||||
return 2
|
|
||||||
elseif str == "WARNING" then
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function lit.puts(msg, kind)
|
|
||||||
local kind = kind or "INFO"
|
|
||||||
local verbosity = lit.debuglevel(PANDOC_STATE.verbosity)
|
|
||||||
level = lit.debuglevel(kind)
|
|
||||||
if level >= verbosity then
|
|
||||||
print("[" .. kind .. "] [LIT] " .. msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function lit.parseyaml(rawyaml)
|
function lit.parseyaml(rawyaml)
|
||||||
local yaml = io.popen("pandoc -t json <<<\"" .. rawyaml .. "\" 2>&1")
|
local yaml = io.popen("pandoc -t json <<<\"" .. rawyaml .. "\" 2>&1")
|
||||||
if yaml:read("*l"):sub(1, 1) == "{" then
|
if yaml:read("*l"):sub(1, 1) == "{" then
|
||||||
yaml = pandoc.read(rawyaml).meta
|
yaml = pandoc.read(rawyaml).meta
|
||||||
if pandoc.utils.stringify(yaml):isempty() then
|
if pandoc.utils.stringify(yaml):isempty() then
|
||||||
lit.puts("Empty YAML", "ERROR")
|
lit.puts("yaml_empty")
|
||||||
else
|
else
|
||||||
return lit.setmeta(yaml)
|
return lit.setmeta(yaml)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
lit.puts("Invalid YAML", "ERROR")
|
lit.puts("yaml_invalid")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function lit.parseblock(parsed)
|
function lit.parseblock(parsed)
|
||||||
lit.puts("Parsing " .. table.concat(parsed, "\n"):linearize())
|
lit.puts("parsing", table.concat(parsed, ""):indent())
|
||||||
local yaml = lit.parseyaml(parsed[1])
|
local yaml = lit.parseyaml(parsed[1])
|
||||||
-- TODO: parsecode
|
-- TODO: parsecode
|
||||||
return "TODO"
|
return "TODO"
|
||||||
|
|
Loading…
Reference in New Issue