T wo T r:main.lua
From LuaTeXWiki
--- Copyright (c) 2021 by Toadstone Enterprises. --- ISC-type license, see License.txt for details. ----------------------------------------------------------------- --- Why is this needed? local main = {} package.loaded[...] = main local util = require("utils") local link_nodes = util.link_nodes local make_glyph = util.make_glyph local make_glue = util.make_glue local make_penalty = util.make_penalty local is_whitespace = util.is_whitespace local is_linefeed = util.is_linefeed local is_nobreak = util.is_nobreak local copy_table = util.copy_table local read_line = util.read_line local reader = require("reader") local read_value = reader.read_value local format = require("format") local update_state = format.update_state local update_locals = format.update_locals local push_tbl = format.push_tbl local pop_tbl = format.pop_tbl local top_tbl = format.top_tbl local pop_do_command_stop = format.pop_do_command_stop local commands = commands or require("commands") local get_command = commands.get_command local initialize_command = commands.initialize_command local pages = pages or require("pages") local build_par = pages.build_par local process_par = pages.process_par ----------------------------------------------------------------- local do_char = function(value, head, tail) -- We are building the hlist that will be passed on to -- tex.linebreak for creating a paragraph. local tbl = top_tbl() local n = nil local p = nil -- for penalties if is_nobreak(value) then -- we treat all unbreakable whitespace equally p = make_penalty(10000) n = make_glue("spaceskip", tbl.space, tbl.space_stretch, tbl.space_shrink) elseif is_whitespace(value) then -- we treat all (breakable) whitespace equally n = make_glue("spaceskip", tbl.space, tbl.space_stretch, tbl.space_shrink) else -- presumably a glyph n = make_glyph(value, tbl.font, tbl.lang, tbl.lefthyphenmin, tbl.righthyphenmin) end if (head == nil) then -- starting a new paragraph, but we add the initial glue in -- build_par. head = n elseif p then -- We have a penalty link_nodes(tail, p, n) else -- only a single node link_nodes(tail, n) end -- n is our new tail return head, n end local reading_par = function(head, tail) -- before we start reading a paragraph, head and tail will be nil. return (node.is_node(head) and node.is_node(tail)) end main.main_loop = function() local head, tail, eat_the_white, eol_seen = update_locals() local value = read_value() while value do if value == unicode.utf8.byte("%") then -- Start of comment. Comment goes to the end of the line. read_line() elseif is_linefeed(value) then if (eol_seen and reading_par(head, tail)) then -- eol_seen ==> this is a blank line, -- reading_par(head, tail) ==> we are in the middle of a paragraph. -- Thus we avoid building 'empty' paragraphs. local par = build_par(head, tail) process_par(par) -- After we process the par, we reset head and tail to nil -- in preparation for the next paragraph to be read in. head = nil tail = nil elseif ((not eat_the_white) and reading_par(head, tail)) then -- (not eat_the_white) ==> this is the first bit of white space -- seen, -- reading_par(head, tail) ==> we are in the middle of a paragraph. -- Thus, we avoid starting a paragraph with white space. head, tail = do_char(value, head, tail) eat_the_white = true eol_seen = true end elseif is_whitespace(value) then if ((not eat_the_white) and reading_par(head, tail)) then -- (not eat_the_white) ==> this is the first bit of white space -- seen, -- reading_par(head, tail) ==> we are in the middle of a paragraph. -- Thus, we avoid starting a paragraph with white space. head, tail = do_char(value, head, tail) -- But we do not set eol_seen to false. Thus an "empty" line can -- contain white space. eat_the_white = true end elseif value == unicode.utf8.byte("\\") then -- get the command, and initialize it command = get_command() update_state(head, tail, false, false) initialize_command(command) -- initialize_command may hace done some stuff, resetting -- head, tail, eat_the_white, and eol_seen so we reset them here. head, tail, eat_the_white, eol_seen = update_locals() elseif value == unicode.utf8.byte("{") then -- enter a group or start a command update_state(head, tail, false , false) local do_command_start = State.do_command_start if do_command_start then -- We have a command, but before executing it, we reset -- State.do_command_start so that we do not get into a loop. State.do_command_start = nil do_command_start() head, tail, eat_the_white, eol_seen = update_locals() else -- enter a group. push_tbl(copy_table(top_tbl())) end elseif value == unicode.utf8.byte("}") then -- leave a group or stop a command local do_command_stop = pop_do_command_stop() if do_command_stop then update_state(head, tail, false, false) do_command_stop() head, tail, eat_the_white, eol_seen = update_locals() else pop_tbl() end else -- presumably a glyph eat_the_white = false eol_seen = false head, tail = do_char(value, head, tail) end value = read_value() end -- while (value) do if reading_par(head, tail) then -- eof, and we may have a par to build. if reading_par(head, tail) then local par = build_par(head, tail) process_par(par) end end update_state(nil, nil, false, false) -- Check for unpopped tbls or do_command_stops? end return main