summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/yamlvars/YAMLvars.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/yamlvars/YAMLvars.lua')
-rw-r--r--macros/luatex/latex/yamlvars/YAMLvars.lua369
1 files changed, 369 insertions, 0 deletions
diff --git a/macros/luatex/latex/yamlvars/YAMLvars.lua b/macros/luatex/latex/yamlvars/YAMLvars.lua
new file mode 100644
index 0000000000..11f75edda3
--- /dev/null
+++ b/macros/luatex/latex/yamlvars/YAMLvars.lua
@@ -0,0 +1,369 @@
+--% Kale Ewasiuk (kalekje@gmail.com)
+--% 2021-09-24
+--%
+--% Copyright (C) 2021 Kale Ewasiuk
+--%
+--% Permission is hereby granted, free of charge, to any person obtaining a copy
+--% of this software and associated documentation files (the "Software"), to deal
+--% in the Software without restriction, including without limitation the rights
+--% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+--% copies of the Software, and to permit persons to whom the Software is
+--% furnished to do so, subject to the following conditions:
+--%
+--% The above copyright notice and this permission notice shall be included in
+--% all copies or substantial portions of the Software.
+--%
+--% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+--% ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+--% TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+--% PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+--% SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+--% ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+--% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+--% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+--% OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+-- tinyyaml license
+--MIT License
+--
+--Copyright (c) 2017 peposso
+--
+--Permission is hereby granted, free of charge, to any person obtaining a copy
+--of this software and associated documentation files (the "Software"), to deal
+--in the Software without restriction, including without limitation the rights
+--to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+--copies of the Software, and to permit persons to whom the Software is
+--furnished to do so, subject to the following conditions:
+--
+--The above copyright notice and this permission notice shall be included in all
+--copies or substantial portions of the Software.
+--
+--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+--IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+--FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+--AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+--LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+--OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+--SOFTWARE.
+
+
+
+YAMLvars = {} -- self table
+YAMLvars.xfm = {}
+YAMLvars.prc = {}
+
+YAMLvars.varsvals = {}
+YAMLvars.varspecs = {}
+
+YAMLvars.prcDefault = 'gdef'
+YAMLvars.dftDefault = nil
+YAMLvars.xfmDefault = {}
+
+YAMLvars.allowUndeclared = false
+
+YAMLvars.tabmidrule = 'hline'
+
+YAMLvars.yaml = require('tinyyaml')
+
+
+-- xfm functions (transforms) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+function YAMLvars.xfm.addxspace(var, val)
+ return val .. '\\xspace'
+end
+
+function YAMLvars.xfm.tab2arr(var, val)
+ return pl.array2d.from_table(val)
+end
+
+function YAMLvars.xfm.arrsort2ZA(var, val)
+ return pl.array2d.sortOP(val, pl.operator.strgt)
+end
+
+function YAMLvars.xfm.addrule2arr(var, val)
+ return pl.array2d.map_slice2(_1..'\\\\\\'.. YAMLvars.tabmidrule..' ', val, 1,-1,-2,-1) -- todo make gmidrule
+end
+
+function YAMLvars.xfm.arr2tabular(var, val)
+ return pl.array2d.toTeX(val)..'\\\\'
+end
+
+
+function YAMLvars.xfm.arr2itemize(var, val)
+ return pl.List(val):map('\\item '.._1):join(' ')
+end
+
+
+function YAMLvars.xfm.arrsortAZ(var, val)
+ return pl.List(val):sort(pl.operator.strlt)
+end
+
+function YAMLvars.xfm.arrsortZA(var, val)
+ return pl.List(val):sort(pl.operator.strgt)
+end
+
+local function complastname(a, b)
+ a = a:split(' ')
+ b = b:split(' ')
+ a = a[#a]
+ b = b[#b]
+ return a < b
+end
+
+function YAMLvars.xfm.arrsortlastnameAZ(var, val)
+ val = pl.List(val):sort(complastname)
+ return val
+end
+
+function YAMLvars.xfm.list2nl(var, val)
+ val = pl.array2d.map_slice1(_1..'\\\\', val, 1,-2)
+ return table.concat(val, '')
+ --return pl.tablex.reduce(_1.._2, val, '')
+end
+
+function YAMLvars.xfm.lb2nl(var, val)
+ val, _ = val:gsub('\n','\\\\ ')
+ return val
+end
+
+function YAMLvars.xfm.lowercase(var, val)
+ return val:lower()
+end
+
+
+function YAMLvars.xfm.markdown(var, val)
+ --return '\\begin{markdown} '..val..'\n \\end{markdown}'
+ help_wrt(val, md)
+ return [[begin markdown ..val..
+
+ par end markdown]]
+end
+
+
+
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+-- prc functions (processing) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+function YAMLvars.prc.gdef(var, val)
+ token.set_macro(var, val, 'global')
+end
+
+function YAMLvars.prc.yvdef(var, val)
+ token.set_macro('yv--'..var, val, 'global')
+end
+
+function YAMLvars.prc.PDFtitle(var, val)
+ tex.print('\\hypersetup{pdftitle={'..val..'}}')
+ --tex.print('\\setPDFtitle{'..val..'}')
+end
+
+function YAMLvars.prc.PDFauthor(var, val)
+ tex.print('\\hypersetup{pdfauthor={'..val..'}}')
+ --tex.print('\\setPDFauthor{'..val..'}')
+end
+
+
+function YAMLvars.prc.setheader(val, rl)
+ local _, count = string.gsub(val, '\\\\', '')
+ if count == 0 then
+ val = '{\\ }\\\\'..val
+ end
+ val = '\\setstretch{0.8}'..val
+ tex.print('\\'..rl..'ohead{'..val..'}')
+end
+
+function YAMLvars.prc.rhead(var, val)
+ YAMLvars.prc.setheader(val, 'r')
+end
+
+function YAMLvars.prc.lhead(var, val)
+ YAMLvars.prc.setheader(val, 'l')
+end
+
+function YAMLvars.prc.title(var, val)
+ token.set_macro('@title', val, 'global')
+end
+
+function YAMLvars.prc.author(var, val)
+ token.set_macro('@author', val, 'global')
+end
+
+function YAMLvars.prc.date(var, val)
+ token.set_macro('@date', val, 'global')
+end
+
+
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+
+
+local function prvcmd(cs, val) -- provide command via lua
+ if token.is_defined(cs) then
+ tex.print('\\PackageError{YAMLvars}{Variable '..cs..' already defined, could not declare}{}')
+ else
+ token.set_macro(cs, val, 'global')
+ end
+end
+
+local function deccmd(cs, def)
+ if def == nil then
+ prvcmd(cs, '\\PackageError{YAMLvars}{Variable "'..cs..'" was declared and used but, not set}{}')
+ else
+ prvcmd(cs, def)
+ end
+end
+
+local function getYAMLfile(y)
+ local f = io.open(y,"r")
+ if f ~= nil then
+ y = f:read('*a')
+ io.close(f)
+ return y
+ else
+ tex.print('\\PackageError{YAMLvars}{YAML file "'..y..'" not found}{}')
+ return 'YAMLvars: FileNotFound'
+ end
+end
+
+
+function YAMLvars.declareYAMLvarsStr(y)
+ local t = YAMLvars.yaml.parse(y)
+ for var, specs in pairs(t) do
+ YAMLvars.varspecs[var] = {xfm=YAMLvars.xfrmDefault,prc=YAMLvars.prcDefault,dft=YAMLvars.dftDefault}
+ if type(specs) == 'string' then
+ specs = {xfm={specs}}
+ end
+ if specs['xfm'] == nil then specs['xfm'] = {} end
+ for s, p in pairs(specs) do
+ if s == 'xfm' and type(p) ~= 'table' then p = {p} end
+ YAMLvars.varspecs[var][s] = p -- set property of var
+ end
+ if YAMLvars.varspecs[var]['prc'] == 'gdef' then
+ deccmd(var, YAMLvars.varspecs[var]['dft'])
+ elseif YAMLvars.varspecs[var]['prc'] == 'yvdef' then
+ deccmd('yv--'..var, YAMLvars.varspecs[var]['dft'])
+ end
+ end
+end
+
+function YAMLvars.declareYAMLvarsFile(y)
+ YAMLvars.declareYAMLvarsStr(getYAMLfile(y))
+end
+
+function YAMLvars.parseYAMLvarsStr(y)
+ YAMLvars.varsvals = YAMLvars.yaml.parse(y)
+ for var, val in pairs(YAMLvars.varsvals) do
+ if YAMLvars.varspecs[var] == nil then
+ if YAMLvars.allowUndeclared then
+ if YAMLvars.prcDefault == 'yvdef' then
+ YAMLvars.prc.yvdef(var, val)
+ else
+ prvcmd(var, val)
+ end
+ else
+ tex.print('\\PackageError{YAMLvars}{Variable "'..var..'" set but not declared}{}')
+ end
+ else
+ --if string.sub(val, 1, 2) == '~' then -- todo
+ -- val = t[string.sub(val, 2, #val)] -- use other val
+ --end
+ for _, func in pairs(YAMLvars.varspecs[var]['xfm']) do --apply cleaning functions
+ local f = YAMLvars.xfm[func]
+ if f == nil then
+ tex.print('\\PackageWarning{YAMLvars}{xfm function "'..func..'" not defined, skipping}{}')
+ else
+ val = f(var, val)
+ end
+ end
+ f = YAMLvars.prc[YAMLvars.varspecs[var]['prc']]
+ if f == nil then
+ tex.print('\\PackageError{YAMLvars}{prc function "'..YAMLvars.varspecs[var]['prc']..'" not defined}{}')
+ end
+ f(var, val) -- prc the value of the variable
+ end
+ end
+end
+
+function YAMLvars.parseYAMLvarsFile(y)
+ YAMLvars.parseYAMLvarsStr(getYAMLfile(y))
+end
+
+
+
+function YAMLvars.print_varspecs()
+ local pretty = require('pl.pretty')
+ texio.write_nl('VVVVVV Var specifications:')
+ texio.write_nl(pretty.write(YAMLvars.varspecs))
+end
+
+
+
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+-- https://tex.stackexchange.com/questions/38150/in-lualatex-how-do-i-pass-the-content-of-an-environment-to-lua-verbatim
+recordedbuf = ""
+function readbuf(buf)
+ i,j = string.find(buf, '\\end{%w+}')
+ if i==nil then -- if not ending an environment
+ recordedbuf = recordedbuf .. buf .. "\n"
+ return ""
+ else
+ return nil
+ end
+end
+
+function startrecording()
+ recordedbuf = ""
+ luatexbase.add_to_callback('process_input_buffer', readbuf, 'readbuf')
+end
+
+function stoprecording()
+ luatexbase.remove_from_callback('process_input_buffer', 'readbuf')
+ recordedbuf = recordedbuf:gsub("\\end{%w+}\n","")
+end
+
+
+
+function YAMLvars.doYAMLfiles(t)
+ if #t == 2 then
+ YAMLvars.declareYAMLvarsFile(t[1])
+ YAMLvars.parseYAMLvarsFile(t[2])
+ elseif #t == 1 then
+ YAMLvars.parseYAMLvarsFile(t[1])
+ else
+ tex.print('\\PackageWarning{YAMLvars}{No .yaml files found in CLI args"}{}')
+ end
+end
+
+function YAMLvars.getYAMLcli()
+ local t = {}
+ if arg then
+ for i,v in pairs(arg) do
+ if v:find('.*%.yaml$') then
+ t[#t+1] = v
+ end
+ end
+ end
+ help_wrt(t)
+ return t
+ end
+
+
+return YAMLvars
+
+
+
+ --clean = clean or true
+ --if clean then -- clean first part of yaml string
+ -- y = clean_tex_spaces(y)
+ --end
+--local function clean_tex_spaces(s)
+-- help_wrt(s)
+-- if s:sub(1,2) == '%s' then
+-- s, _ = s:gsub('%s+','',1)
+-- end
+-- s, _ = s:gsub('\\par ','\n\n')
+-- return s
+--end \ No newline at end of file