|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- http://angg.twu.net/dednat6/dednat6/output.lua
-- http://angg.twu.net/dednat6/dednat6/output.lua.html
-- (find-angg "dednat6/dednat6/output.lua")
-- By Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2021jun06
--
-- Sending (Lua-produced) TeX code back to the TeX interpreter requires
-- some preprocessing... see:
-- (find-es "luatex" "comments-in-tex.print")
-- (find-es "luatex" "spurious-omega")
--
-- Usage:
-- \catcode`\^^J=10 % (find-es "luatex" "spurious-omega")
-- \directlua{output = mytexprint}
-- \directlua{output = printboth}
-- or: (...)
-- «.deletecomments_2015» (to "deletecomments_2015")
-- «.deletecomments_2019» (to "deletecomments_2019")
-- «.deletecomments_2019-tests» (to "deletecomments_2019-tests")
-- «.DeleteComments» (to "DeleteComments")
-- «.Deletecomments-class» (to "Deletecomments-class")
-- «.DeleteComments-tests» (to "DeleteComments-tests")
-- «.deletecomments_2021» (to "deletecomments_2021")
-- «.deletecomments» (to "deletecomments")
-- «.output» (to "output")
-- «.output_dnt» (to "output_dnt")
-- «.write_dnt_file» (to "write_dnt_file")
-- «.write_single_tex_file» (to "write_single_tex_file")
-- «.formatt» (to "formatt")
-- «.bprintt» (to "bprintt")
-- _ _ _ _
-- __| | ___| | ___| |_ ___ ___ ___ _ __ ___ _ __ ___ ___ _ __ | |_ ___
-- / _` |/ _ \ |/ _ \ __/ _ \/ __/ _ \| '_ ` _ \| '_ ` _ \ / _ \ '_ \| __/ __|
-- | (_| | __/ | __/ || __/ (_| (_) | | | | | | | | | | | __/ | | | |_\__ \
-- \__,_|\___|_|\___|\__\___|\___\___/|_| |_| |_|_| |_| |_|\___|_| |_|\__|___/
--
-- «deletecomments_2015» (to ".deletecomments_2015")
-- See: (find-es "luatex" "comments-in-tex.print")
deletecomments_2015 = function (str)
return (str:gsub("%%[^%%\n]*\n[ \t]*", ""))
end
-- «deletecomments_2019» (to ".deletecomments_2019")
-- The version below (from 2019apr29) is a bit better than
-- deletecomments_2015 but still not very smart. It converts each
-- line made of blank spaces followed by something like "%this" to a
-- line made of just the blank spaces, and it treats the "%bar" in a
-- line like "foo\%bar" as comment, and converts that to "foo\".
--
deletecomments1 = function (line)
return line:match"^([^%%]*)"
end
deletecomments_2019 = function (bigstr)
return (bigstr:gsub("([^\n]+)", deletecomments1))
end
-- «deletecomments_2019-tests» (to ".deletecomments_2019-tests")
--[[
• (eepitch-lua51)
• (eepitch-kill)
• (eepitch-lua51)
dofile "output.lua"
-- Good:
= deletecomments_2019 "a % b % c"
= deletecomments_2019 "a % b % c\nd \\% e % f"
-- Bad:
= deletecomments_2019 "foo\\%bar"
= deletecomments_2019 "foo\n %bar\n %plic\n bletch"
--]]
-- «DeleteComments» (to ".DeleteComments")
-- «Deletecomments-class» (to ".Deletecomments-class")
-- New (2021jun05): the class DeleteComments implements a way to
-- delete comments that TRIES to simulate what TeX does. The TeXBook
-- explains in its pages 46-47 that the "eyes" and "mouth" of TeX
-- enter the "State S" (for "skipping blanks") after a "%"; we
-- simulate that by splitting bigstr in a certain way, and then after
-- each "%" we delete the "%..." part of that line plus the
-- whitespaces and newlines in (hopefully) the right places.
--
-- This version doesn't treat backslashes followed by "%"s in the
-- right way. This is still to be done.
--
-- See: (find-es "tex" "comments")
-- (find-es "tex" "comments" "Skipping blanks")
--
DeleteComments = Class {
type = "DeleteComments",
split = function (bigstr)
local A = {}
for _,li in ipairs(splitlines(bigstr)) do
local a,b = li:match("^([^%%]*)(.*)")
table.insert(A, {a, b, "\n"})
end
return DeleteComments(A)
end,
from = function (bigstr)
return DeleteComments.split(bigstr):delcomments():concat()
end,
__tostring = function (dc) return mytabletostring(dc) end,
__index = {
hascomment = function (dc, k) return dc[k][2] ~= "" end,
endswithcmd = function (dc, k)
return dc[k][1]:reverse():match("^[A-Za-z]+\\")
end,
addspaceaftercmd = function (dc, k)
dc[k][1] = dc[k][1].." "
end,
valid = function (dc, k) return 1 <= k and k <= #dc end,
ltrim = function (dc, k)
dc[k][1] = dc[k][1]:match("^[ \t]*(.*)")
end,
delcomment = function (dc, k)
if dc:endswithcmd(k) then dc:addspaceaftercmd(k) end
dc[k][2] = "" -- delete the "%..."
dc[k][3] = "" -- delete the newline
if dc:valid(k+1) then dc:ltrim(k+1) end
end,
delcomments = function (dc)
for k=1,#dc do if dc:hascomment(k) then dc:delcomment(k) end end
return dc
end,
concat = function (dc)
local bigstr = ""
for k=1,#dc-1 do bigstr = bigstr..dc[k][1]..dc[k][2]..dc[k][3] end
if #dc > 0 then bigstr = bigstr..dc[#dc][1]..dc[#dc][2] end
return bigstr
end,
},
}
-- «DeleteComments-tests» (to ".DeleteComments-tests")
-- (find-es "dednat" "deletecomments-2021")
--[==[
• (eepitch-lua51)
• (eepitch-kill)
• (eepitch-lua51)
dofile "output.lua"
bigstr = [[
foo%12
bar\plic%34
qoo%56
blep
bletch
%
woo
]]
dc = DeleteComments.split(bigstr)
= dc
= dc:delcomments()
= dc:concat()
= bigstr
= deletecomments_2019(bigstr)
= deletecomments_2021(bigstr)
--]==]
-- «deletecomments_2021» (to ".deletecomments_2021")
deletecomments_2021 = function (bigstr)
return DeleteComments.from(bigstr)
end
-- «deletecomments» (to ".deletecomments")
-- The default is to use deletecomments_2021.
deletecomments = deletecomments_2021
-- See: (to "write_dnt_file")
dnt_log = ""
-- _ _
-- ___ _ _| |_ _ __ _ _| |_
-- / _ \| | | | __| '_ \| | | | __|
-- | (_) | |_| | |_| |_) | |_| | |_
-- \___/ \__,_|\__| .__/ \__,_|\__|
-- |_|
--
-- «output» (to ".output")
-- `output(str)' is the main way to send TeX code from dednat6 to TeX.
-- The TUGBoat article explains this briefly in sec.3.1. See:
--
-- https://tug.org/TUGboat/tb39-3/tb123ochs-dednat.pdf
-- http://angg.twu.net/dednat6/tugboat-rev2.pdf
--
-- The article says:
--
-- We saw in sections 1 and 2.2 that the "output" of
-- a %:-block is a series of `\defded's and the "output"
-- of a %D-block is a series of `\defdiags's. We can
-- generalize this. For example, the "output" of
--
-- %L output [[\def\Foo{FOO}]]
-- %L output [[\def\Bar{BAR}]]
--
-- is:
--
-- \def\Foo{FOO}
-- \def\Bar{BAR}
--
-- The default behavior of `output(str)' is `output_verbose(str)',
-- that:
--
-- 1) runs tex.print(deletecomments(str)),
-- 2) appends str (with comments!) to dnt_log,
-- 3) prints the current value of tf.nline to stdout,
-- 4) prints str (with comments!) to stdout.
--
-- I always check the output of running `lualatex foo.tex' to see if
-- there were any errors. If there weren't any errors, one of the last
-- lines of the output will be something like
--
-- Output written on foo.pdf (42 pages, 1234567 bytes).
--
-- Making `output(str)' print to stdout means that all TeX code that
-- dednat6 produces is shown in the output of `lualatex foo.tex'; I
-- find that this helps debugging.
-- «output_dnt» (to ".output_dnt")
-- (find-es "dednat" "output_dnt")
output_dnt = function (str)
dnt_log = dnt_log..str.."\n"
end
output_quiet = function (str)
tex.print(deletecomments(str))
output_dnt(str)
end
output_verbose = function (str)
print("% Running the \\pu at line "..tf.nline)
output_quiet(str)
print(str)
end
output = output_verbose
quiet = function () output = output_quiet end
verbose = function () output = output_verbose end
-- _ _ _ _ __ _ _
-- __ ___ __(_) |_ ___ __| |_ __ | |_ / _(_) | ___
-- \ \ /\ / / '__| | __/ _ \ / _` | '_ \| __| | |_| | |/ _ \
-- \ V V /| | | | || __/ | (_| | | | | |_ | _| | | __/
-- \_/\_/ |_| |_|\__\___|___\__,_|_| |_|\__|___|_| |_|_|\___|
-- |_____| |_____|
--
-- «write_dnt_file» (to ".write_dnt_file")
-- Use this to _sort of_ emulate the behavior of dednat4.
-- See: http://angg.twu.net/dednat6.html#no-lua
-- (find-LATEX "dednat6load.lua")
-- (find-dn6 "options6.lua")
-- (find-dn6file "options6.lua" "dooptions_t =")
-- The name of the current .tex file is stored in texlines.name:
-- (find-dn6 "block.lua" "texfile0")
-- (find-dn6 "block.lua" "TexLines")
-- (find-dn6 "block.lua" "TexLines" "read =")
--
write_dnt_file = function (fname)
fname = fname or texlines.name:gsub("%.tex$", "")..".dnt"
print("% Writing: "..fname)
writefile(fname, dnt_log)
end
-- _ _ _ _
-- __ ___ __(_) |_ ___ ___(_)_ __ __ _| | ___
-- \ \ /\ / / '__| | __/ _ \ / __| | '_ \ / _` | |/ _ \
-- \ V V /| | | | || __/ \__ \ | | | | (_| | | __/
-- \_/\_/ |_| |_|\__\___|___|___/_|_| |_|\__, |_|\___|
-- |_____| |___/
--
-- «write_single_tex_file» (to ".write_single_tex_file")
-- Experimental, 2019aug16
write_single_tex_file__pat = "^(.-\n)(%s*)(\\input\\jobname.dnt[^\n]*\n)(.*)$"
write_single_tex_file = function (fname_out)
local fname_in = status.filename
local bigstr_in = ee_readfile(fname_in)
local a,spaces,inputdnt,b = bigstr_in:match(write_single_tex_file__pat)
local header = format("%% Generated from %s\n"..
"%% using write_single_tex_file(\"%s\")\n%%\n",
fname_in, fname_out)
local bigstr_out = header..a..spaces.."% "..inputdnt..dnt_log.."\n"..b
print("% Writing: "..fname_out)
ee_writefile(fname_out, bigstr_out)
end
-- I don't use the functions below this point much...
-- I only use them to generate code for pict2e.
-- «formatt» (to ".formatt")
-- (find-es "lua5" "formatt-and-printt")
formatt = function (...)
local A = {...}
for i=1,#A do if type(A[i]=="table") then A[i] = tostring(A[i]) end end
return format(unpack(A))
end
printt = function (...) print(formatt(...)) end
outputt = function (...) output(formatt(...)) end
--[[
• (eepitch-lua51)
• (eepitch-kill)
• (eepitch-lua51)
dofile "output.lua"
dofile "picture.lua"
p, q = v(3,4), v(5,6)
= formatt("%s--%s", p, q) --> (3,4)--(5,6)
--]]
-- «bprintt» (to ".bprintt")
-- Usage in the REPL:
-- bprint, out = makebprint("verbose")
-- bprint("%s--%s", v(2,3), v(4,5))
-- bprint("%s--%s", v(20,30), v(40,50))
-- = out()
-- Usage in a function:
-- local bprint, out = makebprint()
-- bprint("%s--%s", v(2,3), v(4,5))
-- bprint("%s--%s", v(20,30), v(40,50))
-- return out()
makebprint = function (verbose)
local buffer = {}
local bprint = function (...) table.insert(buffer, formatt(...)) end
local out = function () return table.concat(buffer, "\n") end
if verbose then
local bprint0 = bprint
bprint = function (...) printt(...); bprint0(...) end
end
return bprint, out, buffer
end
-- Local Variables:
-- coding: utf-8-unix
-- End: