luametalatex/luametalatex-firstcode.lua

180 lines
4.6 KiB
Lua

local functions = lua.getfunctionstable()
-- I am not sure why this is necessary, but otherwise LuaMetaTeX resets
-- the functions table every time the getter is called
function lua.get_functions_table() return functions end
local set_lua = token.set_lua
-- local new_luafunction = luatexbase.new_luafunction
local i=12342
local function new_luafunction(name)
i = i+1
return i
end
function token.luacmd(name, func, ...)
local idx = new_luafunction(name)
set_lua(name, idx, ...)
functions[idx] = func
end
local properties = node.get_properties_table()
-- setmetatable(node.direct.get_properties_table(), {
-- __index = function(t, id)
-- local new = {}
-- t[id] = new
-- return new
-- end
-- })
local whatsit_id = node.id'whatsit'
local whatsits = {
[0] = "open",
"write",
"close",
nil,
nil,
nil,
"save_pos",
"late_lua",
"user_defined",
nil,
nil,
nil,
nil,
nil,
nil,
nil,
"pdf_literal",
"pdf_refobj",
"pdf_annot",
"pdf_start_link",
"pdf_end_link",
"pdf_dest",
"pdf_action",
"pdf_thread",
"pdf_start_thread",
"pdf_end_thread",
"pdf_thread_data",
"pdf_link_data",
"pdf_colorstack",
"pdf_setmatrix",
"pdf_save",
"pdf_restore",
}
whatsits[whatsits[0]] = 0
for i = 0,#whatsits do
local v = whatsits[i]
if v then
whatsits[v] = i
end
end
function node.whatsits() return whatsits end
function node.subtype(s) return type(s) == "string" and whatsits[s] or nil end
local spacer_cmd, relax_cmd = token.command_id'spacer', token.command_id'relax'
local function scan_filename()
local name = {}
local quoted = false
local tok, cmd
repeat
tok = token.scan_token()
cmd = tok.command
until cmd ~= spacer_cmd and cmd ~= relax_cmd
while (tok.command <= 12 and tok.mode <= token.biggest_char()
or (token.put_next(tok) and false))
and (quoted or tok.mode ~= string.byte' ') do
if tok.mode == string.byte'"' then
quoted = not quoted
else
name[#name+1] = tok.mode
end
tok = token.scan_token()
end
return utf8.char(table.unpack(name))
end
local ofiles = {}
local function do_openout(p)
if ofiles[p.file] then
error[[Existing file]]
else
local msg
ofiles[p.file], msg = io.open(p.name, 'w')
if not ofiles[p.file] then
error(msg)
end
end
end
functions[39] = function(_, immediate) -- \openout
local file = token.scan_int()
token.scan_keyword'='
local name = scan_filename()
local props = {file = file, name = name, handle = do_openout}
if immediate == "immediate" then
do_openout(props)
else
local whatsit = node.new(whatsit_id, whatsits.open)
properties[whatsit] = props
node.write(whatsit)
end
end
local function do_closeout(p)
if ofiles[p.file] then
ofiles[p.file]:close()
ofiles[p.file] = nil
end
end
functions[40] = function(_, immediate) -- \closeout
local file = token.scan_int()
local props = {file = file, handle = do_closeout}
if immediate == "immediate" then
do_closeout(props)
else
local whatsit = node.new(whatsit_id, whatsits.close)
properties[whatsit] = props
node.write(whatsit)
end
end
local function do_write(p)
local content = token.to_string(p.data) .. '\n'
local file = ofiles[p.file]
if file then
file:write(content)
else
texio.write_nl(p.file < 0 and "log" or "term and log", content)
end
end
functions[41] = function(_, immediate) -- \write
local file = token.scan_int()
local content = token.scan_tokenlist()
local props = {file = file, data = content, handle = do_write}
if immediate == "immediate" then
do_write(props)
else
local whatsit = node.new(whatsit_id, whatsits.write)
properties[whatsit] = props
node.write(whatsit)
end
end
local lua_call_cmd = token.command_id'lua_call'
functions[42] = function() -- \immediate
local next_tok = token.scan_token()
if next_tok.command ~= lua_call_cmd then
return token.put_next(next_tok)
end
local function_id = next_tok.index
functions[function_id](function_id, 'immediate')
end
functions[43] = function() -- \pdfvariable
local name = token.scan_string()
print('Missing \\pdf' .. name)
end
token.set_lua("openout", 39, "protected")
token.set_lua("closeout", 40, "protected")
token.set_lua("write", 41, "protected")
write_tok = token.create'write'
token.set_lua("immediate", 42, "protected")
token.set_lua("pdfvariable", 43)
local prepared_code = lua.bytecode[1]
if prepared_code then
prepared_code()
prepared_code, lua.bytecode[1] = nil, nil
end
require'luametalatex-back-pdf'