From 923b11eb46c4e3930c540a249e6320704a54294d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 14 Feb 2023 16:29:47 +0300 Subject: [PATCH 001/357] fix(inputters): Correct typo in SIL parser, disallow conflicting commands --- inputters/sil.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inputters/sil.lua b/inputters/sil.lua index 32055535d..ac222b1a7 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -62,7 +62,7 @@ function inputter._grammar (_ENV) return str:gsub('\\([{}%%\\])', '%1') end local myID = C(bits.silidentifier) / 1 - local cmdID = myID - P"beign" - P"end" + local cmdID = myID - P"begin" - P"end" local wrapper = function (a) return type(a)=="table" and a or {} end local parameters = (P"[" * bits.parameters * P"]")^-1 / wrapper local comment = ( From 9054f6d6eb2db5d9a86e9c4156959cc414daf5b6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 14 Feb 2023 16:51:23 +0300 Subject: [PATCH 002/357] refactor(inputters): Redo labels used in grammer, esp. drop obsolete 'texlike_' prefix --- core/sile.lua | 4 +-- core/utilities.lua | 2 +- inputters/sil.lua | 52 +++++++++++++++++++-------------------- packages/autodoc/init.lua | 4 +-- packages/math/texlike.lua | 6 ++--- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 6e54d3662..02a839163 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -230,9 +230,9 @@ SILE.process = function (ast) content() elseif SILE.Commands[content.command] then SILE.call(content.command, content.options, content) - elseif content.id == "texlike_stuff" + elseif content.id == "content" or (not content.command and not content.id) then - local pId = SILE.traceStack:pushContent(content, "texlike_stuff") + local pId = SILE.traceStack:pushContent(content, "content") SILE.process(content) SILE.traceStack:pop(pId) elseif type(content) ~= "nil" then diff --git a/core/utilities.lua b/core/utilities.lua index 8b491942b..13ae16b56 100644 --- a/core/utilities.lua +++ b/core/utilities.lua @@ -142,7 +142,7 @@ utilities.debugAST = function (ast, level) return out .. "\\" .. content.command .. " " .. pl.pretty.write(content.options, "") end) if (#content>=1) then utilities.debugAST(content, level+1) end - elseif content.id == "texlike_stuff" or (not content.command and not content.id) then + elseif content.id == "content" or (not content.command and not content.id) then utilities.debugAST(content, level+1) else SU.debug("ast", function () diff --git a/inputters/sil.lua b/inputters/sil.lua index ac222b1a7..9e4e66902 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -72,34 +72,34 @@ function inputter._grammar (_ENV) ) / "" START "document" - document = V"texlike_stuff" * EOF"Unexpected character at end of input" - texlike_stuff = Cg( + document = V"content" * EOF"Unexpected character at end of input" + content = Cg( V"environment" + comment + - V"texlike_text" + - V"texlike_braced_stuff" + - V"texlike_command" + V"text" + + V"braced_content" + + V"command" )^0 - passthrough_stuff = C(Cg( + passthrough_content = C(Cg( V"passthrough_text" + - V"passthrough_debraced_stuff" + V"debraced_passthrough_text" )^0) - passthrough_env_stuff = Cg( - V"passthrough_env_text" + env_passthrough_content = Cg( + V"env_passthrough_text" )^0 - texlike_text = C((1 - specials + escaped_specials)^1) / unescapeSpecials + text = C((1 - specials + escaped_specials)^1) / unescapeSpecials passthrough_text = C((1-S("{}"))^1) - passthrough_env_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1) - texlike_braced_stuff = P"{" * V"texlike_stuff" * ( P"}" + E("} expected") ) - passthrough_braced_stuff = P"{" * V"passthrough_stuff" * ( P"}" + E("} expected") ) - passthrough_debraced_stuff = C(V"passthrough_braced_stuff") - texlike_command = ( + env_passthrough_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1) + braced_content = P"{" * V"content" * ( P"}" + E("} expected") ) + braced_passthrough_content = P"{" * V"passthrough_content" * ( P"}" + E("} expected") ) + debraced_passthrough_text = C(V"braced_passthrough_content") + command = ( P"\\" * Cg(cmdID, "command") * Cg(parameters, "options") * ( - (Cmt(Cb"command", isPassthrough) * V"passthrough_braced_stuff") + - (Cmt(Cb"command", isNotPassthrough) * V"texlike_braced_stuff") + (Cmt(Cb"command", isPassthrough) * V"braced_passthrough_content") + + (Cmt(Cb"command", isNotPassthrough) * V"braced_content") )^0 ) local notpass_end = @@ -117,8 +117,8 @@ function inputter._grammar (_ENV) Cg(cmdID, "command") * P"}" * ( - (Cmt(Cb"command", isPassthrough) * V"passthrough_env_stuff" * pass_end) + - (Cmt(Cb"command", isNotPassthrough) * V"texlike_stuff" * notpass_end) + (Cmt(Cb"command", isPassthrough) * V"env_passthrough_content" * pass_end) + + (Cmt(Cb"command", isNotPassthrough) * V"content" * notpass_end) ) end -- luacheck: pop @@ -168,21 +168,21 @@ local function massage_ast (tree, doc) tree.lno, tree.col = getline(doc, tree.pos) end if tree.id == "document" - or tree.id == "texlike_braced_stuff" - or tree.id == "passthrough_stuff" - or tree.id == "passthrough_braced_stuff" - or tree.id == "passthrough_env_stuff" + or tree.id == "braced_content" + or tree.id == "passthrough_content" + or tree.id == "braced_passthrough_content" + or tree.id == "env_passthrough_content" then return massage_ast(tree[1], doc) end - if tree.id == "texlike_text" + if tree.id == "text" or tree.id == "passthrough_text" - or tree.id == "passthrough_env_text" + or tree.id == "env_passthrough_text" then return tree[1] end for key, val in ipairs(tree) do - if val.id == "texlike_stuff" then + if val.id == "content" then SU.splice(tree, key, key, massage_ast(val, doc)) else tree[key] = massage_ast(val, doc) diff --git a/packages/autodoc/init.lua b/packages/autodoc/init.lua index 75f31a9c1..dbeb2d593 100644 --- a/packages/autodoc/init.lua +++ b/packages/autodoc/init.lua @@ -86,10 +86,10 @@ local function typesetAST (options, content) else seenCommandWithoutArg = true end - elseif ast.id == "texlike_stuff" or (not ast.command and not ast.id) then + elseif ast.id == "content" or (not ast.command and not ast.id) then -- Due to the way it is implemented, the SILE-inputter may generate such -- nodes in the AST. It's poorly documented, so it's not clear why they - -- are even kept there (esp. the "texlike_stuff" nodes), but anyhow, as + -- are even kept there (esp. the "content" nodes), but anyhow, as -- far as autodoc is concerned for presentation purposes, just -- recurse into them. typesetAST(options, ast) diff --git a/packages/math/texlike.lua b/packages/math/texlike.lua index edc5fee4d..6f4fc67f2 100644 --- a/packages/math/texlike.lua +++ b/packages/math/texlike.lua @@ -86,8 +86,8 @@ local mathGrammar = function (_ENV) return table.unpack(t) end - START "texlike_math" - texlike_math = V"mathlist" * EOF"Unexpected character at end of math code" + START "math" + math = V"mathlist" * EOF"Unexpected character at end of math code" mathlist = (comment + (WS * _) + element)^0 supsub = element_no_infix * _ * P"^" * _ * element_no_infix * _ * P"_" * _ * element_no_infix @@ -254,7 +254,7 @@ local function compileToMathML_aux (_, arg_env, tree) return accumulator end tree = fold_pairs(compile_and_insert, tree) - if tree.id == "texlike_math" then + if tree.id == "math" then tree.command = "math" -- If the outermost `mrow` contains only other `mrow`s, remove it -- (allowing vertical stacking). From 5f462836f20f83d7900d3420af6fe8a10bd332ab Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Thu, 17 Nov 2022 16:55:35 +0100 Subject: [PATCH 003/357] chore(classes): Remove obsolete/broken native markdown class --- Makefile.am | 2 +- classes/markdown.lua | 70 -- lua-libraries/LICENSE-lunamark | 20 - lua-libraries/lunamark.lua | 94 -- lua-libraries/lunamark/entities.lua | 282 ----- lua-libraries/lunamark/reader.lua | 20 - lua-libraries/lunamark/reader/markdown.lua | 1172 -------------------- lua-libraries/lunamark/util.lua | 228 ---- lua-libraries/lunamark/writer.lua | 20 - lua-libraries/lunamark/writer/ast.lua | 73 -- lua-libraries/lunamark/writer/context.lua | 194 ---- lua-libraries/lunamark/writer/docbook.lua | 152 --- lua-libraries/lunamark/writer/dzslides.lua | 368 ------ lua-libraries/lunamark/writer/generic.lua | 294 ----- lua-libraries/lunamark/writer/groff.lua | 81 -- lua-libraries/lunamark/writer/html.lua | 191 ---- lua-libraries/lunamark/writer/html5.lua | 37 - lua-libraries/lunamark/writer/latex.lua | 260 ----- lua-libraries/lunamark/writer/man.lua | 130 --- lua-libraries/lunamark/writer/tex.lua | 89 -- lua-libraries/lunamark/writer/xml.lua | 60 - sile.1.in | 2 +- 22 files changed, 2 insertions(+), 3837 deletions(-) delete mode 100644 classes/markdown.lua delete mode 100644 lua-libraries/LICENSE-lunamark delete mode 100644 lua-libraries/lunamark.lua delete mode 100644 lua-libraries/lunamark/entities.lua delete mode 100644 lua-libraries/lunamark/reader.lua delete mode 100644 lua-libraries/lunamark/reader/markdown.lua delete mode 100644 lua-libraries/lunamark/util.lua delete mode 100644 lua-libraries/lunamark/writer.lua delete mode 100644 lua-libraries/lunamark/writer/ast.lua delete mode 100644 lua-libraries/lunamark/writer/context.lua delete mode 100644 lua-libraries/lunamark/writer/docbook.lua delete mode 100644 lua-libraries/lunamark/writer/dzslides.lua delete mode 100644 lua-libraries/lunamark/writer/generic.lua delete mode 100644 lua-libraries/lunamark/writer/groff.lua delete mode 100644 lua-libraries/lunamark/writer/html.lua delete mode 100644 lua-libraries/lunamark/writer/html5.lua delete mode 100644 lua-libraries/lunamark/writer/latex.lua delete mode 100644 lua-libraries/lunamark/writer/man.lua delete mode 100644 lua-libraries/lunamark/writer/tex.lua delete mode 100644 lua-libraries/lunamark/writer/xml.lua diff --git a/Makefile.am b/Makefile.am index 5ffe5aac6..34d1d5387 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,7 +54,7 @@ nobase_nodist_pkgdata_DATA = core/features.lua core/version.lua $(LUAMODULES) dist_man_MANS = sile.1 dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) -dist_license_DATA = LICENSE lua-libraries/LICENSE-lunamark +dist_license_DATA = LICENSE bin_SCRIPTS = sile EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles diff --git a/classes/markdown.lua b/classes/markdown.lua deleted file mode 100644 index e2a997e73..000000000 --- a/classes/markdown.lua +++ /dev/null @@ -1,70 +0,0 @@ --- You will need my lunamark fork from https://github.com/simoncozens/lunamark --- for the AST writer. - -local book = require("classes.book") -local class = pl.class(book) -class._name = "markdown" - -SILE.inputs.markdown = { - order = 2, - appropriate = function (fn, _) - return fn:match("md$") or fn:match("markdown$") - end, - process = function (data) - local lunamark = require("lunamark") - local reader = lunamark.reader.markdown - local writer = lunamark.writer.ast.new() - local parse = reader.new(writer) - local t = parse(data) - t = { [1] = t, id = "document", options = { class = "markdown" }} - -- SILE.inputs.common.init(fn, t) - SILE.process(t[1]) - end -} - -function class:_init (options) - book._init(self, options) - self:loadPackage("url") - self:loadPackage("image") -end - -function class:registerCommands () - - book.registerCommands(self) - - self:registerCommand("sect1", function (options, content) - SILE.call("chapter", options, content) - end) - - self:registerCommand("sect2", function (options, content) - SILE.call("section", options, content) - end) - - self:registerCommand("sect3", function (options, content) - SILE.call("subsection", options, content) - end) - - self:registerCommand("emphasis", function (options, content) - SILE.call("em", options, content) - end) - - self:registerCommand("paragraph", function (_, content) - SILE.process(content) - SILE.call("par") - end) - - self:registerCommand("bulletlist", function (_, content) - SILE.process(content) - end) - - self:registerCommand("link", function (_, content) - SILE.call("verbatim:font", {}, content) - end) - - self:registerCommand("image", function (_, content) - SILE.call("img", {src=content.src}) - end) - -end - -return class diff --git a/lua-libraries/LICENSE-lunamark b/lua-libraries/LICENSE-lunamark deleted file mode 100644 index 48d92db43..000000000 --- a/lua-libraries/LICENSE-lunamark +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2009-2016 John MacFarlane - -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. \ No newline at end of file diff --git a/lua-libraries/lunamark.lua b/lua-libraries/lunamark.lua deleted file mode 100644 index cf8344ece..000000000 --- a/lua-libraries/lunamark.lua +++ /dev/null @@ -1,94 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Copyright © 2009-2011 John MacFarlane. --- --- Released under the MIT license (see LICENSE in the source for details). --- --- ## Description --- --- Lunamark is a lua library for conversion of markdown to --- other textual formats. Currently HTML, Docbook, ConTeXt, --- LaTeX, and Groff man are the supported output formats, --- but lunamark's modular architecture makes it easy to add --- writers and modify the markdown parser (written with a PEG --- grammar). --- --- Lunamark's markdown parser currently supports the following --- extensions (which can be turned on or off individually): --- --- - Smart typography (fancy quotes, dashes, ellipses) --- - Significant start numbers in ordered lists --- - Footnotes --- - Definition lists --- --- More extensions will be supported in later versions. --- --- The library is as portable as lua and has very good performance. --- It is about as fast as the author's own C library --- [peg-markdown](http://github.com/jgm/peg-markdown). --- --- ## Simple usage example --- --- local lunamark = require("lunamark") --- local writer = lunamark.writer.html.new() --- local parse = lunamark.reader.markdown.new(writer, { smart = true }) --- local result, metadata = parse("Here's 'my *text*'...") --- print(result) --- assert(result == 'Here’s ‘my text’…') --- --- ## Customizing the writer --- --- Render emphasized text using `` tags rather than ``. --- --- local unicode = require("unicode") --- function writer.emphasis(s) --- return {"",s,""} --- end --- local parse = lunamark.reader.markdown.new(writer, { smart = true }) --- local result, metadata = parse("*Beiß* nicht in die Hand, die dich *füttert*.") --- print(result) --- assert(result == 'Beiß nicht in die Hand, die dich füttert.') --- --- Eliminate hyperlinks: --- --- function writer.link(lab,url,tit) --- return lab --- end --- local parse = lunamark.reader.markdown.new(writer, { smart = true }) --- local result, metadata = parse("[hi](/url) there") --- print(result) --- assert(result == 'hi there') --- --- ## Customizing the parser --- --- Parse CamelCase words as wikilinks: --- --- lpeg = require("lpeg") --- local writer = lunamark.writer.html.new() --- function add_wikilinks(syntax) --- local capword = lpeg.R("AZ")^1 * lpeg.R("az")^1 --- local parse_wikilink = lpeg.C(capword^2) --- / function(wikipage) --- return writer.link(writer.string(wikipage), --- "/" .. wikipage, --- "Go to " .. wikipage) --- end --- syntax.Inline = parse_wikilink + syntax.Inline --- return syntax --- end --- local parse = lunamark.reader.markdown.new(writer, { alter_syntax = add_wikilinks }) --- local result, metadata = parse("My text with WikiLinks.\n") --- print(result) --- assert(result == 'My text with WikiLinks.') --- - -local G = {} - -setmetatable(G,{ __index = function(t,name) - local mod = require("lunamark." .. name) - rawset(t,name,mod) - return t[name] - end }) - -return G diff --git a/lua-libraries/lunamark/entities.lua b/lua-libraries/lunamark/entities.lua deleted file mode 100644 index 420d8b0c7..000000000 --- a/lua-libraries/lunamark/entities.lua +++ /dev/null @@ -1,282 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Functions for dealing with HTML/XML entities. - -local M = {} - -local luautf8=require("lua-utf8") -utf8_char = luautf8.char - -local character_entities = { - ["quot"] = 0x0022, - ["amp"] = 0x0026, - ["apos"] = 0x0027, - ["lt"] = 0x003C, - ["gt"] = 0x003E, - ["nbsp"] = 160, - ["iexcl"] = 0x00A1, - ["cent"] = 0x00A2, - ["pound"] = 0x00A3, - ["curren"] = 0x00A4, - ["yen"] = 0x00A5, - ["brvbar"] = 0x00A6, - ["sect"] = 0x00A7, - ["uml"] = 0x00A8, - ["copy"] = 0x00A9, - ["ordf"] = 0x00AA, - ["laquo"] = 0x00AB, - ["not"] = 0x00AC, - ["shy"] = 173, - ["reg"] = 0x00AE, - ["macr"] = 0x00AF, - ["deg"] = 0x00B0, - ["plusmn"] = 0x00B1, - ["sup2"] = 0x00B2, - ["sup3"] = 0x00B3, - ["acute"] = 0x00B4, - ["micro"] = 0x00B5, - ["para"] = 0x00B6, - ["middot"] = 0x00B7, - ["cedil"] = 0x00B8, - ["sup1"] = 0x00B9, - ["ordm"] = 0x00BA, - ["raquo"] = 0x00BB, - ["frac14"] = 0x00BC, - ["frac12"] = 0x00BD, - ["frac34"] = 0x00BE, - ["iquest"] = 0x00BF, - ["Agrave"] = 0x00C0, - ["Aacute"] = 0x00C1, - ["Acirc"] = 0x00C2, - ["Atilde"] = 0x00C3, - ["Auml"] = 0x00C4, - ["Aring"] = 0x00C5, - ["AElig"] = 0x00C6, - ["Ccedil"] = 0x00C7, - ["Egrave"] = 0x00C8, - ["Eacute"] = 0x00C9, - ["Ecirc"] = 0x00CA, - ["Euml"] = 0x00CB, - ["Igrave"] = 0x00CC, - ["Iacute"] = 0x00CD, - ["Icirc"] = 0x00CE, - ["Iuml"] = 0x00CF, - ["ETH"] = 0x00D0, - ["Ntilde"] = 0x00D1, - ["Ograve"] = 0x00D2, - ["Oacute"] = 0x00D3, - ["Ocirc"] = 0x00D4, - ["Otilde"] = 0x00D5, - ["Ouml"] = 0x00D6, - ["times"] = 0x00D7, - ["Oslash"] = 0x00D8, - ["Ugrave"] = 0x00D9, - ["Uacute"] = 0x00DA, - ["Ucirc"] = 0x00DB, - ["Uuml"] = 0x00DC, - ["Yacute"] = 0x00DD, - ["THORN"] = 0x00DE, - ["szlig"] = 0x00DF, - ["agrave"] = 0x00E0, - ["aacute"] = 0x00E1, - ["acirc"] = 0x00E2, - ["atilde"] = 0x00E3, - ["auml"] = 0x00E4, - ["aring"] = 0x00E5, - ["aelig"] = 0x00E6, - ["ccedil"] = 0x00E7, - ["egrave"] = 0x00E8, - ["eacute"] = 0x00E9, - ["ecirc"] = 0x00EA, - ["euml"] = 0x00EB, - ["igrave"] = 0x00EC, - ["iacute"] = 0x00ED, - ["icirc"] = 0x00EE, - ["iuml"] = 0x00EF, - ["eth"] = 0x00F0, - ["ntilde"] = 0x00F1, - ["ograve"] = 0x00F2, - ["oacute"] = 0x00F3, - ["ocirc"] = 0x00F4, - ["otilde"] = 0x00F5, - ["ouml"] = 0x00F6, - ["divide"] = 0x00F7, - ["oslash"] = 0x00F8, - ["ugrave"] = 0x00F9, - ["uacute"] = 0x00FA, - ["ucirc"] = 0x00FB, - ["uuml"] = 0x00FC, - ["yacute"] = 0x00FD, - ["thorn"] = 0x00FE, - ["yuml"] = 0x00FF, - ["OElig"] = 0x0152, - ["oelig"] = 0x0153, - ["Scaron"] = 0x0160, - ["scaron"] = 0x0161, - ["Yuml"] = 0x0178, - ["fnof"] = 0x0192, - ["circ"] = 0x02C6, - ["tilde"] = 0x02DC, - ["Alpha"] = 0x0391, - ["Beta"] = 0x0392, - ["Gamma"] = 0x0393, - ["Delta"] = 0x0394, - ["Epsilon"] = 0x0395, - ["Zeta"] = 0x0396, - ["Eta"] = 0x0397, - ["Theta"] = 0x0398, - ["Iota"] = 0x0399, - ["Kappa"] = 0x039A, - ["Lambda"] = 0x039B, - ["Mu"] = 0x039C, - ["Nu"] = 0x039D, - ["Xi"] = 0x039E, - ["Omicron"] = 0x039F, - ["Pi"] = 0x03A0, - ["Rho"] = 0x03A1, - ["Sigma"] = 0x03A3, - ["Tau"] = 0x03A4, - ["Upsilon"] = 0x03A5, - ["Phi"] = 0x03A6, - ["Chi"] = 0x03A7, - ["Psi"] = 0x03A8, - ["Omega"] = 0x03A9, - ["alpha"] = 0x03B1, - ["beta"] = 0x03B2, - ["gamma"] = 0x03B3, - ["delta"] = 0x03B4, - ["epsilon"] = 0x03B5, - ["zeta"] = 0x03B6, - ["eta"] = 0x03B7, - ["theta"] = 0x03B8, - ["iota"] = 0x03B9, - ["kappa"] = 0x03BA, - ["lambda"] = 0x03BB, - ["mu"] = 0x03BC, - ["nu"] = 0x03BD, - ["xi"] = 0x03BE, - ["omicron"] = 0x03BF, - ["pi"] = 0x03C0, - ["rho"] = 0x03C1, - ["sigmaf"] = 0x03C2, - ["sigma"] = 0x03C3, - ["tau"] = 0x03C4, - ["upsilon"] = 0x03C5, - ["phi"] = 0x03C6, - ["chi"] = 0x03C7, - ["psi"] = 0x03C8, - ["omega"] = 0x03C9, - ["thetasym"] = 0x03D1, - ["upsih"] = 0x03D2, - ["piv"] = 0x03D6, - ["ensp"] = 0x2002, - ["emsp"] = 0x2003, - ["thinsp"] = 0x2009, - ["ndash"] = 0x2013, - ["mdash"] = 0x2014, - ["lsquo"] = 0x2018, - ["rsquo"] = 0x2019, - ["sbquo"] = 0x201A, - ["ldquo"] = 0x201C, - ["rdquo"] = 0x201D, - ["bdquo"] = 0x201E, - ["dagger"] = 0x2020, - ["Dagger"] = 0x2021, - ["bull"] = 0x2022, - ["hellip"] = 0x2026, - ["permil"] = 0x2030, - ["prime"] = 0x2032, - ["Prime"] = 0x2033, - ["lsaquo"] = 0x2039, - ["rsaquo"] = 0x203A, - ["oline"] = 0x203E, - ["frasl"] = 0x2044, - ["euro"] = 0x20AC, - ["image"] = 0x2111, - ["weierp"] = 0x2118, - ["real"] = 0x211C, - ["trade"] = 0x2122, - ["alefsym"] = 0x2135, - ["larr"] = 0x2190, - ["uarr"] = 0x2191, - ["rarr"] = 0x2192, - ["darr"] = 0x2193, - ["harr"] = 0x2194, - ["crarr"] = 0x21B5, - ["lArr"] = 0x21D0, - ["uArr"] = 0x21D1, - ["rArr"] = 0x21D2, - ["dArr"] = 0x21D3, - ["hArr"] = 0x21D4, - ["forall"] = 0x2200, - ["part"] = 0x2202, - ["exist"] = 0x2203, - ["empty"] = 0x2205, - ["nabla"] = 0x2207, - ["isin"] = 0x2208, - ["notin"] = 0x2209, - ["ni"] = 0x220B, - ["prod"] = 0x220F, - ["sum"] = 0x2211, - ["minus"] = 0x2212, - ["lowast"] = 0x2217, - ["radic"] = 0x221A, - ["prop"] = 0x221D, - ["infin"] = 0x221E, - ["ang"] = 0x2220, - ["and"] = 0x2227, - ["or"] = 0x2228, - ["cap"] = 0x2229, - ["cup"] = 0x222A, - ["int"] = 0x222B, - ["there4"] = 0x2234, - ["sim"] = 0x223C, - ["cong"] = 0x2245, - ["asymp"] = 0x2248, - ["ne"] = 0x2260, - ["equiv"] = 0x2261, - ["le"] = 0x2264, - ["ge"] = 0x2265, - ["sub"] = 0x2282, - ["sup"] = 0x2283, - ["nsub"] = 0x2284, - ["sube"] = 0x2286, - ["supe"] = 0x2287, - ["oplus"] = 0x2295, - ["otimes"] = 0x2297, - ["perp"] = 0x22A5, - ["sdot"] = 0x22C5, - ["lceil"] = 0x2308, - ["rceil"] = 0x2309, - ["lfloor"] = 0x230A, - ["rfloor"] = 0x230B, - ["lang"] = 0x27E8, - ["rang"] = 0x27E9, - ["loz"] = 0x25CA, - ["spades"] = 0x2660, - ["clubs"] = 0x2663, - ["hearts"] = 0x2665, - ["diams"] = 0x2666, -} - ---- Given a string of decimal digits, returns a UTF-8 encoded --- string encoding a unicode character. -function M.dec_entity(s) - return utf8_char(tonumber(s)) -end - ---- Given a string of hexadecimal digits, returns a UTF-8 encoded --- string encoding a unicode character. -function M.hex_entity(s) - return utf8_char(tonumber("0x"..s)) -end - ---- Given a character entity name (like `ouml`), returns a UTF-8 encoded --- string encoding a unicode character. -function M.char_entity(s) - local n = character_entities[s] - return utf8_char(n) -end - -return M diff --git a/lua-libraries/lunamark/reader.lua b/lua-libraries/lunamark/reader.lua deleted file mode 100644 index 2ee5d0c00..000000000 --- a/lua-libraries/lunamark/reader.lua +++ /dev/null @@ -1,20 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Provides access to all lunamark readers without preloading --- them. Reader modules are loaded only when needed. --- --- local readers = require("lunamark.reader") --- local htmlreader = readers.html -- html reader loaded now --- local myformat = 'markdown' --- local myreader = readers[myformat] -- markdown reader loaded now - -local G = {} - -setmetatable(G,{ __index = function(t,name) - local mod = require("lunamark.reader." .. name) - rawset(t,name,mod) - return t[name] - end }) - -return G diff --git a/lua-libraries/lunamark/reader/markdown.lua b/lua-libraries/lunamark/reader/markdown.lua deleted file mode 100644 index d829b5919..000000000 --- a/lua-libraries/lunamark/reader/markdown.lua +++ /dev/null @@ -1,1172 +0,0 @@ --- (c) 2009-2011 John MacFarlane, Hans Hagen. Released under MIT license. --- See the file LICENSE in the source for details. - -local util = require("lunamark.util") -local lpeg = require("lpeg") -local entities = require("lunamark.entities") -local lower, upper, gsub, format, length = - string.lower, string.upper, string.gsub, string.format, string.len -local P, R, S, V, C, Cg, Cb, Cmt, Cc, Ct, B, Cs = - lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cg, lpeg.Cb, - lpeg.Cmt, lpeg.Cc, lpeg.Ct, lpeg.B, lpeg.Cs -local lpegmatch = lpeg.match -local expand_tabs_in_line = util.expand_tabs_in_line -local luautf8 = require("lua-utf8") - -local M = {} - -local rope_to_string = util.rope_to_string - --- Normalize a markdown reference tag. (Make lowercase, and collapse --- adjacent whitespace characters.) -local function normalize_tag(tag) - return luautf8.lower(gsub(rope_to_string(tag), "[ \n\r\t]+", " ")) -end - ------------------------------------------------------------------------------- --- Character parsers ------------------------------------------------------------------------------- - -local percent = P("%") -local at = P("@") -local comma = P(",") -local asterisk = P("*") -local dash = P("-") -local plus = P("+") -local underscore = P("_") -local period = P(".") -local hash = P("#") -local ampersand = P("&") -local backtick = P("`") -local less = P("<") -local more = P(">") -local space = P(" ") -local squote = P("'") -local dquote = P('"') -local lparent = P("(") -local rparent = P(")") -local lbracket = P("[") -local rbracket = P("]") -local circumflex = P("^") -local slash = P("/") -local equal = P("=") -local colon = P(":") -local semicolon = P(";") -local exclamation = P("!") -local tilde = P("~") -local tab = P("\t") -local newline = P("\n") -local tightblocksep = P("\001") - ---- Create a new markdown parser. --- --- * `writer` is a writer table (see [lunamark.writer.generic]). --- --- * `options` is a table with parsing options. --- The following fields are significant: --- --- `alter_syntax` --- : Function from syntax table to syntax table, --- allowing the user to change or extend the markdown syntax. --- For an example, see the documentation for `lunamark`. --- --- `references` --- : A table of references to be used in resolving links --- in the document. The keys should be all lowercase, with --- spaces and newlines collapsed into single spaces. --- Example: --- --- { foo: { url = "/url", title = "my title" }, --- bar: { url = "http://fsf.org" } } --- --- `preserve_tabs` --- : Preserve tabs instead of converting to spaces. --- --- `smart` --- : Parse quotation marks, dashes, ellipses intelligently. --- --- `startnum` --- : Make the opening number in an ordered list significant. --- --- `notes` --- : Enable footnotes as in pandoc. --- --- `definition_lists` --- : Enable definition lists as in pandoc. --- --- `citations` --- : Enable citations as in pandoc. --- --- `fenced_code_blocks` --- : Enable fenced code blocks. --- --- `pandoc_title_blocks` --- : Parse pandoc-style title block at the beginning of document: --- --- % Title --- % Author1; Author2 --- % Date --- --- `lua_metadata` --- : Enable lua metadata. This is an HTML comment block --- that starts with `"))^0 * P("-->") - - local htmlinstruction = P("" ))^0 * P("?>" ) - - local openelt_any = less * keyword * htmlattribute^0 * sp * more - - local function openelt_exact(s) - return (less * sp * keyword_exact(s) * htmlattribute^0 * sp * more) - end - - local openelt_block = sp * block_keyword * htmlattribute^0 * sp * more - - local closeelt_any = less * sp * slash * keyword * sp * more - - local function closeelt_exact(s) - return (less * sp * slash * keyword_exact(s) * sp * more) - end - - local emptyelt_any = less * sp * keyword * htmlattribute^0 * sp * slash * more - - local emptyelt_block = less * sp * block_keyword * htmlattribute^0 * sp * slash * more - - local displaytext = (any - less)^1 - - -- return content between two matched HTML tags - local function in_matched(s) - return { openelt_exact(s) - * (V(1) + displaytext + (less - closeelt_exact(s)))^0 - * closeelt_exact(s) } - end - - local function parse_matched_tags(s,pos) - local t = lower(lpegmatch(C(keyword),s,pos)) - return lpegmatch(in_matched(t),s,pos-1) - end - - local in_matched_block_tags = less * Cmt(#openelt_block, parse_matched_tags) - - local displayhtml = htmlcomment - + emptyelt_block - + openelt_exact("hr") - + in_matched_block_tags - + htmlinstruction - - local inlinehtml = emptyelt_any - + htmlcomment - + htmlinstruction - + openelt_any - + closeelt_any - - ------------------------------------------------------------------------------ - -- Entities - ------------------------------------------------------------------------------ - - local hexentity = ampersand * hash * S("Xx") * C(hexdigit ^1) * semicolon - local decentity = ampersand * hash * C(digit ^1) * semicolon - local tagentity = ampersand * C(alphanumeric^1) * semicolon - - ------------------------------------------------------------------------------ - -- Inline elements - ------------------------------------------------------------------------------ - - local Inline = V("Inline") - - local Str = normalchar^1 / writer.string - - local Ellipsis = P("...") / writer.ellipsis - - local Dash = P("---") * -dash / writer.mdash - + P("--") * -dash / writer.ndash - + P("-") * #digit * B(digit*1, 2) / writer.ndash - - local DoubleQuoted = dquote * Ct((Inline - dquote)^1) * dquote - / writer.doublequoted - - local squote_start = squote * -spacing - - local squote_end = squote * B(nonspacechar*1, 2) - - local SingleQuoted = squote_start * Ct((Inline - squote_end)^1) * squote_end - / writer.singlequoted - - local Apostrophe = squote * B(nonspacechar*1, 2) / "’" - - local Smart = Ellipsis + Dash + SingleQuoted + DoubleQuoted + Apostrophe - - local Symbol = (specialchar - tightblocksep) / writer.string - - local Code = inticks / writer.code - - local bqstart = more - local headerstart = hash - + (line * (equal^1 + dash^1) * optionalspace * newline) - local fencestart = fencehead(backtick) + fencehead(tilde) - - if options.require_blank_before_blockquote then - bqstart = fail - end - - if options.require_blank_before_header then - headerstart = fail - end - - if not options.fenced_code_blocks or - options.blank_before_fenced_code_blocks then - fencestart = fail - end - - local Endline = newline * -( -- newline, but not before... - blankline -- paragraph break - + tightblocksep -- nested list - + eof -- end of document - + bqstart - + headerstart - + fencestart - ) * spacechar^0 / writer.space - - local Space = spacechar^2 * Endline / writer.linebreak - + spacechar^1 * Endline^-1 * eof / "" - + spacechar^1 * Endline^-1 * optionalspace / writer.space - - local NonbreakingEndline - = newline * -( -- newline, but not before... - blankline -- paragraph break - + tightblocksep -- nested list - + eof -- end of document - + bqstart - + headerstart - + fencestart - ) * spacechar^0 / writer.nbsp - - local NonbreakingSpace - = spacechar^2 * Endline / writer.linebreak - + spacechar^1 * Endline^-1 * eof / "" - + spacechar^1 * Endline^-1 * optionalspace / writer.nbsp - - -- parse many p between starter and ender - local function between(p, starter, ender) - local ender2 = B(nonspacechar) * ender - return (starter * #nonspacechar * Ct(p * (p - ender2)^0) * ender2) - end - - local Strong = ( between(Inline, doubleasterisks, doubleasterisks) - + between(Inline, doubleunderscores, doubleunderscores) - ) / writer.strong - - local Emph = ( between(Inline, asterisk, asterisk) - + between(Inline, underscore, underscore) - ) / writer.emphasis - - local urlchar = anyescaped - newline - more - - local AutoLinkUrl = less - * C(alphanumeric^1 * P("://") * urlchar^1) - * more - / function(url) return writer.link(writer.string(url),url) end - - local AutoLinkEmail = less - * C((alphanumeric + S("-._+"))^1 * P("@") * urlchar^1) - * more - / function(email) return writer.link(writer.string(email),"mailto:"..email) end - - local DirectLink = (tag / parse_inlines_no_link) -- no links inside links - * spnl - * lparent - * (url + Cc("")) -- link can be empty [foo]() - * optionaltitle - * rparent - / writer.link - - local IndirectLink = tag * (C(spnl) * tag)^-1 / indirect_link - - -- parse a link or image (direct or indirect) - local Link = DirectLink + IndirectLink - - local DirectImage = exclamation - * (tag / parse_inlines) - * spnl - * lparent - * (url + Cc("")) -- link can be empty [foo]() - * optionaltitle - * rparent - / writer.image - - local IndirectImage = exclamation * tag * (C(spnl) * tag)^-1 / indirect_image - - local Image = DirectImage + IndirectImage - - local TextCitations = Ct(Cc("") - * citation_name - * ((spnl - * lbracket - * citation_headless_body - * rbracket) + Cc(""))) / - function(raw_cites) - return citations(true, raw_cites) - end - - local ParenthesizedCitations - = Ct(lbracket - * citation_body - * rbracket) / - function(raw_cites) - return citations(false, raw_cites) - end - - local Citations = TextCitations + ParenthesizedCitations - - -- avoid parsing long strings of * or _ as emph/strong - local UlOrStarLine = asterisk^4 + underscore^4 / writer.string - - local EscapedChar = S("\\") * C(escapable) / writer.string - - local InlineHtml = C(inlinehtml) / writer.inline_html - - local HtmlEntity = hexentity / entities.hex_entity / writer.string - + decentity / entities.dec_entity / writer.string - + tagentity / entities.char_entity / writer.string - - ------------------------------------------------------------------------------ - -- Block elements - ------------------------------------------------------------------------------ - - local Block = V("Block") - - local DisplayHtml = C(displayhtml) / expandtabs / writer.display_html - - local Verbatim = Cs( (blanklines - * ((indentedline - blankline))^1)^1 - ) / expandtabs / writer.verbatim - - local TildeFencedCodeBlock - = fencehead(tilde) - * Cs(fencedline(tilde)^0) - * fencetail(tilde) - - local BacktickFencedCodeBlock - = fencehead(backtick) - * Cs(fencedline(backtick)^0) - * fencetail(backtick) - - local FencedCodeBlock - = (TildeFencedCodeBlock + BacktickFencedCodeBlock) - / function(infostring, code) - return writer.fenced_code( - expandtabs(code), - writer.string(infostring)) - end - - -- strip off leading > and indents, and run through blocks - local Blockquote = Cs(( - ((leader * more * space^-1)/"" * linechar^0 * newline)^1 - * (-blankline * linechar^1 * newline)^0 - * blankline^0 - )^1) / parse_blocks / writer.blockquote - - local function lineof(c) - return (leader * (P(c) * optionalspace)^3 * newline * blankline^1) - end - - local HorizontalRule = ( lineof(asterisk) - + lineof(dash) - + lineof(underscore) - ) / writer.hrule - - local Reference = define_reference_parser / register_link - - local Paragraph = nonindentspace * Ct(Inline^1) * newline - * ( blankline^1 - + #hash - + #(leader * more * space^-1) - ) - / writer.paragraph - - local Plain = nonindentspace * Ct(Inline^1) / writer.plain - - ------------------------------------------------------------------------------ - -- Lists - ------------------------------------------------------------------------------ - - local starter = bullet + enumerator - - -- we use \001 as a separator between a tight list item and a - -- nested list under it. - local NestedList = Cs((optionallyindentedline - starter)^1) - / function(a) return "\001"..a end - - local ListBlockLine = optionallyindentedline - - blankline - (indent^-1 * starter) - - local ListBlock = line * ListBlockLine^0 - - local ListContinuationBlock = blanklines * (indent / "") * ListBlock - - local function TightListItem(starter) - return -HorizontalRule - * (Cs(starter / "" * ListBlock * NestedList^-1) / parse_blocks) - * -(blanklines * indent) - end - - local function LooseListItem(starter) - return -HorizontalRule - * Cs( starter / "" * ListBlock * Cc("\n") - * (NestedList + ListContinuationBlock^0) - * (blanklines / "\n\n") - ) / parse_blocks - end - - local BulletList = ( Ct(TightListItem(bullet)^1) - * Cc(true) * skipblanklines * -bullet - + Ct(LooseListItem(bullet)^1) - * Cc(false) * skipblanklines ) / writer.bulletlist - - local function ordered_list(s,tight,startnum) - if options.startnum then - startnum = tonumber(startnum) or 1 -- fallback for '#' - else - startnum = nil - end - return writer.orderedlist(s,tight,startnum) - end - - local OrderedList = Cg(enumerator, "listtype") * - ( Ct(TightListItem(Cb("listtype")) * TightListItem(enumerator)^0) - * Cc(true) * skipblanklines * -enumerator - + Ct(LooseListItem(Cb("listtype")) * LooseListItem(enumerator)^0) - * Cc(false) * skipblanklines - ) * Cb("listtype") / ordered_list - - local defstartchar = S("~:") - local defstart = ( defstartchar * #spacing * (tab + space^-3) - + space * defstartchar * #spacing * (tab + space^-2) - + space * space * defstartchar * #spacing * (tab + space^-1) - + space * space * space * defstartchar * #spacing - ) - - local dlchunk = Cs(line * (indentedline - blankline)^0) - - local function definition_list_item(term, defs, tight) - return { term = parse_inlines(term), definitions = defs } - end - - local DefinitionListItemLoose = C(line) * skipblanklines - * Ct((defstart * indented_blocks(dlchunk) / parse_blocks)^1) - * Cc(false) - / definition_list_item - - local DefinitionListItemTight = C(line) - * Ct((defstart * dlchunk / parse_blocks)^1) - * Cc(true) - / definition_list_item - - local DefinitionList = ( Ct(DefinitionListItemLoose^1) * Cc(false) - + Ct(DefinitionListItemTight^1) - * (skipblanklines * -DefinitionListItemLoose * Cc(true)) - ) / writer.definitionlist - - ------------------------------------------------------------------------------ - -- Lua metadata - ------------------------------------------------------------------------------ - - local function lua_metadata(s) -- run lua code in comment in sandbox - local env = { m = parse_markdown, markdown = parse_blocks } - local scode = s:match("^") - local untrusted_table, message = load(scode, nil, "t", env) - if not untrusted_table then - util.err(message, 37) - end - local ok, msg = pcall(untrusted_table) - if not ok then - util.err(msg) - end - for k,v in pairs(env) do - writer.set_metadata(k,v) - end - return "" - end - - local LuaMeta = fail - if options.lua_metadata then - LuaMeta = #P(" - - - - - - - - - - - - - - - - - - - - - -]===] - - return DZSlides -end - -return M diff --git a/lua-libraries/lunamark/writer/generic.lua b/lua-libraries/lunamark/writer/generic.lua deleted file mode 100644 index 92133e473..000000000 --- a/lua-libraries/lunamark/writer/generic.lua +++ /dev/null @@ -1,294 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Generic writer for lunamark. --- This serves as generic documentation for lunamark writers, --- which all export a table with the same functions defined. --- --- New writers can simply modify the generic writer: for example, --- --- local Xml = generic.new(options) --- --- Xml.linebreak = "" --- --- local escaped = { --- ["<" ] = "<", --- [">" ] = ">", --- ["&" ] = "&", --- ["\"" ] = """, --- ["'" ] = "'" --- } --- --- function Xml.string(s) --- return s:gsub(".",escaped) --- end - -local util = require("lunamark.util") -local M = {} -local W = {} - -local meta = {} -meta.__index = - function(_, key) - io.stderr:write(string.format("WARNING: Undefined writer function '%s'\n",key)) - return (function(...) return table.concat({...}," ") end) - end -setmetatable(W, meta) - -local rope_to_string = util.rope_to_string - ---- Returns a table with functions defining a generic lunamark writer, --- which outputs plain text with no formatting. `options` is an optional --- table with the following fields: --- --- `layout` --- : `minimize` (no space between blocks) --- : `compact` (no extra blank lines between blocks) --- : `default` (blank line between blocks) -function M.new(options) - ---- The table contains the following fields: - - options = options or {} - local metadata = {} - - --- Set metadata field `key` to `val`. - function W.set_metadata(key, val) - metadata[key] = val - return "" - end - - --- Add `val` to an array in metadata field `key`. - function W.add_metadata(key, val) - local cur = metadata[key] - if type(cur) == "table" then - table.insert(cur,val) - elseif cur then - metadata[key] = {cur, val} - else - metadata[key] = {val} - end - end - - --- Return metadata table. - function W.get_metadata() - return metadata - end - - -- Turn list of output into final result. - function W.merge(result) - return rope_to_string(result) - end - - --- A space (string). - W.space = " " - - --- Setup tasks at beginning of document. - function W.start_document() - return "" - end - - --- Finalization tasks at end of document. - function W.stop_document() - return "" - end - - --- Plain text block (not formatted as a pragraph). - function W.plain(s) - return s - end - - --- A line break (string). - W.linebreak = "\n" - - --- Line breaks to use between block elements. - W.interblocksep = "\n\n" - - --- Line breaks to use between a container (like a `
` - -- tag) and the adjacent block element. - W.containersep = "\n" - - if options.layout == "minimize" then - W.interblocksep = "" - W.containersep = "" - elseif options.layout == "compact" then - W.interblocksep = "\n" - W.containersep = "\n" - end - - --- Ellipsis (string). - W.ellipsis = "…" - - --- Em dash (string). - W.mdash = "—" - - --- En dash (string). - W.ndash = "–" - - --- Non-breaking space. - W.nbsp = " " - - --- String in curly single quotes. - function W.singlequoted(s) - return {"‘", s, "’"} - end - - --- String in curly double quotes. - function W.doublequoted(s) - return {"“", s, "”"} - end - - --- String, escaped as needed for the output format. - function W.string(s) - return s - end - - --- Inline (verbatim) code. - function W.code(s) - return s - end - - --- A link with link text `label`, uri `uri`, - -- and title `title`. - function W.link(label, uri, title) - return label - end - - --- An image link with alt text `label`, - -- source `src`, and title `title`. - function W.image(label, src, title) - return label - end - - --- A paragraph. - function W.paragraph(s) - return s - end - - --- A bullet list with contents `items` (an array). If - -- `tight` is true, returns a "tight" list (with - -- minimal space between items). - function W.bulletlist(items,tight) - return util.intersperse(items,W.interblocksep) - end - - --- An ordered list with contents `items` (an array). If - -- `tight` is true, returns a "tight" list (with - -- minimal space between items). If optional - -- number `startnum` is present, use it as the - -- number of the first list item. - function W.orderedlist(items,tight,startnum) - return util.intersperse(items,W.interblocksep) - end - - --- Inline HTML. - function W.inline_html(s) - return "" - end - - --- Display HTML (HTML block). - function W.display_html(s) - return "" - end - - --- Emphasized text. - function W.emphasis(s) - return s - end - - --- Strongly emphasized text. - function W.strong(s) - return s - end - - --- Block quotation. - function W.blockquote(s) - return s - end - - --- Verbatim block. - function W.verbatim(s) - return s - end - - --- Fenced code block, with infostring `i`. - function W.fenced_code(s, i) - return s - end - - --- Header level `level`, with text `s`. - function W.header(s, level) - return s - end - - --- Horizontal rule. - W.hrule = "" - - --- A string of one or more citations. `text_cites` is a boolean, true if the - -- citations are in-text citations. `cites` - is an array of tables, each of - -- the form `{ prenote = q, name = n, postnote = e, suppress_author = s }`, - -- where: - -- - `q` is a nil or a rope that should be inserted before the citation, - -- - `e` is a nil or a rope that should be inserted after the citation, - -- - `n` is a string with the citation name, and - -- - `s` is a boolean, true if the author should be omitted from the - -- citation. - function W.citations(text_cites, cites) - local buffer = {} - local opened_brackets = false - for i, cite in ipairs(cites) do - if i == 1 then -- Opening in-text citation - if text_cites then - buffer[#buffer + 1] = {cite.suppress_author and "-" or "", "@", - cite.name} - if cite.postnote then - opened_brackets = true - buffer[#buffer + 1] = {" [", cite.postnote} - end - else -- Opening regular citation - opened_brackets = true - buffer[#buffer + 1] = {"[", cite.prenote and {cite.prenote, " "} or "", - cite.suppress_author and "-" or "", "@", cite.name, cite.postnote and - {" ", cite.postnote}} - end - else -- Continuation citation - buffer[#buffer + 1] = {"; ", cite.prenote and {cite.prenote, " "} or "", - cite.suppress_author and "-" or "", "@", cite.name, cite.postnote and - {" ", cite.postnote}} - end - end - if opened_brackets then - buffer[#buffer + 1] = "]" - end - return buffer - end - - --- A footnote or endnote. - function W.note(contents) - return contents - end - - --- A definition list. `items` is an array of tables, - -- each of the form `{ term = t, definitions = defs, tight = tight }`, - -- where `t` is a string and `defs` is an array of strings. - -- `tight` is a boolean, true if it is a tight list. - function W.definitionlist(items, tight) - local buffer = {} - for _,item in ipairs(items) do - buffer[#buffer + 1] = item.t - buffer[#buffer + 1] = util.intersperse(item.definitions, W.interblocksep) - end - return util.intersperse(buffer,W.interblocksep) - end - - --- A cosmo template to be used in producing a standalone document. - -- `$body` is replaced with the document body, `$title` with the - -- title, and so on. - W.template = [[ -$body -]] - - return util.table_copy(W) -end - -return M diff --git a/lua-libraries/lunamark/writer/groff.lua b/lua-libraries/lunamark/writer/groff.lua deleted file mode 100644 index d722fea92..000000000 --- a/lua-libraries/lunamark/writer/groff.lua +++ /dev/null @@ -1,81 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Generic groff writer for lunamark. --- This is currently used as the basis for [lunamark.writer.man]. --- In principle other groff-based writers could also extend it. - -local M = {} - -local util = require("lunamark.util") -local generic = require("lunamark.writer.generic") - ---- Returns a new Groff writer. --- For a list of all fields, see [lunamark.writer.generic]. -function M.new(options) - options = options or {} - local Groff = generic.new(options) - - Groff.interblocksep = "\n\n" -- insensitive to layout - - Groff.containersep = "\n" - - Groff.linebreak = ".br\n" - - Groff.ellipsis = "\\&..." - - Groff.mdash = "\\[em]" - - Groff.ndash = "\\[en]" - - Groff.nbsp = "\\~" - - function Groff.singlequoted(s) - return {"`",s,"'"} - end - - function Groff.doublequoted(s) - return {"\\[lq]",s,"\\[rq]"} - end - - Groff.escaped = { - ["@"] = "\\@", - ["\\"] = "\\\\", - } - - local escaped_utf8_triplet = { - ["\226\128\156"] = "\\[lq]", - ["\226\128\157"] = "\\[rq]", - ["\226\128\152"] = "`", - ["\226\128\153"] = "'", - ["\226\128\148"] = "\\[em]", - ["\226\128\147"] = "\\[en]", - ["\194\160"] = "\\ ", - } - - local escape = util.escaper(Groff.escaped, escaped_utf8_triplet) - - Groff.string = escape - - function Groff.inline_html(s) - end - - function Groff.display_html(s) - end - - function Groff.code(s) - return {"\\f[C]",s,"\\f[]"} - end - - function Groff.emphasis(s) - return {"\\f[I]",s,"\\f[]"} - end - - function Groff.strong(s) - return {"\\f[B]",s,"\\f[]"} - end - - return Groff -end - -return M diff --git a/lua-libraries/lunamark/writer/html.lua b/lua-libraries/lunamark/writer/html.lua deleted file mode 100644 index eba6e8eb3..000000000 --- a/lua-libraries/lunamark/writer/html.lua +++ /dev/null @@ -1,191 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- HTML writer for lunamark. --- Extends [lunamark.writer.xml]. - -local M = {} - -local xml = require("lunamark.writer.xml") -local util = require("lunamark.util") -local flatten, intersperse, map = util.flatten, util.intersperse, util.map - ---- Return a new HTML writer. --- For a list of all fields in the writer, see [lunamark.writer.generic]. --- ---`options` is a table that can contain the following fields: --- --- `containers` --- : Put sections in `
` tags. --- --- `slides` --- : Do not allow containers to nest; when a subsection begins, --- close the section's container and start a new one. --- --- `layout` --- : `minimize` removes semantically insignificant white space. --- : `compact` removes unneeded blank lines. --- : `default` puts blank lines between block elements. -function M.new(options) - options = options or {} - local Html = xml.new(options) - - local endnotes = {} - local containersep = Html.containersep - local interblocksep = Html.interblocksep - - Html.container = "div" - Html.linebreak = "
" - Html.nbsp = " " - - function Html.code(s) - return {"", Html.string(s), ""} - end - - function Html.link(lab,src,tit) - local titattr - if type(tit) == "string" and #tit > 0 - then titattr = " title=\"" .. Html.string(tit) .. "\"" - else titattr = "" - end - return {"", lab, ""} - end - - function Html.image(lab,src,tit) - local titattr - if type(tit) == "string" and #tit > 0 - then titattr = " title=\"" .. Html.string(tit) .. "\"" - else titattr = "" - end - return {"\"","} - end - - function Html.paragraph(s) - return {"

", s, "

"} - end - - local function listitem(s) - return {"
  • ", s, "
  • "} - end - - function Html.bulletlist(items,tight) - return {"
      ", containersep, intersperse(map(items, listitem), containersep), containersep, "
    "} - end - - function Html.orderedlist(items,tight,startnum) - local start = "" - if startnum and startnum ~= 1 then - start = " start=\"" .. startnum .. "\"" - end - return {"", containersep, intersperse(map(items, listitem), containersep), containersep, ""} - end - - function Html.inline_html(s) - return s - end - - function Html.display_html(s) - return s - end - - function Html.emphasis(s) - return {"", s, ""} - end - - function Html.strong(s) - return {"", s, ""} - end - - function Html.blockquote(s) - return {"
    ", containersep, s, containersep, "
    "} - end - - function Html.verbatim(s) - return {"
    ", Html.string(s), "
    "} - end - - function Html.fenced_code(s,i) - if i ~= "" then - return {'
    ', Html.string(s), "
    "} - else - return Html.verbatim(s) - end - end - - function Html.header(s,level) - local sep = "" - if options.slides or options.containers then - local lev = (options.slides and 1) or level - local stop = Html.stop_section(lev) - if stop ~= "" then - stop = stop .. Html.interblocksep - end - sep = stop .. Html.start_section(lev) .. Html.containersep - end - return {sep, "", s, ""} - end - - Html.hrule = "
    " - - function Html.note(contents) - local num = #endnotes + 1 - local backref = ' ' - local contentsf = flatten(contents) - if contentsf[#contentsf] == "

    " then - table.insert(contentsf, #contentsf, backref) - else - contentsf[#contentsf + 1] = backref - end - endnotes[num] = {'
  • ', contentsf, '
  • '} - return {'', num, ''} - end - - function Html.start_document() - endnotes = {} - return "" - end - - function Html.stop_document() - return function() - local stop = Html.stop_section(1) -- close section containers - if stop ~= "" then stop = Html.containersep .. stop end - if #endnotes == 0 then - return stop - else - return {stop, interblocksep, '
    ', interblocksep, '
      ', - containersep, intersperse(endnotes, interblocksep), containersep, '
    '} - end - end - end - - function Html.definitionlist(items, tight) - local buffer = {} - local sep - if tight then sep = "" else sep = Html.containersep end - for _,item in ipairs(items) do - local defs = {} - for _,def in ipairs(item.definitions) do - defs[#defs + 1] = {"
    ", sep, def, sep, "
    "} - end - buffer[#buffer + 1] = {"
    ", item.term, "
    ", containersep, intersperse(defs, containersep)} - end - return {"
    ", containersep, intersperse(buffer, containersep), containersep, "
    "} - end - - Html.template = [[ - - - -$title - - -$body - - -]] - - return Html -end - -return M diff --git a/lua-libraries/lunamark/writer/html5.lua b/lua-libraries/lunamark/writer/html5.lua deleted file mode 100644 index cfb1db937..000000000 --- a/lua-libraries/lunamark/writer/html5.lua +++ /dev/null @@ -1,37 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- HTML 5 writer for lunamark. --- Extends [lunamark.writer.html], but uses `
    ` tags for sections --- if `options.containers` is true. - -local M = {} - -local html = require("lunamark.writer.html") - ---- Returns a new HTML 5 writer. --- `options` is as in `lunamark.writer.html`. --- For a list of fields, see [lunamark.writer.generic]. -function M.new(options) - options = options or {} - local Html5 = html.new(options) - - Html5.container = "section" - - Html5.template = [[ - - - - -$title - - -$body - - -]] - - return Html5 -end - -return M diff --git a/lua-libraries/lunamark/writer/latex.lua b/lua-libraries/lunamark/writer/latex.lua deleted file mode 100644 index 3b9f7e3c3..000000000 --- a/lua-libraries/lunamark/writer/latex.lua +++ /dev/null @@ -1,260 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- LaTeX writer for lunamark. --- Extends the [lunamark.writer.tex]. - -local M = {} - -local tex = require("lunamark.writer.tex") -local util = require("lunamark.util") -local format = string.format - ---- Returns a new LaTeX writer. --- --- * `options` is a table with parsing options. --- The following fields are significant: --- --- `citations` --- : Enable citations as in pandoc. Either a boolean or one of --- the following strings should be specified: --- --- - `latex` -- produce basic LaTeX2e citations, --- - `natbib` -- produce citations for the Natbib package, or --- - `biblatex` -- produce citations for the BibLaTeX package. --- --- For a list of fields in the writer, see [lunamark.writer.generic]. -function M.new(options) - options = options or {} - local LaTeX = tex.new(options) - - function LaTeX.code(s) - return {"\\texttt{",LaTeX.string(s),"}"} - end - - function LaTeX.link(lab,src,tit) - return {"\\href{",LaTeX.string(src),"}{",lab,"}"} - end - - function LaTeX.image(lab,src,tit) - return {"\\includegraphics{",LaTeX.string(src),"}"} - end - - local function listitem(s) - return {"\\item ",s} - end - - function LaTeX.bulletlist(items) - local buffer = {} - for _,item in ipairs(items) do - buffer[#buffer + 1] = listitem(item) - end - local contents = util.intersperse(buffer,"\n") - return {"\\begin{itemize}\n",contents,"\n\\end{itemize}"} - end - - function LaTeX.orderedlist(items) - local buffer = {} - for _,item in ipairs(items) do - buffer[#buffer + 1] = listitem(item) - end - local contents = util.intersperse(buffer,"\n") - return {"\\begin{enumerate}\n",contents,"\n\\end{enumerate}"} - end - - function LaTeX.emphasis(s) - return {"\\emph{",s,"}"} - end - - function LaTeX.strong(s) - return {"\\textbf{",s,"}"} - end - - function LaTeX.blockquote(s) - return {"\\begin{quote}\n",s,"\n\\end{quote}"} - end - - function LaTeX.verbatim(s) - return {"\\begin{verbatim}\n",s,"\\end{verbatim}"} - end - - LaTeX.fenced_code = LaTeX.verbatim - - function LaTeX.header(s,level) - local cmd - if level == 1 then - cmd = "\\section" - elseif level == 2 then - cmd = "\\subsection" - elseif level == 3 then - cmd = "\\subsubsection" - elseif level == 4 then - cmd = "\\paragraph" - elseif level == 5 then - cmd = "\\subparagraph" - else - cmd = "" - end - return {cmd,"{",s,"}"} - end - - LaTeX.hrule = "\\hspace{\\fill}\\rule{.6\\linewidth}{0.4pt}\\hspace{\\fill}" - - function LaTeX.note(contents) - return {"\\footnote{",contents,"}"} - end - - local function citation_optargs(cite) - if cite.prenote and cite.postnote then - return {"[", cite.prenote, "][", cite.postnote, "]"} - elseif cite.prenote and not cite.postnote then - return {"[", cite.prenote, "][]"} - elseif not cite.prenote and cite.postnote then - return {"[", cite.postnote, "]"} - else - return "" - end - end - - if options.citations == true or options.citations == "latex" then - --- Basic LaTeX2e citations - function LaTeX.citations(_, cites) - local buffer = {} - local opened_braces = false - for i, cite in ipairs(cites) do - if cite.prenote or cite.postnote then -- A separate complex citation - buffer[#buffer + 1] = {opened_braces and "}" or "", - cite.prenote and {i == 1 and "" or " ", cite.prenote, "~"} or - "", {(i == 1 or cite.prenote) and "" or " ", "\\cite"}, - cite.postnote and {"[", cite.postnote, "]"} or "", "{", cite.name, - cite_postnote and {"~", cite_postnote} or "", "}"} - opened_braces = false - else -- A string of simple citations - buffer[#buffer + 1] = {opened_braces and ", " or {i == 1 and "" or - " ", "\\cite{"}, cite.name} - opened_braces = true - end - end - if opened_braces then - buffer[#buffer + 1] = "}" - end - return buffer - end - elseif options.citations == "natbib" then - --- NatBib citations - function LaTeX.citations(text_cites, cites) - if #cites == 1 then -- A single citation - local cite = cites[1] - if text_cites then - return {"\\citet", citation_optargs(cite), "{", cite.name, "}"} - else - return {cite.suppress_author and "\\citeyearpar" or "\\citep", - citation_optargs(cite), "{", cite.name, "}"} - end - else -- A string of citations - local complex = false - local last_suppressed = nil - for _, cite in ipairs(cites) do - if cite.prenote or cite.postnote or - cite.suppress_author == not last_suppressed then - complex = true - break - end - last_suppressed = cite.suppress_author - end - if complex then -- A string of complex citations - local buffer = {"\\citetext{"} - for i, cite in ipairs(cites) do - buffer[#buffer + 1] = {i ~= 1 and "; " or "", cite.suppress_author - and "\\citeyear" or (text_cites and "\\citealt" or "\\citealp"), - citation_optargs(cite), "{", cite.name, "}"} - end - buffer[#buffer + 1] = "}" - return buffer - else -- A string of simple citations - local buffer = {} - for i, cite in ipairs(cites) do - buffer[#buffer + 1] = {i == 1 and (text_cites and "\\citet{" or - "\\citep{") or ", ", cite.name} - end - buffer[#buffer + 1] = "}" - return buffer - end - end - end - elseif options.citations == "biblatex" then - --- BibLaTeX citations - function LaTeX.citations(text_cites, cites) - if #cites == 1 then -- A single citation - local cite = cites[1] - if text_cites then - return {"\\textcite", citation_optargs(cite), "{", cite.name, "}"} - else - return {"\\autocite", cite.suppress_author and "*" or "", - citation_optargs(cite), "{", cite.name, "}"} - end - else -- A string of citations - local buffer = {text_cites and "\\textcites" or "\\autocites"} - for _, cite in ipairs(cites) do - buffer[#buffer + 1] = {citation_optargs(cite), "{", cite.name, "}"} - end - return buffer - end - end - end - - function LaTeX.definitionlist(items) - local buffer = {} - for _,item in ipairs(items) do - buffer[#buffer + 1] = format("\\item[%s]\n%s", - item.term, util.intersperse(item.definitions, LaTeX.interblocksep)) - end - local contents = util.intersperse(buffer, LaTeX.containersep) - return {"\\begin{description}\n",contents,"\n\\end{description}"} - end - - LaTeX.template = [===[ -\documentclass{article} -\usepackage{amssymb,amsmath} -\usepackage{ifxetex,ifluatex} -\ifxetex - \usepackage{fontspec,xltxtra,xunicode} - \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} -\else - \ifluatex - \usepackage{fontspec} - \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} - \else - \usepackage[utf8]{inputenc} - \fi -\fi -\ifxetex - \usepackage[setpagesize=false, % page size defined by xetex - unicode=false, % unicode breaks when used with xetex - xetex]{hyperref} -\else - \usepackage[unicode=true]{hyperref} -\fi -\hypersetup{breaklinks=true, pdfborder={0 0 0}} -\setlength{\parindent}{0pt} -\setlength{\parskip}{6pt plus 2pt minus 1pt} -\setlength{\emergencystretch}{3em} % prevent overfull lines -\setcounter{secnumdepth}{0} - -\title{$title} -\author{$sepby{author}[=[$it]=][=[ \and ]=]} -\date{$date} - -\begin{document} - -$if{ title }[[\maketitle -]] -$body - -\end{document} -]===] - - return LaTeX -end - -return M diff --git a/lua-libraries/lunamark/writer/man.lua b/lua-libraries/lunamark/writer/man.lua deleted file mode 100644 index db4992a64..000000000 --- a/lua-libraries/lunamark/writer/man.lua +++ /dev/null @@ -1,130 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Groff man writer for lunamark. --- Extends [lunamark.writer.groff]. --- --- Note: continuation paragraphs in lists are not --- handled properly. - -local M = {} - -local groff = require("lunamark.writer.groff") -local util = require("lunamark.util") -local format = string.format - ---- Returns a new groff writer. --- For a list of fields, see [lunamark.writer.generic]. -function M.new(options) - options = options or {} - local Man = groff.new(options) - - local endnotes = {} - - function Man.link(lab,src,tit) - return {lab," (",src,")"} - end - - function Man.image(lab,src,tit) - return {"[IMAGE (",lab,")]"} - end - - -- TODO handle continuations properly. - -- pandoc does this: - -- .IP \[bu] 2 - -- one - -- .RS 2 - -- .PP - -- cont - -- .RE - - function Man.paragraph(contents) - return {".PP\n",contents} - end - - function Man.bulletlist(items,tight) - local buffer = {} - for _,item in ipairs(items) do - local revitem = item - -- we don't want to have .IP then .PP - if revitem[1][1] == ".PP\n" then revitem[1][1] = "" end - buffer[#buffer + 1] = {".IP \\[bu] 2\n",item} - end - return util.intersperse(buffer, Man.containersep) - end - - function Man.orderedlist(items,tight,startnum) - local buffer = {} - local num = startnum or 1 - for _,item in ipairs(items) do - local revitem = item - -- we don't want to have .IP then .PP - if revitem[1][1] == ".PP\n" then revitem[1][1] = "" end - buffer[#buffer + 1] = {format(".IP \"%d.\" 4\n",num),item} - num = num + 1 - end - return util.intersperse(buffer, Man.containersep) - end - - function Man.blockquote(s) - return {".RS\n",s,"\n.RE"} - end - - function Man.verbatim(s) - return {".IP\n.nf\n\\f[C]\n",s,".fi"} - end - - Man.fenced_code = Man.verbatim - - function Man.header(s,level) - local hcode = ".SS" - if level == 1 then hcode = ".SH" end - return {hcode," ",s} - end - - Man.hrule = ".PP\n * * * * *" - - function Man.note(contents) - local num = #endnotes + 1 - endnotes[num] = {format(".SS [%d]\n",num),contents} - return format('[%d]', num) - end - - function Man.definitionlist(items,tight) - local buffer = {} - local ds - for _,item in ipairs(items) do - if tight then - ds = util.intersperse(item.definitions,"\n.RS\n.RE\n") - buffer[#buffer + 1] = {".TP\n.B ",item.term,"\n",ds,"\n.RS\n.RE"} - else - ds = util.intersperse(item.definitions,"\n.RS\n.RE\n") - buffer[#buffer + 1] = {".TP\n.B ",item.term,"\n.RS\n",ds,"\n.RE"} - end - end - local contents = util.intersperse(buffer,"\n") - return contents - end - - function Man.start_document() - endnotes = {} - return "" - end - - function Man.stop_document() - if #endnotes == 0 then - return "" - else - return {"\n.SH NOTES\n", util.intersperse(endnotes, "\n")} - end - end - - Man.template = [===[ -.TH "$title" "$section" "$date" "$left_footer" "$center_header" -$body -]===] - - return Man -end - -return M diff --git a/lua-libraries/lunamark/writer/tex.lua b/lua-libraries/lunamark/writer/tex.lua deleted file mode 100644 index 09cb24e08..000000000 --- a/lua-libraries/lunamark/writer/tex.lua +++ /dev/null @@ -1,89 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Generic TeX writer for lunamark. --- It extends [lunamark.writer.generic] and is extended by --- [lunamark.writer.latex] and [lunamark.writer.context]. - -local M = {} - -local util = require("lunamark.util") -local generic = require("lunamark.writer.generic") -local format = string.format - ---- Returns a new TeX writer. --- For a list ofy fields, see [lunamark.writer.generic]. -function M.new(options) - options = options or {} - local TeX = generic.new(options) - - TeX.interblocksep = "\n\n" -- insensitive to layout - - TeX.containersep = "\n" - - TeX.linebreak = "\\\\" - - TeX.ellipsis = "\\ldots{}" - - TeX.mdash = "---" - - TeX.ndash = "--" - - TeX.nbsp = "~" - - function TeX.singlequoted(s) - return format("`%s'",s) - end - - function TeX.doublequoted(s) - return format("``%s''",s) - end - - TeX.escaped = { - ["{"] = "\\{", - ["}"] = "\\}", - ["$"] = "\\$", - ["%"] = "\\%", - ["&"] = "\\&", - ["_"] = "\\_", - ["#"] = "\\#", - ["^"] = "\\^{}", - ["\\"] = "\\char92{}", - ["~"] = "\\char126{}", - ["|"] = "\\char124{}", - ["<"] = "\\char60{}", - [">"] = "\\char62{}", - ["["] = "{[}", -- to avoid interpretation as optional argument - ["]"] = "{]}", - } - - local str_escaped = { - ["\226\128\156"] = "``", - ["\226\128\157"] = "''", - ["\226\128\152"] = "`", - ["\226\128\153"] = "'", - ["\226\128\148"] = "---", - ["\226\128\147"] = "--", - ["\194\160"] = "~", - } - - local escaper = util.escaper(TeX.escaped, str_escaped) - - TeX.string = escaper - - function TeX.inline_html(s) - return "" - end - - function TeX.display_html(s) - return "" - end - - function TeX.paragraph(s) - return s - end - - return TeX -end - -return M diff --git a/lua-libraries/lunamark/writer/xml.lua b/lua-libraries/lunamark/writer/xml.lua deleted file mode 100644 index 8d02ec1fa..000000000 --- a/lua-libraries/lunamark/writer/xml.lua +++ /dev/null @@ -1,60 +0,0 @@ --- (c) 2009-2011 John MacFarlane. Released under MIT license. --- See the file LICENSE in the source for details. - ---- Generic XML writer for lunamark. --- It extends [lunamark.writer.generic] and is extended by --- [lunamark.writer.html] and [lunamark.writer.docbook]. - -local M = {} - -local generic = require("lunamark.writer.generic") -local util = require("lunamark.util") - ---- Returns a new XML writer. --- For a list of fields, see [lunamark.writer.generic]. -function M.new(options) - options = options or {} - local Xml = generic.new(options) - - Xml.container = "section" - -- {1,2} means: a second level header inside a first-level - local header_level_stack = {} - - function Xml.start_section(level) - header_level_stack[#header_level_stack + 1] = level - return "<" .. Xml.container .. ">" - end - - function Xml.stop_section(level) - local len = #header_level_stack - if len == 0 then - return "" - else - local last = header_level_stack[len] - local res = {} - while last >= level do - header_level_stack[len] = nil - table.insert(res, "") - len = len - 1 - last = (len > 0 and header_level_stack[len]) or 0 - end - return table.concat(res, Xml.containersep) - end - end - - Xml.linebreak = "" - - local escape = util.escaper { - ["<" ] = "<", - [">" ] = ">", - ["&" ] = "&", - ["\"" ] = """, - ["'" ] = "'" - } - - Xml.string = escape - - return Xml -end - -return M diff --git a/sile.1.in b/sile.1.in index 3fdc46541..69626942a 100644 --- a/sile.1.in +++ b/sile.1.in @@ -36,7 +36,7 @@ Other available backends include \fIcairo\fR, \fIdebug\fR, \fItext\fR, and \fIdu Set the document class. The default for documents that do not specify is \fIplain\fR. Can be used to either change the default class or to override the class specified in a document. -Other default classes include \fIbase\fR, \fIbible\fR, \fIbook\fR, \fIdiglot\fR, \fIdocbook\fR, \fIdocbook.sil \fIjbook\fR, \fIjplain\fR, \fIletter\fR, \fImarkdown\fR, \fIpecha\fR, \fItbook\fR, \fItplain\fR, and \fItriglot\fR. +Other default classes include \fIbase\fR, \fIbible\fR, \fIbook\fR, \fIdiglot\fR, \fIdocbook\fR, \fIdocbook.sil \fIjbook\fR, \fIjplain\fR, \fIletter\fR, \fIpecha\fR, \fItbook\fR, \fItplain\fR, and \fItriglot\fR. .TP .BR \-d ", " \-\-debug= \fIvalue\fR[,\fIvalue\fR] Debug SILE's operation. From 84269555928cc1d66743ad8262dd80b4a6a0dbb2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 12:29:18 +0300 Subject: [PATCH 004/357] chore(core): Begin work on Rust wrapper (again) --- .gitignore | 5 +++++ Cargo.lock | 7 +++++++ Cargo.toml | 16 ++++++++++++++++ src/main.rs | 3 +++ 4 files changed, 31 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index f28c1d13f..9575dfae3 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,8 @@ core/version.lua # Nix symlink to builds /result + + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..3f0125c9f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "sile" +version = "0.14.8" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..0f10c1808 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sile" +version = "0.14.8" +edition = "2021" +description = "Simon’s Improved Layout Engine" +authors = [ + "Simon Cozens", + "Caleb Maclennan ", + "Olivier Nicole", + "Didier Willis" +] +rust-version = "1.68" +homepage = "https://sile-typesetter.org" +license = "MIT" + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 000000000..e7a11a969 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} From 4836a9369cdd9bd6da54e443d7fefb37a6bd4558 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 13 Apr 2023 00:15:34 +0300 Subject: [PATCH 005/357] chore(core)!: Remove deprecated package manager BREAKING CHANGE: The internal package manager that installed stuff to the system from inside SILE was deprecated back in v0.13.2. It is now completely removed. External 3rd party packages are fully supported using LuaRocks and are much more robust. --- .luacheckrc | 4 +- .luarc.json | 4 +- core/deprecations.lua | 22 +++++ core/packagemanager.lua | 211 ---------------------------------------- core/sile.lua | 3 +- sile.in | 4 - 6 files changed, 25 insertions(+), 223 deletions(-) delete mode 100644 core/packagemanager.lua diff --git a/.luacheckrc b/.luacheckrc index 55574cc41..610918736 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -25,9 +25,7 @@ globals = { "SU", "luautf8", "pl", - "fluent", - "SYSTEM_SILE_PATH", - "SHARED_LIB_EXT" + "fluent" } max_line_length = false ignore = { diff --git a/.luarc.json b/.luarc.json index 3b7cf8fcd..cc25312fe 100644 --- a/.luarc.json +++ b/.luarc.json @@ -6,9 +6,7 @@ "SU", "luautf8", "pl", - "fluent", - "SYSTEM_SILE_PATH", - "SHARED_LIB_EXT" + "fluent" ], "Lua.workspace.preloadFileSize": 5120, "Lua.workspace.checkThirdParty": false diff --git a/core/deprecations.lua b/core/deprecations.lua index faaece860..73f050dee 100644 --- a/core/deprecations.lua +++ b/core/deprecations.lua @@ -82,3 +82,25 @@ function SILE.doTexlike (doc) [[Add format argument "sil" to skip content detection and assume SIL input]]) return SILE.processString(doc, "sil") end + +local nopackagemanager = function () + SU.deprecated("SILE.PackageManager", nil, "0.13.2", "0.15.0", [[ + The built in SILE package manager has been completely deprecated. In its place + SILE can now load classes, packages, and other resources installed via + LuaRocks. Any SILE package may be published on LuaRocks.org or any private + repository. Rocks may be installed to the host system root filesystem, a user + directory, or a custom location. Please see the SILE manual for usage + instructions. Package authors especially can review the template repository + on GitHub for how to create a package. + ]]) +end + +SILE.PackageManager = {} +setmetatable(SILE.PackageManager, { + __index = nopackagemanager +}) + +-- luacheck: ignore updatePackage +-- luacheck: ignore installPackage +updatePackage = nopackagemanager +installPackage = nopackagemanager diff --git a/core/packagemanager.lua b/core/packagemanager.lua deleted file mode 100644 index 10b98b70e..000000000 --- a/core/packagemanager.lua +++ /dev/null @@ -1,211 +0,0 @@ -local lfs = require("lfs") - -local catalogueURL = "https://raw.githubusercontent.com/sile-typesetter/sile-packages/master/packages.lua" -local packageHome = tostring(SYSTEM_SILE_PATH) .. "/packagemanager/" -local catalogueHome = packageHome .. "catalogue.lua" -local installedCatalogue = packageHome .. "installed.lua" - -local http = require("ssl.https") -local recentlyUpdated = false -local recentlyReloaded = false -local origcpath = package.cpath -- for idempotence -local origpath = package.path - -SILE.PackageManager = { - installed = {}, - Catalogue = {} -} - -local _deprecated = function () - SU.deprecated("SILE.PackageManager", nil, "0.13.2", "0.15.0", [[ - The built in SILE package manager has been completely deprecated. In its place - SILE can now load classes, packages, and other resources installed via - LuaRocks. Any SILE package may be published on LuaRocks.org or any private - repository. Rocks may be installed to the host system root filesystem, a user - directory, or a custom location. Please see the SILE manual for usage - instructions. Package authors especially can review the template repository - on GitHub for how to create a package. - ]]) -end - -local function loadInSandbox(untrusted_code) - _deprecated() - if _ENV then -- simple Lua 5.2 version check - local env = {} - local untrusted_function, message = load(untrusted_code, nil, 't', env) - if not untrusted_function then return nil, message end - return pcall(untrusted_function) - else - if untrusted_code:byte(1) == 27 then return nil, "binary bytecode prohibited" end - local untrusted_function, message = load(untrusted_code) - if not untrusted_function then return nil, message end - -- luacheck: globals setfenv env - -- (At least there is in Lua 5.1) - setfenv(untrusted_function, env) - return pcall(untrusted_function) - end -end - -local function dumpTable(tbl) - _deprecated() - if type(tbl) == 'table' then - local str = '{ ' - for k, v in pairs(tbl) do - if type(k) ~= 'number' then k = '"'..k..'"' end - str = str .. '['..k..'] = ' .. dumpTable(v) .. ',' - end - return str .. '} ' - else - -- This only works because we are only storing strings! - return '"' .. tostring(tbl) .. '"' - end -end - -local function fixupPaths() - local paths = "" - local cpaths = "" - for pkg, _ in pairs(SILE.PackageManager.installed) do - _deprecated() - paths = paths .. packageHome .. pkg .. '/?.lua;' - cpaths = cpaths .. packageHome .. pkg .. "/?."..SHARED_LIB_EXT.. ";" - end - if paths:len() >= 1 then package.path = paths .. ";" .. origpath end - if cpaths:len() >= 1 then package.cpath = cpaths .. ";" .. origcpath end -end - -local function saveInstalled() - _deprecated() - local dump = dumpTable(SILE.PackageManager.installed) - local file, err = io.open(installedCatalogue, "w") - if err then - SU.error("Could not write installed package list at"..installedCatalogue..": "..err) - end - file:write("return "..dump) - file:close() - fixupPaths() -end - -local function updateCatalogue () - if not lfs.attributes(packageHome) then - if not lfs.mkdir(packageHome) then - SU.error("Error making package manager home directory: "..packageHome) - end - end - print("Loading catalogue from "..catalogueURL) - local result, statuscode, _ = http.request(catalogueURL) - if statuscode ~= 200 then - SU.error("Could not load catalogue from "..catalogueURL..": "..statuscode) - end - local file, err = io.open(catalogueHome, "w") - if err then - SU.error("Could not write package catalogue at"..catalogueHome..": "..err) - end - print("Writing "..(#result).." bytes to "..catalogueHome) - file:write(result) - file:close() - recentlyUpdated = true - recentlyReloaded = false -end - -local function loadInstalledCatalogue() - local file = io.open(installedCatalogue, "r") - if file ~= nil then - local contents = file:read("*all") - local success, res = loadInSandbox(contents) - if not success then - SU.error("Error loading installed package list: "..res) - end - SILE.PackageManager.installed = res - end -end - -local function reloadCatalogue() - local file = io.open(catalogueHome, "r") - if file ~= nil then - local contents = file:read("*all") - local success, res = loadInSandbox(contents) - if not success then - SU.error("Error loading package catalogue: "..res) - end - SILE.PackageManager.Catalogue = res - end - loadInstalledCatalogue() - print("Package catalogue reloaded") - recentlyReloaded = true -end - --- These functions are global so they can be used from the REPL --- luacheck: ignore updatePackage --- luacheck: ignore installPackage - -function updatePackage(packageName, branch) - _deprecated() - local target = packageHome .. packageName - -- Are we already there? - if SILE.PackageManager.installed[packageName] == branch and branch ~= "master" then - print("Nothing to do!") - return true - end - local cwd = lfs.currentdir() - local _, err = lfs.chdir(target) - if err then - SU.warn("Package directory "..target.." went away! Trying again...") - SILE.PackageManager.installed[packageName] = nil - saveInstalled() - installPackage(packageName) - end - - local ret = os.execute("git pull") - if not ret then - SU.error("Error updating repository for package "..packageName..": "..ret) - end - ret = os.execute("git checkout "..branch) - if not ret then - SU.error("Error updating repository for package "..packageName..": "..ret) - end - lfs.chdir(cwd) - SILE.PackageManager.installed[packageName] = branch - saveInstalled() -end - -function installPackage(packageName) - _deprecated() - if not recentlyUpdated then updateCatalogue() end - if not recentlyReloaded then reloadCatalogue() end - if not SILE.PackageManager.Catalogue[packageName] then - -- Add support for URL-based package names later. - SU.error("Can't install "..packageName..": package not known") - end - - local metadata = SILE.PackageManager.Catalogue[packageName] - - -- Check dependencies - if metadata.depends then - for _, pkg in ipairs(metadata.depends) do - if not SILE.PackageManager.installed[pkg] then - print(packageName.." requires "..pkg..", installing that...") - installPackage(pkg) - end - end - end - - -- Clone repo in temp directory - if metadata.repository then - local branch = metadata.version or "master" - local target = packageHome .. packageName - if lfs.attributes(target) then - updatePackage(packageName, branch) - else - local ret = os.execute("git clone -c advice.detachedHead=false -b "..branch.." "..metadata.repository.." "..target) - if not ret then -- This should return status code but it's returning true for me... - SU.error("Error cloning repository for package "..packageName..": "..ret) - end - end - SILE.PackageManager.installed[packageName] = branch - saveInstalled() - end -end - --- Set up the world -loadInstalledCatalogue() -fixupPaths() diff --git a/core/sile.lua b/core/sile.lua index d19f5cdf8..4073168dd 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -443,7 +443,6 @@ end SILE.settings = require("core.settings")() require("core.hyphenator-liang") require("core.languages") -require("core.packagemanager") SILE.linebreak = require("core.break") require("core.frame") SILE.cli = require("core.cli") @@ -451,7 +450,7 @@ SILE.repl = require("core.repl") SILE.font = require("core.font") -- For warnings and shims scheduled for removal that are easier to keep track --- of when they are not spead across so many locations... +-- of when they are not spread across so many locations... require("core/deprecations") return SILE diff --git a/sile.in b/sile.in index 94695fef6..37582c548 100755 --- a/sile.in +++ b/sile.in @@ -1,9 +1,5 @@ #!@LUA@ --- globals used only in core/packagemanager, soon to be deprecated -SYSTEM_SILE_PATH = "@SILE_PATH@" -SHARED_LIB_EXT = "@SHARED_LIB_EXT@" - local executable = debug.getinfo(1, "S").source local luaversion = _VERSION:match("%d+%.%d+") From 492f1d8f74e2bf05d38667c881c56b92eeaf87a9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 15:53:26 +0300 Subject: [PATCH 006/357] chore(cli): Move Lua based CLI out of the way for adventures in RIIR --- Makefile.am | 8 ++++---- configure.ac | 4 ++-- sile.1.in => sile-lua.1.in | 0 3 files changed, 6 insertions(+), 6 deletions(-) rename sile.1.in => sile-lua.1.in (100%) diff --git a/Makefile.am b/Makefile.am index 5ffe5aac6..202ee56ff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,7 +43,7 @@ TESTPREVIEWS ?= $(addsuffix .pdf,$(basename $(filter-out $(_DISABLEDSRCS),$(_TES include $(wildcard Makefile-distfiles) MANUAL := documentation/sile.pdf -SILE := $(PACKAGE_NAME) +SILE := $(PACKAGE_NAME)-lua if MANUAL _MANUAL = $(MANUAL) @@ -51,11 +51,11 @@ endif nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = core/features.lua core/version.lua $(LUAMODULES) -dist_man_MANS = sile.1 +dist_man_MANS = sile-lua.1 dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE lua-libraries/LICENSE-lunamark -bin_SCRIPTS = sile +bin_SCRIPTS = sile-lua EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles EXTRA_DIST += build-aux/action-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh @@ -220,7 +220,7 @@ luarocks-lint: $(LUAMODSPEC) luacheck: $(LUACHECK) -j$(shell nproc) -q . -busted: $(SILE) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) +busted: $(SILELUA) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) set -f; IFS=';' if SYSTEM_LUAROCKS packagecpath=(./{,core/}?.$(SHARED_LIB_EXT)) diff --git a/configure.ac b/configure.ac index 4981a75bc..bf6c292c9 100644 --- a/configure.ac +++ b/configure.ac @@ -248,8 +248,8 @@ AC_SUBST([SILE_LIB_PATH]) AX_SUBST_MAN_DATE AC_CONFIG_FILES([build-aux/list-dist-files.sh], [chmod +x build-aux/list-dist-files.sh]) -AC_CONFIG_FILES([Makefile src/Makefile sile.1 core/features.lua core/version.lua]) -AC_CONFIG_FILES([sile tests/regressions.pl], [chmod +x sile tests/regressions.pl]) +AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/version.lua]) +AC_CONFIG_FILES([sile-lua:sile.in tests/regressions.pl], [chmod +x sile-lua tests/regressions.pl]) AC_ARG_PROGRAM diff --git a/sile.1.in b/sile-lua.1.in similarity index 100% rename from sile.1.in rename to sile-lua.1.in From 242de51a72b1e886c261491fdf2a91590b43b4af Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 15:26:58 +0300 Subject: [PATCH 007/357] chore(tooling): Add configure time check for Rust compiler --- configure.ac | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/configure.ac b/configure.ac index bf6c292c9..fae991134 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,12 @@ LT_INIT([dlopen]) AC_CANONICAL_HOST +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug],[Build Rust code with debugging information [default=no]]), + [debug_release=$enableval], + [debug_release=no]) +AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"]) + AC_ARG_ENABLE([dependency-checks], AS_HELP_STRING([--disable-dependency-checks], [Disable dependency checks])) @@ -203,7 +209,20 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_PROGVAR([perl]) ]) + AX_PROGVAR([cargo]) + AX_PROGVAR([rustc]) + +]) + +AC_MSG_CHECKING(whether to build Rust code with debugging information) +AM_COND_IF([DEBUG_RELEASE], [ + AC_MSG_RESULT(yes) + RUST_TARGET_SUBDIR=debug +], [ + AC_MSG_RESULT(no) + RUST_TARGET_SUBDIR=release ]) +AC_SUBST([RUST_TARGET_SUBDIR]) AM_CONDITIONAL([APPKIT], [test "x$have_appkit" = "xyes"]) AM_CONDITIONAL([ICU], [test "x$with_icu" = "xyes"]) From 4bb6678239e955b7af03705df2c273520cc261e4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 15:00:19 +0300 Subject: [PATCH 008/357] chore(cli): Add boilerplate for Clap-based CLI --- Cargo.lock | 417 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 47 +++++- build.rs | 75 +++++++++ src/bin/sile.rs | 10 ++ src/cli.rs | 6 + src/lib.rs | 6 + src/main.rs | 3 - 7 files changed, 557 insertions(+), 7 deletions(-) create mode 100644 build.rs create mode 100644 src/bin/sile.rs create mode 100644 src/cli.rs create mode 100644 src/lib.rs delete mode 100644 src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 3f0125c9f..68b12afd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,423 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-wincon", + "concolor-override", + "concolor-query", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + +[[package]] +name = "anstyle-parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-wincon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +dependencies = [ + "anstyle", + "windows-sys 0.45.0", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "clap" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c22dcfb410883764b29953103d9ef7bb8fe21b3fa1158bc99986c2067294bd" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + +[[package]] +name = "clap_mangen" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4237e29de9c6949982ba87d51709204504fb8ed2fd38232fcb1e5bf7d4ba48c8" +dependencies = [ + "clap", + "roff", +] + +[[package]] +name = "concolor-override" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" + +[[package]] +name = "concolor-query" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" +dependencies = [ + "windows-sys 0.45.0", +] + +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "libc" +version = "0.2.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" + +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "roff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" + +[[package]] +name = "rustix" +version = "0.37.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + [[package]] name = "sile" version = "0.14.8" +dependencies = [ + "clap", + "clap_complete", + "clap_mangen", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/Cargo.toml b/Cargo.toml index 0f10c1808..293a28bc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,13 +4,52 @@ version = "0.14.8" edition = "2021" description = "Simon’s Improved Layout Engine" authors = [ - "Simon Cozens", - "Caleb Maclennan ", - "Olivier Nicole", - "Didier Willis" + "Simon Cozens", + "Caleb Maclennan ", + "Olivier Nicole", + "Didier Willis" ] rust-version = "1.68" homepage = "https://sile-typesetter.org" license = "MIT" +build = "build.rs" + +[[bin]] +name = "sile" +required-features = ["cli"] [dependencies] + + [dependencies.clap] + version = "4.2" + optional = true + features = [ "derive", "wrap_help" ] + +[build-dependencies] + + [build-dependencies.clap_complete] + version = "4.2" + optional = true + + [build-dependencies.clap_mangen] + version = "0.2" + optional = true + + [build-dependencies.clap] + version = "4.0" + optional = true + features = [ "derive" ] + +[features] +default = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"] +completions = ["cli", "clap_complete"] +cli = ["clap"] +bash = ["completions"] +elvish = ["completions"] +fish = ["completions"] +manpage = ["clap_mangen"] +powershell = ["completions"] +zsh = ["completions"] + +[profile.release] +lto = true diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..da32a2bc0 --- /dev/null +++ b/build.rs @@ -0,0 +1,75 @@ +#[cfg(feature = "completions")] +use clap::CommandFactory; +#[cfg(feature = "completions")] +use clap_complete::generator::generate_to; +#[cfg(feature = "completions")] +use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; +#[cfg(feature = "manpage")] +use clap_mangen::Man; +use std::env; +#[cfg(feature = "completions")] +use std::{fs, path}; + +#[cfg(feature = "completions")] +include!("src/cli.rs"); + +fn main() { + #[cfg(feature = "manpage")] + generate_manpage(); + #[cfg(feature = "completions")] + generate_shell_completions(); +} + +/// Generate man page +#[cfg(feature = "manpage")] +fn generate_manpage() { + let out_dir = match env::var_os("OUT_DIR") { + None => return, + Some(out_dir) => out_dir, + }; + let manpage_dir = path::Path::new(&out_dir); + fs::create_dir_all(manpage_dir).expect("Unable to create directory for generated manpages"); + let app = Cli::command(); + let bin_name: &str = app + .get_bin_name() + .expect("Could not retrieve bin-name from generated Clap app"); + let app = Cli::command(); + let man = Man::new(app); + let mut buffer: Vec = Default::default(); + man.render(&mut buffer) + .expect("Unable to render man page to UTF-8 string"); + fs::write(manpage_dir.join(format!("{bin_name}.1")), buffer) + .expect("Unable to write manepage to file"); +} + +/// Generate shell completion files from CLI interface +#[cfg(feature = "completions")] +fn generate_shell_completions() { + let out_dir = match env::var_os("OUT_DIR") { + None => return, + Some(out_dir) => out_dir, + }; + let completions_dir = path::Path::new(&out_dir).join("completions"); + fs::create_dir_all(&completions_dir) + .expect("Could not create directory in which to place completions"); + let app = Cli::command(); + let bin_name: &str = app + .get_bin_name() + .expect("Could not retrieve bin-name from generated Clap app"); + let mut app = Cli::command(); + #[cfg(feature = "bash")] + generate_to(Bash, &mut app, bin_name, &completions_dir) + .expect("Unable to generate bash completions"); + #[cfg(feature = "elvish")] + generate_to(Elvish, &mut app, bin_name, &completions_dir) + .expect("Unable to generate elvish completions"); + #[cfg(feature = "fish")] + generate_to(Fish, &mut app, bin_name, &completions_dir) + .expect("Unable to generate fish completions"); + #[cfg(feature = "powershell")] + generate_to(PowerShell, &mut app, bin_name, &completions_dir) + .expect("Unable to generate powershell completions"); + #[cfg(feature = "zsh")] + generate_to(Zsh, &mut app, bin_name, &completions_dir) + .expect("Unable to generate zsh completions"); +} diff --git a/src/bin/sile.rs b/src/bin/sile.rs new file mode 100644 index 000000000..1c5853eea --- /dev/null +++ b/src/bin/sile.rs @@ -0,0 +1,10 @@ +use clap::CommandFactory; + +use sile::cli::Cli; + +fn main() -> sile::Result<()> { + let app = Cli::command(); + let matches = app.get_matches(); + println!("Hello, world!"); + Ok(()) +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 000000000..e43aa9b1b --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,6 @@ +use clap::Parser; + +/// The SILE typesetter, Lua wrapped in Rust. +#[derive(Parser, Debug)] +#[clap(author, bin_name = "sile")] +pub struct Cli {} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..096aaab2c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,6 @@ +use std::{error, result}; + +#[cfg(feature = "cli")] +pub mod cli; + +pub type Result = result::Result>; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a969..000000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} From ea027a5c2999eb84d40f73a73953293c13229720 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 15:18:08 +0300 Subject: [PATCH 009/357] chore(cli): Bring version info to Rust CLI --- Cargo.lock | 305 +++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 5 + build.rs | 11 ++ src/bin/sile.rs | 3 +- 4 files changed, 322 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68b12afd5..fe3d618c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,6 +42,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "anyhow" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" + [[package]] name = "bitflags" version = "1.3.2" @@ -53,6 +59,15 @@ name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" @@ -97,7 +112,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] @@ -131,6 +146,26 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "enum-iterator" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "706d9e7cf1c7664859d79cd524e4e53ea2b67ea03c98cc2870c5e539695d597e" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355f93763ef7b0ae1c43c4d8eccc9d5848d84ad1a1d8ce61c421d1ac85a19d05" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "errno" version = "0.3.0" @@ -152,6 +187,40 @@ dependencies = [ "libc", ] +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "getset" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "git2" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "url", +] + [[package]] name = "heck" version = "0.4.1" @@ -164,6 +233,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "io-lifetimes" version = "1.0.10" @@ -187,24 +266,108 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + [[package]] name = "libc" version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +[[package]] +name = "libgit2-sys" +version = "0.14.2+1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + [[package]] name = "once_cell" version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.56" @@ -243,6 +406,18 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "serde" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" + [[package]] name = "sile" version = "0.14.8" @@ -250,6 +425,7 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", + "vergen", ] [[package]] @@ -258,6 +434,17 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.13" @@ -279,18 +466,134 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vergen" +version = "7.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" +dependencies = [ + "anyhow", + "cfg-if", + "enum-iterator", + "getset", + "git2", + "rustversion", + "thiserror", + "time", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "windows-sys" version = "0.45.0" diff --git a/Cargo.toml b/Cargo.toml index 293a28bc5..db2d23301 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,11 @@ required-features = ["cli"] optional = true features = [ "derive" ] + [build-dependencies.vergen] + version = "7.4" + default-features = false + features = [ "build", "git" ] + [features] default = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"] completions = ["cli", "clap_complete"] diff --git a/build.rs b/build.rs index da32a2bc0..3a61e66e0 100644 --- a/build.rs +++ b/build.rs @@ -9,11 +9,22 @@ use clap_mangen::Man; use std::env; #[cfg(feature = "completions")] use std::{fs, path}; +use vergen::{vergen, Config}; #[cfg(feature = "completions")] include!("src/cli.rs"); fn main() { + let mut flags = Config::default(); + if let Ok(val) = env::var("SILE_VERSION") { + *flags.git_mut().semver_mut() = false; + println!("cargo:rustc-env=VERGEN_GIT_SEMVER={val}") + }; + if vergen(flags).is_err() { + let mut flags = Config::default(); + *flags.git_mut().enabled_mut() = false; + vergen(flags).expect("Unable to generate the cargo keys!"); + } #[cfg(feature = "manpage")] generate_manpage(); #[cfg(feature = "completions")] diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 1c5853eea..9b6c352d4 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -3,7 +3,8 @@ use clap::CommandFactory; use sile::cli::Cli; fn main() -> sile::Result<()> { - let app = Cli::command(); + let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); + let app = Cli::command().version(version); let matches = app.get_matches(); println!("Hello, world!"); Ok(()) From 394be74ae8f3674cdd31393f0961ee34e5c38c13 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 15:36:33 +0300 Subject: [PATCH 010/357] chore(tooling): Add adapted autotools+cargo interface boilerplate --- Makefile.am | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-- configure.ac | 46 +++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 202ee56ff..369a72166 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,7 +43,7 @@ TESTPREVIEWS ?= $(addsuffix .pdf,$(basename $(filter-out $(_DISABLEDSRCS),$(_TES include $(wildcard Makefile-distfiles) MANUAL := documentation/sile.pdf -SILE := $(PACKAGE_NAME)-lua +SILELUA := $(PACKAGE_NAME)-lua if MANUAL _MANUAL = $(MANUAL) @@ -51,11 +51,14 @@ endif nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = core/features.lua core/version.lua $(LUAMODULES) -dist_man_MANS = sile-lua.1 +dist_man_MANS = sile.1 sile-lua.1 dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE lua-libraries/LICENSE-lunamark bin_SCRIPTS = sile-lua +bin_PROGRAMS = sile +sile_SOURCES = Cargo.toml build.rs src/bin/sile.rs src/lib.rs src/cli.rs +EXTRA_sile_SOURCES = Cargo.lock .version EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles EXTRA_DIST += build-aux/action-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh @@ -71,6 +74,78 @@ CLEANFILES = $(bin_SCRIPTS) $(dist_man_MANS) $(BUILT_SOURCES) $(DEPFILES) $(ACTU Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ +if DEBUG_RELEASE +CARGO_RELEASE_ARGS = --all-features +else +CARGO_RELEASE_ARGS = --release --locked --all-features +endif + +CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target +RUST_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) +_RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir +COMPLETIONS_OUT_DIR = completions + +if ENABLE_BASH_COMPLETION +bashcompletiondir = $(BASH_COMPLETION_DIR) +nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_bashcompletion_DATA) +endif + +if ENABLE_FISH_COMPLETION +fishcompletiondir = $(FISH_COMPLETION_DIR) +nodist_fishcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish +CLEANFILES += $(nodist_fishcompletion_DATA) +endif + +if ENABLE_ZSH_COMPLETION +zshcompletiondir = $(ZSH_COMPLETION_DIR) +nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_zshcompletion_DATA) +endif + +export SILE_VERSION = v$(VERSION) +SILE := $(PACKAGE_NAME)$(EXEEXT) + +# Leave some tips for cargo to use so CLI knows where it is +export CONFIGURE_PREFIX = $(prefix)/ +export CONFIGURE_DATADIR = $(datadir)/ +export CONFIGURE_BINDIR = $(bindir)/ + +CARGO_VERBOSE = $(cargo_verbose_$(V)) +cargo_verbose_ = $(cargo_verbose_$(AM_DEFAULT_VERBOSITY)) +cargo_verbose_0 = +cargo_verbose_1 = --verbose + +$(COMPLETIONS_OUT_DIR): + $(MKDIR_P) $@ + +$(SILE): $(RUST_BIN) + $(INSTALL) $(RUST_BIN) $@ + +$(PACKAGE_NAME).1: $(RUST_BIN) + $(INSTALL) -D $$(cat $(_RUST_OUT))/$@ $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).bash $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).elv: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).elv $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).fish $@ + +$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME).ps1: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME).ps1 $@ + +$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ + +$(_RUST_OUT) $(RUST_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) + cd $(top_srcdir) + $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_RELEASE_ARGS) + $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_RELEASE_ARGS) | + $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) + _BRANCH_REF != $(AWK) '{print ".git/" $$2}' .git/HEAD 2>/dev/null ||: .version: $(_BRANCH_REF) diff --git a/configure.ac b/configure.ac index fae991134..f393816d6 100644 --- a/configure.ac +++ b/configure.ac @@ -89,7 +89,8 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_FONT(Gentium Plus) - AC_PATH_PROG([PDFINFO], [pdfinfo]) + AX_PROGVAR([pdfinfo]) + AX_PROGVAR([jq]) AC_MSG_CHECKING([for OS X]) have_appkit=no @@ -224,6 +225,49 @@ AM_COND_IF([DEBUG_RELEASE], [ ]) AC_SUBST([RUST_TARGET_SUBDIR]) +AC_ARG_WITH([bash-completion-dir], + AS_HELP_STRING([--with-bash-completion-dir[=PATH]], + [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_bash_completion_dir=yes]) +if test "x$with_bash_completion_dir" = "xyes"; then + PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], + [BASH_COMPLETION_DIR="`pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion`"], + [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) + else + BASH_COMPLETION_DIR="$with_bash_completion_dir" +fi +AC_SUBST([BASH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) + +AC_ARG_WITH([fish-completion-dir], + AS_HELP_STRING([--with-fish-completion-dir[=PATH]], + [Install the fish auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_fish_completion_dir=yes]) +if test "x$with_fish_completion_dir" = "xyes"; then + PKG_CHECK_MODULES([FISH_COMPLETION], [fish >= 3.0], + [FISH_COMPLETION_DIR="`pkg-config --define-variable=datadir=$datadir --variable=completionsdir fish`"], + [FISH_COMPLETION_DIR="$datadir/fish/vendor_completions.d"]) + else + FISH_COMPLETION_DIR="$with_fish_completion_dir" +fi +AC_SUBST([FISH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_FISH_COMPLETION],[test "x$with_fish_completion_dir" != "xno"]) + +AC_ARG_WITH([zsh-completion-dir], + AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], + [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_zsh_completion_dir=yes]) +if test "x$with_zsh_completion_dir" = "xyes"; then + ZSH_COMPLETION_DIR="$datadir/zsh/site-functions" +else + ZSH_COMPLETION_DIR="$with_zsh_completion_dir" +fi +AC_SUBST([ZSH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_ZSH_COMPLETION],[test "x$with_zsh_completion_dir" != "xno"]) + AM_CONDITIONAL([APPKIT], [test "x$have_appkit" = "xyes"]) AM_CONDITIONAL([ICU], [test "x$with_icu" = "xyes"]) From 540b0cf7d836bec9bd702ba09236bf14791df421 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Fri, 28 Apr 2023 21:34:42 +0200 Subject: [PATCH 011/357] feat(typesetter,shaper): Add automated italic correction heuristics --- languages/fr.lua | 3 + shapers/harfbuzz.lua | 9 +- src/justenoughharfbuzz.c | 8 ++ typesetters/base.lua | 191 ++++++++++++++++++++++++++++++++------- 4 files changed, 172 insertions(+), 39 deletions(-) diff --git a/languages/fr.lua b/languages/fr.lua index 5e3c25bc2..b707a1bce 100644 --- a/languages/fr.lua +++ b/languages/fr.lua @@ -67,6 +67,9 @@ local getSpaceGlue = function(options, parameter) SILE.settings:set("font.filename", options.filename) sg = sg:absolute() end) + -- Track a subtype on that kern: + -- See automated italic correction at the typesetter level. + sg.subtype = "punctspace" return sg end diff --git a/shapers/harfbuzz.lua b/shapers/harfbuzz.lua index ac0022707..b932ef867 100644 --- a/shapers/harfbuzz.lua +++ b/shapers/harfbuzz.lua @@ -121,11 +121,12 @@ function shaper.preAddNodes (_, items, nnodeValue) -- Check for complex nodes end function shaper.addShapedGlyphToNnodeValue (_, nnodevalue, shapedglyph) - if nnodevalue.complex then + -- Note: previously we stored the shaped items only for "complex" nodes + -- (nodevalue.comple). We now always do it, so as to have them at hand for + -- italic correction. + if not nnodevalue.items then nnodevalue.items = {} end + nnodevalue.items[#nnodevalue.items+1] = shapedglyph - if not nnodevalue.items then nnodevalue.items = {} end - nnodevalue.items[#nnodevalue.items+1] = shapedglyph - end if not nnodevalue.glyphString then nnodevalue.glyphString = {} end if not nnodevalue.glyphNames then nnodevalue.glyphNames = {} end table.insert(nnodevalue.glyphString, shapedglyph.gid) diff --git a/src/justenoughharfbuzz.c b/src/justenoughharfbuzz.c index edc2de790..336d49baa 100644 --- a/src/justenoughharfbuzz.c +++ b/src/justenoughharfbuzz.c @@ -228,6 +228,8 @@ int shape (lua_State *L) { double height = extents.y_bearing * point_size / upem; double tHeight = extents.height * point_size / upem; double width = glyph_pos[j].x_advance * point_size / upem; + double x_bearing = extents.x_bearing * point_size / upem; + double glyphWidth = extents.width * point_size / upem; /* The PDF model expects us to make positioning adjustments after a glyph is painted. For this we need to know the natural @@ -254,6 +256,12 @@ int shape (lua_State *L) { lua_pushstring(L, "depth"); lua_pushnumber(L, -tHeight - height); lua_settable(L, -3); + lua_pushstring(L, "x_bearing"); + lua_pushnumber(L, x_bearing); + lua_settable(L, -3); + lua_pushstring(L, "glyphWidth"); + lua_pushnumber(L, glyphWidth); + lua_settable(L, -3); } /* Cleanup */ hb_buffer_destroy(buf); diff --git a/typesetters/base.lua b/typesetters/base.lua index 6c6584884..24daed857 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -132,6 +132,13 @@ function typesetter.declareSettings(_) help = "Width to break lines at" }) + SILE.settings:declare({ + parameter = "typesetter.italicCorrection", + type = "boolean", + default = false, + help = "Whether italic correction is activated or not" + }) + end function typesetter:initState () @@ -315,18 +322,147 @@ function typesetter:breakIntoLines (nodelist, breakWidth) return self:breakpointsToLines(breakpoints) end -function typesetter.shapeAllNodes (_, nodelist) - local newNl = {} - for i = 1, #nodelist do - if nodelist[i].is_unshaped then - pl.tablex.insertvalues(newNl, nodelist[i]:shape()) +local function getLastShape(nodelist) + local last + if nodelist then + -- The node list may contain nnodes, penalties, kern and glue + -- We skip the latter, and retrieve the last shaped item. + for i = #nodelist, 1, -1 do + local n = nodelist[i] + if n.is_nnode then + local items = n.nodes[#n.nodes].value.items + last = items[#items] + break + end + if n.is_kern and n.subtype == "punctspace" then + -- Some languages such as French insert a special space around + -- punctuations. In those case, we should not need italic correction. + break + end + end + end + return last +end +local function getFirstShape(nodelist) + local first + if nodelist then + -- The node list may contain nnodes, penalties, kern and glue + -- We skip the latter, and retrieve the first shaped item. + for i = 1, #nodelist do + local n = nodelist[i] + if n.is_nnode then + local items = n.nodes[1].value.items + first = items[1] + break + end + if n.is_kern and n.subtype == "punctspace" then + -- Some languages such as French insert a special space around + -- punctuations. In those case, we should not need italic correction. + break + end + end + end + return first +end + +local function fromItalicCorrection (precShape, curShape) + local xOffset + if not curShape or not precShape then + xOffset = 0 + else + -- Computing italic correction is at best heuristics. + -- The strong assumption is that italic is slanted to the right. + -- Thus, the part of the character that goes beyond its width is usually + -- maximal at the top of the glyph. + -- E.g. consider a "f", that would be the top hook extent. + -- Pathological cases exist, such as fonts with a Q with a long tail, + -- but these will rarely occur in usual languages. For instance, Klingon's + -- "QaQ" might be an issue, but there's not much we can do... + -- Another assumption is that we can distribute that extent in proportion + -- with the next character's height. + -- This might not work that well with non-Latin scripts. + local d = precShape.glyphWidth + precShape.x_bearing + local delta = d > precShape.width and d - precShape.width or 0 + xOffset = precShape.height <= curShape.height + and delta + or delta * curShape.height / precShape.height + end + return xOffset +end + +local function toItalicCorrection (precShape, curShape) + if not SILE.settings:get("typesetter.italicCorrection") then return end + local xOffset + if not curShape or not precShape then + xOffset = 0 + else + -- Same assumptions as fromItalicCorrection(), but on the starting side of + -- the glyph. + local d = curShape.x_bearing + local delta = d < 0 and -d or 0 + xOffset = precShape.depth >= curShape.depth + and delta + or delta * precShape.depth / curShape.depth + end + return xOffset +end + +local function isItalicLike(nnode) + -- We could do... + -- return nnode and string.lower(nnode.options.style) == "italic" + -- But it's probably more robust to use the italic angle, so that + -- thin italic, oblique or slanted fonts etc. may work too. + local ot = require("core.opentype-parser") + local face = SILE.font.cache(nnode.options, SILE.shaper.getFace) + local font = ot.parseFont(face) + return font.post.italicAngle ~= 0 +end + +function typesetter.shapeAllNodes (_, nodelist, inplace) + inplace = SU.boolean(inplace, true) -- Compatibility with earlier versions + local newNodelist = {} + local prec + local precShapedNodes + for _, current in ipairs(nodelist) do + if current.is_unshaped then + local shapedNodes = current:shape() + + if SILE.settings:get("typesetter.italicCorrection") and prec then + local itCorrOffset + if isItalicLike(prec) and not isItalicLike(current) then + local precShape = getLastShape(precShapedNodes) + local curShape = getFirstShape(shapedNodes) + itCorrOffset = fromItalicCorrection(precShape, curShape) + elseif not isItalicLike(prec) and isItalicLike(current) then + local precShape = getLastShape(precShapedNodes) + local curShape = getFirstShape(shapedNodes) + itCorrOffset = toItalicCorrection(precShape, curShape) + end + if itCorrOffset then + newNodelist[#newNodelist+1] = SILE.nodefactory.kern({ + width = SILE.length(itCorrOffset), + subtype = "itcorr" + }) + end + end + + pl.tablex.insertvalues(newNodelist, shapedNodes) + + prec = current + precShapedNodes = shapedNodes else - newNl[#newNl+1] = nodelist[i] + prec = nil + newNodelist[#newNodelist+1] = current end end - for i =1, #newNl do nodelist[i]=newNl[i] end - if #nodelist > #newNl then - for i=#newNl+1, #nodelist do nodelist[i]=nil end + + if not inplace then + return newNodelist + end + + for i =1, #newNodelist do nodelist[i] = newNodelist[i] end + if #nodelist > #newNodelist then + for i= #newNodelist + 1, #nodelist do nodelist[i] = nil end end end @@ -641,12 +777,7 @@ end function typesetter:leaveHmode (independent) if self.state.hmodeOnly then - -- HACK HBOX - -- This should likely be an error, but may break existing uses - -- (although these are probably already defective). - -- See also comment HACK HBOX in typesetter:makeHbox(). - SU.warn([[Building paragraphs in this context may have unpredictable results. -It will likely break in future versions]]) + SU.error([[Paragraphs are forbidden in restricted horizontal mode.]]) end SU.debug("typesetter", "Leaving hmode") local margins = self:getMargins() @@ -877,33 +1008,23 @@ function typesetter:makeHbox (content) local recentContribution = {} local migratingNodes = {} - -- HACK HBOX - -- This is from the original implementation. - -- It would be somewhat cleaner to use a temporary typesetter state - -- (pushState/popState) rather than using the current one, removing - -- the processed nodes from it afterwards. However, as long - -- as leaving horizontal mode is not strictly forbidden here, it would - -- lead to a possibly different result (the output queue being skipped). - -- See also HACK HBOX comment in typesetter:leaveHmode(). - local index = #(self.state.nodes)+1 + self:pushState() self.state.hmodeOnly = true SILE.process(content) - self.state.hmodeOnly = false -- Wouldn't be needed in a temporary state + -- We must do a first pass for shaping the nnodes: + -- This is also where italic correction may occur. + local nodes = self:shapeAllNodes(self.state.nodes, false) + + -- Then we can process and measure the nodes. local l = SILE.length() local h, d = SILE.length(), SILE.length() - for i = index, #(self.state.nodes) do - local node = self.state.nodes[i] + for i = 1, #nodes do + local node = nodes[i] if node.is_migrating then migratingNodes[#migratingNodes+1] = node elseif node.is_unshaped then - local shape = node:shape() - for _, attr in ipairs(shape) do - recentContribution[#recentContribution+1] = attr - h = attr.height > h and attr.height or h - d = attr.depth > d and attr.depth or d - l = l + attr:lineContribution():absolute() - end + SU.error("DOH") elseif node.is_discretionary then -- HACK https://github.com/sile-typesetter/sile/issues/583 -- Discretionary nodes have a null line contribution... @@ -927,8 +1048,8 @@ function typesetter:makeHbox (content) h = node.height > h and node.height or h d = node.depth > d and node.depth or d end - self.state.nodes[i] = nil -- wouldn't be needed in a temporary state end + self:popState() local hbox = SILE.nodefactory.hbox({ height = h, From b46cd08c837273f013919934941b84cfea84a978 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 29 Apr 2023 11:37:11 +0200 Subject: [PATCH 012/357] test(typesetter): Add a test for automated italic correction --- tests/feat-italic-correction.expected | 458 ++++++++++++++++++++++++++ tests/feat-italic-correction.sil | 60 ++++ 2 files changed, 518 insertions(+) create mode 100644 tests/feat-italic-correction.expected create mode 100644 tests/feat-italic-correction.sil diff --git a/tests/feat-italic-correction.expected b/tests/feat-italic-correction.expected new file mode 100644 index 000000000..7dc7a5a4e --- /dev/null +++ b/tests/feat-italic-correction.expected @@ -0,0 +1,458 @@ +Set paper size 297.6377985 419.5275636 +Begin page +Mx 14.8819 +My 33.4764 +Set font Gentium Plus;16;400;;normal;;;LTR +T 2149 w=6.5625 (−) +Mx 25.6818 +T 11 w=5.0703 (() +Mx 30.7521 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 55.5958 +Set font Gentium Plus;16;400;;normal;;;LTR +T 12 w=5.0703 ()) +Mx 64.9035 +T 163 w=4.3516 (¡) +Mx 69.2551 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) +Mx 122.1385 +T 83 85 82 82 73 w=31.0859 (proof) +Mx 153.2244 +Set font Gentium Plus;16;400;;normal;;;LTR +T 4 w=4.3516 (!) +Mx 161.8134 +T 62 w=4.9219 ([) +Mx 166.7352 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 83 88 747 w=24.2578 (puff) +Mx 190.9930 +Set font Gentium Plus;16;400;;normal;;;LTR +T 64 w=4.9219 (]) +Mx 200.1523 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 224.9960 +Set font Gentium Plus;16;400;;normal;;;LTR +T 2011 w=5.2578 (²) +Mx 14.8819 +My 52.6764 +T 14 w=6.5625 (+) +Mx 25.6796 +T 11 w=5.0703 (() +Mx 31.2573 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 58.7886 +Set font Gentium Plus;16;400;;normal;;;LTR +T 12 w=5.0703 ()) +Mx 68.0941 +T 163 w=4.3516 (¡) +Mx 73.2269 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) +Mx 126.1084 +T 83 85 82 82 73 w=31.0859 (proof) +Mx 159.8111 +Set font Gentium Plus;16;400;;normal;;;LTR +T 4 w=4.3516 (!) +Mx 168.3979 +T 62 w=4.9219 ([) +Mx 173.3511 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 83 88 747 w=24.2578 (puff) +Mx 200.2965 +Set font Gentium Plus;16;400;;normal;;;LTR +T 64 w=4.9219 (]) +Mx 209.9932 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 237.2433 +Set font Gentium Plus;16;400;;normal;;;LTR +T 2011 w=5.2578 (²) +Mx 14.8819 +My 71.8764 +T 2149 w=6.5625 (−) +Mx 25.6864 +T 95 w=3.9063 (|) +Mx 29.5927 +T 11 w=5.0703 (() +Mx 34.6630 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 59.5067 +Set font Gentium Plus;16;400;;normal;;;LTR +T 12 w=5.0703 ()) +Mx 68.8191 +T 163 w=4.3516 (¡) +Mx 73.1707 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) +Mx 126.0583 +T 83 85 82 82 73 w=31.0859 (proof) +Mx 157.1443 +Set font Gentium Plus;16;400;;normal;;;LTR +T 4 w=4.3516 (!) +Mx 165.7379 +T 62 w=4.9219 ([) +Mx 170.6597 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 83 88 747 w=24.2578 (puff) +Mx 194.9176 +Set font Gentium Plus;16;400;;normal;;;LTR +T 64 w=4.9219 (]) +Mx 199.8394 +T 95 w=3.9063 (|) +Mx 14.8819 +My 91.0764 +T 14 w=6.5625 (+) +Mx 25.6848 +T 95 w=3.9063 (|) +Mx 29.5910 +T 11 w=5.0703 (() +Mx 35.1688 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 62.7000 +Set font Gentium Plus;16;400;;normal;;;LTR +T 12 w=5.0703 ()) +Mx 72.0107 +T 163 w=4.3516 (¡) +Mx 77.1435 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) +Mx 130.0297 +T 83 85 82 82 73 w=31.0859 (proof) +Mx 163.7324 +Set font Gentium Plus;16;400;;normal;;;LTR +T 4 w=4.3516 (!) +Mx 172.3244 +T 62 w=4.9219 ([) +Mx 177.2777 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 83 88 747 w=24.2578 (puff) +Mx 204.2230 +Set font Gentium Plus;16;400;;normal;;;LTR +T 64 w=4.9219 (]) +Mx 209.1449 +T 95 w=3.9063 (|) +Mx 14.8819 +My 110.2764 +T 2149 w=6.5625 (−) +Mx 25.6878 +T 169 w=7.7656 («) +Mx 36.8405 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 65.0713 +Set font Gentium Plus;16;400;;normal;;;LTR +T 170 w=7.7656 (») +Mx 77.0803 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 73 85 72 81 70 75 w=38.3594 (french) +Mx 119.2974 +T 83 85 82 82 73 w=31.0859 (proof) +Mx 152.4974 +Set font Gentium Plus;16;400;;normal;;;LTR +T 4 w=4.3516 (!) +Mx 161.0923 +T 11 w=5.0703 (() +Mx 166.1626 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 191.0064 +Set font Gentium Plus;16;400;;normal;;;LTR +T 12 w=5.0703 ()) +Mx 14.8819 +My 129.4764 +T 14 w=6.5625 (+) +Mx 25.6872 +T 169 w=7.7656 («) +Mx 36.8398 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 65.0704 +Set font Gentium Plus;16;400;;normal;;;LTR +T 170 w=7.7656 (») +Mx 77.0515 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 73 85 72 81 70 75 w=38.3594 (french) +Mx 119.2680 +T 83 85 82 82 73 w=31.0859 (proof) +Mx 152.4680 +Set font Gentium Plus;16;400;;normal;;;LTR +T 4 w=4.3516 (!) +Mx 161.0624 +T 11 w=5.0703 (() +Mx 166.6401 +Set font Gentium Plus;16;400;Italic;normal;;;LTR +T 739 88 747 w=24.8438 (fluff) +Mx 194.1714 +Set font Gentium Plus;16;400;;normal;;;LTR +T 12 w=5.0703 ()) +Mx 14.8819 +My 148.6764 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2531 w=6.3680 (−) +Mx 25.7546 +T 2403 w=4.9440 (() +Mx 30.6986 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 54.4266 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2404 w=4.9440 ()) +Mx 63.8754 +T 2372 w=3.9520 (¡) +Mx 67.8274 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +Mx 3.8880 +Mx 6.9440 +Mx 7.5360 +Mx 5.5200 +Mx 7.2000 +Mx 4.1920 +Mx 7.4400 +Mx 3.7920 +T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) +Mx 118.8441 +Mx 6.5120 +Mx 5.1520 +Mx 6.3680 +Mx 6.3680 +Mx 4.1920 +T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2371 w=3.9520 (!) +Mx 155.8928 +T 2407 w=4.3840 ([) +Mx 160.2768 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 604 634 816 w=22.0960 (puff) +Mx 182.3728 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2408 w=4.3840 (]) +Mx 191.2616 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 214.9896 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2328 w=4.0160 (²) +Mx 14.8819 +My 167.8764 +T 2530 w=6.3680 (+) +Mx 25.7524 +T 2403 w=4.9440 (() +Mx 31.4242 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 57.2482 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2404 w=4.9440 ()) +Mx 66.6947 +T 2372 w=3.9520 (¡) +Mx 72.3427 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +Mx 3.8880 +Mx 6.9440 +Mx 7.5360 +Mx 5.5200 +Mx 7.2000 +Mx 4.1920 +Mx 7.4400 +Mx 3.7920 +T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) +Mx 123.3573 +Mx 6.5120 +Mx 5.1520 +Mx 6.3680 +Mx 6.3680 +Mx 4.1920 +T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) +Mx 153.7652 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2371 w=3.9520 (!) +Mx 162.2198 +T 2407 w=4.3840 ([) +Mx 167.0311 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 604 634 816 w=22.0960 (puff) +Mx 191.2202 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2408 w=4.3840 (]) +Mx 200.8283 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 226.6523 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2328 w=4.0160 (²) +Mx 14.8819 +My 187.0764 +T 2531 w=6.3680 (−) +Mx 25.7597 +T 2627 w=2.6880 (|) +Mx 28.4477 +T 2403 w=4.9440 (() +Mx 33.3917 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 57.1197 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2404 w=4.9440 ()) +Mx 66.5734 +T 2372 w=3.9520 (¡) +Mx 70.5254 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +Mx 3.8880 +Mx 6.9440 +Mx 7.5360 +Mx 5.5200 +Mx 7.2000 +Mx 4.1920 +Mx 7.4400 +Mx 3.7920 +T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) +Mx 121.5472 +Mx 6.5120 +Mx 5.1520 +Mx 6.3680 +Mx 6.3680 +Mx 4.1920 +T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2371 w=3.9520 (!) +Mx 158.6009 +T 2407 w=4.3840 ([) +Mx 162.9849 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 604 634 816 w=22.0960 (puff) +Mx 185.0809 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2408 w=4.3840 (]) +Mx 189.4649 +T 2627 w=2.6880 (|) +Mx 14.8819 +My 206.2764 +T 2530 w=6.3680 (+) +Mx 25.7580 +T 2627 w=2.6880 (|) +Mx 28.4460 +T 2403 w=4.9440 (() +Mx 34.1177 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 59.9417 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2404 w=4.9440 ()) +Mx 69.3938 +T 2372 w=3.9520 (¡) +Mx 75.0418 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +Mx 3.8880 +Mx 6.9440 +Mx 7.5360 +Mx 5.5200 +Mx 7.2000 +Mx 4.1920 +Mx 7.4400 +Mx 3.7920 +T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) +Mx 126.0619 +Mx 6.5120 +Mx 5.1520 +Mx 6.3680 +Mx 6.3680 +Mx 4.1920 +T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) +Mx 156.4699 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2371 w=3.9520 (!) +Mx 164.9300 +T 2407 w=4.3840 ([) +Mx 169.7413 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 604 634 816 w=22.0960 (puff) +Mx 193.9304 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2408 w=4.3840 (]) +Mx 198.3144 +T 2627 w=2.6880 (|) +Mx 14.8819 +My 225.4764 +T 2531 w=6.3680 (−) +Mx 25.7604 +T 2441 w=7.2960 («) +Mx 36.6559 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 63.9835 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2442 w=7.2960 (») +Mx 75.7900 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +Mx 4.1920 +Mx 5.1520 +Mx 5.4880 +Mx 7.5360 +Mx 5.5200 +Mx 7.1200 +T 517 a=4.1920 607 a=5.4400 498 a=5.4880 567 a=7.4400 486 a=5.5200 527 a=7.1200 (french) +Mx 115.3085 +Mx 6.5120 +Mx 5.1520 +Mx 6.3680 +Mx 6.3680 +Mx 4.1920 +T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) +Mx 146.1469 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2371 w=3.9520 (!) +Mx 154.6094 +T 2403 w=4.9440 (() +Mx 159.5534 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 183.2814 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2404 w=4.9440 ()) +Mx 14.8819 +My 244.6764 +T 2530 w=6.3680 (+) +Mx 25.7599 +T 2441 w=7.2960 («) +Mx 36.6553 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 63.9827 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2442 w=7.2960 (») +Mx 75.5482 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +Mx 4.1920 +Mx 5.1520 +Mx 5.4880 +Mx 7.5360 +Mx 5.5200 +Mx 7.1200 +T 517 a=4.1920 607 a=5.4400 498 a=5.4880 567 a=7.4400 486 a=5.5200 527 a=7.1200 (french) +Mx 115.0662 +Mx 6.5120 +Mx 5.1520 +Mx 6.3680 +Mx 6.3680 +Mx 4.1920 +T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) +Mx 145.9046 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2371 w=3.9520 (!) +Mx 154.3666 +T 2403 w=4.9440 (() +Mx 160.0384 +Set font Cormorant Infant;16;400;Italic;normal;;;LTR +T 718 555 634 816 w=23.7280 (fluff) +Mx 185.8624 +Set font Cormorant Infant;16;400;;normal;;;LTR +T 2404 w=4.9440 ()) +End page +Finish diff --git a/tests/feat-italic-correction.sil b/tests/feat-italic-correction.sil new file mode 100644 index 000000000..9cca94056 --- /dev/null +++ b/tests/feat-italic-correction.sil @@ -0,0 +1,60 @@ +\begin[papersize=a6]{document} +\nofolios +\neverindent +\font[size=16pt] +\use[module=packages.math] +% Italic correction. +% The setting plays at paragraph level +% Disabled: +\set[parameter=typesetter.italicCorrection, value=false] +− (\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}² + +% Enabled: +\set[parameter=typesetter.italicCorrection, value=true] ++ (\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}² + +% The setting also works in hbox-built content. +% We want to be sure the hbox width is still properly computed +% Hence the | marks. +% Disabled: +\set[parameter=typesetter.italicCorrection, value=false] +− |\hbox{(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}]}| + +% Enabled: +\set[parameter=typesetter.italicCorrection, value=true] ++ |\hbox{(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}]}| + +% Extra check with French exceptions. +\language[main=fr]{% +% Disabled: +\set[parameter=typesetter.italicCorrection, value=false] +− «\em{fluff}» \em{french proof}! (\em{fluff}) + +% Enabled: +\set[parameter=typesetter.italicCorrection, value=true] ++ «\em{fluff}» \em{french proof}! (\em{fluff}) +} + +% Repeated with another font +\font[family=Cormorant Infant] +\set[parameter=typesetter.italicCorrection, value=false] +− (\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}² + +\set[parameter=typesetter.italicCorrection, value=true] ++ (\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}² + +\set[parameter=typesetter.italicCorrection, value=false] +− |\hbox{(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}]}| + +\set[parameter=typesetter.italicCorrection, value=true] ++ |\hbox{(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}]}| + +\language[main=fr]{% +\set[parameter=typesetter.italicCorrection, value=false] +− «\em{fluff}» \em{french proof}! (\em{fluff}) + +\set[parameter=typesetter.italicCorrection, value=true] ++ «\em{fluff}» \em{french proof}! (\em{fluff}) +} + +\end{document} From 99dec874f7f4985dbc4596402b821379541fa790 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 29 Apr 2023 16:21:36 +0200 Subject: [PATCH 013/357] docs(manual): Add section on automated italic correction --- documentation/c07-settings.sil | 40 ++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/documentation/c07-settings.sil b/documentation/c07-settings.sil index 0154f9c06..4c01506f5 100644 --- a/documentation/c07-settings.sil +++ b/documentation/c07-settings.sil @@ -212,7 +212,9 @@ saying that anyone who would letterspace lowercase would steal sheep.\footnote{H \section{Typesetter settings} The settings which affect SILE’s spacing controls have the most obvious effect -on a document; the typesetter itself has some knobs that can be twiddled: +on a document; the typesetter itself has some knobs that can be twiddled. + +\subsection{Paragraphing} \autodoc:setting{typesetter.widowpenalty} and \autodoc:setting{typesetter.orphanpenalty}\footnote{TeX users, please notice the renaming.} affect how strongly SILE is averse to @@ -260,7 +262,41 @@ off the filling glue at the end of the paragraph. \par \end{autodoc:example} -\medskip +\subsection{Automated italic correction} + +When an italicized word is followed or preceded by non-italicized text, the spacing may need to be adjusted, or “corrected”, so that the characters do not overlap. +You might thus want to insert some additional space between italicized words and non-italicized ones. + +Here is some gibberish exemplifying the issue. + +\begin{autodoc:example}% +\quad{}(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}ⁿ +\par +\end{autodoc:example} + +Inserting the necessary spaces manually is quite tedious, not to say impractical. +However, the concept of italic correction does not exist in OpenType fonts, and they do not provide the metrics that would allow a typesetting system to implement it easily.\footnote{% +This would apply to Graphite fonts too. +More generally, there is no known font format supporting kerning across font style changes. +(Well, some TeX fonts have such a possibility, but it does not really help here.)} +A heuristic approach is to use the difference between a glyph’s bounding box and its advance width (when switching from italics to roman) or its bearing width (the other way round). +Assuming italics is slanted forward (in left-to-right writing direction) and that italicized glyphs usually reach their maximum extent to the right towards their top (and towards their bottom, on their left side), then it is possible to approximate a fairly decent correction. + +Be aware, nevertheless, that this solution cannot be made perfect, even assuming a reasonable choice of fonts. +Pathological cases may still occur, even in latin scripts, for which there is no solution but using manual kerning. + +To enable automated italic correction, you can set the \autodoc:setting{typesetter.italicCorrection} setting to \code{true}. +Let’s turn it on and check how our previous gibberish now behaves. + +\begin{autodoc:example}% +\set[parameter=typesetter.italicCorrection, value=true]{% +\quad{}(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}ⁿ +\par} +\end{autodoc:example} + +Note that this setting only works on full paragraphs, or with horizontal boxes constructed with \autodoc:command{\hbox{}}.\footnote{% +That is, when characters are actually \em{shaped}, so that SILE knows their properties and metrics.} +In other terms, turning it on or off around just a few words in a sentence will not have the intended effect. \section{Linebreaking settings} From 4e1be5202f8816a48b8f5039f8917a7ff015bf3f Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Mon, 1 May 2023 21:54:29 +0200 Subject: [PATCH 014/357] chore(typesetter): Italic correction shall not cancel line breaks --- tests/feat-italic-correction.expected | 993 ++++++++++++++------------ tests/feat-italic-correction.sil | 18 +- typesetters/base.lua | 31 +- 3 files changed, 589 insertions(+), 453 deletions(-) diff --git a/tests/feat-italic-correction.expected b/tests/feat-italic-correction.expected index 7dc7a5a4e..9056935f1 100644 --- a/tests/feat-italic-correction.expected +++ b/tests/feat-italic-correction.expected @@ -1,458 +1,567 @@ Set paper size 297.6377985 419.5275636 Begin page Mx 14.8819 -My 33.4764 -Set font Gentium Plus;16;400;;normal;;;LTR -T 2149 w=6.5625 (−) -Mx 25.6818 -T 11 w=5.0703 (() -Mx 30.7521 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 55.5958 -Set font Gentium Plus;16;400;;normal;;;LTR -T 12 w=5.0703 ()) -Mx 64.9035 -T 163 w=4.3516 (¡) -Mx 69.2551 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) -Mx 122.1385 -T 83 85 82 82 73 w=31.0859 (proof) -Mx 153.2244 -Set font Gentium Plus;16;400;;normal;;;LTR -T 4 w=4.3516 (!) -Mx 161.8134 -T 62 w=4.9219 ([) -Mx 166.7352 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 83 88 747 w=24.2578 (puff) -Mx 190.9930 -Set font Gentium Plus;16;400;;normal;;;LTR -T 64 w=4.9219 (]) -Mx 200.1523 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 224.9960 -Set font Gentium Plus;16;400;;normal;;;LTR -T 2011 w=5.2578 (²) +My 32.6951 +Set font Gentium Plus;15;400;;normal;;;LTR +T 2149 w=6.1523 (−) +Mx 25.0090 +T 11 w=4.7534 (() +Mx 29.7624 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 53.0534 +Set font Gentium Plus;15;400;;normal;;;LTR +T 12 w=4.7534 ()) +Mx 61.7816 +T 163 w=4.0796 (¡) +Mx 65.8612 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=45.9668 (fancyful) +Mx 115.4414 +T 83 85 82 82 73 w=29.1431 (proof) +Mx 144.5845 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 152.6388 +T 62 w=4.6143 ([) +Mx 157.2531 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 83 88 747 w=22.7417 (puff) +Mx 179.9948 +Set font Gentium Plus;15;400;;normal;;;LTR +T 64 w=4.6143 (]) +Mx 188.5838 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 211.8748 +Set font Gentium Plus;15;400;;normal;;;LTR +T 2011 w=4.9292 (²) Mx 14.8819 -My 52.6764 -T 14 w=6.5625 (+) -Mx 25.6796 -T 11 w=5.0703 (() -Mx 31.2573 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 58.7886 -Set font Gentium Plus;16;400;;normal;;;LTR -T 12 w=5.0703 ()) -Mx 68.0941 -T 163 w=4.3516 (¡) -Mx 73.2269 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) -Mx 126.1084 -T 83 85 82 82 73 w=31.0859 (proof) -Mx 159.8111 -Set font Gentium Plus;16;400;;normal;;;LTR -T 4 w=4.3516 (!) -Mx 168.3979 -T 62 w=4.9219 ([) -Mx 173.3511 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 83 88 747 w=24.2578 (puff) -Mx 200.2965 -Set font Gentium Plus;16;400;;normal;;;LTR -T 64 w=4.9219 (]) -Mx 209.9932 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 237.2433 -Set font Gentium Plus;16;400;;normal;;;LTR -T 2011 w=5.2578 (²) +My 50.6951 +T 14 w=6.1523 (+) +Mx 25.0071 +T 11 w=4.7534 (() +Mx 30.2362 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 56.0468 +Set font Gentium Plus;15;400;;normal;;;LTR +T 12 w=4.7534 ()) +Mx 64.7730 +T 163 w=4.0796 (¡) +Mx 69.5851 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=45.9668 (fancyful) +Mx 119.1635 +T 83 85 82 82 73 w=29.1431 (proof) +Mx 150.7598 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 158.8123 +T 62 w=4.6143 ([) +Mx 163.4560 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 83 88 747 w=22.7417 (puff) +Mx 188.7172 +Set font Gentium Plus;15;400;;normal;;;LTR +T 64 w=4.6143 (]) +Mx 197.8102 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 223.3572 +Set font Gentium Plus;15;400;;normal;;;LTR +T 2011 w=4.9292 (²) Mx 14.8819 -My 71.8764 -T 2149 w=6.5625 (−) -Mx 25.6864 -T 95 w=3.9063 (|) -Mx 29.5927 -T 11 w=5.0703 (() -Mx 34.6630 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 59.5067 -Set font Gentium Plus;16;400;;normal;;;LTR -T 12 w=5.0703 ()) -Mx 68.8191 -T 163 w=4.3516 (¡) -Mx 73.1707 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) -Mx 126.0583 -T 83 85 82 82 73 w=31.0859 (proof) -Mx 157.1443 -Set font Gentium Plus;16;400;;normal;;;LTR -T 4 w=4.3516 (!) -Mx 165.7379 -T 62 w=4.9219 ([) -Mx 170.6597 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 83 88 747 w=24.2578 (puff) -Mx 194.9176 -Set font Gentium Plus;16;400;;normal;;;LTR -T 64 w=4.9219 (]) -Mx 199.8394 -T 95 w=3.9063 (|) +My 68.6951 +T 2149 w=6.1523 (−) +Mx 25.0131 +T 95 w=3.6621 (|) +Mx 28.6752 +T 11 w=4.7534 (() +Mx 33.4286 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 56.7196 +Set font Gentium Plus;15;400;;normal;;;LTR +T 12 w=4.7534 ()) +Mx 65.4519 +T 163 w=4.0796 (¡) +Mx 69.5315 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=45.9668 (fancyful) +Mx 119.1155 +T 83 85 82 82 73 w=29.1431 (proof) +Mx 148.2585 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 156.3170 +T 62 w=4.6143 ([) +Mx 160.9312 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 83 88 747 w=22.7417 (puff) +Mx 183.6729 +Set font Gentium Plus;15;400;;normal;;;LTR +T 64 w=4.6143 (]) +Mx 188.2872 +T 95 w=3.6621 (|) Mx 14.8819 -My 91.0764 -T 14 w=6.5625 (+) -Mx 25.6848 -T 95 w=3.9063 (|) -Mx 29.5910 -T 11 w=5.0703 (() -Mx 35.1688 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 62.7000 -Set font Gentium Plus;16;400;;normal;;;LTR -T 12 w=5.0703 ()) -Mx 72.0107 -T 163 w=4.3516 (¡) -Mx 77.1435 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 73 68 81 70 92 73 88 79 w=49.0313 (fancyful) -Mx 130.0297 -T 83 85 82 82 73 w=31.0859 (proof) -Mx 163.7324 -Set font Gentium Plus;16;400;;normal;;;LTR -T 4 w=4.3516 (!) -Mx 172.3244 -T 62 w=4.9219 ([) -Mx 177.2777 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 83 88 747 w=24.2578 (puff) -Mx 204.2230 -Set font Gentium Plus;16;400;;normal;;;LTR -T 64 w=4.9219 (]) -Mx 209.1449 -T 95 w=3.9063 (|) +My 86.6951 +T 14 w=6.1523 (+) +Mx 25.0117 +T 95 w=3.6621 (|) +Mx 28.6738 +T 11 w=4.7534 (() +Mx 33.9029 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 59.7134 +Set font Gentium Plus;15;400;;normal;;;LTR +T 12 w=4.7534 ()) +Mx 68.4443 +T 163 w=4.0796 (¡) +Mx 73.2563 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 73 68 81 70 92 73 88 79 w=45.9668 (fancyful) +Mx 122.8389 +T 83 85 82 82 73 w=29.1431 (proof) +Mx 154.4352 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 162.4922 +T 62 w=4.6143 ([) +Mx 167.1359 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 83 88 747 w=22.7417 (puff) +Mx 192.3972 +Set font Gentium Plus;15;400;;normal;;;LTR +T 64 w=4.6143 (]) +Mx 197.0114 +T 95 w=3.6621 (|) Mx 14.8819 -My 110.2764 -T 2149 w=6.5625 (−) -Mx 25.6878 -T 169 w=7.7656 («) -Mx 36.8405 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 65.0713 -Set font Gentium Plus;16;400;;normal;;;LTR -T 170 w=7.7656 (») -Mx 77.0803 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 73 85 72 81 70 75 w=38.3594 (french) -Mx 119.2974 -T 83 85 82 82 73 w=31.0859 (proof) -Mx 152.4974 -Set font Gentium Plus;16;400;;normal;;;LTR -T 4 w=4.3516 (!) -Mx 161.0923 -T 11 w=5.0703 (() -Mx 166.1626 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 191.0064 -Set font Gentium Plus;16;400;;normal;;;LTR -T 12 w=5.0703 ()) +My 104.6951 +T 2149 w=6.1523 (−) +Mx 25.0143 +T 169 w=7.2803 («) +Mx 35.4705 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 61.9375 +Set font Gentium Plus;15;400;;normal;;;LTR +T 170 w=7.2803 (») +Mx 73.1978 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 73 85 72 81 70 75 w=35.9619 (french) +Mx 112.7779 +T 83 85 82 82 73 w=29.1431 (proof) +Mx 143.9029 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 151.9626 +T 11 w=4.7534 (() +Mx 156.7160 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 180.0070 +Set font Gentium Plus;15;400;;normal;;;LTR +T 12 w=4.7534 ()) Mx 14.8819 -My 129.4764 -T 14 w=6.5625 (+) -Mx 25.6872 -T 169 w=7.7656 («) -Mx 36.8398 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 65.0704 -Set font Gentium Plus;16;400;;normal;;;LTR -T 170 w=7.7656 (») -Mx 77.0515 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 73 85 72 81 70 75 w=38.3594 (french) -Mx 119.2680 -T 83 85 82 82 73 w=31.0859 (proof) -Mx 152.4680 -Set font Gentium Plus;16;400;;normal;;;LTR -T 4 w=4.3516 (!) -Mx 161.0624 -T 11 w=5.0703 (() -Mx 166.6401 -Set font Gentium Plus;16;400;Italic;normal;;;LTR -T 739 88 747 w=24.8438 (fluff) -Mx 194.1714 -Set font Gentium Plus;16;400;;normal;;;LTR -T 12 w=5.0703 ()) +My 122.6951 +T 14 w=6.1523 (+) +Mx 25.0138 +T 169 w=7.2803 («) +Mx 35.4699 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 61.9367 +Set font Gentium Plus;15;400;;normal;;;LTR +T 170 w=7.2803 (») +Mx 73.1709 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 73 85 72 81 70 75 w=35.9619 (french) +Mx 112.7506 +T 83 85 82 82 73 w=29.1431 (proof) +Mx 143.8756 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 151.9347 +T 11 w=4.7534 (() +Mx 157.1638 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 182.9744 +Set font Gentium Plus;15;400;;normal;;;LTR +T 12 w=4.7534 ()) Mx 14.8819 -My 148.6764 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2531 w=6.3680 (−) -Mx 25.7546 -T 2403 w=4.9440 (() -Mx 30.6986 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 54.4266 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2404 w=4.9440 ()) -Mx 63.8754 -T 2372 w=3.9520 (¡) -Mx 67.8274 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -Mx 3.8880 -Mx 6.9440 -Mx 7.5360 -Mx 5.5200 -Mx 7.2000 -Mx 4.1920 -Mx 7.4400 -Mx 3.7920 -T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) -Mx 118.8441 -Mx 6.5120 -Mx 5.1520 -Mx 6.3680 -Mx 6.3680 -Mx 4.1920 -T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2371 w=3.9520 (!) -Mx 155.8928 -T 2407 w=4.3840 ([) -Mx 160.2768 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 604 634 816 w=22.0960 (puff) -Mx 182.3728 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2408 w=4.3840 (]) -Mx 191.2616 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 214.9896 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2328 w=4.0160 (²) +My 140.6951 +T 2149 w=6.1523 (−) +Mx 27.4228 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 50.7138 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 61.1819 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 90.8614 +Set font Gentium Plus;15;400;;normal;;;LTR +T 739 88 747 w=26.0083 (fluff) +Mx 123.2583 +T 68 68 68 68 68 68 68 w=48.1934 (aaaaaaa) +Mx 177.8402 +T 68 68 68 68 w=27.5391 (aaaa) +Mx 211.7678 +T 68 68 68 68 68 68 w=41.3086 (aaaaaa) +Mx 259.4649 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) Mx 14.8819 -My 167.8764 -T 2530 w=6.3680 (+) -Mx 25.7524 -T 2403 w=4.9440 (() -Mx 31.4242 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 57.2482 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2404 w=4.9440 ()) -Mx 66.6947 -T 2372 w=3.9520 (¡) -Mx 72.3427 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -Mx 3.8880 -Mx 6.9440 -Mx 7.5360 -Mx 5.5200 -Mx 7.2000 -Mx 4.1920 -Mx 7.4400 -Mx 3.7920 -T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) -Mx 123.3573 -Mx 6.5120 -Mx 5.1520 -Mx 6.3680 -Mx 6.3680 -Mx 4.1920 -T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) -Mx 153.7652 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2371 w=3.9520 (!) -Mx 162.2198 -T 2407 w=4.3840 ([) -Mx 167.0311 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 604 634 816 w=22.0960 (puff) -Mx 191.2202 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2408 w=4.3840 (]) -Mx 200.8283 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 226.6523 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2328 w=4.0160 (²) +My 158.6951 +Set font Gentium Plus;15;400;;normal;;;LTR +T 739 88 747 w=26.0083 (fluff) +My 176.6951 +T 14 w=6.1523 (+) +Mx 26.4319 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 52.1762 +Set font Gentium Plus;15;400;;normal;;;LTR +T 4 w=4.0796 (!) +Mx 62.0234 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) +Mx 93.5412 +Set font Gentium Plus;15;400;;normal;;;LTR +T 739 88 747 w=26.0083 (fluff) +Mx 125.2568 +T 68 68 68 68 68 68 68 w=48.1934 (aaaaaaa) +Mx 179.1574 +T 68 68 68 68 w=27.5391 (aaaa) +Mx 212.4037 +T 68 68 68 68 68 68 w=41.3086 (aaaaaa) +Mx 259.4649 +Set font Gentium Plus;15;400;Italic;normal;;;LTR +T 739 88 747 w=23.2910 (fluff) Mx 14.8819 -My 187.0764 -T 2531 w=6.3680 (−) -Mx 25.7597 -T 2627 w=2.6880 (|) -Mx 28.4477 -T 2403 w=4.9440 (() -Mx 33.3917 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 57.1197 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2404 w=4.9440 ()) -Mx 66.5734 -T 2372 w=3.9520 (¡) -Mx 70.5254 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -Mx 3.8880 -Mx 6.9440 -Mx 7.5360 -Mx 5.5200 -Mx 7.2000 -Mx 4.1920 -Mx 7.4400 -Mx 3.7920 -T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) -Mx 121.5472 -Mx 6.5120 -Mx 5.1520 -Mx 6.3680 -Mx 6.3680 -Mx 4.1920 -T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2371 w=3.9520 (!) -Mx 158.6009 -T 2407 w=4.3840 ([) -Mx 162.9849 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 604 634 816 w=22.0960 (puff) -Mx 185.0809 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2408 w=4.3840 (]) -Mx 189.4649 -T 2627 w=2.6880 (|) +My 194.6951 +Set font Gentium Plus;15;400;;normal;;;LTR +T 739 88 747 w=26.0083 (fluff) +My 212.6951 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2531 w=5.9700 (−) +Mx 25.0773 +T 2403 w=4.6350 (() +Mx 29.7123 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 51.9573 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2404 w=4.6350 ()) +Mx 60.8177 +T 2372 w=3.7050 (¡) +Mx 64.5227 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +Mx 3.6450 +Mx 6.5100 +Mx 7.0650 +Mx 5.1750 +Mx 6.7500 +Mx 3.9300 +Mx 6.9750 +Mx 3.5550 +T 680 a=3.6450 457 a=6.5100 567 a=6.9750 486 a=5.1750 665 a=6.5400 517 a=3.9300 634 a=6.9750 555 a=3.5550 (fancyful) +Mx 112.3532 +Mx 6.1050 +Mx 4.8300 +Mx 5.9700 +Mx 5.9700 +Mx 3.9300 +T 604 a=6.1050 607 a=5.1000 577 a=5.9700 577 a=5.9700 517 a=3.9300 (proof) +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 147.0886 +T 2407 w=4.1100 ([) +Mx 151.1986 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 604 634 816 w=20.7150 (puff) +Mx 171.9136 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2408 w=4.1100 (]) +Mx 180.2490 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 202.4940 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2328 w=3.7650 (²) Mx 14.8819 -My 206.2764 -T 2530 w=6.3680 (+) -Mx 25.7580 -T 2627 w=2.6880 (|) -Mx 28.4460 -T 2403 w=4.9440 (() -Mx 34.1177 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 59.9417 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2404 w=4.9440 ()) -Mx 69.3938 -T 2372 w=3.9520 (¡) -Mx 75.0418 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -Mx 3.8880 -Mx 6.9440 -Mx 7.5360 -Mx 5.5200 -Mx 7.2000 -Mx 4.1920 -Mx 7.4400 -Mx 3.7920 -T 680 a=3.8880 457 a=6.9440 567 a=7.4400 486 a=5.5200 665 a=6.9760 517 a=4.1920 634 a=7.4400 555 a=3.7920 (fancyful) -Mx 126.0619 -Mx 6.5120 -Mx 5.1520 -Mx 6.3680 -Mx 6.3680 -Mx 4.1920 -T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) -Mx 156.4699 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2371 w=3.9520 (!) -Mx 164.9300 -T 2407 w=4.3840 ([) -Mx 169.7413 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 604 634 816 w=22.0960 (puff) -Mx 193.9304 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2408 w=4.3840 (]) -Mx 198.3144 -T 2627 w=2.6880 (|) +My 230.6951 +T 2530 w=5.9700 (+) +Mx 25.0754 +T 2403 w=4.6350 (() +Mx 30.3927 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 54.6027 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2404 w=4.6350 ()) +Mx 63.4612 +T 2372 w=3.7050 (¡) +Mx 68.7562 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +Mx 3.6450 +Mx 6.5100 +Mx 7.0650 +Mx 5.1750 +Mx 6.7500 +Mx 3.9300 +Mx 6.9750 +Mx 3.5550 +T 680 a=3.6450 457 a=6.5100 567 a=6.9750 486 a=5.1750 665 a=6.5400 517 a=3.9300 634 a=6.9750 555 a=3.5550 (fancyful) +Mx 116.5847 +Mx 6.1050 +Mx 4.8300 +Mx 5.9700 +Mx 5.9700 +Mx 3.9300 +T 604 a=6.1050 607 a=5.1000 577 a=5.9700 577 a=5.9700 517 a=3.9300 (proof) +Mx 145.0921 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 153.0206 +T 2407 w=4.1100 ([) +Mx 157.5312 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 604 634 816 w=20.7150 (puff) +Mx 180.2085 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2408 w=4.1100 (]) +Mx 189.2185 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 213.4285 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2328 w=3.7650 (²) Mx 14.8819 -My 225.4764 -T 2531 w=6.3680 (−) -Mx 25.7604 -T 2441 w=7.2960 («) -Mx 36.6559 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 63.9835 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2442 w=7.2960 (») -Mx 75.7900 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -Mx 4.1920 -Mx 5.1520 -Mx 5.4880 -Mx 7.5360 -Mx 5.5200 -Mx 7.1200 -T 517 a=4.1920 607 a=5.4400 498 a=5.4880 567 a=7.4400 486 a=5.5200 527 a=7.1200 (french) -Mx 115.3085 -Mx 6.5120 -Mx 5.1520 -Mx 6.3680 -Mx 6.3680 -Mx 4.1920 -T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) -Mx 146.1469 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2371 w=3.9520 (!) -Mx 154.6094 -T 2403 w=4.9440 (() -Mx 159.5534 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 183.2814 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2404 w=4.9440 ()) +My 248.6951 +T 2531 w=5.9700 (−) +Mx 25.0817 +T 2627 w=2.5200 (|) +Mx 27.6017 +T 2403 w=4.6350 (() +Mx 32.2367 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 54.4817 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2404 w=4.6350 ()) +Mx 63.3466 +T 2372 w=3.7050 (¡) +Mx 67.0516 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +Mx 3.6450 +Mx 6.5100 +Mx 7.0650 +Mx 5.1750 +Mx 6.7500 +Mx 3.9300 +Mx 6.9750 +Mx 3.5550 +T 680 a=3.6450 457 a=6.5100 567 a=6.9750 486 a=5.1750 665 a=6.5400 517 a=3.9300 634 a=6.9750 555 a=3.5550 (fancyful) +Mx 114.8864 +Mx 6.1050 +Mx 4.8300 +Mx 5.9700 +Mx 5.9700 +Mx 3.9300 +T 604 a=6.1050 607 a=5.1000 577 a=5.9700 577 a=5.9700 517 a=3.9300 (proof) +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 149.6263 +T 2407 w=4.1100 ([) +Mx 153.7363 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 604 634 816 w=20.7150 (puff) +Mx 174.4513 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2408 w=4.1100 (]) +Mx 178.5613 +T 2627 w=2.5200 (|) Mx 14.8819 -My 244.6764 -T 2530 w=6.3680 (+) -Mx 25.7599 -T 2441 w=7.2960 («) -Mx 36.6553 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 63.9827 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2442 w=7.2960 (») -Mx 75.5482 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -Mx 4.1920 -Mx 5.1520 -Mx 5.4880 -Mx 7.5360 -Mx 5.5200 -Mx 7.1200 -T 517 a=4.1920 607 a=5.4400 498 a=5.4880 567 a=7.4400 486 a=5.5200 527 a=7.1200 (french) -Mx 115.0662 -Mx 6.5120 -Mx 5.1520 -Mx 6.3680 -Mx 6.3680 -Mx 4.1920 -T 604 a=6.5120 607 a=5.4400 577 a=6.3680 577 a=6.3680 517 a=4.1920 (proof) -Mx 145.9046 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2371 w=3.9520 (!) -Mx 154.3666 -T 2403 w=4.9440 (() -Mx 160.0384 -Set font Cormorant Infant;16;400;Italic;normal;;;LTR -T 718 555 634 816 w=23.7280 (fluff) -Mx 185.8624 -Set font Cormorant Infant;16;400;;normal;;;LTR -T 2404 w=4.9440 ()) +My 266.6951 +T 2530 w=5.9700 (+) +Mx 25.0803 +T 2627 w=2.5200 (|) +Mx 27.6003 +T 2403 w=4.6350 (() +Mx 32.9175 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 57.1275 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2404 w=4.6350 ()) +Mx 65.9909 +T 2372 w=3.7050 (¡) +Mx 71.2859 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +Mx 3.6450 +Mx 6.5100 +Mx 7.0650 +Mx 5.1750 +Mx 6.7500 +Mx 3.9300 +Mx 6.9750 +Mx 3.5550 +T 680 a=3.6450 457 a=6.5100 567 a=6.9750 486 a=5.1750 665 a=6.5400 517 a=3.9300 634 a=6.9750 555 a=3.5550 (fancyful) +Mx 119.1193 +Mx 6.1050 +Mx 4.8300 +Mx 5.9700 +Mx 5.9700 +Mx 3.9300 +T 604 a=6.1050 607 a=5.1000 577 a=5.9700 577 a=5.9700 517 a=3.9300 (proof) +Mx 147.6268 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 155.5602 +T 2407 w=4.1100 ([) +Mx 160.0708 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 604 634 816 w=20.7150 (puff) +Mx 182.7480 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2408 w=4.1100 (]) +Mx 186.8580 +T 2627 w=2.5200 (|) +Mx 14.8819 +My 284.6951 +T 2531 w=5.9700 (−) +Mx 25.0824 +T 2441 w=6.8400 («) +Mx 35.2975 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 60.9177 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2442 w=6.8400 (») +Mx 71.9882 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +Mx 3.9300 +Mx 4.8300 +Mx 5.1450 +Mx 7.0650 +Mx 5.1750 +Mx 6.6750 +T 517 a=3.9300 607 a=5.1000 498 a=5.1450 567 a=6.9750 486 a=5.1750 527 a=6.6750 (french) +Mx 109.0387 +Mx 6.1050 +Mx 4.8300 +Mx 5.9700 +Mx 5.9700 +Mx 3.9300 +T 604 a=6.1050 607 a=5.1000 577 a=5.9700 577 a=5.9700 517 a=3.9300 (proof) +Mx 137.9497 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 145.8851 +T 2403 w=4.6350 (() +Mx 150.5201 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 172.7651 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2404 w=4.6350 ()) +Mx 14.8819 +My 302.6951 +T 2530 w=5.9700 (+) +Mx 25.0820 +T 2441 w=6.8400 («) +Mx 35.2970 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 60.9170 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2442 w=6.8400 (») +Mx 71.7616 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +Mx 3.9300 +Mx 4.8300 +Mx 5.1450 +Mx 7.0650 +Mx 5.1750 +Mx 6.6750 +T 517 a=3.9300 607 a=5.1000 498 a=5.1450 567 a=6.9750 486 a=5.1750 527 a=6.6750 (french) +Mx 108.8116 +Mx 6.1050 +Mx 4.8300 +Mx 5.9700 +Mx 5.9700 +Mx 3.9300 +T 604 a=6.1050 607 a=5.1000 577 a=5.9700 577 a=5.9700 517 a=3.9300 (proof) +Mx 137.7226 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 145.6577 +T 2403 w=4.6350 (() +Mx 150.9750 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 175.1850 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2404 w=4.6350 ()) +Mx 14.8819 +My 320.6951 +T 2531 w=5.9700 (−) +Mx 26.7967 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 49.0417 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 58.6916 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 86.8815 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 952 699 936 w=24.9000 (fluff) +Mx 117.7263 +T 522 522 522 522 522 522 522 w=51.4500 (aaaaaaa) +Mx 175.1212 +T 522 522 522 522 w=29.4000 (aaaa) +Mx 210.4660 +T 522 522 522 522 522 522 w=44.1000 (aaaaaa) +Mx 260.5109 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 14.8819 +My 338.6951 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 952 699 936 w=24.9000 (fluff) +My 356.6951 +T 2530 w=5.9700 (+) +Mx 26.1564 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 50.1038 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 2371 w=3.7050 (!) +Mx 59.2925 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 88.9226 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 952 699 936 w=24.9000 (fluff) +Mx 119.2428 +T 522 522 522 522 522 522 522 w=51.4500 (aaaaaaa) +Mx 176.1129 +T 522 522 522 522 w=29.4000 (aaaa) +Mx 210.9330 +T 522 522 522 522 522 522 w=44.1000 (aaaaaa) +Mx 260.5109 +Set font Cormorant Infant;15;400;Italic;normal;;;LTR +T 718 555 634 816 w=22.2450 (fluff) +Mx 14.8819 +My 374.6951 +Set font Cormorant Infant;15;400;;normal;;;LTR +T 952 699 936 w=24.9000 (fluff) End page Finish diff --git a/tests/feat-italic-correction.sil b/tests/feat-italic-correction.sil index 9cca94056..8820db833 100644 --- a/tests/feat-italic-correction.sil +++ b/tests/feat-italic-correction.sil @@ -1,7 +1,7 @@ \begin[papersize=a6]{document} \nofolios \neverindent -\font[size=16pt] +\font[size=15pt] \use[module=packages.math] % Italic correction. % The setting plays at paragraph level @@ -35,6 +35,16 @@ + «\em{fluff}» \em{french proof}! (\em{fluff}) } +% We want to insert the correction as a kern or glue depending on context, +% so that line breaking may still occur where it should. +% Disabled +\set[parameter=typesetter.italicCorrection, value=false] +− \em{fluff}! \em{fluff} fluff aaaaaaa aaaa aaaaaa \em{fluff} fluff + +% Enabled +\set[parameter=typesetter.italicCorrection, value=true] ++ \em{fluff}! \em{fluff} fluff aaaaaaa aaaa aaaaaa \em{fluff} fluff + % Repeated with another font \font[family=Cormorant Infant] \set[parameter=typesetter.italicCorrection, value=false] @@ -57,4 +67,10 @@ + «\em{fluff}» \em{french proof}! (\em{fluff}) } +\set[parameter=typesetter.italicCorrection, value=false] +− \em{fluff}! \em{fluff} fluff aaaaaaa aaaa aaaaaa \em{fluff} fluff + +\set[parameter=typesetter.italicCorrection, value=true] ++ \em{fluff}! \em{fluff} fluff aaaaaaa aaaa aaaaaa \em{fluff} fluff + \end{document} diff --git a/typesetters/base.lua b/typesetters/base.lua index 24daed857..53bab6eed 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -323,6 +323,7 @@ function typesetter:breakIntoLines (nodelist, breakWidth) end local function getLastShape(nodelist) + local hasGlue local last if nodelist then -- The node list may contain nnodes, penalties, kern and glue @@ -339,12 +340,14 @@ local function getLastShape(nodelist) -- punctuations. In those case, we should not need italic correction. break end + if n.is_glue then hasGlue = true end end end - return last + return last, hasGlue end local function getFirstShape(nodelist) local first + local hasGlue if nodelist then -- The node list may contain nnodes, penalties, kern and glue -- We skip the latter, and retrieve the first shaped item. @@ -360,9 +363,10 @@ local function getFirstShape(nodelist) -- punctuations. In those case, we should not need italic correction. break end + if n.is_glue then hasGlue = true end end end - return first + return first, hasGlue end local function fromItalicCorrection (precShape, curShape) @@ -429,17 +433,26 @@ function typesetter.shapeAllNodes (_, nodelist, inplace) if SILE.settings:get("typesetter.italicCorrection") and prec then local itCorrOffset + local isGlue if isItalicLike(prec) and not isItalicLike(current) then - local precShape = getLastShape(precShapedNodes) - local curShape = getFirstShape(shapedNodes) + local precShape, precHasGlue = getLastShape(precShapedNodes) + local curShape, curHasGlue = getFirstShape(shapedNodes) + isGlue = precHasGlue or curHasGlue itCorrOffset = fromItalicCorrection(precShape, curShape) elseif not isItalicLike(prec) and isItalicLike(current) then - local precShape = getLastShape(precShapedNodes) - local curShape = getFirstShape(shapedNodes) + local precShape, precHasGlue = getLastShape(precShapedNodes) + local curShape, curHasGlue = getFirstShape(shapedNodes) + isGlue = precHasGlue or curHasGlue itCorrOffset = toItalicCorrection(precShape, curShape) end - if itCorrOffset then - newNodelist[#newNodelist+1] = SILE.nodefactory.kern({ + if itCorrOffset and itCorrOffset ~= 0 then + -- If one of the node contains a glue (e.g. "a \em{proof} is..."), + -- line breaking may occur between them, so our correction shall be + -- a glue too. + -- Otherwise, the font change is considered to occur at a non-breaking + -- point (e.g. "\em{proof}!") and the correction shall be a kern. + local makeItCorrNode = isGlue and SILE.nodefactory.glue or SILE.nodefactory.kern + newNodelist[#newNodelist+1] = makeItCorrNode({ width = SILE.length(itCorrOffset), subtype = "itcorr" }) @@ -1023,8 +1036,6 @@ function typesetter:makeHbox (content) local node = nodes[i] if node.is_migrating then migratingNodes[#migratingNodes+1] = node - elseif node.is_unshaped then - SU.error("DOH") elseif node.is_discretionary then -- HACK https://github.com/sile-typesetter/sile/issues/583 -- Discretionary nodes have a null line contribution... From 8c4b19a08b48b94e1c8053ef8fc3052fdc7eedef Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 16:05:41 +0300 Subject: [PATCH 015/357] chore(tooling): Bring some lint and test action to the Rust side --- Makefile.am | 17 ++++++++++++++--- configure.ac | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 369a72166..318edf829 100644 --- a/Makefile.am +++ b/Makefile.am @@ -277,7 +277,7 @@ patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(DEPDIRS) $(LUAMODLOCK) .PHONY: force force: ; -PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm +PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck rustfmt clippy cargo-test busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm .PHONY: $(PHONY_DEVELOPER_TARGETS) if DEVELOPER @@ -285,9 +285,9 @@ if DEVELOPER regressions: $(TESTSRCS) $(ACTUALS) $(LOCALTESTFONTS) $(REGRESSIONSCRIPT) $(TESTSRCS) -test: regressions busted +test: regressions busted cargo-test -lint: luacheck luarocks-lint +lint: luacheck luarocks-lint rustfmt clippy luarocks-lint: $(LUAMODSPEC) $(LUAROCKS) lint $(LUAMODSPEC) @@ -295,6 +295,17 @@ luarocks-lint: $(LUAMODSPEC) luacheck: $(LUACHECK) -j$(shell nproc) -q . +rustfmt: + $(GIT) ls-files '*.rs' | $(XARGS) rustfmt --check + +clippy: + cd $(srcdir) + $(CARGO_ENV) $(CARGO) clippy -- -D warnings + +cargo-test: $(SILE) + cd $(srcdir) + $(CARGO_ENV) $(CARGO) test --locked + busted: $(SILELUA) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) set -f; IFS=';' if SYSTEM_LUAROCKS diff --git a/configure.ac b/configure.ac index f393816d6..9557e0234 100644 --- a/configure.ac +++ b/configure.ac @@ -91,6 +91,7 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_PROGVAR([pdfinfo]) AX_PROGVAR([jq]) + AX_PROGVAR([xargs]) AC_MSG_CHECKING([for OS X]) have_appkit=no From a0ca2dcf072c21bc1bb0c7a5c4fcdca210158c80 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 16:23:11 +0300 Subject: [PATCH 016/357] chore(cli): Add Lua interpreter as main CLI function --- Cargo.lock | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +++ src/bin/sile.rs | 10 ++++++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index fe3d618c7..648d005be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,12 +48,27 @@ version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + [[package]] name = "cc" version = "1.0.79" @@ -326,6 +341,55 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "lua-src" +version = "544.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708ba3c844d5e9d38def4a09dd871c17c370f519b3c4b7261fbabe4a613a814c" +dependencies = [ + "cc", +] + +[[package]] +name = "luajit-src" +version = "210.4.5+resty2cf5186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b7992a40e602786272d84c6f2beca44a588ededcfd57b48ec6f82008a7cb97" +dependencies = [ + "cc", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mlua" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8ce6788556a67d90567809c7de94dfef2ff1f47ff897aeee935bcfbcdf5735" +dependencies = [ + "bstr", + "cc", + "lua-src", + "luajit-src", + "num-traits", + "once_cell", + "pkg-config", + "rustc-hash", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -392,6 +456,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.37.7" @@ -425,6 +495,7 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", + "mlua", "vergen", ] diff --git a/Cargo.toml b/Cargo.toml index db2d23301..f6ebb411a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,10 @@ required-features = ["cli"] optional = true features = [ "derive", "wrap_help" ] + [dependencies.mlua] + version = "0.8" + features = [ "lua54", "vendored" ] + [build-dependencies] [build-dependencies.clap_complete] diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 9b6c352d4..ab29d2dec 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -1,11 +1,19 @@ use clap::CommandFactory; +use mlua::prelude::*; use sile::cli::Cli; fn main() -> sile::Result<()> { let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); let app = Cli::command().version(version); + #[allow(unused_variables)] let matches = app.get_matches(); - println!("Hello, world!"); + sile_lua()?; + Ok(()) +} + +fn sile_lua() -> LuaResult<()> { + let lua = Lua::new(); + lua.load("print('Hello, world!')").exec()?; Ok(()) } From 4f8a58f634ce7fbf9655574a8afb0dcb8eac1a69 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 16:46:06 +0300 Subject: [PATCH 017/357] chore(cli): Use mlua to load SILE core Lua --- src/bin/sile.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index ab29d2dec..07f48fc0a 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -8,12 +8,20 @@ fn main() -> sile::Result<()> { let app = Cli::command().version(version); #[allow(unused_variables)] let matches = app.get_matches(); - sile_lua()?; + sile()?; Ok(()) } -fn sile_lua() -> LuaResult<()> { - let lua = Lua::new(); - lua.load("print('Hello, world!')").exec()?; +fn sile() -> LuaResult<()> { + let lua = unsafe { Lua::unsafe_new() }; + lua.load( + r#" + package.path = ";;./?.lua;./?/init.lua;./lua-libraries/?.lua;./lua-libraries/?/init.lua;./lua_modules/share/lua/5.4/?.lua;./lua_modules/share/lua/5.4/?/init.lua" + package.cpath = ";;./?.so;./lua_modules/lib/lua/5.4/?.so" + require("core.sile") + SU.dump(SILE) + "#, + ) + .exec()?; Ok(()) } From 38641ec2f276617baa42695bbb56fb553c5227f1 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 6 Apr 2023 19:13:38 +0300 Subject: [PATCH 018/357] chore(tooling): Update Git ignore list with Rust artifacts --- .gitignore | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 9575dfae3..7a5c9ab35 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ build-aux/ltsugar.m4 build-aux/ltversion.m4 build-aux/lt~obsolete.m4 build-aux/missing +build-aux/list-dist-files.sh +tests/regressions.pl # Other autojunk .deps @@ -76,14 +78,19 @@ documentation/*.pdf gource.webm .fonts/* .sources/* -/sile -sile.1 +/sile-lua +sile-lua.1 /.version /.version-prev /.tarball-version /.built-subdirs *.so core/version.lua +core/features.lua +/target +/completions +/sile +/sile.1 # Nix symlink to builds /result From 2a145ae0f258ba9480094a615b322eb26089876b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 7 Apr 2023 00:26:58 +0300 Subject: [PATCH 019/357] chore(cli): Fixup loading C modules in Lua under Rust wrapper --- .cargo/config.toml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..0f236658a --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.x86_64-apple-darwin] +rustflags = ["-C", "link-args=-rdynamic"] + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "link-args=-rdynamic"] From 0d8e6cd85c633a41687e6966654a87e336fc22f7 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 7 Apr 2023 00:55:22 +0300 Subject: [PATCH 020/357] chore(cli): Process XML file and output a PDF from new Rust wrapper --- src/bin/sile.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 07f48fc0a..7e805c787 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -18,8 +18,15 @@ fn sile() -> LuaResult<()> { r#" package.path = ";;./?.lua;./?/init.lua;./lua-libraries/?.lua;./lua-libraries/?/init.lua;./lua_modules/share/lua/5.4/?.lua;./lua_modules/share/lua/5.4/?/init.lua" package.cpath = ";;./?.so;./lua_modules/lib/lua/5.4/?.so" - require("core.sile") - SU.dump(SILE) + SILE = require("core.sile") + io.stderr:write(" [ Rust ]" .. SILE.full_version .. '\n') + SILE.init() + SILE.masterFilename = "tests/absmin" + SILE.masterDir = "tests" + SILE.input.filename = "tests/absmin.xml" + SILE.processFile(SILE.input.filename) + SILE.outputter:finish() + SILE.finish() "#, ) .exec()?; From 2bc7a6d529751d9ec2f7d0041eca2341334fb469 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 8 Apr 2023 17:36:28 +0300 Subject: [PATCH 021/357] chore(cli): Start migrating CLI options to Rust --- src/cli.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/cli.rs b/src/cli.rs index e43aa9b1b..11140ada1 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,4 +3,32 @@ use clap::Parser; /// The SILE typesetter, Lua wrapped in Rust. #[derive(Parser, Debug)] #[clap(author, bin_name = "sile")] -pub struct Cli {} +pub struct Cli { + // cliargs:option("-b, --backend=VALUE", "choose an alternative output backend") + // cliargs:option("-c, --class=VALUE", "override default document class") + // cliargs:option("-d, --debug=VALUE", "show debug information for tagged aspects of SILE’s operation", {}) + /// Evaluate Lua expression before processing input + #[clap(short, long)] + pub evaluate: Option, + + /// Evaluate Lua expression after processing input + #[clap(short = 'E', long)] + pub evaluate_after: Option, + + // cliargs:option("-E, --evaluate-after=VALUE", "", {}) + // cliargs:option("-f, --fontmanager=VALUE", "choose an alternative font manager") + // cliargs:option("-I, --include=FILE", "deprecated, see --use, --preamble, or --postamble", {}) + // cliargs:option("-m, --makedeps=FILE", "generate a list of dependencies in Makefile format") + // cliargs:option("-o, --output=FILE", "explicitly set output file name") + // cliargs:option("-O, --options=PARAMETER=VALUE[,PARAMETER=VALUE]", "set document class options", {}) + // cliargs:option("-p, --preamble=FILE", "process SIL, XML, or other content before the input document", {}) + // cliargs:option("-P, --postamble=FILE", "process SIL, XML, or other content after the input document", {}) + // cliargs:option("-u, --use=MODULE[[PARAMETER=VALUE][,PARAMETER=VALUE]]", "load and initialize a module before processing input", {}) + /// Discard all non-error output messages + #[clap(short, long)] + pub quiet: bool, + + /// Display detailed location trace on errors and warnings + #[clap(short, long)] + pub traceback: bool, +} From f73b340ac1fc3cb4bc794d3f25ecdd0e3ad0139d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 12 Apr 2023 17:48:46 +0300 Subject: [PATCH 022/357] chore(build): Retool Lua rockspec to start integration with autotools --- .gitignore | 1 + configure.ac | 4 ++++ sile-dev-1.rockspec | 36 ------------------------------ sile.rockspec.in | 53 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 36 deletions(-) delete mode 100644 sile-dev-1.rockspec create mode 100644 sile.rockspec.in diff --git a/.gitignore b/.gitignore index a64747267..194069c90 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ tags Makefile-distfiles documentation/*.pdf gource.webm +*.rockspec .fonts/* .sources/* sile diff --git a/configure.ac b/configure.ac index 9557e0234..8a0181b52 100644 --- a/configure.ac +++ b/configure.ac @@ -309,11 +309,15 @@ adl_RECURSIVE_EVAL(["${libdir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_LIB_PATH]) AC_DEFINE_UNQUOTED([SILE_LIB_PATH],["${SILE_LIB_PATH}"],[Path for SILE libraries]) AC_SUBST([SILE_LIB_PATH]) +AC_SUBST([ROCKSPECWARNING], ["DO NOT EDIT! Modify template sile.rockspec.in"]) +AC_SUBST([ROCKREV], [1]) + AX_SUBST_MAN_DATE AC_CONFIG_FILES([build-aux/list-dist-files.sh], [chmod +x build-aux/list-dist-files.sh]) AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/version.lua]) AC_CONFIG_FILES([sile-lua:sile.in tests/regressions.pl], [chmod +x sile-lua tests/regressions.pl]) +AC_CONFIG_FILES([sile-dev-1.rockspec:sile.rockspec.in]) AC_ARG_PROGRAM diff --git a/sile-dev-1.rockspec b/sile-dev-1.rockspec deleted file mode 100644 index bd9ba0058..000000000 --- a/sile-dev-1.rockspec +++ /dev/null @@ -1,36 +0,0 @@ -package = "sile" -description = { - summary = "Simon’s Improved Layout Engine", - license = "MIT" -} -version = "dev-1" -source = { - url = "..." -} -dependencies = { - "lua >= 5.1", - "bit32", -- only required on Lua < 5.2, versions vary between Rock and VM provided - "cassowary == 2.3.2-1", - "cldr == 0.3.0-0", - "compat53 == 0.8-1", -- only required on Lua < 5.3 - "cosmo == 16.06.04-1", - "fluent == 0.2.0-0", - "linenoise == 0.9-1", - "loadkit == 1.1.0-1", - "lpeg == 1.0.2-1", - "lua-zlib == 1.2-2", - "lua_cliargs == 3.0-2", - "luaepnf == 0.3-2", - "luaexpat == 1.5.1-1", - "luafilesystem == 1.8.0-1", - "luarepl == 0.10-1", - "luasec == 1.3.1-1", - "luasocket == 3.1.0-1", - "luautf8 == 0.1.5-1", - "penlight == 1.13.1-1", - "vstruct == 2.1.1-1" -} -build = { - type = "builtin", - modules = {} -} diff --git a/sile.rockspec.in b/sile.rockspec.in new file mode 100644 index 000000000..24f2baf4d --- /dev/null +++ b/sile.rockspec.in @@ -0,0 +1,53 @@ +-- @ROCKSPECWARNING@ +rockspec_format = "3.0" +package = "@TRANSFORMED_PACKAGE_NAME@" +version = "dev-@ROCKREV@" + +source = { + url = "git+https://github.com/sile-typesetter/sile.git", + branch = "master" +} + +description = { + summary = "Simon’s Improved Layout Engine", + detailed = [[SILE is a typesetting system; its job is to produce beautiful printed documents. + Conceptually, SILE is similar to TeX—from which it borrows some concepts and even + syntax and algorithms—but the similarities end there. Rather than being a + derivative of the TeX family SILE is a new typesetting and layout engine written + from the ground up using modern technologies and borrowing some ideas from + graphical systems such as InDesign.]], + license = "MIT", + homepage = "https://github.com/sile-typesetter/fontproof", + issues_url = "https://github.com/sile-typesetter/fontproof/issues", + maintainer = "Caleb Maclennan ", + labels = { "typesetting" } +} + +dependencies = { + "lua >= 5.1", + "bit32", -- only required on Lua < 5.2, versions vary between Rock and VM provided + "cassowary == 2.3.2-1", + "cldr == 0.3.0-0", + "compat53 == 0.8-1", -- only required on Lua < 5.3 + "cosmo == 16.06.04-1", + "fluent == 0.2.0-0", + "linenoise == 0.9-1", + "loadkit == 1.1.0-1", + "lpeg == 1.0.2-1", + "lua-zlib == 1.2-2", + "lua_cliargs == 3.0-2", + "luaepnf == 0.3-2", + "luaexpat == 1.5.1-1", + "luafilesystem == 1.8.0-1", + "luarepl == 0.10-1", + "luasec == 1.3.1-1", + "luasocket == 3.1.0-1", + "luautf8 == 0.1.5-1", + "penlight == 1.13.1-1", + "vstruct == 2.1.1-1" +} + +build = { + type = "builtin", + modules = {} +} From 1b8a19fe69431242c0184b339dac4d9a4f979df2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 12 Apr 2023 21:36:12 +0300 Subject: [PATCH 023/357] chore(cli): Finish sketching out arguments in Clap --- src/cli.rs | 85 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 11140ada1..9e7b8d793 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,29 +1,64 @@ -use clap::Parser; +use clap::{Parser, ValueEnum}; +use std::path::PathBuf; -/// The SILE typesetter, Lua wrapped in Rust. +/// The SILE typesetter reads a single input file, by default in either SIL or XML format, and +/// processes it to generate a single output file, by default in PDF format. The output file will +/// be written to the same name as the input file with the extension changed to .pdf. Additional +/// input or output formats can be handled by requiring a module that adds support for them first. #[derive(Parser, Debug)] #[clap(author, bin_name = "sile")] pub struct Cli { - // cliargs:option("-b, --backend=VALUE", "choose an alternative output backend") - // cliargs:option("-c, --class=VALUE", "override default document class") - // cliargs:option("-d, --debug=VALUE", "show debug information for tagged aspects of SILE’s operation", {}) + /// Input document, by default in SIL or XML format + pub input: String, + + /// Choose an alternative output backend + #[clap(short, long, value_enum, default_value_t=Backend::Libtexpdf)] + pub backend: Backend, + + /// Override default document class + #[clap(short, long)] + pub class: Option, + + /// Show debug information for tagged aspects of SILE’s operation + #[clap(short, long)] + pub debug: Option>, + /// Evaluate Lua expression before processing input #[clap(short, long)] - pub evaluate: Option, + pub evaluate: Option>, /// Evaluate Lua expression after processing input #[clap(short = 'E', long)] - pub evaluate_after: Option, - - // cliargs:option("-E, --evaluate-after=VALUE", "", {}) - // cliargs:option("-f, --fontmanager=VALUE", "choose an alternative font manager") - // cliargs:option("-I, --include=FILE", "deprecated, see --use, --preamble, or --postamble", {}) - // cliargs:option("-m, --makedeps=FILE", "generate a list of dependencies in Makefile format") - // cliargs:option("-o, --output=FILE", "explicitly set output file name") - // cliargs:option("-O, --options=PARAMETER=VALUE[,PARAMETER=VALUE]", "set document class options", {}) - // cliargs:option("-p, --preamble=FILE", "process SIL, XML, or other content before the input document", {}) - // cliargs:option("-P, --postamble=FILE", "process SIL, XML, or other content after the input document", {}) - // cliargs:option("-u, --use=MODULE[[PARAMETER=VALUE][,PARAMETER=VALUE]]", "load and initialize a module before processing input", {}) + pub evaluate_after: Option>, + + /// Choose an alternative font manager + #[clap(short, long, value_enum, default_value_t=FontManager::Fontconfig)] + pub fontmanager: FontManager, + + /// Generate a list of dependencies in Makefile format + #[clap(short, long)] + pub makedeps: Option, + + /// Explicitly set output file name + #[clap(short, long)] + pub output: Option, + + /// Set document class options + #[clap(short = 'O', long)] + pub options: Option>, + + /// Process SIL, XML, or other content before the input document + #[clap(short, long)] + pub preamble: Option>, + + /// Process SIL, XML, or other content after the input document + #[clap(short = 'P', long)] + pub postamble: Option>, + + /// Load and initialize a module before processing input + #[clap(short, long)] + pub r#use: Option>, + /// Discard all non-error output messages #[clap(short, long)] pub quiet: bool, @@ -32,3 +67,19 @@ pub struct Cli { #[clap(short, long)] pub traceback: bool, } + +#[derive(ValueEnum, Debug, Clone)] +pub enum Backend { + Libtexpdf, + Debug, + Text, + Dummy, + Cairo, + Podofo, +} + +#[derive(ValueEnum, Debug, Clone)] +pub enum FontManager { + Fontconfig, + Macfonts, +} From 8f5eb31196a4cc1e87c796b198f8f5021c87e00b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 12 Apr 2023 23:32:46 +0300 Subject: [PATCH 024/357] chore(cli): Add more useful argument hints --- src/cli.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 9e7b8d793..f4f40eb65 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -20,15 +20,16 @@ pub struct Cli { pub class: Option, /// Show debug information for tagged aspects of SILE’s operation - #[clap(short, long)] + #[clap(short, long, value_name = "DEBUGFLAG[,DEBUGFLAG]")] + // TODO: switch to num_args(0..) to allow space separated inputs pub debug: Option>, /// Evaluate Lua expression before processing input - #[clap(short, long)] + #[clap(short, long, value_name = "EXRPESION")] pub evaluate: Option>, /// Evaluate Lua expression after processing input - #[clap(short = 'E', long)] + #[clap(short = 'E', long, value_name = "EXRPESION")] pub evaluate_after: Option>, /// Choose an alternative font manager @@ -36,11 +37,11 @@ pub struct Cli { pub fontmanager: FontManager, /// Generate a list of dependencies in Makefile format - #[clap(short, long)] + #[clap(short, long, value_name = "FILE")] pub makedeps: Option, /// Explicitly set output file name - #[clap(short, long)] + #[clap(short, long, value_name = "FILE")] pub output: Option, /// Set document class options @@ -48,15 +49,19 @@ pub struct Cli { pub options: Option>, /// Process SIL, XML, or other content before the input document - #[clap(short, long)] + #[clap(short, long, value_name = "FILE")] pub preamble: Option>, /// Process SIL, XML, or other content after the input document - #[clap(short = 'P', long)] + #[clap(short = 'P', long, value_name = "FILE")] pub postamble: Option>, /// Load and initialize a module before processing input - #[clap(short, long)] + #[clap( + short, + long, + value_name = "MODULE[[PARAMETER=VALUE[,PARAMETER=VALUE]]]" + )] pub r#use: Option>, /// Discard all non-error output messages From b18b2f0e87db61623f6a8e6ee927176de90290dd Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 13 Apr 2023 01:10:40 +0300 Subject: [PATCH 025/357] refactor(core): Move path setup out of main CLI for reuse in library --- Makefile.am | 2 +- configure.ac | 2 +- sile.in | 70 +--------------------------------------------------- 3 files changed, 3 insertions(+), 71 deletions(-) diff --git a/Makefile.am b/Makefile.am index 318edf829..1e34f0d26 100644 --- a/Makefile.am +++ b/Makefile.am @@ -67,7 +67,7 @@ EXTRA_DIST += default.nix flake.nix flake.lock libtexpdf.git-rev shell.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) -BUILT_SOURCES = .version core/features.lua core/version.lua Makefile-distfiles +BUILT_SOURCES = .version core/features.lua core/pathsetup.lua core/version.lua Makefile-distfiles CLEANFILES = $(bin_SCRIPTS) $(dist_man_MANS) $(BUILT_SOURCES) $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) .version-prev diff --git a/configure.ac b/configure.ac index 8a0181b52..71b0c4fff 100644 --- a/configure.ac +++ b/configure.ac @@ -315,7 +315,7 @@ AC_SUBST([ROCKREV], [1]) AX_SUBST_MAN_DATE AC_CONFIG_FILES([build-aux/list-dist-files.sh], [chmod +x build-aux/list-dist-files.sh]) -AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/version.lua]) +AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/pathsetup.lua core/version.lua]) AC_CONFIG_FILES([sile-lua:sile.in tests/regressions.pl], [chmod +x sile-lua tests/regressions.pl]) AC_CONFIG_FILES([sile-dev-1.rockspec:sile.rockspec.in]) diff --git a/sile.in b/sile.in index 94695fef6..8a04789ac 100755 --- a/sile.in +++ b/sile.in @@ -4,75 +4,7 @@ SYSTEM_SILE_PATH = "@SILE_PATH@" SHARED_LIB_EXT = "@SHARED_LIB_EXT@" -local executable = debug.getinfo(1, "S").source -local luaversion = _VERSION:match("%d+%.%d+") - --- Normalize possibly dirty Lua path formatting shortcut: /./ → / --- Even leafo/gh-actions-luarocks takes this shortcut which inhibits duplicate cleanup -package.path = package.path:gsub("/%./", "/") -package.cpath = package.cpath:gsub("/%./", "/") - -local function prepend_and_dedup (segment, path) - local escaped = segment:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1') -- copied from pl.utils.escape() which we can't load yet - local striped = path:gsub(("^%s"):format(escaped), ""):gsub((";%s"):format(escaped), "") - return ("%s;%s"):format(segment, striped) -end - -local function prependPath (path) - package.path = prepend_and_dedup(path .. "/?/init.lua", package.path) - package.path = prepend_and_dedup(path .. "/?.lua", package.path) -end - -local function prependCPath (path) - package.cpath = prepend_and_dedup(path .. "/?.@SHARED_LIB_EXT@", package.cpath) -end - -local function extendPaths (path, ours) - prependCPath(path) - prependPath(path) - if ours then - prependPath(path .. "/lua-libraries") - if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks - prependCPath(path .. "/lua_modules/lib/lua/" .. luaversion) - prependPath(path .. "/lua_modules/share/lua/" .. luaversion) - end - else - prependCPath(path .. "/sile") - prependPath(path .. "/sile") - end -end - --- Facilitate loading SILE classes & packages from system LuaRocks --- Also weed out CWD relative paths, we add them in a different order later -local luapath = {} -local extpath = {} -for path in package.path:gmatch("[^;]+") do - table.insert(extpath, tostring(path:gsub("%?", "sile/?"))) - table.insert(luapath, path) -end -package.path = table.concat(luapath, ";") - -extendPaths("@SILE_PATH@", true) -extendPaths("@SILE_LIB_PATH@", true) - -package.path = table.concat(extpath, ";") .. ";" .. package.path - -local pathvar = os.getenv("SILE_PATH") -if pathvar then - for path in string.gmatch(pathvar, "[^;]+") do - if not path:match("^./") and path:len() >= 1 then - extendPaths(path) - end - end -end - -local cwd = executable:gsub("(.*)(/.*)", "%1") -if cwd:match("^@") then -- Consider "ours" for the sake of Nix Flake - extendPaths(".", true) -else - if cwd ~= "./" then extendPaths(cwd) end - extendPaths(".") -end +local executable, extendPaths = require("core.pathsetup") -- This global is set here and *also* in the core library, since this -- effectively passes the same table they are interchangeable (for now). From 677284928af346c96d5ec8a7d648a0755423b38d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 13 Apr 2023 01:34:58 +0300 Subject: [PATCH 026/357] chore(cli): Reuse path handling in both CLI variants --- .gitignore | 1 + core/pathsetup.lua.in | 73 +++++++++++++++++++++++++++++++++++++++++++ sile.in | 2 +- src/bin/sile.rs | 4 +-- 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 core/pathsetup.lua.in diff --git a/.gitignore b/.gitignore index 194069c90..916392aac 100644 --- a/.gitignore +++ b/.gitignore @@ -92,6 +92,7 @@ core/version.lua core/features.lua target/ completions/ +core/pathsetup.lua # Nix symlink to builds result/ diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in new file mode 100644 index 000000000..46fc3c9a9 --- /dev/null +++ b/core/pathsetup.lua.in @@ -0,0 +1,73 @@ +local executable = debug.getinfo(3, "S").source +local luaversion = _VERSION:match("%d+%.%d+") + +-- Normalize possibly dirty Lua path formatting shortcut: /./ → / +-- Even leafo/gh-actions-luarocks takes this shortcut which inhibits duplicate cleanup +package.path = package.path:gsub("/%./", "/") +package.cpath = package.cpath:gsub("/%./", "/") + +local function prepend_and_dedup (segment, path) + local escaped = segment:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1') -- copied from pl.utils.escape() which we can't load yet + local striped = path:gsub(("^%s"):format(escaped), ""):gsub((";%s"):format(escaped), "") + return ("%s;%s"):format(segment, striped) +end + +local function prependPath (path) + package.path = prepend_and_dedup(path .. "/?/init.lua", package.path) + package.path = prepend_and_dedup(path .. "/?.lua", package.path) +end + +local function prependCPath (path) + package.cpath = prepend_and_dedup(path .. "/?.@SHARED_LIB_EXT@", package.cpath) +end + +local function extendPaths (path, ours) + prependCPath(path) + prependPath(path) + if ours then + prependPath(path .. "/lua-libraries") + if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks + prependCPath(path .. "/lua_modules/lib/lua/" .. luaversion) + prependPath(path .. "/lua_modules/share/lua/" .. luaversion) + end + else + prependCPath(path .. "/sile") + prependPath(path .. "/sile") + end +end + +-- Facilitate loading SILE classes & packages from system LuaRocks +-- Also weed out CWD relative paths, we add them in a different order later +local luapath = {} +local extpath = {} +for path in package.path:gmatch("[^;]+") do + table.insert(extpath, tostring(path:gsub("%?", "sile/?"))) + table.insert(luapath, path) +end +package.path = table.concat(luapath, ";") + +extendPaths("@SILE_PATH@", true) +extendPaths("@SILE_LIB_PATH@", true) + +package.path = table.concat(extpath, ";") .. ";" .. package.path + +local pathvar = os.getenv("SILE_PATH") +if pathvar then + for path in string.gmatch(pathvar, "[^;]+") do + if not path:match("^./") and path:len() >= 1 then + extendPaths(path) + end + end +end + +local cwd = executable:gsub("(.*)(/.*)", "%1") +if cwd:match("^@") then -- Consider "ours" for the sake of Nix Flake + extendPaths(".", true) +else + if cwd ~= "./" then extendPaths(cwd) end + extendPaths(".") +end + +return function () + return executable, extendPaths +end diff --git a/sile.in b/sile.in index 8a04789ac..288bca0cd 100755 --- a/sile.in +++ b/sile.in @@ -4,7 +4,7 @@ SYSTEM_SILE_PATH = "@SILE_PATH@" SHARED_LIB_EXT = "@SHARED_LIB_EXT@" -local executable, extendPaths = require("core.pathsetup") +local executable, extendPaths = require("core.pathsetup")() -- This global is set here and *also* in the core library, since this -- effectively passes the same table they are interchangeable (for now). diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 7e805c787..14cab10e5 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -16,8 +16,8 @@ fn sile() -> LuaResult<()> { let lua = unsafe { Lua::unsafe_new() }; lua.load( r#" - package.path = ";;./?.lua;./?/init.lua;./lua-libraries/?.lua;./lua-libraries/?/init.lua;./lua_modules/share/lua/5.4/?.lua;./lua_modules/share/lua/5.4/?/init.lua" - package.cpath = ";;./?.so;./lua_modules/lib/lua/5.4/?.so" + package.path = "./?.lua" + local executable, extendPaths = require("core.pathsetup")() SILE = require("core.sile") io.stderr:write(" [ Rust ]" .. SILE.full_version .. '\n') SILE.init() From 737cf2c36acb86e35a33745a9bdb42e54b38edba Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 18 Apr 2023 16:31:49 +0300 Subject: [PATCH 027/357] refactor(cli): Move masterDir and masterFilename generation re require less intervention --- .luacheckrc | 1 + .luarc.json | 1 + core/cli.lua | 5 ----- core/pathsetup.lua.in | 4 +++- core/sile.lua | 14 +++++++++++++- sile.in | 8 ++------ src/bin/sile.rs | 2 +- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 55574cc41..fa9a64efe 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -26,6 +26,7 @@ globals = { "luautf8", "pl", "fluent", + "extendSilePath", "SYSTEM_SILE_PATH", "SHARED_LIB_EXT" } diff --git a/.luarc.json b/.luarc.json index 3b7cf8fcd..1dec11cee 100644 --- a/.luarc.json +++ b/.luarc.json @@ -7,6 +7,7 @@ "luautf8", "pl", "fluent", + "extendSilePath", "SYSTEM_SILE_PATH", "SHARED_LIB_EXT" ], diff --git a/core/cli.lua b/core/cli.lua index 2fc777046..423265de3 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -47,11 +47,6 @@ cli.parseArguments = function () opts.INPUT = "-" end SILE.input.filename = opts.INPUT - -- Turn slashes around in the event we get passed a path from a Windows shell - local filename = opts.INPUT:gsub("\\", "/") - -- Strip extension - SILE.masterFilename = string.match(filename, "(.+)%..-$") or filename - SILE.masterDir = SILE.masterFilename:match("(.-)[^%/]+$") end if opts.backend then SILE.backend = opts.backend diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index 46fc3c9a9..a35b6c8d9 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -68,6 +68,8 @@ else extendPaths(".") end +_G.extendSilePath = extendPaths + return function () - return executable, extendPaths + return executable end diff --git a/core/sile.lua b/core/sile.lua index d19f5cdf8..332a05b47 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -306,6 +306,18 @@ function SILE.processFile (filename, format, options) filename = "STDIN" doc = io.stdin:read("*a") else + -- Turn slashes around in the event we get passed a path from a Windows shell + filename = filename:gsub("\\", "/") + if not SILE.masterFilename then + -- Strip extension + SILE.masterFilename = string.match(filename, "(.+)%..-$") or filename + end + if SILE.masterFilename and not SILE.masterDir then + SILE.masterDir = SILE.masterFilename:match("(.-)[^%/]+$") + end + if SILE.masterDir and SILE.masterDir:len() >= 1 then + extendSilePath(SILE.masterDir) + end filename = SILE.resolveFile(filename) if not filename then SU.error("Could not find file") @@ -356,7 +368,7 @@ function SILE.resolveFile (filename, pathprefix) candidates[#candidates+1] = "?" -- Iterate through the directory of the master file, the SILE_PATH variable, and the current directory -- Check for prefixed paths first, then the plain path in that fails - if SILE.masterFilename then + if SILE.masterDir then for path in SU.gtoke(SILE.masterDir..";"..tostring(os.getenv("SILE_PATH")), ";") do if path.string and path.string ~= "nil" then if pathprefix then candidates[#candidates+1] = pl.path.join(path.string, pathprefix, "?") end diff --git a/sile.in b/sile.in index 288bca0cd..3b531f56e 100755 --- a/sile.in +++ b/sile.in @@ -4,7 +4,7 @@ SYSTEM_SILE_PATH = "@SILE_PATH@" SHARED_LIB_EXT = "@SHARED_LIB_EXT@" -local executable, extendPaths = require("core.pathsetup")() +local executable = require("core.pathsetup")() -- This global is set here and *also* in the core library, since this -- effectively passes the same table they are interchangeable (for now). @@ -29,11 +29,7 @@ end SILE.init() -if SILE.masterFilename then - - if SILE.masterDir:len() >= 1 then - extendPaths(SILE.masterDir) - end +if SILE.input.filename and SILE.input.filename:len() > 0 then if SU.debugging("profile") then ProFi:start() diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 14cab10e5..92fcffa42 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -17,7 +17,7 @@ fn sile() -> LuaResult<()> { lua.load( r#" package.path = "./?.lua" - local executable, extendPaths = require("core.pathsetup")() + require("core.pathsetup")() SILE = require("core.sile") io.stderr:write(" [ Rust ]" .. SILE.full_version .. '\n') SILE.init() From 7e24f451f002f68bb33d279602f432c1cb06afda Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 15 Apr 2023 00:36:20 +0300 Subject: [PATCH 028/357] chore(cli): Pass some data to Lua library from Rust cli --- src/bin/sile.rs | 81 +++++++++++++++++++++++++++++++++++++------------ src/cli.rs | 2 +- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 92fcffa42..a48636cac 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -1,5 +1,6 @@ -use clap::CommandFactory; +use clap::{CommandFactory, FromArgMatches}; use mlua::prelude::*; +use std::path::PathBuf; use sile::cli::Cli; @@ -8,27 +9,69 @@ fn main() -> sile::Result<()> { let app = Cli::command().version(version); #[allow(unused_variables)] let matches = app.get_matches(); - sile()?; + let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); + run_sile(args.input, args.debug, args.traceback)?; Ok(()) } -fn sile() -> LuaResult<()> { +fn run_sile(input: PathBuf, debug: Option>, traceback: bool) -> sile::Result<()> { let lua = unsafe { Lua::unsafe_new() }; - lua.load( - r#" - package.path = "./?.lua" - require("core.pathsetup")() - SILE = require("core.sile") - io.stderr:write(" [ Rust ]" .. SILE.full_version .. '\n') - SILE.init() - SILE.masterFilename = "tests/absmin" - SILE.masterDir = "tests" - SILE.input.filename = "tests/absmin.xml" - SILE.processFile(SILE.input.filename) - SILE.outputter:finish() - SILE.finish() - "#, - ) - .exec()?; + let sile: LuaTable = lua + .load( + r#" + package.path = "./?.lua" + local executable = require("core.pathsetup")() + return require("core.sile") + "#, + ) + .eval()?; + sile.set("traceback", traceback)?; + if let Some(flags) = debug { + sile.set("debugFlags", flags)?; + } + let full_version: String = sile.get("full_version")?; + eprintln!("{full_version} [Rust]"); + let sile_input: LuaTable = sile.get("input")?; + if let Some(expressions) = evaluate { + sile_input.set("evaluates", expressions)?; + } + if let Some(expressions) = evaluate_after { + sile_input.set("evaluateAfters", expressions)?; + } + if let Some(backend) = backend { + sile.set("backend", backend)?; + } + if let Some(fontmanager) = fontmanager { + sile.set("fontmanager", fontmanager)?; + } + if let Some(class) = class { + sile_input.set("class", class)?; + } + if let Some(paths) = preamble { + sile_input.set("preambles", pbs_to_sts(paths))?; + } + if let Some(paths) = postamble { + sile_input.set("postamble", pbs_to_sts(paths))?; + } + if let Some(path) = makedeps { + sile_input.set("makedeps", pb_to_st(&path))?; + } + if let Some(options) = options { + sile_input.set("options", options)?; + } + if let Some(modules) = r#use { + sile_input.set("use", modules)?; + } + let input_filename: LuaString = lua.create_string(&pb_to_st(&input))?; + if let Some(path) = output { + sile.set("outputFilename", pb_to_st(&path))?; + } + sile_input.set("filename", input_filename)?; + let init: LuaFunction = sile.get("init")?; + init.call::<_, _>(())?; + let process_file: LuaFunction = sile.get("processFile")?; + process_file.call::(sile_input.get("filename")?)?; + let finish: LuaFunction = sile.get("finish")?; + finish.call::<(), ()>(())?; Ok(()) } diff --git a/src/cli.rs b/src/cli.rs index f4f40eb65..f0542cd76 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; #[clap(author, bin_name = "sile")] pub struct Cli { /// Input document, by default in SIL or XML format - pub input: String, + pub input: PathBuf, /// Choose an alternative output backend #[clap(short, long, value_enum, default_value_t=Backend::Libtexpdf)] From 16b5350077e73b434d325b469f2f66c58795e269 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 19 Apr 2023 00:37:04 +0300 Subject: [PATCH 029/357] chore(cli): Pass quiet flag from Rust CLI --- src/bin/sile.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index a48636cac..3ea7f03d4 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -10,11 +10,16 @@ fn main() -> sile::Result<()> { #[allow(unused_variables)] let matches = app.get_matches(); let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); - run_sile(args.input, args.debug, args.traceback)?; + run_sile(args.input, args.debug, args.quiet, args.traceback)?; Ok(()) } -fn run_sile(input: PathBuf, debug: Option>, traceback: bool) -> sile::Result<()> { +fn run_sile( + input: PathBuf, + debug: Option>, + quiet: bool, + traceback: bool, +) -> sile::Result<()> { let lua = unsafe { Lua::unsafe_new() }; let sile: LuaTable = lua .load( @@ -26,6 +31,7 @@ fn run_sile(input: PathBuf, debug: Option>, traceback: bool) -> sile ) .eval()?; sile.set("traceback", traceback)?; + sile.set("quiet", quiet)?; if let Some(flags) = debug { sile.set("debugFlags", flags)?; } From 7a63856823a4223453b065e126ac640bb127a472 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 19 Apr 2023 12:40:50 +0300 Subject: [PATCH 030/357] chore(cli): Pass most remaining values from Rust CLI --- src/bin/sile.rs | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 3ea7f03d4..0dc6698b9 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -2,7 +2,7 @@ use clap::{CommandFactory, FromArgMatches}; use mlua::prelude::*; use std::path::PathBuf; -use sile::cli::Cli; +use sile::cli::{Backend, Cli, FontManager}; fn main() -> sile::Result<()> { let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); @@ -10,13 +10,40 @@ fn main() -> sile::Result<()> { #[allow(unused_variables)] let matches = app.get_matches(); let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); - run_sile(args.input, args.debug, args.quiet, args.traceback)?; + run_sile( + args.input, + args.backend, + args.class, + args.debug, + args.evaluate, + args.evaluate_after, + args.fontmanager, + args.makedeps, + args.output, + args.options, + args.preamble, + args.postamble, + args.r#use, + args.quiet, + args.traceback, + )?; Ok(()) } fn run_sile( input: PathBuf, + backend: Backend, + class: Option, debug: Option>, + evaluate: Option>, + evaluate_after: Option>, + fontmanager: FontManager, + makedeps: Option, + output: Option, + options: Option>, + preamble: Option>, + postamble: Option>, + r#use: Option>, quiet: bool, traceback: bool, ) -> sile::Result<()> { @@ -44,12 +71,6 @@ fn run_sile( if let Some(expressions) = evaluate_after { sile_input.set("evaluateAfters", expressions)?; } - if let Some(backend) = backend { - sile.set("backend", backend)?; - } - if let Some(fontmanager) = fontmanager { - sile.set("fontmanager", fontmanager)?; - } if let Some(class) = class { sile_input.set("class", class)?; } @@ -78,6 +99,14 @@ fn run_sile( let process_file: LuaFunction = sile.get("processFile")?; process_file.call::(sile_input.get("filename")?)?; let finish: LuaFunction = sile.get("finish")?; - finish.call::<(), ()>(())?; + finish.call::<_, _>(())?; Ok(()) } + +fn pb_to_st(path: &PathBuf) -> String { + path.clone().into_os_string().into_string().unwrap() +} + +fn pbs_to_sts(paths: Vec) -> Vec { + paths.iter().map(|p| pb_to_st(p)).collect() +} From 0ce3c2f0862dda515123c9dc8c117d46dd5d789e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 19 Apr 2023 16:31:42 +0300 Subject: [PATCH 031/357] chore(cli): Ditch structs because we need custom string support on the Lua side --- src/bin/sile.rs | 12 +++++++++--- src/cli.rs | 26 +++++--------------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 0dc6698b9..f00504241 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -2,7 +2,7 @@ use clap::{CommandFactory, FromArgMatches}; use mlua::prelude::*; use std::path::PathBuf; -use sile::cli::{Backend, Cli, FontManager}; +use sile::cli::Cli; fn main() -> sile::Result<()> { let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); @@ -32,12 +32,12 @@ fn main() -> sile::Result<()> { fn run_sile( input: PathBuf, - backend: Backend, + backend: Option, class: Option, debug: Option>, evaluate: Option>, evaluate_after: Option>, - fontmanager: FontManager, + fontmanager: Option, makedeps: Option, output: Option, options: Option>, @@ -71,6 +71,12 @@ fn run_sile( if let Some(expressions) = evaluate_after { sile_input.set("evaluateAfters", expressions)?; } + if let Some(backend) = backend { + sile.set("backend", backend)?; + } + if let Some(fontmanager) = fontmanager { + sile.set("fontmanager", fontmanager)?; + } if let Some(class) = class { sile_input.set("class", class)?; } diff --git a/src/cli.rs b/src/cli.rs index f0542cd76..cd2c6f2a1 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,4 +1,4 @@ -use clap::{Parser, ValueEnum}; +use clap::Parser; use std::path::PathBuf; /// The SILE typesetter reads a single input file, by default in either SIL or XML format, and @@ -12,8 +12,8 @@ pub struct Cli { pub input: PathBuf, /// Choose an alternative output backend - #[clap(short, long, value_enum, default_value_t=Backend::Libtexpdf)] - pub backend: Backend, + #[clap(short, long, value_name = "BACKEND")] + pub backend: Option, /// Override default document class #[clap(short, long)] @@ -33,8 +33,8 @@ pub struct Cli { pub evaluate_after: Option>, /// Choose an alternative font manager - #[clap(short, long, value_enum, default_value_t=FontManager::Fontconfig)] - pub fontmanager: FontManager, + #[clap(short, long, value_name = "FONTMANAGER")] + pub fontmanager: Option, /// Generate a list of dependencies in Makefile format #[clap(short, long, value_name = "FILE")] @@ -72,19 +72,3 @@ pub struct Cli { #[clap(short, long)] pub traceback: bool, } - -#[derive(ValueEnum, Debug, Clone)] -pub enum Backend { - Libtexpdf, - Debug, - Text, - Dummy, - Cairo, - Podofo, -} - -#[derive(ValueEnum, Debug, Clone)] -pub enum FontManager { - Fontconfig, - Macfonts, -} From 2c8549cba831d6ba8a23a3b7b40086de78aac791 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 19 Apr 2023 22:05:23 +0300 Subject: [PATCH 032/357] chore(cli): Fix debug flag assignment from Rust --- src/bin/sile.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index f00504241..0ba8fb0ab 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -60,7 +60,10 @@ fn run_sile( sile.set("traceback", traceback)?; sile.set("quiet", quiet)?; if let Some(flags) = debug { - sile.set("debugFlags", flags)?; + let debug_flags: LuaTable = sile.get("debugFlags")?; + for flag in flags { + debug_flags.set(flag, true)?; + } } let full_version: String = sile.get("full_version")?; eprintln!("{full_version} [Rust]"); From 8b31f6df1904740f1a2dae9e7f276367bb8280f8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sun, 23 Apr 2023 15:28:33 +0300 Subject: [PATCH 033/357] chore(cli): Use anyhow to get sane error message formatting back --- Cargo.lock | 1 + Cargo.toml | 3 +++ src/lib.rs | 4 +--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 648d005be..457641008 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -492,6 +492,7 @@ checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" name = "sile" version = "0.14.8" dependencies = [ + "anyhow", "clap", "clap_complete", "clap_mangen", diff --git a/Cargo.toml b/Cargo.toml index f6ebb411a..35cc352e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ required-features = ["cli"] [dependencies] + [dependencies.anyhow] + version = "1.0" + [dependencies.clap] version = "4.2" optional = true diff --git a/src/lib.rs b/src/lib.rs index 096aaab2c..e621c1561 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,4 @@ -use std::{error, result}; - #[cfg(feature = "cli")] pub mod cli; -pub type Result = result::Result>; +pub type Result = anyhow::Result; From 163b2eb3416874c54da146d6c17f37ca3367c1c8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 24 Apr 2023 11:03:21 +0300 Subject: [PATCH 034/357] chore(build): Setup configure to pass system Lua version to Rust --- Cargo.toml | 9 +++++++-- Makefile.am | 21 ++++++++++++++------- build.rs => build-aux/build.rs | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) rename build.rs => build-aux/build.rs (99%) diff --git a/Cargo.toml b/Cargo.toml index 35cc352e1..b7ea9cdf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ authors = [ rust-version = "1.68" homepage = "https://sile-typesetter.org" license = "MIT" -build = "build.rs" +build = "build-aux/build.rs" [[bin]] name = "sile" @@ -30,7 +30,7 @@ required-features = ["cli"] [dependencies.mlua] version = "0.8" - features = [ "lua54", "vendored" ] + features = [ "vendored" ] [build-dependencies] @@ -54,6 +54,11 @@ required-features = ["cli"] [features] default = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"] +lua54 = ["mlua/lua54"] +lua53 = ["mlua/lua53"] +lua52 = ["mlua/lua52"] +lua51 = ["mlua/lua51"] +luajit = ["mlua/luajit"] completions = ["cli", "clap_complete"] cli = ["clap"] bash = ["completions"] diff --git a/Makefile.am b/Makefile.am index 1e34f0d26..a328c6a83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,7 +57,7 @@ dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE lua-libraries/LICENSE-lunamark bin_SCRIPTS = sile-lua bin_PROGRAMS = sile -sile_SOURCES = Cargo.toml build.rs src/bin/sile.rs src/lib.rs src/cli.rs +sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli.rs EXTRA_sile_SOURCES = Cargo.lock .version EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles @@ -75,11 +75,18 @@ Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ if DEBUG_RELEASE -CARGO_RELEASE_ARGS = --all-features +CARGO_RELEASE_ARGS = else -CARGO_RELEASE_ARGS = --release --locked --all-features +CARGO_RELEASE_ARGS = --release --locked endif +if LUAJIT +MLUAVER = luajit +else +MLUAVER = lua$(LUA_SHORT_VERSION) +endif +CARGO_FEATURE_ARGS = --features $(MLUAVER) + CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target RUST_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) _RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir @@ -142,8 +149,8 @@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS $(_RUST_OUT) $(RUST_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) cd $(top_srcdir) - $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_RELEASE_ARGS) - $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_RELEASE_ARGS) | + $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) + $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) _BRANCH_REF != $(AWK) '{print ".git/" $$2}' .git/HEAD 2>/dev/null ||: @@ -300,11 +307,11 @@ rustfmt: clippy: cd $(srcdir) - $(CARGO_ENV) $(CARGO) clippy -- -D warnings + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clippy $(CARGO_FEATURE_ARGS) -- -D warnings cargo-test: $(SILE) cd $(srcdir) - $(CARGO_ENV) $(CARGO) test --locked + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) test $(CARGO_FEATURE_ARGS) --locked busted: $(SILELUA) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) set -f; IFS=';' diff --git a/build.rs b/build-aux/build.rs similarity index 99% rename from build.rs rename to build-aux/build.rs index 3a61e66e0..a698a8166 100644 --- a/build.rs +++ b/build-aux/build.rs @@ -12,7 +12,7 @@ use std::{fs, path}; use vergen::{vergen, Config}; #[cfg(feature = "completions")] -include!("src/cli.rs"); +include!("../src/cli.rs"); fn main() { let mut flags = Config::default(); From 6162a65f2193401719c76b03eff2f5b9ccdc894e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 24 Apr 2023 11:34:18 +0300 Subject: [PATCH 035/357] chore(cli): Bring REPL to Rust based CLI --- core/sile.lua | 3 +++ sile.in | 4 ---- src/bin/sile.rs | 25 +++++++++++++++---------- src/cli.rs | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 332a05b47..8717cfe11 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -449,6 +449,9 @@ function SILE.finish () if not SILE.quiet then io.stderr:write("\n") end + if SU.debugging("versions") then + SILE.shaper:debugVersions() + end end -- Internal libraries that run core SILE functions on load diff --git a/sile.in b/sile.in index 3b531f56e..86330bd8d 100755 --- a/sile.in +++ b/sile.in @@ -72,10 +72,6 @@ if SILE.input.filename and SILE.input.filename:len() > 0 then ProFi:writeReport(SILE.masterFilename..'.profile.txt') end - if SU.debugging("versions") then - SILE.shaper:debugVersions() - end - else SILE.repl:enter() end diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 0ba8fb0ab..6ee26ec83 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -31,7 +31,7 @@ fn main() -> sile::Result<()> { } fn run_sile( - input: PathBuf, + input: Option, backend: Option, class: Option, debug: Option>, @@ -98,17 +98,22 @@ fn run_sile( if let Some(modules) = r#use { sile_input.set("use", modules)?; } - let input_filename: LuaString = lua.create_string(&pb_to_st(&input))?; - if let Some(path) = output { - sile.set("outputFilename", pb_to_st(&path))?; - } - sile_input.set("filename", input_filename)?; let init: LuaFunction = sile.get("init")?; init.call::<_, _>(())?; - let process_file: LuaFunction = sile.get("processFile")?; - process_file.call::(sile_input.get("filename")?)?; - let finish: LuaFunction = sile.get("finish")?; - finish.call::<_, _>(())?; + if let Some(input) = input { + let input_filename: LuaString = lua.create_string(&pb_to_st(&input))?; + if let Some(path) = output { + sile.set("outputFilename", pb_to_st(&path))?; + } + sile_input.set("filename", input_filename)?; + let process_file: LuaFunction = sile.get("processFile")?; + process_file.call::(sile_input.get("filename")?)?; + let finish: LuaFunction = sile.get("finish")?; + finish.call::<_, _>(())?; + } else { + let repl: LuaTable = sile.get("repl")?; + repl.call_method::<_, _, _>("enter", ())?; + } Ok(()) } diff --git a/src/cli.rs b/src/cli.rs index cd2c6f2a1..a05f07834 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; #[clap(author, bin_name = "sile")] pub struct Cli { /// Input document, by default in SIL or XML format - pub input: PathBuf, + pub input: Option, /// Choose an alternative output backend #[clap(short, long, value_name = "BACKEND")] From 465e8e5510d7868952b02b1f0fa12ee770c36cc8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 24 Apr 2023 12:36:39 +0300 Subject: [PATCH 036/357] chore(cli): Move profiler to where both CLIs and also library mode can use it --- core/sile.lua | 15 +++++++++++++++ sile.in | 20 -------------------- src/bin/sile.rs | 4 +++- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 8717cfe11..9ed4d7ef2 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -29,6 +29,9 @@ fluent = require("fluent")() -- Includes for _this_ scope local lfs = require("lfs") +-- Developer tooling profiler +local ProFi + SILE.utilities = require("core.utilities") SU = SILE.utilities -- regrettable global alias @@ -131,6 +134,14 @@ SILE.init = function () SILE.outputter = SILE.outputters.dummy() end SILE.pagebuilder = SILE.pagebuilders.base() + io.stdout:setvbuf("no") + if SU.debugging("profile") then + ProFi = require("ProFi") + ProFi:start() + end + if SILE.makeDeps then + SILE.makeDeps:add(executable) + end runEvals(SILE.input.evaluates, "evaluate") end @@ -449,6 +460,10 @@ function SILE.finish () if not SILE.quiet then io.stderr:write("\n") end + if SU.debugging("profile") then + ProFi:stop() + ProFi:writeReport(SILE.masterFilename..'.profile.txt') + end if SU.debugging("versions") then SILE.shaper:debugVersions() end diff --git a/sile.in b/sile.in index 86330bd8d..0efd738c8 100755 --- a/sile.in +++ b/sile.in @@ -10,31 +10,16 @@ local executable = require("core.pathsetup")() -- effectively passes the same table they are interchangeable (for now). SILE = require("core.sile") -io.stdout:setvbuf 'no' - SILE.cli:parseArguments() if not os.getenv 'LUA_REPL_RLWRAP' and not SILE.quiet then io.stderr:write(SILE.full_version .. '\n') end -local ProFi -if SU.debugging("profile") then - ProFi = require("ProFi") -end - -if SILE.makeDeps then - SILE.makeDeps:add(executable) -end - SILE.init() if SILE.input.filename and SILE.input.filename:len() > 0 then - if SU.debugging("profile") then - ProFi:start() - end - -- Deprecated, notice given in core.cli when argument used for _, path in ipairs(SILE.input.includes) do if not SILE.quiet then @@ -67,11 +52,6 @@ if SILE.input.filename and SILE.input.filename:len() > 0 then SILE.finish() - if SU.debugging("profile") then - ProFi:stop() - ProFi:writeReport(SILE.masterFilename..'.profile.txt') - end - else SILE.repl:enter() end diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 6ee26ec83..de008aaec 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -66,7 +66,6 @@ fn run_sile( } } let full_version: String = sile.get("full_version")?; - eprintln!("{full_version} [Rust]"); let sile_input: LuaTable = sile.get("input")?; if let Some(expressions) = evaluate { sile_input.set("evaluates", expressions)?; @@ -98,6 +97,9 @@ fn run_sile( if let Some(modules) = r#use { sile_input.set("use", modules)?; } + if !quiet { + eprintln!("{full_version} [Rust]"); + } let init: LuaFunction = sile.get("init")?; init.call::<_, _>(())?; if let Some(input) = input { From 44b114c966a36acf3ebc1cca443be15a01f19fe0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 25 Apr 2023 21:08:37 +0300 Subject: [PATCH 037/357] chore(cli): Read system Lua path at compile time and save for emulation --- Cargo.lock | 64 +++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 +++- Makefile-luarocks | 3 +++ src/bin/sile.rs | 22 ++++++++++++---- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 457641008..4760bfb8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.2.6" @@ -161,6 +170,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "enum-iterator" version = "1.4.0" @@ -281,6 +296,15 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.6" @@ -296,6 +320,12 @@ dependencies = [ "libc", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.141" @@ -375,12 +405,28 @@ dependencies = [ "cc", "lua-src", "luajit-src", + "mlua_derive", "num-traits", "once_cell", "pkg-config", "rustc-hash", ] +[[package]] +name = "mlua_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9214e60d3cf1643013b107330fcd374ccec1e4ba1eef76e7e5da5e8202e71c0" +dependencies = [ + "itertools", + "once_cell", + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -450,6 +496,23 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" + [[package]] name = "roff" version = "0.2.1" @@ -496,6 +559,7 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", + "lazy_static", "mlua", "vergen", ] diff --git a/Cargo.toml b/Cargo.toml index b7ea9cdf1..fbb675cfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,9 +28,12 @@ required-features = ["cli"] optional = true features = [ "derive", "wrap_help" ] + [dependencies.lazy_static] + version = "1.4" + [dependencies.mlua] version = "0.8" - features = [ "vendored" ] + features = [ "macros", "vendored" ] [build-dependencies] diff --git a/Makefile-luarocks b/Makefile-luarocks index 46e5c8ef3..7ea0dc624 100644 --- a/Makefile-luarocks +++ b/Makefile-luarocks @@ -17,4 +17,7 @@ $(LUAMODLOCK): lua_modules $(LUAMODSPEC) $(genrockslock) > $@ else LUAMODLOCK := +LUA_PATH := $(shell lua$(LUA_VERSION) -e 'print(package.path)') +LUA_CPATH := $(shell lua$(LUA_VERSION) -e 'print(package.cpath)') +export LUA_PATH LUA_CPATH endif diff --git a/src/bin/sile.rs b/src/bin/sile.rs index de008aaec..c6263a43d 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -1,9 +1,20 @@ use clap::{CommandFactory, FromArgMatches}; +use lazy_static::lazy_static; +use mlua::chunk; use mlua::prelude::*; use std::path::PathBuf; use sile::cli::Cli; +// These env vars are generated by autoconf *at compile time* in order to emulate the system +// default Lua interpreter. If they exist we use them, else keep it to ourselves. +lazy_static! { + #[derive(Debug)] + pub static ref LUA_PATH: &'static str = option_env!["LUA_PATH"].unwrap_or_else(|| "./?.lua"); + #[derive(Debug)] + pub static ref LUA_CPATH: &'static str = option_env!["LUA_CPATH"].unwrap_or_else(|| ""); +} + fn main() -> sile::Result<()> { let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); let app = Cli::command().version(version); @@ -48,14 +59,15 @@ fn run_sile( traceback: bool, ) -> sile::Result<()> { let lua = unsafe { Lua::unsafe_new() }; + let lua_path: LuaString = lua.create_string(&LUA_PATH.clone()).unwrap(); + let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone()).unwrap(); let sile: LuaTable = lua - .load( - r#" - package.path = "./?.lua" + .load(chunk! { + package.path = $lua_path + package.cpath = $lua_cpath local executable = require("core.pathsetup")() return require("core.sile") - "#, - ) + }) .eval()?; sile.set("traceback", traceback)?; sile.set("quiet", quiet)?; From 5a52b02f51f01380e0edc2e600095a4a91dcd127 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 26 Apr 2023 15:18:34 +0300 Subject: [PATCH 038/357] refactor(cli): Move runner functions to library --- src/bin/sile.rs | 114 +----------------------------------------------- src/lib.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 112 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index c6263a43d..39575173a 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -1,19 +1,7 @@ use clap::{CommandFactory, FromArgMatches}; -use lazy_static::lazy_static; -use mlua::chunk; -use mlua::prelude::*; -use std::path::PathBuf; use sile::cli::Cli; - -// These env vars are generated by autoconf *at compile time* in order to emulate the system -// default Lua interpreter. If they exist we use them, else keep it to ourselves. -lazy_static! { - #[derive(Debug)] - pub static ref LUA_PATH: &'static str = option_env!["LUA_PATH"].unwrap_or_else(|| "./?.lua"); - #[derive(Debug)] - pub static ref LUA_CPATH: &'static str = option_env!["LUA_CPATH"].unwrap_or_else(|| ""); -} +use sile::run; fn main() -> sile::Result<()> { let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); @@ -21,7 +9,7 @@ fn main() -> sile::Result<()> { #[allow(unused_variables)] let matches = app.get_matches(); let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); - run_sile( + run( args.input, args.backend, args.class, @@ -40,101 +28,3 @@ fn main() -> sile::Result<()> { )?; Ok(()) } - -fn run_sile( - input: Option, - backend: Option, - class: Option, - debug: Option>, - evaluate: Option>, - evaluate_after: Option>, - fontmanager: Option, - makedeps: Option, - output: Option, - options: Option>, - preamble: Option>, - postamble: Option>, - r#use: Option>, - quiet: bool, - traceback: bool, -) -> sile::Result<()> { - let lua = unsafe { Lua::unsafe_new() }; - let lua_path: LuaString = lua.create_string(&LUA_PATH.clone()).unwrap(); - let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone()).unwrap(); - let sile: LuaTable = lua - .load(chunk! { - package.path = $lua_path - package.cpath = $lua_cpath - local executable = require("core.pathsetup")() - return require("core.sile") - }) - .eval()?; - sile.set("traceback", traceback)?; - sile.set("quiet", quiet)?; - if let Some(flags) = debug { - let debug_flags: LuaTable = sile.get("debugFlags")?; - for flag in flags { - debug_flags.set(flag, true)?; - } - } - let full_version: String = sile.get("full_version")?; - let sile_input: LuaTable = sile.get("input")?; - if let Some(expressions) = evaluate { - sile_input.set("evaluates", expressions)?; - } - if let Some(expressions) = evaluate_after { - sile_input.set("evaluateAfters", expressions)?; - } - if let Some(backend) = backend { - sile.set("backend", backend)?; - } - if let Some(fontmanager) = fontmanager { - sile.set("fontmanager", fontmanager)?; - } - if let Some(class) = class { - sile_input.set("class", class)?; - } - if let Some(paths) = preamble { - sile_input.set("preambles", pbs_to_sts(paths))?; - } - if let Some(paths) = postamble { - sile_input.set("postamble", pbs_to_sts(paths))?; - } - if let Some(path) = makedeps { - sile_input.set("makedeps", pb_to_st(&path))?; - } - if let Some(options) = options { - sile_input.set("options", options)?; - } - if let Some(modules) = r#use { - sile_input.set("use", modules)?; - } - if !quiet { - eprintln!("{full_version} [Rust]"); - } - let init: LuaFunction = sile.get("init")?; - init.call::<_, _>(())?; - if let Some(input) = input { - let input_filename: LuaString = lua.create_string(&pb_to_st(&input))?; - if let Some(path) = output { - sile.set("outputFilename", pb_to_st(&path))?; - } - sile_input.set("filename", input_filename)?; - let process_file: LuaFunction = sile.get("processFile")?; - process_file.call::(sile_input.get("filename")?)?; - let finish: LuaFunction = sile.get("finish")?; - finish.call::<_, _>(())?; - } else { - let repl: LuaTable = sile.get("repl")?; - repl.call_method::<_, _, _>("enter", ())?; - } - Ok(()) -} - -fn pb_to_st(path: &PathBuf) -> String { - path.clone().into_os_string().into_string().unwrap() -} - -fn pbs_to_sts(paths: Vec) -> Vec { - paths.iter().map(|p| pb_to_st(p)).collect() -} diff --git a/src/lib.rs b/src/lib.rs index e621c1561..6fe8ff1e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,115 @@ +use lazy_static::lazy_static; +use mlua::chunk; +use mlua::prelude::*; +use std::path::PathBuf; #[cfg(feature = "cli")] pub mod cli; pub type Result = anyhow::Result; + +// These env vars are generated by autoconf *at compile time* in order to emulate the system +// default Lua interpreter. If they exist we use them, else keep it to ourselves. +lazy_static! { + #[derive(Debug)] + pub static ref LUA_PATH: &'static str = option_env!["LUA_PATH"].unwrap_or_else(|| "./?.lua"); + #[derive(Debug)] + pub static ref LUA_CPATH: &'static str = option_env!["LUA_CPATH"].unwrap_or_else(|| ""); +} + +pub fn run( + input: Option, + backend: Option, + class: Option, + debug: Option>, + evaluate: Option>, + evaluate_after: Option>, + fontmanager: Option, + makedeps: Option, + output: Option, + options: Option>, + preamble: Option>, + postamble: Option>, + r#use: Option>, + quiet: bool, + traceback: bool, +) -> crate::Result<()> { + let lua = unsafe { Lua::unsafe_new() }; + let lua_path: LuaString = lua.create_string(&LUA_PATH.clone()).unwrap(); + let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone()).unwrap(); + let sile: LuaTable = lua + .load(chunk! { + package.path = $lua_path + package.cpath = $lua_cpath + local executable = require("core.pathsetup")() + return require("core.sile") + }) + .eval()?; + sile.set("traceback", traceback)?; + sile.set("quiet", quiet)?; + if let Some(flags) = debug { + let debug_flags: LuaTable = sile.get("debugFlags")?; + for flag in flags { + debug_flags.set(flag, true)?; + } + } + let full_version: String = sile.get("full_version")?; + let sile_input: LuaTable = sile.get("input")?; + if let Some(expressions) = evaluate { + sile_input.set("evaluates", expressions)?; + } + if let Some(expressions) = evaluate_after { + sile_input.set("evaluateAfters", expressions)?; + } + if let Some(backend) = backend { + sile.set("backend", backend)?; + } + if let Some(fontmanager) = fontmanager { + sile.set("fontmanager", fontmanager)?; + } + if let Some(class) = class { + sile_input.set("class", class)?; + } + if let Some(paths) = preamble { + sile_input.set("preambles", pbs_to_sts(paths))?; + } + if let Some(paths) = postamble { + sile_input.set("postamble", pbs_to_sts(paths))?; + } + if let Some(path) = makedeps { + sile_input.set("makedeps", pb_to_st(&path))?; + } + if let Some(options) = options { + sile_input.set("options", options)?; + } + if let Some(modules) = r#use { + sile_input.set("use", modules)?; + } + if !quiet { + eprintln!("{full_version} [Rust]"); + } + let init: LuaFunction = sile.get("init")?; + init.call::<_, _>(())?; + if let Some(input) = input { + let input_filename: LuaString = lua.create_string(&pb_to_st(&input))?; + if let Some(path) = output { + sile.set("outputFilename", pb_to_st(&path))?; + } + sile_input.set("filename", input_filename)?; + let process_file: LuaFunction = sile.get("processFile")?; + process_file.call::(sile_input.get("filename")?)?; + let finish: LuaFunction = sile.get("finish")?; + finish.call::<_, _>(())?; + } else { + let repl: LuaTable = sile.get("repl")?; + repl.call_method::<_, _, _>("enter", ())?; + } + Ok(()) +} + +fn pb_to_st(path: &PathBuf) -> String { + path.clone().into_os_string().into_string().unwrap() +} + +fn pbs_to_sts(paths: Vec) -> Vec { + paths.iter().map(pb_to_st).collect() +} From 3636548cc7164e3676538fc58f4f71d9edf064b0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 29 Apr 2023 11:10:23 +0300 Subject: [PATCH 039/357] chore(build): Tweak Rust env vars for easier local testing --- .cargo/config.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 0f236658a..fa4b7d557 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,3 +3,11 @@ rustflags = ["-C", "link-args=-rdynamic"] [target.x86_64-unknown-linux-gnu] rustflags = ["-C", "link-args=-rdynamic"] + +# Since autotools sets this and we are *not* forcing it here, this will not +# affect release builds. It will affect `cargo run` and make it easier to test +# locally since the Lua loader path will be relative to the current sources. +# For debug builds it is assumed you configured `--without-system-luarocks`, +# this convenience won't enable you to use system packages in debug builds. +[env] +SILE_PATH = { value = "", relative = true } From a2f7480744b9e20b03e4b9374f72799be88853f5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 29 Apr 2023 14:51:34 +0300 Subject: [PATCH 040/357] chore(cli): Normalize -V flag and related version outputs --- Cargo.toml | 2 +- core/cli.lua | 6 +++--- src/bin/sile.rs | 11 ++++++++--- src/cli.rs | 2 +- src/lib.rs | 19 +++++++++++++++++++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fbb675cfd..c1488851a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ required-features = ["cli"] [dependencies.clap] version = "4.2" optional = true - features = [ "derive", "wrap_help" ] + features = [ "derive", "string", "wrap_help" ] [dependencies.lazy_static] version = "1.4" diff --git a/core/cli.lua b/core/cli.lua index 423265de3..dfda89768 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -2,8 +2,8 @@ local cli = pl.class() cli.parseArguments = function () local cliargs = require("cliargs") - local print_version = function() - print(SILE.full_version) + local print_version = function(flag) + print(flag == "V" and "SILE " .. SILE.version or SILE.full_version) os.exit(0) end cliargs:set_colsz(0, 120) @@ -32,7 +32,7 @@ cli.parseArguments = function () cliargs:flag("-q, --quiet", "suppress warnings and informational messages during processing") cliargs:flag("-t, --traceback", "display detailed location trace on errors and warnings") cliargs:flag("-h, --help", "display this help, then exit") - cliargs:flag("-v, --version", "display version information, then exit", print_version) + cliargs:flag("-V, --version", "display version information, then exit", print_version) -- Work around cliargs not processing - as an alias for STDIO streams: -- https://github.com/amireh/lua_cliargs/issues/67 local _arg = pl.tablex.imap(luautf8.gsub, _G.arg, "^-$", "STDIO") diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 39575173a..3aaa9ad12 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -1,15 +1,20 @@ use clap::{CommandFactory, FromArgMatches}; use sile::cli::Cli; -use sile::run; fn main() -> sile::Result<()> { let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); - let app = Cli::command().version(version); + let version = version.replacen('-', ".r", 1); + let long_version = sile::version()? + .strip_prefix("SILE ") + .unwrap_or("") + .to_string(); + let long_version = format!("{} [Rust]", long_version); + let app = Cli::command().version(version).long_version(long_version); #[allow(unused_variables)] let matches = app.get_matches(); let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); - run( + sile::run( args.input, args.backend, args.class, diff --git a/src/cli.rs b/src/cli.rs index a05f07834..d9a151ce6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -6,7 +6,7 @@ use std::path::PathBuf; /// be written to the same name as the input file with the extension changed to .pdf. Additional /// input or output formats can be handled by requiring a module that adds support for them first. #[derive(Parser, Debug)] -#[clap(author, bin_name = "sile")] +#[clap(author, name = "SILE", bin_name = "sile")] pub struct Cli { /// Input document, by default in SIL or XML format pub input: Option, diff --git a/src/lib.rs b/src/lib.rs index 6fe8ff1e7..2c1b3a6f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,25 @@ lazy_static! { pub static ref LUA_CPATH: &'static str = option_env!["LUA_CPATH"].unwrap_or_else(|| ""); } +pub fn version() -> crate::Result { + let lua = unsafe { Lua::unsafe_new() }; + let lua_path: LuaString = lua.create_string(&LUA_PATH.clone())?; + let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone())?; + let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; + let sile: LuaTable = lua + .load(chunk! { + package.path = $lua_path + package.cpath = $lua_cpath + local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") + if not status then + dofile("./core/pathsetup.lua") + end + return require("core.sile") + }) + .eval()?; + Ok(sile.get("full_version")?) +} + pub fn run( input: Option, backend: Option, From 68d8c04d29f7574eae708a11f45c249ae3655c71 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 29 Apr 2023 16:47:53 +0300 Subject: [PATCH 041/357] chore(tooling): Add script to bump Cargo versions on release --- Makefile.am | 2 +- build-aux/cargo-updater.js | 12 ++++++++++++ package.json | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 build-aux/cargo-updater.js diff --git a/Makefile.am b/Makefile.am index 322cef7e9..72ce1c914 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,7 @@ sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli. EXTRA_sile_SOURCES = Cargo.lock .version EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles -EXTRA_DIST += build-aux/action-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh +EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh EXTRA_DIST += Dockerfile build-aux/docker-bootstrap.sh build-aux/docker-fontconfig.conf hooks/build EXTRA_DIST += default.nix flake.nix flake.lock shell.nix EXTRA_DIST += package.json # imported by both Nix and Docker diff --git a/build-aux/cargo-updater.js b/build-aux/cargo-updater.js new file mode 100644 index 000000000..1b64fda44 --- /dev/null +++ b/build-aux/cargo-updater.js @@ -0,0 +1,12 @@ +const TOML = require('@iarna/toml') + +module.exports.readVersion = function (contents) { + const data = TOML.parse(contents) + return data.package.version +} + +module.exports.writeVersion = function (contents, version) { + const data = TOML.parse(contents) + data.package.version = version + return TOML.stringify(data) +} diff --git a/package.json b/package.json index 7f9619236..a74342900 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,10 @@ { "filename": "package.json", "type": "json" + }, + { + "filename": "Cargo.toml", + "updater": "build-aux/cargo-updater.js" } ], "infile": "CHANGELOG.md", From bdfeecd9c87b74e355ba297b698f817b95d32fef Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 20 May 2023 09:34:44 +0300 Subject: [PATCH 042/357] feat(cli): Allow more than one input document (Rust edition) --- src/bin/sile.rs | 2 +- src/cli.rs | 2 +- src/lib.rs | 31 ++++++++++++++++++++++++------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 3aaa9ad12..2df463373 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -15,7 +15,7 @@ fn main() -> sile::Result<()> { let matches = app.get_matches(); let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); sile::run( - args.input, + args.inputs, args.backend, args.class, args.debug, diff --git a/src/cli.rs b/src/cli.rs index d9a151ce6..758374113 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; #[clap(author, name = "SILE", bin_name = "sile")] pub struct Cli { /// Input document, by default in SIL or XML format - pub input: Option, + pub inputs: Option>, /// Choose an alternative output backend #[clap(short, long, value_name = "BACKEND")] diff --git a/src/lib.rs b/src/lib.rs index 2c1b3a6f8..3b145dc83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ pub fn version() -> crate::Result { } pub fn run( - input: Option, + inputs: Option>, backend: Option, class: Option, debug: Option>, @@ -65,6 +65,7 @@ pub fn run( .eval()?; sile.set("traceback", traceback)?; sile.set("quiet", quiet)?; + let mut has_input_filename = false; if let Some(flags) = debug { let debug_flags: LuaTable = sile.get("debugFlags")?; for flag in flags { @@ -97,6 +98,10 @@ pub fn run( if let Some(path) = makedeps { sile_input.set("makedeps", pb_to_st(&path))?; } + if let Some(path) = output { + sile.set("outputFilename", pb_to_st(&path))?; + has_input_filename = true; + } if let Some(options) = options { sile_input.set("options", options)?; } @@ -108,14 +113,26 @@ pub fn run( } let init: LuaFunction = sile.get("init")?; init.call::<_, _>(())?; - if let Some(input) = input { - let input_filename: LuaString = lua.create_string(&pb_to_st(&input))?; - if let Some(path) = output { - sile.set("outputFilename", pb_to_st(&path))?; + if let Some(inputs) = inputs { + let input_filenames: LuaTable = lua.create_table()?; + for input in inputs.iter() { + let path = &pb_to_st(input); + if !has_input_filename && path != "-" { + has_input_filename = true; + } + input_filenames.push(lua.create_string(path)?)?; + } + if !has_input_filename { + panic!( + "\nUnable to derive an output filename (perhaps because input is a STDIO stream)\nPlease use --output to set one explicitly." + ); } - sile_input.set("filename", input_filename)?; + sile_input.set("filenames", input_filenames)?; + let input_filenames: LuaTable = sile_input.get("filenames")?; let process_file: LuaFunction = sile.get("processFile")?; - process_file.call::(sile_input.get("filename")?)?; + for file in input_filenames.sequence_values::() { + process_file.call::(file?)?; + } let finish: LuaFunction = sile.get("finish")?; finish.call::<_, _>(())?; } else { From 60c218863d6e2f968cdd29f956b4fc080975021b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 15:11:49 +0300 Subject: [PATCH 043/357] chore(build): Avoid duplicated flags --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 72ce1c914..8615beb11 100644 --- a/Makefile.am +++ b/Makefile.am @@ -219,7 +219,7 @@ DEPDIR := .deps REGRESSIONSCRIPT := ./tests/regressions.pl LOCALTESTFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig -BUSTEDFLAGS ?= $(and $(SILE_COVERAGE),-c) +BUSTEDFLAGS ?= TESTPDFS = $(addsuffix .pdf,$(basename $(TESTSRCS))) EXPECTEDS ?= $(filter $(addsuffix .expected,$(basename $(TESTSRCS))),$(TESTEXPECTS)) @@ -324,7 +324,7 @@ endif $(LOCALTESTFONTS) $(BUSTED) --cpath="$${packagecpath[*]};;" --lpath="$${packagepath[*]};;" $(BUSTEDFLAGS) . coverage: export SILE_COVERAGE=1 -coverage: BUSTEDFLAGS = -c +coverage: BUSTEDFLAGS += -c coverage: regression_previews busted HEADSHA ?= HEAD From 231a2508b8292a7fc01909b0e5f65ea42492bd0a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 15:16:33 +0300 Subject: [PATCH 044/357] chore(build): Match version of Lua run in busted with Rust --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 8615beb11..502e3eb4f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -321,7 +321,8 @@ else packagecpath=(./{,core/,lua_modules/lib/lua/$(LUA_VERSION)/}?.$(SHARED_LIB_EXT)) packagepath=(./{,lua_modules/share/lua/$(LUA_VERSION)/,lua-libraries/}?{,/init}.lua) endif - $(LOCALTESTFONTS) $(BUSTED) --cpath="$${packagecpath[*]};;" --lpath="$${packagepath[*]};;" $(BUSTEDFLAGS) . +# Note: use of --lua causes this to be passed back through a shell loosing one layer of quoting. Drop single quotes if removing. + $(LOCALTESTFONTS) $(BUSTED) --lua=$(LUA) --cpath="'$${packagecpath[*]};;'" --lpath="'$${packagepath[*]};;'" $(BUSTEDFLAGS) . coverage: export SILE_COVERAGE=1 coverage: BUSTEDFLAGS += -c From cbfb263e9d08b2719172260e962b510dc34c7055 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 16:02:13 +0300 Subject: [PATCH 045/357] ci(actions): Add workflow for Rust lints --- .github/workflows/rust_lint.yml | 42 +++++++++++++++++++++++++++++++++ rust-toolchain | 1 + 2 files changed, 43 insertions(+) create mode 100644 .github/workflows/rust_lint.yml create mode 100644 rust-toolchain diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml new file mode 100644 index 000000000..25dd6e644 --- /dev/null +++ b/.github/workflows/rust_lint.yml @@ -0,0 +1,42 @@ +name: Rust Lint + +on: [ push, pull_request ] + +jobs: + + rustfmt: + strategy: + fail-fast: false + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + components: rustfmt + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + - name: Run rustfmt + run: | + git ls-files '*.rs' | xargs rustfmt --check + + clippy: + strategy: + fail-fast: false + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + components: clippy + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ github.token }} + args: -- -D warnings diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..2bf5ad044 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +stable From 98cdaf19dfcf313dcf8ed2888abc3f87d11717ba Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 16:09:23 +0300 Subject: [PATCH 046/357] ci(actions): Install Rust and run Cargo tests --- .github/workflows/test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4ae336891..420152d4e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,6 +39,8 @@ jobs: path: | lua_modules key: luarocks-${{ matrix.luaVersion[0] }}-${{ hashFiles('Makefile-luarocks', 'sile.rockspec.in') }} + - name: Cache Rust + uses: Swatinem/rust-cache@v2 - name: Fetch tags run: | git fetch --prune --tags ||: @@ -47,6 +49,8 @@ jobs: with: luaVersion: ${{ matrix.luaVersion[0] }} luaCompileFlags: ${{ matrix.luaVersion[1] }} + - name: Setup ‘cargo’ + uses: actions-rs/toolchain@v1 - name: Setup ‘luarocks’ uses: leafo/gh-actions-luarocks@v4 - name: Prep system Lua for use @@ -85,6 +89,10 @@ jobs: timeout-minutes: ${{ runner.debug && 60 || 6 }} run: | make regressions + - name: Test Cargo + timeout-minutes: ${{ runner.debug && 60 || 6 }} + run: | + make cargo-test - name: Upload artifacts uses: actions/upload-artifact@v3 with: From 9c831cb932c1bcdbbeb02ef5dea3ce75c96c0a71 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 16:33:40 +0300 Subject: [PATCH 047/357] chore(build): Update Nix Flake with Rust tooling --- flake.nix | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index ea0adc2ca..bc9023649 100644 --- a/flake.nix +++ b/flake.nix @@ -107,11 +107,20 @@ # Don't build the manual as it's time consuming, and it requires fonts # that are not available in the sandbox due to internet connection # missing. - configureFlags = pkgs.lib.lists.remove "--with-manual" oldAttr.configureFlags; + configureFlags = [ + "PDFINFO=false" + ] ++ ( + pkgs.lib.lists.remove "--with-manual" oldAttr.configureFlags + ); nativeBuildInputs = oldAttr.nativeBuildInputs ++ [ pkgs.autoreconfHook ]; buildInputs = [ + # Build inputs added since release in nixpkgs + pkgs.cargo + pkgs.jq + pkgs.rustc + ] ++ [ # Add here inputs needed for development, and not for Nixpkgs' build. pkgs.libarchive pkgs.perl From 88e9103ab366793bea6dbecb7d0707a2d2a1dcb8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 23:54:11 +0300 Subject: [PATCH 048/357] chore(tooling): Setup Rust code lint overrides and fiddle with smell tests --- .cargo/config.toml | 10 ++++++++++ src/lib.rs | 20 ++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index fa4b7d557..9037819ed 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -11,3 +11,13 @@ rustflags = ["-C", "link-args=-rdynamic"] # this convenience won't enable you to use system packages in debug builds. [env] SILE_PATH = { value = "", relative = true } + +[target.'cfg(all())'] +rustflags = [ + # CLIPPY LINT SETTINGS + # This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML. + # See: `https://github.com/rust-lang/cargo/issues/5034` + # `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395` + "-Aclippy::clone_double_ref", + "-Aclippy::ptr_arg", +] diff --git a/src/lib.rs b/src/lib.rs index 3b145dc83..4800fd0f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,10 @@ pub fn version() -> crate::Result { Ok(sile.get("full_version")?) } +// Yes I know this should be taking a struct, probably 1 with what ends up being SILE.input and one +// with other stuff the CLI may inject, but I'm playing with what a minimum/maximum set of +// parameters would look like here while maintaining compatiblitiy with the Lua CLI. +#[allow(clippy::too_many_arguments)] pub fn run( inputs: Option>, backend: Option, @@ -90,16 +94,16 @@ pub fn run( sile_input.set("class", class)?; } if let Some(paths) = preamble { - sile_input.set("preambles", pbs_to_sts(paths))?; + sile_input.set("preambles", paths_to_strings(paths))?; } if let Some(paths) = postamble { - sile_input.set("postamble", pbs_to_sts(paths))?; + sile_input.set("postamble", paths_to_strings(paths))?; } if let Some(path) = makedeps { - sile_input.set("makedeps", pb_to_st(&path))?; + sile_input.set("makedeps", path_to_string(&path))?; } if let Some(path) = output { - sile.set("outputFilename", pb_to_st(&path))?; + sile.set("outputFilename", path_to_string(&path))?; has_input_filename = true; } if let Some(options) = options { @@ -116,7 +120,7 @@ pub fn run( if let Some(inputs) = inputs { let input_filenames: LuaTable = lua.create_table()?; for input in inputs.iter() { - let path = &pb_to_st(input); + let path = &path_to_string(input); if !has_input_filename && path != "-" { has_input_filename = true; } @@ -142,10 +146,10 @@ pub fn run( Ok(()) } -fn pb_to_st(path: &PathBuf) -> String { +fn path_to_string(path: &PathBuf) -> String { path.clone().into_os_string().into_string().unwrap() } -fn pbs_to_sts(paths: Vec) -> Vec { - paths.iter().map(pb_to_st).collect() +fn paths_to_strings(paths: Vec) -> Vec { + paths.iter().map(path_to_string).collect() } From 26dc6192f2ed87f8f6d74d9c7a17a93ae1295f08 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 27 May 2023 10:43:04 +0300 Subject: [PATCH 049/357] ci(cirrus): Update runner to latest FreeBSD 13 point release --- .cirrus.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index fe2e5dbc7..08411ef41 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,7 +2,7 @@ task: name: Cirrus CI (FreeBSD) freebsd_instance: matrix: - - image_family: freebsd-13-0 + - image_family: freebsd-13-2 - image_family: freebsd-12-3 env: MAKEFLAGS: -j$(nproc) -Otarget @@ -24,9 +24,7 @@ task: fingerprint_script: cat sile.rockspec.in dependencies_script: - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz libtool pkgconf png - - pkg install -y lua54 lua54-lpeg lua54-luafilesystem lua54-luarocks lua54-luasec lua54-luasocket - # lua54-luaexpat exists but seems boken on 13.0, system doesn't have expat 2.4+ so 1.5.x isn't an option either - - luarocks54 install luaexpat 1.4.1 + - pkg install -y lua54 lua54-luaexpat lua54-lpeg lua54-luafilesystem lua54-luarocks lua54-luasec lua54-luasocket - luarocks54 install cassowary - luarocks54 install cldr - luarocks54 install compat53 From 24dc4f13831aadee0c8831daae39c3e2adfc77fd Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 23:42:23 +0300 Subject: [PATCH 050/357] chore(tooling): Use BSD `install` compatible notation --- Makefile.am | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index 502e3eb4f..046cd034d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,22 +132,22 @@ $(SILE): $(RUST_BIN) $(INSTALL) $(RUST_BIN) $@ $(PACKAGE_NAME).1: $(RUST_BIN) - $(INSTALL) -D $$(cat $(_RUST_OUT))/$@ $@ + $(INSTALL) -m644 $$(cat $(_RUST_OUT))/$@ $@ $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).bash $@ + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).bash $@ $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).elv: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).elv $@ + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).elv $@ $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).fish $@ + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).fish $@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME).ps1: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME).ps1 $@ + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME).ps1 $@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -D $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ $(_RUST_OUT) $(RUST_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) cd $(top_srcdir) From a5b919d53909afc0b12cadb9f0364200f53046af Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 26 May 2023 23:42:23 +0300 Subject: [PATCH 051/357] ci(actions,cirrus): Install Rust and other new build deps in CI runner --- .cirrus.yml | 4 ++-- .github/workflows/build.yml | 4 ++-- .github/workflows/test.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 08411ef41..34f9860a6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -23,7 +23,7 @@ task: folder: /usr/local/lib/lua fingerprint_script: cat sile.rockspec.in dependencies_script: - - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz libtool pkgconf png + - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz jq libtool pkgconf png rust - pkg install -y lua54 lua54-luaexpat lua54-lpeg lua54-luafilesystem lua54-luarocks lua54-luasec lua54-luasocket - luarocks54 install cassowary - luarocks54 install cldr @@ -44,7 +44,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false NIX=false \ + --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false PDFINFO=false NIX=false \ --disable-font-variations \ --with-system-luarocks \ --without-manual diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 034b41eb1..9879429f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,11 +34,11 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install fonts-sil-gentiumplus libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev liblua5.3-dev libpng-dev lua5.3 lua-sec lua-socket lua-zlib-dev luarocks poppler-utils + sudo apt-get install cargo fonts-sil-gentiumplus jq libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev liblua5.3-dev libpng-dev lua5.3 lua-sec lua-socket lua-zlib-dev luarocks poppler-utils - name: Configure run: | ./bootstrap.sh - ./configure \ + ./configure PDFINFO=false \ --disable-font-variations \ --without-system-luarocks \ --with-manual diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 420152d4e..611a909a6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -72,7 +72,7 @@ jobs: - name: Configure run: | ./bootstrap.sh - ./configure \ + ./configure PDFINFO=false \ --enable-developer LUACHECK=false NIX=false \ --disable-font-variations \ --without-system-luarocks \ From d37da35a292bd86738832fc3edb084ff82a5d311 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 2 Jun 2023 21:50:20 +0300 Subject: [PATCH 052/357] fix(build): Avoid race condition by making sure binary exists before use --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 046cd034d..7e09f49c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -228,7 +228,7 @@ ACTUALS = $(addsuffix .actual,$(basename $(EXPECTEDS))) check: selfcheck .PHONY: selfcheck -selfcheck: | $(_BUILT_SUBDIRS) +selfcheck: | $(SILE) $(_BUILT_SUBDIRS) output=$$(mktemp -t selfcheck-XXXXXX.pdf) trap 'rm -f $$output' EXIT HUP TERM echo "foo" | ./$(SILE) -o $$output - @@ -269,7 +269,7 @@ $(_SUBDIR_TELLS): $(MAKE) $(AM_MAKEFLAGS) all-recursive # $(error Running `make install`, `make dist`, or other end-game targets before `make all` unspported.) -patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) +patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(SILE) $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) %.pdf: %.sil $$(patterndeps) $(runsile) From 0511dfeab71427d8b0059052d1f825081bce27ec Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 2 Jun 2023 22:39:24 +0300 Subject: [PATCH 053/357] chore(cli): Handle module path discovery the same in Rust as Lua --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4800fd0f7..f1e53ed11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,11 +59,15 @@ pub fn run( let lua = unsafe { Lua::unsafe_new() }; let lua_path: LuaString = lua.create_string(&LUA_PATH.clone()).unwrap(); let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone()).unwrap(); + let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; let sile: LuaTable = lua .load(chunk! { package.path = $lua_path package.cpath = $lua_cpath - local executable = require("core.pathsetup")() + local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") + if not status then + dofile("./core/pathsetup.lua") + end return require("core.sile") }) .eval()?; From 38c533491d77adea64d50f4179d0c5a9a17d2a72 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 2 Jun 2023 23:53:23 +0300 Subject: [PATCH 054/357] ci(actions): Build source package including manual with Luajit --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 931bfd4b1..d8004931d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,11 +34,13 @@ jobs: - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install cargo fonts-sil-gentiumplus jq libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev liblua5.3-dev libpng-dev lua5.3 lua-sec lua-socket lua-zlib-dev luarocks poppler-utils + sudo apt-get install cargo fonts-sil-gentiumplus jq libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev libluajit-5.1-dev libpng-dev luajit lua-sec lua-socket lua-zlib-dev luarocks poppler-utils - name: Configure run: | ./bootstrap.sh ./configure PDFINFO=false \ + --datarootdir=$(cd ..; pwd) \ + --with-luajit \ --disable-font-variations \ --without-system-luarocks \ --with-manual From ab0befc8c84900c119f70cd29496b0d7ed3b752b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 3 Jun 2023 00:52:23 +0300 Subject: [PATCH 055/357] chore(build): Make building the manual and running tests more ergonomic --- .github/workflows/build.yml | 1 - Makefile.am | 18 ++++++++++-------- configure.ac | 11 +++++++++-- core/pathsetup.lua.in | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d8004931d..3ae9d10aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,6 @@ jobs: run: | ./bootstrap.sh ./configure PDFINFO=false \ - --datarootdir=$(cd ..; pwd) \ --with-luajit \ --disable-font-variations \ --without-system-luarocks \ diff --git a/Makefile.am b/Makefile.am index 7e09f49c6..6fbbd3974 100644 --- a/Makefile.am +++ b/Makefile.am @@ -231,7 +231,8 @@ check: selfcheck selfcheck: | $(SILE) $(_BUILT_SUBDIRS) output=$$(mktemp -t selfcheck-XXXXXX.pdf) trap 'rm -f $$output' EXIT HUP TERM - echo "foo" | ./$(SILE) -o $$output - + export SILE_PATH + echo "foo" | SILE_PATH=$(PWD) ./$(SILE) -o $$output - $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" .PHONY: docs @@ -241,7 +242,8 @@ docs: $(MANUAL) # garantee the TOC is up to date, simplify when #230 is fixed. hastoc = [ -f $(subst .pdf,.toc,$@) ] && echo true || echo false pages = $(PDFINFO) $@ | $(AWK) '$$1 == "Pages:" {print $$2}' || echo 0 -silepass = $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false +localsile = $(LOCALTESTFONTS) SILE_PATH=$(PWD) ./$(SILE) $(SILEFLAGS) +silepass = $(localsile) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false define runsile = set -e pg=$$($(pages)) hadtoc=$$($(hastoc)) @@ -350,27 +352,27 @@ time-%.json: benchmark-%/time.json update_expecteds: $(EXPECTEDS) tests/%.expected: tests/%.sil $$(patterndeps) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.expected: tests/%.xml $$(patterndeps) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.expected: tests/%.nil $$(patterndeps) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ regression_previews: $(TESTPREVIEWS) tests/%.actual: tests/%.sil $$(patterndeps) -$(if $(CLEAN),rm -f $@,:) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.actual: tests/%.xml $$(patterndeps) -$(if $(CLEAN),rm -f $@,:) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ tests/%.actual: tests/%.nil $$(patterndeps) -$(if $(CLEAN),rm -f $@,:) - $(LOCALTESTFONTS) ./$(SILE) $(SILEFLAGS) -b debug $< -o $@ + $(localsile) -b debug $< -o $@ DEPFILES = $(addsuffix .d,$(addprefix $(DEPDIR)/,$(basename $(TESTSRCS) $(MANUAL)))) DEPDIRS = $(sort $(dir $(DEPFILES))) diff --git a/configure.ac b/configure.ac index 369c01d16..cf76583c3 100644 --- a/configure.ac +++ b/configure.ac @@ -302,8 +302,15 @@ AC_SUBST([LUAROCKSARGS]) AX_SUBST_TRANSFORMED_PACKAGE_NAME -adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) -AC_DEFINE_UNQUOTED([SILE_PATH],["${SILE_PATH}"],[Path for SILE packages and classes]) +# Avoid need for `--datarootdir=$(cd ..; pwd)` hack to run locally for +# tests/manual build when developer mode is enabled +AM_COND_IF([DEVELOPER], [ + AC_DEFINE_UNQUOTED([SILE_PATH],["$(pwd)"],[Path for SILE packages and classes]) + ],[ + adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) + AC_DEFINE_UNQUOTED([SILE_PATH],["${SILE_PATH}"],[Path for SILE packages and classes]) +]) + AC_SUBST([SILE_PATH]) adl_RECURSIVE_EVAL(["${libdir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_LIB_PATH]) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index ea9ad466f..b9ef4bc29 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -55,7 +55,7 @@ local pathvar = os.getenv("SILE_PATH") if pathvar then for path in string.gmatch(pathvar, "[^;]+") do if not path:match("^./") and path:len() >= 1 then - extendPaths(path) + extendPaths(path, true) end end end From aa538e215ddb4716e8360899e98fb6ef1512e477 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 23 Aug 2023 20:11:48 +0200 Subject: [PATCH 056/357] feat(classes,outputters,packages): New approach to full bleed printing, cropmarks, background Decorrelate frame cursor position from actual outputter cursor. Add base class options (bleed, sheetsize) Move most of the direct low-level libtexpdf call to the outputter. --- classes/base.lua | 34 ++++++++++ outputters/base.lua | 6 ++ outputters/libtexpdf.lua | 126 +++++++++++++++++++++++++++++++++-- packages/background/init.lua | 76 +++++++++++++++------ packages/cropmarks/init.lua | 110 +++++++++++++----------------- packages/pdf/init.lua | 67 +++++++------------ packages/rotate/init.lua | 55 ++++++++------- packages/scalebox/init.lua | 17 ++--- 8 files changed, 319 insertions(+), 172 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 7cd902029..5e8249f56 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -80,9 +80,29 @@ end function class:setOptions (options) options = options or {} options.papersize = options.papersize or "a4" + options.bleed = options.bleed or "0" for option, value in pairs(options) do self.options[option] = value end + + if not SILE.documentState.sheetSize then + SILE.documentState.sheetSize = { + SILE.documentState.paperSize[1], + SILE.documentState.paperSize[2] + } + end + if SILE.documentState.sheetSize[1] < SILE.documentState.paperSize[1] + or SILE.documentState.sheetSize[2] < SILE.documentState.paperSize[2] then + SU.error("Sheet size shall not be smaller than the paper size") + end + if SILE.documentState.sheetSize[1] < SILE.documentState.paperSize[1] + SILE.documentState.bleed then + SU.debug("frames", "Sheet size width augmented to take page bleed into account") + SILE.documentState.sheetSize[1] = SILE.documentState.paperSize[1] + SILE.documentState.bleed + end + if SILE.documentState.sheetSize[2] < SILE.documentState.paperSize[2] + SILE.documentState.bleed then + SU.debug("frames", "Sheet size height augmented to take page bleed into account") + SILE.documentState.sheetSize[2] = SILE.documentState.paperSize[2] + SILE.documentState.bleed + end end function class:declareOption (option, setter) @@ -116,6 +136,20 @@ function class:declareOptions () end return self.papersize end) + self:declareOption("sheetsize", function (_, size) + if size then + self.sheetsize = size + SILE.documentState.sheetSize = SILE.papersize(size) + end + return self.sheetsize + end) + self:declareOption("bleed", function (_, dimen) + if dimen then + self.bleed = dimen + SILE.documentState.bleed = SU.cast("measurement", dimen):tonumber() + end + return self.bleed + end) end function class.declareSettings (_) diff --git a/outputters/base.lua b/outputters/base.lua index a5ce0aacd..30fd6d75b 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -34,6 +34,12 @@ function outputter.debugFrame (_, _, _) end function outputter.debugHbox (_, _, _) end +function outputter.linkAnchor (_, _, _) end + +function outputter.enterLinkTarget (_, _, _) end + +function outputter.leaveLinkTarget (_, _, _, _, _, _, _) end + function outputter:getOutputFilename () local fname if SILE.outputFilename then diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index 80f2e37de..35a29dec9 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -22,13 +22,29 @@ local outputter = pl.class(base) outputter._name = "libtexpdf" outputter.extension = "pdf" +-- Sometimes setCoord is called before the outputter has ensure initialization! +local deltaX +local deltaY +local function trueXCoord (x) + if not deltaX then + deltaX = SILE.documentState.sheetSize[1] - SILE.documentState.paperSize[1] + end + return x + deltaX / 2 +end +local function trueYCoord (y) + if not deltaY then + deltaY = SILE.documentState.sheetSize[2] - SILE.documentState.paperSize[2] + end + return y + deltaY / 2 +end + -- The outputter init can't actually initialize output (as logical as it might -- have seemed) because that requires a page size which we don't know yet. -- function outputter:_init () end function outputter:_ensureInit () if not started then - local w, h = SILE.documentState.paperSize[1], SILE.documentState.paperSize[2] + local w, h = SILE.documentState.sheetSize[1], SILE.documentState.sheetSize[2] local fname = self:getOutputFilename() pdf.init(fname == "-" and "/dev/stdout" or fname, w, h, SILE.full_version) pdf.beginpage() @@ -90,7 +106,7 @@ function outputter:_drawString (str, width, x_offset, y_offset) local x, y = self:getCursor() pdf.colorpush_rgb(0,0,0) pdf.colorpop() - pdf.setstring(x+x_offset, y+y_offset, str, string.len(str), _font, width) + pdf.setstring(trueXCoord(x+x_offset), trueYCoord(y+y_offset), str, string.len(str), _font, width) end function outputter:drawHbox (value, width) @@ -157,7 +173,7 @@ function outputter:drawImage (src, x, y, width, height, pageno) width = SU.cast("number", width) height = SU.cast("number", height) self:_ensureInit() - pdf.drawimage(src, x, y, width, height, pageno or 1) + pdf.drawimage(src, trueXCoord(x), trueYCoord(y), width, height, pageno or 1) end function outputter:getImageSize (src, pageno) @@ -174,8 +190,8 @@ function outputter:drawSVG (figure, x, y, _, height, scalefactor) pdf.add_content("q") self:setCursor(x, y) x, y = self:getCursor() - local newy = y - SILE.documentState.paperSize[2] + height - pdf.add_content(table.concat({ scalefactor, 0, 0, -scalefactor, x, newy, "cm" }, " ")) + local newy = y - SILE.documentState.paperSize[2] / 2 + height - SILE.documentState.sheetSize[2] / 2 + pdf.add_content(table.concat({ scalefactor, 0, 0, -scalefactor, trueXCoord(x), newy, "cm" }, " ")) pdf.add_content(figure) pdf.add_content("Q") end @@ -187,7 +203,7 @@ function outputter:drawRule (x, y, width, height) height = SU.cast("number", height) self:_ensureInit() local paperY = SILE.documentState.paperSize[2] - pdf.setrule(x, paperY - y - height, width, height) + pdf.setrule(trueXCoord(x), trueYCoord(paperY - y - height), width, height) end function outputter:debugFrame (frame) @@ -228,4 +244,102 @@ function outputter:debugHbox (hbox, scaledWidth) self:popColor() end +-- The methods below are only implemented on outputters supporting these features. +-- In PDF, it relies on transformation matrices, but other backends may call +-- for a different strategy. +-- ! The API is unstable and subject to change. ! + +function outputter:scaleFn (xorigin, yorigin, xratio, yratio, callback) + xorigin = SU.cast("number", xorigin) + yorigin = SU.cast("number", yorigin) + local x0 = trueXCoord(xorigin) + local y0 = -trueYCoord(yorigin) + self:_ensureInit() + pdf:gsave() + pdf.setmatrix(1, 0, 0, 1, x0, y0) + pdf.setmatrix(xratio, 0, 0, yratio, 0, 0) + pdf.setmatrix(1, 0, 0, 1, -x0, -y0) + callback() + pdf:grestore() +end + +function outputter:rotateFn (xorigin, yorigin, theta, callback) + xorigin = SU.cast("number", xorigin) + yorigin = SU.cast("number", yorigin) + local x0 = trueXCoord(xorigin) + local y0 = -trueYCoord(yorigin) + self:_ensureInit() + pdf:gsave() + pdf.setmatrix(1, 0, 0, 1, x0, y0) + pdf.setmatrix(math.cos(theta), math.sin(theta), -math.sin(theta), math.cos(theta), 0, 0) + pdf.setmatrix(1, 0, 0, 1, -x0, -y0) + callback() + pdf:grestore() +end + +-- Other rotation unstable APIs + +function outputter:enterFrameRotate (xa, xb, y, theta) -- Unstable API see rotate package + xa = SU.cast("number", xa) + xb = SU.cast("number", xb) + y = SU.cast("number", y) + -- Keep center point the same? + local cx0 = trueXCoord(xa) + local cx1 = trueXCoord(xb) + local cy = -trueYCoord(y) + self:_ensureInit() + pdf:gsave() + pdf.setmatrix(1, 0, 0, 1, cx1, cy) + pdf.setmatrix(math.cos(theta), math.sin(theta), -math.sin(theta), math.cos(theta), 0, 0) + pdf.setmatrix(1, 0, 0, 1, -cx0, -cy) +end + +function outputter.leaveFrameRotate (_) + pdf:grestore() +end + +-- Unstable link APIs + +function outputter:linkAnchor (x, y, name) + x = SU.cast("number", x) + y = SU.cast("number", y) + self:_ensureInit() + pdf.destination(name, trueXCoord(x), trueYCoord(y)) +end + +local function borderColor (color) + if color then + if color.r then return "/C [" .. color.r .. " " .. color.g .. " " .. color.b .. "]" end + if color.c then return "/C [" .. color.c .. " " .. color.m .. " " .. color.y .. " " .. color.k .. "]" end + if color.l then return "/C [" .. color.l .. "]" end + end + return "" +end +local function borderStyle (style, width) + if style == "underline" then return "/BS<>" end + if style == "dashed" then return "/BS<>" end + return "/Border[0 0 " .. width .. "]" +end + +function outputter:enterLinkTarget (_, _) -- destination, options as argument + -- HACK: + -- Looking at the code, pdf.begin_annotation does nothing, and Simon wrote a comment + -- about tracking boxes. Unsure what he implied with this obscure statement. + -- Sure thing is that some backends may need the destination here, e.g. an HTML backend + -- would generate a , as well as the options possibly for styling + -- on the link opening? + self:_ensureInit() + pdf.begin_annotation() +end +function outputter.leaveLinkTarget (_, x0, y0, x1, y1, dest, opts) + local bordercolor = borderColor(opts.bordercolor) + local borderwidth = SU.cast("integer", opts.borderwidth) + local borderstyle = borderStyle(opts.borderstyle, borderwidth) + local target = opts.external and "/Type/Action/S/URI/URI" or "/S/GoTo/D" + local d = "<>>>" + pdf.end_annotation(d, + trueXCoord(x0) , trueYCoord(y0 - opts.borderoffset), + trueXCoord(x1), trueYCoord(y1 + opts.borderoffset)) +end + return outputter diff --git a/packages/background/init.lua b/packages/background/init.lua index 02e2fbd6a..00740bae9 100644 --- a/packages/background/init.lua +++ b/packages/background/init.lua @@ -3,48 +3,80 @@ local base = require("packages.base") local package = pl.class(base) package._name = "background" -local outputBackground = function (color) - local page = SILE.getFrame("page") - local backgroundColor = SILE.color(color) - SILE.outputter:pushColor(backgroundColor) - SILE.outputter:drawRule(page:left(), page:top(), page:right(), page:bottom()) - SILE.outputter:popColor() +local outputBackground = function (background) + local pagea = SILE.getFrame("page") + local offset = SILE.documentState.bleed / 2 + if type(background.bg) == "string" then + -- FIXME + SILE.outputter:drawImage(background.bg, + pagea:left() - offset, pagea:top() - offset, + pagea:width() + 2 * offset, pagea:height() + 2 * offset) + elseif background.bg then + SILE.outputter:pushColor(background.bg) + SILE.outputter:drawRule( + pagea:left() - offset, pagea:top() - offset, + pagea:width() + 2 * offset, pagea:height() + 2 * offset) + SILE.outputter:popColor() + end + if not background.allpages then + background.bg = nil + end end +SILE.scratch.background = SILE.scratch.background or {} + function package:_init () base._init(self) - self:loadPackage("color") + self.class:registerHook("newpage", function (_) + outputBackground(SILE.scratch.background) + end ) end function package:registerCommands () self:registerCommand("background", function (options, _) - options.color = options.color or "white" - options.allpages = options.allpages or true - outputBackground(options.color) - if options.allpages and options.allpages ~= "false" then - local oldNewPage = SILE.documentState.documentClass.newPage - SILE.documentState.documentClass.newPage = function (self_) - local page = oldNewPage(self_) - outputBackground(options.color) - return page - end + if SU.boolean(options.disable, false) then + -- This option is certainly better than enforcing a white color. + SILE.scratch.background.bg = nil + return + end + + local allpages = SU.boolean(options.allpages, true) + SILE.scratch.background.allpages = allpages + local color = options.color and SILE.color(options.color) + local src = options.src + if src then + SILE.scratch.background.bg = src and SILE.resolveFile(src) or SU.error("Couldn't find file "..src) + elseif color then + SILE.scratch.background.bg = color + else + SU.error("background requires a color or an image src parameter") end - end, "Draws a solid background color on pages after initialization.") + outputBackground(SILE.scratch.background) + end, "Output a solid background color or an image on pages after initialization.") end package.documentation = [[ \begin{document} \use[module=packages.background] -The \autodoc:package{background} package allows you to set the color of the canvas background (by drawing a solid color block the full size of the page on page initialization). -The package provides a \autodoc:command{\background} command which requires at least one parameter, \autodoc:parameter{color=}, and sets the background of the current and all following pages to that color. -If you want to set only the current page background different from the default, use the parameter \autodoc:parameter{allpages=false}. -The color specification in the same as specified in the \autodoc:package{color} package. +As its name implies, the \autodoc:package{background} package allows you to set the color of the page canvas background or to use a background image extending to the full page width and height. + +The package provides a \autodoc:command{\background} command which requires one of the following parameters: +\begin{itemize} +\item{\autodoc:parameter{color=} sets the background of the current and all following pages to that color. The color specification has the same syntax as specified in the \autodoc:package{color} package.} +\item{\autodoc:parameter{src=} sets the backgound of the current and all following pages to the specified image. The latter will be scaled to the target dimension.} +\end{itemize} + +The background extends to the page trim area (“page bleed”) if the latter is defined. +This is to ensure that it indeed “bleeds” off the sides of the page, so as to avoid thin white lignes on an otherwise full color page when the paper sheet is cut to dimension but some pages are trimmed slightly more than others. +If setting only the current page background different from the default is desired, an extra parameter \autodoc:parameter{allpages=false} can be passed. \background[color=#e9d8ba,allpages=false] So, for example, \autodoc:command{\background[color=#e9d8ba,allpages=false]} will set a sepia tone background on the current page. +The \autodoc:parameter{disable=true} parameter allows disabling the background on the following pages. +It may be useful when \autodoc:parameter{allpages} is active from a previous invocation. \end{document} ]] diff --git a/packages/cropmarks/init.lua b/packages/cropmarks/init.lua index 59b6b8f71..8c7c65c91 100644 --- a/packages/cropmarks/init.lua +++ b/packages/cropmarks/init.lua @@ -7,51 +7,45 @@ local outcounter = 1 local function outputMarks () local page = SILE.getFrame("page") - SILE.outputter:drawRule(page:left() - 10, page:top(), -10, 0.5) - SILE.outputter:drawRule(page:left(), page:top() - 10, 0.5, -10) - SILE.outputter:drawRule(page:right() + 10, page:top(), 10, 0.5) - SILE.outputter:drawRule(page:right(), page:top() - 10, 0.5, -10) - SILE.outputter:drawRule(page:left() - 10, page:bottom(), -10, 0.5) - SILE.outputter:drawRule(page:left(), page:bottom() + 10, 0.5, 10) - SILE.outputter:drawRule(page:right() + 10, page:bottom(), 10, 0.5) - SILE.outputter:drawRule(page:right(), page:bottom() + 10, 0.5, 10) + -- Length of cromark bars + local cropsz = 20 + -- Ensure the crop marks stay outside the bleed area + local offset = math.max(10, SILE.documentState.bleed / 2) + + SILE.outputter:drawRule(page:left() - offset, page:top(), -cropsz, 0.5) + SILE.outputter:drawRule(page:left(), page:top() - offset, 0.5, -cropsz) + SILE.outputter:drawRule(page:right() + offset, page:top(), cropsz, 0.5) + SILE.outputter:drawRule(page:right(), page:top() - offset, 0.5, -cropsz) + SILE.outputter:drawRule(page:left() - offset, page:bottom(), -cropsz, 0.5) + SILE.outputter:drawRule(page:left() , page:bottom() + offset, 0.5, cropsz) + SILE.outputter:drawRule(page:right() + offset, page:bottom(), cropsz, 0.5) + SILE.outputter:drawRule(page:right(), page:bottom() + offset, 0.5, cropsz) local hbox, hlist = SILE.typesetter:makeHbox(function () SILE.settings:temporarily(function () SILE.call("noindent") SILE.call("font", { size="6pt" }) - SILE.call("crop:header") + if SILE.Commands["crop:header"] then + -- Deprecation shim: + -- If user redefined this command, still use it with a warning... + SU.deprecated("crop:header", "cropmarks:header", "0.14.0", "0.16.0") + SILE.call("crop:header") + else + SILE.call("cropmarks:header") + end end) end) if #hlist > 0 then - SU.error("Forbidden migrating content in crop header") + SU.error("Migrating content is forbidden in crop header") end - SILE.typesetter.frame.state.cursorX = page:left() + 10 - SILE.typesetter.frame.state.cursorY = page:top() - 13 + SILE.typesetter.frame.state.cursorX = page:left() + offset + SILE.typesetter.frame.state.cursorY = page:top() - offset - 4 outcounter = outcounter + 1 if hbox then - for i = 1, #(hbox.value) do hbox.value[i]:outputYourself(SILE.typesetter, { ratio = 1 }) end - end -end - -local function reconstrainFrameset (fs) - for n, f in pairs(fs) do - if n ~= "page" then - if f:isAbsoluteConstraint("right") then - f.constraints.right = "left(page) + (" .. f.constraints.right .. ")" - end - if f:isAbsoluteConstraint("left") then - f.constraints.left = "left(page) + (" .. f.constraints.left .. ")" - end - if f:isAbsoluteConstraint("top") then - f.constraints.top = "top(page) + (" .. f.constraints.top .. ")" - end - if f:isAbsoluteConstraint("bottom") then - f.constraints.bottom = "top(page) + (" .. f.constraints.bottom .. ")" - end - f:invalidate() + for i = 1, #(hbox.value) do + hbox.value[i]:outputYourself(SILE.typesetter, { ratio = 1 }) end end end @@ -63,52 +57,38 @@ end function package:registerCommands () - self:registerCommand("crop:header", function (_, _) - local info = SILE.input.filenames[1] .. " - " .. self.class:date("%x %X") .. " - " .. outcounter + self:registerCommand("cropmarks:header", function (_, _) + local info = SILE.masterFilename + .. " - " + .. self.class.packages.date:date({ format = "%x %X" }) + .. " - " .. outcounter SILE.typesetter:typeset(info) end) - self:registerCommand("crop:setup", function (options, _) - local papersize = SU.required(options, "papersize", "setting up crop marks") - local size = SILE.papersize(papersize) - local oldsize = SILE.documentState.paperSize - SILE.documentState.paperSize = size - local offsetx = ( SILE.documentState.paperSize[1] - oldsize[1] ) /2 - local offsety = ( SILE.documentState.paperSize[2] - oldsize[2] ) /2 - local page = SILE.getFrame("page") - page:constrain("right", page:right() + offsetx) - page:constrain("left", offsetx) - page:constrain("bottom", page:bottom() + offsety) - page:constrain("top", offsety) - if SILE.scratch.masters then - for _, v in pairs(SILE.scratch.masters) do - reconstrainFrameset(v.frames) - end - else - reconstrainFrameset(SILE.documentState.documentClass.pageTemplate.frames) - end - if SILE.typesetter.frame then SILE.typesetter.frame:init() end - local oldEndPage = SILE.documentState.documentClass.endPage - SILE.documentState.documentClass.endPage = function (self_) - oldEndPage(self_) + self:registerCommand("cropmarks:setup", function (_, _) + self.class:registerHook("endpage", function (_) outputMarks() - end + end ) end) + self:registerCommand("crop:setup", function (_, _) + SU.deprecated("crop:setup", "cropmarks:setup", "0.14.10", "0.17.0") + SILE.call("cropmarks:setup") + end) end package.documentation = [[ \begin{document} -When preparing a document for printing, you may be asked by the printer to add crop marks. -This means that you need to output the document on a slightly larger page size than your target paper and add printer’s crop marks to show where the paper should be trimmed down to the correct size. -(This is to ensure that pages where the content “bleeds” off the side of the page are correctly cut.) +When preparing a document for printing, you may be asked by the printer add crop marks. +This means that you need to output the document on a slightly larger page size than your target paper and add crop marks to show where the paper sheet should be trimmed down to the correct size. -This package provides the \autodoc:command{\crop:setup} command which should be run early in your document file. -It takes one argument, \autodoc:parameter{papersize}, which is the true target paper size. -It place cropmarks around the true page content. +Actual paper size, true page content area and bleed/trim area can all be set via class options. +This package provides the \autodoc:command{\cropmarks:setup} command which should be run early in your document file. +It places crop marks around the true page content. +The crop marks are guaranteed to stay outside the bleed/trim area, when defined. It also adds a header at the top of the page with the filename, date and output sheet number. -You can customize this header by redefining \autodoc:command{\crop:header}. +You can customize this header by redefining \autodoc:command{\cropmarks:header}. \end{document} ]] diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index f6622a3bc..c31d4e624 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -5,21 +5,6 @@ package._name = "pdf" local pdf -local function borderColor (color) - if color then - if color.r then return "/C [" .. color.r .. " " .. color.g .. " " .. color.b .. "]" end - if color.c then return "/C [" .. color.c .. " " .. color.m .. " " .. color.y .. " " .. color.k .. "]" end - if color.l then return "/C [" .. color.l .. "]" end - end - return "" -end - -local function borderStyle (style, width) - if style == "underline" then return "/BS<>" end - if style == "dashed" then return "/BS<>" end - return "/Border[0 0 " .. width .. "]" -end - local function validate_date (date) return string.match(date, [[^D:%d+%s*-%s*%d%d%s*'%s*%d%d%s*'?$]]) ~= nil end @@ -36,9 +21,6 @@ function package:registerCommands () self:registerCommand("pdf:destination", function (options, _) local name = SU.required(options, "name", "pdf:destination") - if type(SILE.outputter._ensureInit) == "function" then - SILE.outputter:_ensureInit() - end SILE.typesetter:pushHbox({ outputYourself = function (_, typesetter, line) local state = typesetter.frame.state @@ -46,7 +28,7 @@ function package:registerCommands () local x, y = state.cursorX, state.cursorY typesetter.frame:advancePageDirection(line.height) local _y = SILE.documentState.paperSize[2] - y - pdf.destination(name, x:tonumber(), _y:tonumber()) + SILE.outputter:linkAnchor(x, _y, name) end }) end) @@ -93,43 +75,44 @@ function package:registerCommands () self:registerCommand("pdf:link", function (options, content) local dest = SU.required(options, "dest", "pdf:link") - local target = options.external and "/Type/Action/S/URI/URI" or "/S/GoTo/D" + local external = SU.boolean(options.external, false) local borderwidth = options.borderwidth and SU.cast("measurement", options.borderwidth):tonumber() or 0 - local bordercolor = borderColor(SILE.color(options.bordercolor or "blue")) + local bordercolor = SILE.color(options.bordercolor or "blue") local borderoffset = SU.cast("measurement", options.borderoffset or "1pt"):tonumber() - local borderstyle = borderStyle(options.borderstyle, borderwidth) - local llx, lly - if type(SILE.outputter._ensureInit) == "function" then - SILE.outputter:_ensureInit() - end + local opts = { + external = external, + borderstyle = options.borderstyle, + bordercolor = bordercolor, + borderwidth = borderwidth, + borderoffset = borderoffset + } + + local x0, y0 SILE.typesetter:pushHbox({ value = nil, - height = SILE.measurement(0), - width = SILE.measurement(0), - depth = SILE.measurement(0), + height = 0, + width = 0, + depth = 0, outputYourself = function (_, typesetter, _) - llx = typesetter.frame.state.cursorX:tonumber() - lly = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber() - pdf.begin_annotation() + x0 = typesetter.frame.state.cursorX:tonumber() + y0 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber() + SILE.outputter:enterLinkTarget(dest, opts) end }) - local hbox, hlist = SILE.typesetter:makeHbox(content) -- hack SILE.typesetter:pushHbox(hbox) - SILE.typesetter:pushHlist(hlist) - SILE.typesetter:pushHbox({ value = nil, - height = SILE.measurement(0), - width = SILE.measurement(0), - depth = SILE.measurement(0), + height = 0, + width = 0, + depth = 0, outputYourself = function (_, typesetter, _) - local d = "<>>>" - local x = typesetter.frame.state.cursorX:tonumber() - local y = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + hbox.height):tonumber() - pdf.end_annotation(d, llx , lly - borderoffset, x, y + borderoffset) + local x1 = typesetter.frame.state.cursorX:tonumber() + local y1 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + hbox.height):tonumber() + SILE.outputter:leaveLinkTarget(x0, y0, x1, y1, dest, opts) -- Unstable API end }) + SILE.typesetter:pushHlist(hlist) end) self:registerCommand("pdf:metadata", function (options, _) diff --git a/packages/rotate/init.lua b/packages/rotate/init.lua index 5982f0c2c..6aad18cca 100644 --- a/packages/rotate/init.lua +++ b/packages/rotate/init.lua @@ -3,23 +3,25 @@ local base = require("packages.base") local package = pl.class(base) package._name = "rotate" -local pdf = require("justenoughlibtexpdf") - local enter = function (self, _) + -- Probably broken, see: + -- https://github.com/sile-typesetter/sile/issues/427 if not self.rotate then return end - local x = -math.rad(self.rotate) + if not SILE.outputter.enterFrameRotate then + return SU.warn("Frame '".. self.id "' will not be rotated: backend '" .. SILE.outputter._name .. "' does not support rotation") + end + local theta = -math.rad(self.rotate) -- Keep center point the same - pdf:gsave() - local cx = self:left():tonumber() - local cy = -self:bottom():tonumber() - pdf.setmatrix(1, 0, 0, 1, cx + math.sin(x) * self:height():tonumber(), cy) - pdf.setmatrix(math.cos(x), math.sin(x), -math.sin(x), math.cos(x), 0, 0) - pdf.setmatrix(1, 0, 0, 1, -cx, -cy) + local x0 = self:left():tonumber() + local x1 = x0 + math.sin(theta) * self:height():tonumber() + local y0 = self:bottom():tonumber() + SILE.outputter:enterFrameRotate(x0, x1, y0, theta) -- Unstable API end -local leave = function(self, _) +local leave = function(self, _) if not self.rotate then return end - pdf:grestore() + if not SILE.outputter.enterFrameRotate then return end -- no enter no leave. + SILE.outputter:leaveFrameRotate() end -- What is the width, depth and height of a rectangle width w and height h rotated by angle theta? @@ -35,20 +37,20 @@ end local outputRotatedHbox = function (self, typesetter, line) local origbox = self.value.orig - local x = self.value.theta + local theta = self.value.theta + -- Find origin of untransformed hbox - local save = typesetter.frame.state.cursorX - typesetter.frame.state.cursorX = typesetter.frame.state.cursorX - (origbox.width.length-self.width)/2 - - local horigin = (typesetter.frame.state.cursorX + origbox.width.length / 2):tonumber() - local vorigin = -(typesetter.frame.state.cursorY - (origbox.height - origbox.depth) / 2):tonumber() - pdf:gsave() - pdf.setmatrix(1, 0, 0, 1, horigin, vorigin) - pdf.setmatrix(math.cos(x), math.sin(x), -math.sin(x), math.cos(x), 0, 0) - pdf.setmatrix(1, 0, 0, 1, -horigin, -vorigin) - origbox:outputYourself(typesetter, line) - pdf:grestore() - typesetter.frame.state.cursorX = save + local X = typesetter.frame.state.cursorX + local Y = typesetter.frame.state.cursorY + typesetter.frame.state.cursorX = X - (origbox.width.length-self.width)/2 + local horigin = X + origbox.width.length / 2 + local vorigin = Y - (origbox.height - origbox.depth) / 2 + + SILE.outputter:rotateFn(horigin, vorigin, theta, function () + origbox:outputYourself(typesetter, line) + end) + typesetter.frame.state.cursorX = X + typesetter.frame.state.cursorY = Y typesetter.frame:advanceWritingDirection(self.width) end @@ -65,6 +67,10 @@ end function package:registerCommands () self:registerCommand("rotate", function(options, content) + if not SILE.outputter.rotateFn then + SU.warn("Output will not be rotated: backend '" .. SILE.outputter._name .. "' does not support rotation") + return SILE.process(content) + end local angle = SU.required(options, "angle", "rotate command") local theta = -math.rad(angle) local origbox, hlist = SILE.typesetter:makeHbox(content) @@ -92,7 +98,6 @@ function package:registerCommands () end depth = -depth if depth < SILE.length(0) then depth = SILE.length(0) end - SILE.outputter:_ensureInit() SILE.typesetter:pushHbox({ value = { orig = origbox, theta = theta}, height = height, diff --git a/packages/scalebox/init.lua b/packages/scalebox/init.lua index f4d8375c2..8ab331fbb 100644 --- a/packages/scalebox/init.lua +++ b/packages/scalebox/init.lua @@ -6,12 +6,10 @@ package._name = "scalebox" function package:registerCommands () self:registerCommand("scalebox", function(options, content) - if SILE.outputter._name ~= "libtexpdf" then - SU.warn("Output will not be scaled: \\scalebox only works with the libtexpdf backend") + if not SILE.outputter.scaleFn then + SU.warn("Output will not be scaled: backend '" .. SILE.outputter._name .. "' does not support scaling") return SILE.process(content) end - SILE.outputter:_ensureInit() - local pdf = require("justenoughlibtexpdf") local hbox, hlist = SILE.typesetter:makeHbox(content) local xratio, yratio = SU.cast("number", options.xratio or 1), SU.cast("number", options.yratio or 1) @@ -37,18 +35,13 @@ function package:registerCommands () local outputWidth = SU.rationWidth(node.width, node.width, line.ratio) local X = typesetter.frame.state.cursorX local Y = typesetter.frame.state.cursorY - local x0 = X:tonumber() - local y0 = -Y:tonumber() if xratio < 0 then typesetter.frame:advanceWritingDirection(-outputWidth) end - pdf:gsave() - pdf.setmatrix(1, 0, 0, 1, x0, y0) - pdf.setmatrix(xratio, 0, 0, yratio, 0, 0) - pdf.setmatrix(1, 0, 0, 1, -x0, -y0) - hbox.outputYourself(hbox, typesetter, line) - pdf:grestore() + SILE.outputter:scaleFn(X, Y, xratio, yratio, function () + hbox:outputYourself(typesetter, line) + end) typesetter.frame.state.cursorX = X typesetter.frame.state.cursorY = Y typesetter.frame:advanceWritingDirection(outputWidth) From c5113b72ddb44f2f6712ac45ff3e5b1668e27166 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Tue, 22 Aug 2023 02:43:08 +0200 Subject: [PATCH 057/357] fix(typesetters): Debug hbox could show incorrectly offset boxes --- typesetters/base.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/typesetters/base.lua b/typesetters/base.lua index 6c6584884..f086cbcd5 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -940,16 +940,20 @@ function typesetter:makeHbox (content) local ox = atypesetter.frame.state.cursorX local oy = atypesetter.frame.state.cursorY SILE.outputter:setCursor(atypesetter.frame.state.cursorX, atypesetter.frame.state.cursorY) + -- BEGIN SILEX FIX DEBUG + SU.debug("hboxes", function () + -- setCursor also invoked by the internal hboxes etc. + -- so we must show our debug box before outputting its content. + SILE.outputter:debugHbox(box, box:scaledWidth(line)) + return "Drew debug outline around hbox" + end) + -- END SILEX FIX DEBUG for _, node in ipairs(box.value) do node:outputYourself(atypesetter, line) end atypesetter.frame.state.cursorX = ox atypesetter.frame.state.cursorY = oy _post() - SU.debug("hboxes", function () - SILE.outputter:debugHbox(box, box:scaledWidth(line)) - return "Drew debug outline around hbox" - end) end }) return hbox, migratingNodes From d5a89cb0dd65f5ee80489d7c8f29faff1a973cac Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 11:41:38 +0300 Subject: [PATCH 058/357] chore(deps): Drop now-obsolete lua-cosmo dependency --- .cirrus.yml | 1 - build-aux/create-homebrew-formula.pl | 1 - configure.ac | 1 - flake.nix | 1 - sile-dev-1.rockspec | 1 - 5 files changed, 5 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 378771fe8..377e461c5 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -30,7 +30,6 @@ task: - luarocks54 install cassowary - luarocks54 install cldr - luarocks54 install compat53 - - luarocks54 install cosmo - luarocks54 install fluent - luarocks54 install linenoise - luarocks54 install loadkit diff --git a/build-aux/create-homebrew-formula.pl b/build-aux/create-homebrew-formula.pl index 6fcb9748b..b4ce6cdfb 100644 --- a/build-aux/create-homebrew-formula.pl +++ b/build-aux/create-homebrew-formula.pl @@ -13,7 +13,6 @@ my %rock_url_templates = ( cassowary => "https://github.com/sile-typesetter/cassowary.lua/archive/vVERSION.tar.gz", - cosmo => "https://github.com/mascarenhas/cosmo/archive/vVERSION.tar.gz", linenoise => "https://github.com/hoelzro/lua-linenoise/archive/VERSION.tar.gz", lpeg => "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-VERSION.tar.gz", lua_cliargs => "https://github.com/amireh/lua_cliargs/archive/vUNSTRIPPEDVERSION.tar.gz", diff --git a/configure.ac b/configure.ac index 4981a75bc..49bab60d6 100644 --- a/configure.ac +++ b/configure.ac @@ -168,7 +168,6 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AS_IF([test "$LUA_SHORT_VERSION" -lt 53], AX_LUA_MODULE([compat53], [compat53]) ) - AX_LUA_MODULE([cosmo], [cosmo]) AX_LUA_MODULE([cldr], [cldr]) AX_LUA_MODULE([fluent], [fluent]) AX_LUA_MODULE([linenoise], [linenoise]) diff --git a/flake.nix b/flake.nix index 2fe4eacb5..51a4c6edf 100644 --- a/flake.nix +++ b/flake.nix @@ -42,7 +42,6 @@ luaEnv = pkgs.lua5_3.withPackages(ps: with ps; [ cassowary cldr - cosmo fluent linenoise loadkit diff --git a/sile-dev-1.rockspec b/sile-dev-1.rockspec index 72775ce9e..2d45ff672 100644 --- a/sile-dev-1.rockspec +++ b/sile-dev-1.rockspec @@ -13,7 +13,6 @@ dependencies = { "cassowary == 2.3.2-1", "cldr == 0.3.0-0", "compat53 == 0.8-1", -- only required on Lua < 5.3 - "cosmo == 16.06.04-1", "fluent == 0.2.0-0", "linenoise == 0.9-1", "loadkit == 1.1.0-1", From ee270d385afd451910c09433e7f7195ed25305e3 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 12 Sep 2023 14:06:04 +0300 Subject: [PATCH 059/357] chore(build): Bump Nix flake dependencies --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 17ea5fc9f..e1f2d0d37 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "lastModified": 1692799911, + "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", "owner": "numtide", "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", "type": "github" }, "original": { @@ -41,11 +41,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1694102001, + "narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6", "type": "github" }, "original": { @@ -72,11 +72,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1682109806, - "narHash": "sha256-d9g7RKNShMLboTWwukM+RObDWWpHKaqTYXB48clBWXI=", + "lastModified": 1694343207, + "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2362848adf8def2866fabbffc50462e929d7fffb", + "rev": "78058d810644f5ed276804ce7ea9e82d92bee293", "type": "github" }, "original": { From a52e6e5aa2087719356f8d0cc0cafdbac46927c0 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 12 Sep 2023 14:07:06 +0300 Subject: [PATCH 060/357] feat(tooling): Add direnv support --- .envrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 000000000..3550a30f2 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake From f53904c629d99d8eeeee7704fdfa6c396b899633 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 12 Sep 2023 14:10:19 +0300 Subject: [PATCH 061/357] fix(tooling): Fix Nix build for rustier sile Use pkg.nix for most of sile's build Nix expression and document in comments the small differences between pkg.nix and Nixpkgs' `sile/default.nix` expression. --- flake.nix | 96 +++++------------------------- pkg.nix | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+), 82 deletions(-) create mode 100644 pkg.nix diff --git a/flake.nix b/flake.nix index 3a9634790..b094b3b9a 100644 --- a/flake.nix +++ b/flake.nix @@ -37,36 +37,7 @@ inherit (gitignore.lib) gitignoreSource; # https://discourse.nixos.org/t/passing-git-commit-hash-and-tag-to-build-with-flakes/11355/2 version_rev = if (self ? rev) then (builtins.substring 0 7 self.rev) else "dirty"; - # Prepare a different luaEnv to be used in the overridden expression, - # this is also the place to choose a different lua interpreter, such as - # lua5_4 or luajit - luaEnv = pkgs.lua5_3.withPackages(ps: with ps; [ - cassowary - cldr - fluent - linenoise - loadkit - lpeg - lua-zlib - lua_cliargs - luaepnf - luaexpat - luafilesystem - luarepl - luasec - luasocket - luautf8 - penlight - vstruct - # lua packages needed for testing - busted - luacheck - # If we want to test things with lua5.2 or an even older lua, we uncomment these - #bit32 - #compat53 - ]); - # Use the expression from Nixpkgs instead of rewriting it here. - sile = pkgs.sile.overrideAttrs(oldAttr: rec { + sile = pkgs.callPackage ./pkg.nix { version = "${(pkgs.lib.importJSON ./package.json).version}-${version_rev}-flake"; src = pkgs.lib.cleanSourceWith { # Ignore many files that gitignoreSource doesn't ignore, see: @@ -95,62 +66,23 @@ ]); src = gitignoreSource ./.; }; - # Add the libtexpdf src instead of the git submodule. - # Also pretend to be a tarball release so sile --version will not say `vUNKNOWN`. - preAutoreconf = '' - rm -rf ./libtexpdf - # From some reason without this flag, libtexpdf/ is unwriteable - cp --no-preserve=mode -r ${libtexpdf-src} ./libtexpdf/ - echo ${version} > .tarball-version - ''; - # Don't build the manual as it's time consuming, and it requires fonts - # that are not available in the sandbox due to internet connection - # missing. - configureFlags = [ - "PDFINFO=false" - ] ++ ( - pkgs.lib.lists.remove "--with-manual" oldAttr.configureFlags - ); - nativeBuildInputs = oldAttr.nativeBuildInputs ++ [ - pkgs.autoreconfHook - ]; - buildInputs = [ - # Build inputs added since release in nixpkgs - pkgs.cargo - pkgs.jq - pkgs.rustc - ] ++ [ - # Add here inputs needed for development, and not for Nixpkgs' build. - pkgs.libarchive - pkgs.perl - # This line, along with the `pkgs.list.drop 1` line afterwards, - # replaces the luaEnv originated in `oldAttr.buildInputs`. - luaEnv - ] ++ ( - # Add all buildInputs from Nixpkgs' derivation, besides the 1st - # one, which is Nixpkgs' luaEnv. NOTE it's not mandatory to `drop` - # the first buildInput of `oldAttr` as so, because the first `lua` - # interpreter that would have been found otherwise would have been - # the one belonging to the first `luaEnv` of the final - # `buildInputs`. However, we'd like to keep the `buildInputs` clean - # never the less. - pkgs.lib.lists.drop 1 oldAttr.buildInputs - ); - meta = oldAttr.meta // { - changelog = "https://github.com/sile-typesetter/sile/raw/master/CHANGELOG.md"; - }; - }); + inherit libtexpdf-src; + }; + inherit (sile.passthru) luaEnv; in rec { devShells = { default = pkgs.mkShell { - inherit (sile) checkInputs buildInputs FONTCONFIG_FILE; + inherit (sile) + buildInputs + nativeCheckInputs + FONTCONFIG_FILE + ; configureFlags = sile.configureFlags ++ [ "--enable-developer" ]; - nativeBuildInputs = sile.nativeBuildInputs ++ [ pkgs.luarocks-nix ]; - # This is written in Nixpkgs' expression as well, but we need to write - # this here so that the overridden luaEnv will be used instead. - passthru = { - inherit luaEnv; - }; + nativeBuildInputs = sile.nativeBuildInputs ++ [ + pkgs.luarocks + # For commitlint git hook + pkgs.yarn + ]; }; }; packages.sile = sile; diff --git a/pkg.nix b/pkg.nix new file mode 100644 index 000000000..3ecd2c29c --- /dev/null +++ b/pkg.nix @@ -0,0 +1,173 @@ +# NOTE: This file is supposed to be similar to what is in Nixpkgs, except for +# the `version`, `src` and `libtexpdf-src` attributes that are given by the +# `flake.nix`. In Nixpkgs, we don't need `libtexpdf-src` because we use +# `fetchFromGitHub` with fetchSubmodules = true;`. +{ lib +, stdenv +, version, src, libtexpdf-src +, autoreconfHook +, gitMinimal +, pkg-config +, jq +, cargo +, rustc +, rustPlatform +, makeWrapper +, poppler_utils +, harfbuzz +, icu +, fontconfig +, lua +, libiconv +, darwin +, makeFontsConf +, gentium +, runCommand +}: + +let + luaEnv = lua.withPackages(ps: with ps; [ + cassowary + cldr + cosmo + fluent + linenoise + loadkit + lpeg + lua-zlib + lua_cliargs + luaepnf + luaexpat + luafilesystem + luarepl + luasec + luasocket + luautf8 + penlight + vstruct + # lua packages needed for testing + busted + luacheck + # NOTE: Add lua packages here, to change the luaEnv also read by `flake.nix` + ] ++ lib.optionals (lib.versionOlder lua.luaversion "5.2") [ + bit32 + ] ++ lib.optionals (lib.versionOlder lua.luaversion "5.3") [ + compat53 + ]); +in stdenv.mkDerivation (finalAttrs: { + pname = "sile"; + inherit version src; + + preAutoreconf = '' + # Add the libtexpdf src instead of the git submodule. (From some reason + # without --no-preserve=mode flag, libtexpdf/ is unwriteable). As explained + # before, in Nixpkgs, we won't need to run these commands. + rm -rf ./libtexpdf + cp --no-preserve=mode -r ${libtexpdf-src} ./libtexpdf/ + # pretend to be a tarball release so sile --version will not say `vUNKNOWN`. + echo ${finalAttrs.version} > .tarball-version + ''; + + nativeBuildInputs = [ + autoreconfHook + gitMinimal + pkg-config + jq + cargo + rustc + rustPlatform.cargoSetupHook + poppler_utils + makeWrapper + ]; + # In Nixpkgs, we don't copy the Cargo.lock file from the repo to Nixpkgs' + # repo, but we inherit src, and specify a hash (it is a fixed output + # derivation). `nix-update` and `nixpkgs-update` should be able to catch that + # hash and update it as well when performing updates. + cargoDeps = rustPlatform.importCargoLock { + lockFile = ./Cargo.lock; + }; + + buildInputs = [ + luaEnv + harfbuzz + icu + fontconfig + libiconv + ] ++ lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.AppKit + ]; + + configureFlags = [ + "--with-system-luarocks" + # TODO: Explain this flag + "PDFINFO=false" + #"--with-manual" In Nixpkgs we add this flag, here its not important enough + ]; + + postPatch = '' + patchShebangs build-aux/*.sh + '' + lib.optionalString stdenv.isDarwin '' + sed -i -e 's|@import AppKit;|#import |' src/macfonts.m + ''; + + NIX_LDFLAGS = lib.optionalString stdenv.isDarwin "-framework AppKit"; + + FONTCONFIG_FILE = makeFontsConf { + fontDirectories = [ + gentium + ]; + }; + + enableParallelBuilding = true; + + preBuild = lib.optionalString stdenv.cc.isClang '' + substituteInPlace libtexpdf/dpxutil.c \ + --replace "ASSERT(ht && ht->table && iter);" "ASSERT(ht && iter);" + ''; + + # remove forbidden references to $TMPDIR + preFixup = lib.optionalString stdenv.isLinux '' + for f in "$out"/bin/*; do + if isELF "$f"; then + patchelf --shrink-rpath --allowed-rpath-prefixes "$NIX_STORE" "$f" + fi + done + ''; + + passthru = { + # So it will be easier to inspect this environment, in comparison to others + inherit luaEnv; + # Copied from Makefile.am + tests.test = lib.optionalAttrs (!(stdenv.isDarwin && stdenv.isAarch64)) ( + runCommand "${finalAttrs.pname}-test" { + nativeBuildInputs = [ poppler_utils finalAttrs.finalPackage ]; + inherit (finalAttrs) FONTCONFIG_FILE; + } '' + output=$(mktemp -t selfcheck-XXXXXX.pdf) + echo "foo" | sile -o $output - + pdfinfo $output | grep "SILE v${finalAttrs.version}" > $out + ''); + }; + + outputs = [ "out" "doc" "man" "dev" ]; + + meta = { + description = "A typesetting system"; + longDescription = '' + SILE is a typesetting system; its job is to produce beautiful + printed documents. Conceptually, SILE is similar to TeX—from + which it borrows some concepts and even syntax and + algorithms—but the similarities end there. Rather than being a + derivative of the TeX family SILE is a new typesetting and + layout engine written from the ground up using modern + technologies and borrowing some ideas from graphical systems + such as InDesign. + ''; + homepage = "https://sile-typesetter.org"; + # In nixpkgs we use a version specific URL for CHANGELOG.md + changelog = "https://github.com/sile-typesetter/sile/raw/master/CHANGELOG.md"; + platforms = lib.platforms.unix; + maintainers = with lib.maintainers; [ doronbehar alerque ]; + license = lib.licenses.mit; + }; +}) From 34b0493aa3fbc9447f1a723f4101ad2419b69d7f Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 12 Sep 2023 14:41:38 +0300 Subject: [PATCH 062/357] fix(tooling): Really ignore all nix symlinks --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 916392aac..ac5f9a5ea 100644 --- a/.gitignore +++ b/.gitignore @@ -95,4 +95,7 @@ completions/ core/pathsetup.lua # Nix symlink to builds -result/ +result +result-man +result-doc +result-dev From c28cd9410d817d4a8c6e432076e2f8b5cdae80a7 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 12 Sep 2023 17:44:16 +0300 Subject: [PATCH 063/357] feat(tooling): Add nix builds with various lua versions --- flake.nix | 13 ++++++++++++- pkg.nix | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index b094b3b9a..5a1bb103a 100644 --- a/flake.nix +++ b/flake.nix @@ -85,7 +85,18 @@ ]; }; }; - packages.sile = sile; + packages = { + sile-lua5_2 = sile; + sile-lua5_3 = sile.override { + lua = pkgs.lua5_3; + }; + sile-lua5_4 = sile.override { + lua = pkgs.lua5_4; + }; + sile-luajit = sile.override { + lua = pkgs.luajit; + }; + }; defaultPackage = sile; apps = rec { default = sile; diff --git a/pkg.nix b/pkg.nix index 3ecd2c29c..5d87bfc96 100644 --- a/pkg.nix +++ b/pkg.nix @@ -102,6 +102,8 @@ in stdenv.mkDerivation (finalAttrs: { # TODO: Explain this flag "PDFINFO=false" #"--with-manual" In Nixpkgs we add this flag, here its not important enough + ] ++ lib.optionals lua.pkgs.isLuaJIT [ + "--with-luajit" ]; postPatch = '' From 8dd4aed071da295b159b988db4c303c870433c8c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 19:05:09 +0300 Subject: [PATCH 064/357] chore(build): Finish up --enable-developer not needing --datarootdir for local hacking --- configure.ac | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index a8556081b..e6de19dba 100644 --- a/configure.ac +++ b/configure.ac @@ -308,16 +308,17 @@ AX_SUBST_TRANSFORMED_PACKAGE_NAME # Avoid need for `--datarootdir=$(cd ..; pwd)` hack to run locally for # tests/manual build when developer mode is enabled AM_COND_IF([DEVELOPER], [ - AC_DEFINE_UNQUOTED([SILE_PATH],["$(pwd)"],[Path for SILE packages and classes]) + adl_RECURSIVE_EVAL(["$(pwd)"], [SILE_PATH]) + AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) ],[ adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) - AC_DEFINE_UNQUOTED([SILE_PATH],["${SILE_PATH}"],[Path for SILE packages and classes]) + AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) ]) AC_SUBST([SILE_PATH]) adl_RECURSIVE_EVAL(["${libdir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_LIB_PATH]) -AC_DEFINE_UNQUOTED([SILE_LIB_PATH],["${SILE_LIB_PATH}"],[Path for SILE libraries]) +AC_DEFINE_UNQUOTED([SILE_LIB_PATH],["${SILE_LIB_PATH}"], [Path for SILE libraries]) AC_SUBST([SILE_LIB_PATH]) AC_SUBST([ROCKSPECWARNING], ["DO NOT EDIT! Modify template sile.rockspec.in"]) From 52b567f001f9e310c2d0285a4bb5d8b786fd1670 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 20:31:53 +0300 Subject: [PATCH 065/357] chore(build): Pass build time lua package path to Rust runtime --- .cargo/config.toml | 4 +--- Makefile-luarocks | 4 ++-- configure.ac | 6 ++++++ core/pathsetup.lua.in | 6 ++++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 9037819ed..2d560c29a 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,11 +4,9 @@ rustflags = ["-C", "link-args=-rdynamic"] [target.x86_64-unknown-linux-gnu] rustflags = ["-C", "link-args=-rdynamic"] -# Since autotools sets this and we are *not* forcing it here, this will not +# Since autotools sets these and we are *not* forcing them here, this will not # affect release builds. It will affect `cargo run` and make it easier to test # locally since the Lua loader path will be relative to the current sources. -# For debug builds it is assumed you configured `--without-system-luarocks`, -# this convenience won't enable you to use system packages in debug builds. [env] SILE_PATH = { value = "", relative = true } diff --git a/Makefile-luarocks b/Makefile-luarocks index 7ea0dc624..c4ded991d 100644 --- a/Makefile-luarocks +++ b/Makefile-luarocks @@ -17,7 +17,7 @@ $(LUAMODLOCK): lua_modules $(LUAMODSPEC) $(genrockslock) > $@ else LUAMODLOCK := -LUA_PATH := $(shell lua$(LUA_VERSION) -e 'print(package.path)') -LUA_CPATH := $(shell lua$(LUA_VERSION) -e 'print(package.cpath)') +LUA_PATH := $(shell $(LUA) -e 'print(package.path)') +LUA_CPATH := $(shell $(LUA) -e 'print(package.cpath)') export LUA_PATH LUA_CPATH endif diff --git a/configure.ac b/configure.ac index e6de19dba..fec7e61d2 100644 --- a/configure.ac +++ b/configure.ac @@ -310,12 +310,18 @@ AX_SUBST_TRANSFORMED_PACKAGE_NAME AM_COND_IF([DEVELOPER], [ adl_RECURSIVE_EVAL(["$(pwd)"], [SILE_PATH]) AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) + adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.path)')"], [LUA_PATH]) + AC_DEFINE_UNQUOTED([LUA_PATH], ["${LUA_PATH}"],[System Lua package path]) + adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.cpath)')"], [LUA_CPATH]) + AC_DEFINE_UNQUOTED([LUA_CPATH], ["${LUA_CPATH}"], [System Lua package cpath]) ],[ adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) ]) AC_SUBST([SILE_PATH]) +AC_SUBST([LUA_PATH]) +AC_SUBST([LUA_CPATH]) adl_RECURSIVE_EVAL(["${libdir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_LIB_PATH]) AC_DEFINE_UNQUOTED([SILE_LIB_PATH],["${SILE_LIB_PATH}"], [Path for SILE libraries]) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index b9ef4bc29..413d3ce65 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -1,3 +1,9 @@ +-- Allow autoconf to setup system lua paths at compile time, not run time (only used in developer mode) +if "@LUA_PATH@" ~= "" then + package.path = "@LUA_PATH@" + package.cpath = "@LUA_CPATH@" +end + local executable = debug.getinfo(3, "S").source local luaversion = _VERSION:match("%d+%.%d+") From bec64f4128193b51e07accf57c51fcae6a6270de Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 21:15:31 +0300 Subject: [PATCH 066/357] chore(build): Remove unused msys specific build-time configuration --- configure.ac | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index fec7e61d2..330d6e2fc 100644 --- a/configure.ac +++ b/configure.ac @@ -158,15 +158,7 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ fi ]) - case $host_os in - msys) - LUA_VERSION=5.3 # By fiat. This is obviously not good. - ;; - *) - AX_PROG_LUA([5.1]) - ;; - esac - + AX_PROG_LUA([5.1]) AX_LUA_HEADERS AX_LUA_LIBS From 8c8f44cd14663719ce16712a30c0d991b3963fbf Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 21:31:40 +0300 Subject: [PATCH 067/357] chore(tooling): Rename clippy lint to follow upstream tooling --- .cargo/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 2d560c29a..96522a110 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -16,6 +16,6 @@ rustflags = [ # This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML. # See: `https://github.com/rust-lang/cargo/issues/5034` # `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395` - "-Aclippy::clone_double_ref", + "-Asuspicious_double_ref_op", "-Aclippy::ptr_arg", ] From 20db7df1f9b5b621dce7eb26cd407f01d7d085ef Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 21:55:44 +0300 Subject: [PATCH 068/357] chore(build): Always set built-in lua paths --- configure.ac | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 330d6e2fc..0e1bb67bb 100644 --- a/configure.ac +++ b/configure.ac @@ -302,17 +302,20 @@ AX_SUBST_TRANSFORMED_PACKAGE_NAME AM_COND_IF([DEVELOPER], [ adl_RECURSIVE_EVAL(["$(pwd)"], [SILE_PATH]) AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) - adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.path)')"], [LUA_PATH]) - AC_DEFINE_UNQUOTED([LUA_PATH], ["${LUA_PATH}"],[System Lua package path]) - adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.cpath)')"], [LUA_CPATH]) - AC_DEFINE_UNQUOTED([LUA_CPATH], ["${LUA_CPATH}"], [System Lua package cpath]) ],[ adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) ]) AC_SUBST([SILE_PATH]) + +# In order for our Rust CLI binary to use the same default package.path as the system Lua, +# we test the system Lua (required only at build not run time) for its current package.path. +adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.path)')"], [LUA_PATH]) +AC_DEFINE_UNQUOTED([LUA_PATH], ["${LUA_PATH}"],[System Lua package path]) AC_SUBST([LUA_PATH]) +adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.cpath)')"], [LUA_CPATH]) +AC_DEFINE_UNQUOTED([LUA_CPATH], ["${LUA_CPATH}"], [System Lua package cpath]) AC_SUBST([LUA_CPATH]) adl_RECURSIVE_EVAL(["${libdir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_LIB_PATH]) From dbbdf0b2dea9691f34d17f0ebe97e5a5e4dd5f06 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 22:10:45 +0300 Subject: [PATCH 069/357] chore(cli): Drop unusued overrides of Lua vars --- Cargo.lock | 7 ------- Cargo.toml | 3 --- src/lib.rs | 18 ------------------ 3 files changed, 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4760bfb8a..61cf64834 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,12 +320,6 @@ dependencies = [ "libc", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.141" @@ -559,7 +553,6 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", - "lazy_static", "mlua", "vergen", ] diff --git a/Cargo.toml b/Cargo.toml index c1488851a..5d7a07569 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,9 +28,6 @@ required-features = ["cli"] optional = true features = [ "derive", "string", "wrap_help" ] - [dependencies.lazy_static] - version = "1.4" - [dependencies.mlua] version = "0.8" features = [ "macros", "vendored" ] diff --git a/src/lib.rs b/src/lib.rs index f1e53ed11..b9c0477bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -use lazy_static::lazy_static; use mlua::chunk; use mlua::prelude::*; use std::path::PathBuf; @@ -7,24 +6,11 @@ pub mod cli; pub type Result = anyhow::Result; -// These env vars are generated by autoconf *at compile time* in order to emulate the system -// default Lua interpreter. If they exist we use them, else keep it to ourselves. -lazy_static! { - #[derive(Debug)] - pub static ref LUA_PATH: &'static str = option_env!["LUA_PATH"].unwrap_or_else(|| "./?.lua"); - #[derive(Debug)] - pub static ref LUA_CPATH: &'static str = option_env!["LUA_CPATH"].unwrap_or_else(|| ""); -} - pub fn version() -> crate::Result { let lua = unsafe { Lua::unsafe_new() }; - let lua_path: LuaString = lua.create_string(&LUA_PATH.clone())?; - let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone())?; let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; let sile: LuaTable = lua .load(chunk! { - package.path = $lua_path - package.cpath = $lua_cpath local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") if not status then dofile("./core/pathsetup.lua") @@ -57,13 +43,9 @@ pub fn run( traceback: bool, ) -> crate::Result<()> { let lua = unsafe { Lua::unsafe_new() }; - let lua_path: LuaString = lua.create_string(&LUA_PATH.clone()).unwrap(); - let lua_cpath: LuaString = lua.create_string(&LUA_CPATH.clone()).unwrap(); let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; let sile: LuaTable = lua .load(chunk! { - package.path = $lua_path - package.cpath = $lua_cpath local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") if not status then dofile("./core/pathsetup.lua") From 8a8b506fde16c677e5229f0ad5f60be28aeb7373 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 00:20:51 +0300 Subject: [PATCH 070/357] feat(build): Set default Lua version to prefer LuaJIT (#1873) --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0e1bb67bb..9480e8876 100644 --- a/configure.ac +++ b/configure.ac @@ -74,8 +74,8 @@ AC_SUBST([SYSTEM_LUAROCKS]) AC_ARG_WITH([luajit], AS_HELP_STRING([--with-luajit], - [Run under LuaJIT instead of Lua])) -AM_CONDITIONAL([LUAJIT], [test "x$with_luajit" = "xyes"]) + [Prefer LuaJIT over PUC Lua, even if the latter is newer])) +AM_CONDITIONAL([LUAJIT], [test "x$with_luajit" != "xno"]) AC_ARG_WITH([manual], AS_HELP_STRING([--with-manual], From c437b388df948d67acd6b5f595f795bce6cf982c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 12 Sep 2023 22:26:14 +0300 Subject: [PATCH 071/357] chore(cli): Use runtime SILE_PATH if set, then fall back to buildtime one --- src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b9c0477bc..673d458a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use mlua::chunk; use mlua::prelude::*; -use std::path::PathBuf; +use std::{env, path::PathBuf}; #[cfg(feature = "cli")] pub mod cli; @@ -8,7 +8,11 @@ pub type Result = anyhow::Result; pub fn version() -> crate::Result { let lua = unsafe { Lua::unsafe_new() }; - let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; + let sile_path = match env::var("SILE_PATH") { + Ok(val) => val, + Err(_) => env!("SILE_PATH").to_string(), + }; + let sile_path: LuaString = lua.create_string(&sile_path)?; let sile: LuaTable = lua .load(chunk! { local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") @@ -43,7 +47,11 @@ pub fn run( traceback: bool, ) -> crate::Result<()> { let lua = unsafe { Lua::unsafe_new() }; - let sile_path: LuaString = lua.create_string(env!("SILE_PATH"))?; + let sile_path = match env::var("SILE_PATH") { + Ok(val) => val, + Err(_) => env!("SILE_PATH").to_string(), + }; + let sile_path: LuaString = lua.create_string(&sile_path)?; let sile: LuaTable = lua .load(chunk! { local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") From 2853474c5855ea38cba6493f3b43ae438cfd0a7d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 01:16:48 +0300 Subject: [PATCH 072/357] style(tooling): Stop mixing tabs and spaces in autotools macros --- build-aux/ax_lua.m4 | 88 ++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/build-aux/ax_lua.m4 b/build-aux/ax_lua.m4 index e9b952257..085dc49ad 100644 --- a/build-aux/ax_lua.m4 +++ b/build-aux/ax_lua.m4 @@ -9,8 +9,8 @@ AC_DEFUN([AX_PROG_LUA], dnl Find a Lua interpreter. AM_COND_IF([LUAJIT], - [_ax_lua_interpreter_list="luajit luajit-2.1.0-beta3 luajit-2.0.5 luajit-2.0.4 luajit-2.0.3"], - [_ax_lua_interpreter_list="lua lua5.4 lua54 lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua5.0 lua50"]) + [_ax_lua_interpreter_list="luajit luajit-2.1.0-beta3 luajit-2.0.5 luajit-2.0.4 luajit-2.0.3"], + [_ax_lua_interpreter_list="lua lua5.4 lua54 lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua5.0 lua50"]) m4_if([$1], [], [ dnl No version check is needed. Find any Lua interpreter. @@ -71,21 +71,21 @@ AC_DEFUN([AX_PROG_LUA], m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])]) ], [ dnl Query Lua for its version number. - AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version], - [ ax_cv_lua_version=`$LUA -e 'print(_VERSION:match "(%d+%.%d+)")'` ]) - AS_IF([test "x$ax_cv_lua_version" = 'x'], - [AC_MSG_ERROR([invalid Lua version number])]) - AC_SUBST([LUA_VERSION], [$ax_cv_lua_version]) - AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`]) - - AM_COND_IF([LUAJIT], [ - AC_CACHE_CHECK([for $ax_display_LUA jit version], [ax_cv_luajit_version], - [ ax_cv_luajit_version=`$LUA -e 'print(jit and jit.version:match "(%d+%..+)")'` ]) - AS_IF([test "x$ax_cv_luajit_version" = 'x'], - [AC_MSG_ERROR([invalid Lua version number])]) - AC_SUBST([LUAJIT_VERSION], [$ax_cv_luajit_version]) - AC_SUBST([LUAJIT_SHORT_VERSION], [`echo "$LUAJIT_VERSION" | $SED 's|\.|§|;s|\..*||;s|§|.|'`]) - ]) + AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version], + [ ax_cv_lua_version=`$LUA -e 'print(_VERSION:match "(%d+%.%d+)")'` ]) + AS_IF([test "x$ax_cv_lua_version" = 'x'], + [AC_MSG_ERROR([invalid Lua version number])]) + AC_SUBST([LUA_VERSION], [$ax_cv_lua_version]) + AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`]) + + AM_COND_IF([LUAJIT], [ + AC_CACHE_CHECK([for $ax_display_LUA jit version], [ax_cv_luajit_version], + [ ax_cv_luajit_version=`$LUA -e 'print(jit and jit.version:match "(%d+%..+)")'` ]) + AS_IF([test "x$ax_cv_luajit_version" = 'x'], + [AC_MSG_ERROR([invalid Lua version number])]) + AC_SUBST([LUAJIT_VERSION], [$ax_cv_luajit_version]) + AC_SUBST([LUAJIT_SHORT_VERSION], [`echo "$LUAJIT_VERSION" | $SED 's|\.|§|;s|\..*||;s|§|.|'`]) + ]) dnl The following check is not supported: dnl At times (like when building shared libraries) you may want to know @@ -196,12 +196,12 @@ AC_DEFUN([_AX_LUA_CHK_VER], AC_DEFUN([_AX_LUAJIT_CHK_VER], [ AS_IF([$1 2>/dev/null -e ' - function norm (v) - i,j=v:match "(%d+)%.(%d+)" if i then return 100 * i + j end - end - v, toobig=norm (jit.version), norm "$3" or math.huge - os.exit ((v >= norm ("$2") and v < toobig) and 0 or 1)'], - [$4], [$5]) + function norm (v) + i,j=v:match "(%d+)%.(%d+)" if i then return 100 * i + j end + end + v, toobig=norm (jit.version), norm "$3" or math.huge + os.exit ((v >= norm ("$2") and v < toobig) and 0 or 1)'], + [$4], [$5]) ]) @@ -246,8 +246,8 @@ AC_DEFUN([AX_LUA_HEADERS], dnl Some default directories to search. AM_COND_IF([LUAJIT], - [_ax_lua_include_list="/usr/include/luajit-$LUAJIT_VERSION /usr/include/luajit-$LUAJIT_SHORT_VERSION /usr/local/include/luajit-$LUAJIT_VERSION /usr/local/include/luajit-$LUAJIT_SHORT_VERSION"], - [_ax_lua_include_list="/usr/include/lua$LUA_VERSION /usr/include/lua/$LUA_VERSION /usr/include/lua$LUA_SHORT_VERSION /usr/local/include/lua$LUA_VERSION /usr/local/include/lua-$LUA_VERSION /usr/local/include/lua/$LUA_VERSION /usr/local/include/lua$LUA_SHORT_VERSION"]) + [_ax_lua_include_list="/usr/include/luajit-$LUAJIT_VERSION /usr/include/luajit-$LUAJIT_SHORT_VERSION /usr/local/include/luajit-$LUAJIT_VERSION /usr/local/include/luajit-$LUAJIT_SHORT_VERSION"], + [_ax_lua_include_list="/usr/include/lua$LUA_VERSION /usr/include/lua/$LUA_VERSION /usr/include/lua$LUA_SHORT_VERSION /usr/local/include/lua$LUA_VERSION /usr/local/include/lua-$LUA_VERSION /usr/local/include/lua/$LUA_VERSION /usr/local/include/lua$LUA_SHORT_VERSION"]) dnl Try to find the headers. _ax_lua_saved_cppflags=$CPPFLAGS @@ -258,12 +258,12 @@ AC_DEFUN([AX_LUA_HEADERS], dnl Try some other directories if LUA_INCLUDE was not set. AS_IF([test "x$LUA_INCLUDE" = 'x' && - test "x$ac_cv_header_lua_h" != "xyes" || - test "x$with_luajit" = "xyes" && - test "x$ac_cv_header_luajit_h" != 'xyes'], - [ dnl Try some common include paths. - for _ax_include_path in $_ax_lua_include_list; do - test ! -d "$_ax_include_path" && continue + test "x$ac_cv_header_lua_h" != "xyes" || + test "x$with_luajit" = "xyes" && + test "x$ac_cv_header_luajit_h" != 'xyes'], + [ dnl Try some common include paths. + for _ax_include_path in $_ax_lua_include_list; do + test ! -d "$_ax_include_path" && continue AC_MSG_CHECKING([for Lua headers in]) AC_MSG_RESULT([$_ax_include_path]) @@ -277,7 +277,7 @@ AC_DEFUN([AX_LUA_HEADERS], _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I$_ax_include_path" AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) - AM_COND_IF([LUAJIT], [AC_CHECK_HEADERS([luajit.h])]) + AM_COND_IF([LUAJIT], [AC_CHECK_HEADERS([luajit.h])]) CPPFLAGS=$_ax_lua_saved_cppflags AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], @@ -397,18 +397,18 @@ AC_DEFUN([AX_LUA_LIBS], dnl Try to find the Lua libs. _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" - AM_COND_IF([LUAJIT], - [AC_SEARCH_LIBS([lua_load], - [luajit$LUA_VERSION luajit$LUA_SHORT_VERSION luajit-$LUA_VERSION luajit-$LUA_SHORT_VERSION luajit], - [_ax_found_lua_libs='yes'], - [_ax_found_lua_libs='no'], - [$_ax_lua_extra_libs])], - [AC_SEARCH_LIBS([lua_load], - [lua$LUA_VERSION lua$LUA_SHORT_VERSION lua-$LUA_VERSION lua-$LUA_SHORT_VERSION lua], - [_ax_found_lua_libs='yes'], - [_ax_found_lua_libs='no'], - [$_ax_lua_extra_libs])]) - LIBS=$_ax_lua_saved_libs + AM_COND_IF([LUAJIT], + [AC_SEARCH_LIBS([lua_load], + [luajit$LUA_VERSION luajit$LUA_SHORT_VERSION luajit-$LUA_VERSION luajit-$LUA_SHORT_VERSION luajit], + [_ax_found_lua_libs='yes'], + [_ax_found_lua_libs='no'], + [$_ax_lua_extra_libs])], + [AC_SEARCH_LIBS([lua_load], + [lua$LUA_VERSION lua$LUA_SHORT_VERSION lua-$LUA_VERSION lua-$LUA_SHORT_VERSION lua], + [_ax_found_lua_libs='yes'], + [_ax_found_lua_libs='no'], + [$_ax_lua_extra_libs])]) + LIBS=$_ax_lua_saved_libs AS_IF([test "x$ac_cv_search_lua_load" != 'xno' && test "x$ac_cv_search_lua_load" != 'xnone required'], From 49f85422ceebe5ce53cf2117358627f34e45e7ef Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 01:08:13 +0300 Subject: [PATCH 073/357] chore(build): Fixup ./configure --help with new default luajit defaults --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9480e8876..98831621e 100644 --- a/configure.ac +++ b/configure.ac @@ -73,7 +73,7 @@ AM_CONDITIONAL([SYSTEM_LUAROCKS], [test "x$with_system_luarocks" = "xyes"]) AC_SUBST([SYSTEM_LUAROCKS]) AC_ARG_WITH([luajit], - AS_HELP_STRING([--with-luajit], + AS_HELP_STRING([--without-luajit], [Prefer LuaJIT over PUC Lua, even if the latter is newer])) AM_CONDITIONAL([LUAJIT], [test "x$with_luajit" != "xno"]) From d387816cded196f2c1da316105bd91b7795d8ee1 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 12:10:04 +0300 Subject: [PATCH 074/357] ci(actions): Re-enable page count checking for CI jobs that build PDFs --- .github/workflows/build.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51e8713d9..a401e9f56 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,7 +35,7 @@ jobs: - name: Configure run: | ./bootstrap.sh - ./configure PDFINFO=false \ + ./configure \ --with-luajit \ --disable-font-variations \ --without-system-luarocks \ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7c983200..0839eb64f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,7 +69,7 @@ jobs: - name: Configure run: | ./bootstrap.sh - ./configure PDFINFO=false \ + ./configure \ --enable-developer LUACHECK=false NIX=false \ --disable-font-variations \ --without-system-luarocks \ From c31ba002f78884837c6a5b934fc32785d207b802 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 21 Sep 2023 00:42:13 +0300 Subject: [PATCH 075/357] chore(tooling): Keep Git version parser from tripping on alpha/beta/rc semver tags --- build-aux/git-version-gen | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build-aux/git-version-gen b/build-aux/git-version-gen index 2a79f1f67..b971f41c2 100755 --- a/build-aux/git-version-gen +++ b/build-aux/git-version-gen @@ -1,4 +1,5 @@ -#!/bin/sh +#!/usr/bin/env sh + # Print a version string. scriptversion=2012-03-18.17; # UTC @@ -165,8 +166,8 @@ then # Newer: v6.10-77-g0f8faeb # Older: v6.10-g0f8faeb case $v in - *-*-*) : git describe is okay three part flavor ;; - *-*) + *-*-g*) : git describe is okay three part flavor ;; + *-g*) : git describe is older two part flavor # Recreate the number of commits and rewrite such that the # result is the same as if we were using the newer version @@ -181,7 +182,7 @@ then ;; esac - v=`echo "$v" | sed 's/-/.r/'`; + v=`echo "$v" | sed 's/-\([0-9]\)/.r\1/'`; v_from_git=1 else v=UNKNOWN From aef359463d3598685cc235a61e475ab29070dc43 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 21 Sep 2023 10:15:01 +0300 Subject: [PATCH 076/357] refactor(build): Cleanup odds and ends in Makefile --- Makefile.am | 116 +++++++++++++++++++++++++-------------------------- configure.ac | 6 ++- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6f5468e39..26bfcf517 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,10 +5,9 @@ ACLOCAL_AMFLAGS = -I build-aux .SECONDEXPANSION: .DELETE_ON_ERROR: -if SYSTEM_LIBTEXPDF SUBDIRS = src -else -SUBDIRS = libtexpdf src +if SYSTEM_LIBTEXPDF +SUBDIRS += libtexpdf endif licensedir = $(datarootdir)/licenses/$(TRANSFORMED_PACKAGE_NAME) @@ -54,18 +53,16 @@ endif $(MANUAL): $(FIGURES) -nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) -nobase_nodist_pkgdata_DATA = core/features.lua core/version.lua $(LUAMODULES) +bin_PROGRAMS = sile +bin_SCRIPTS = sile-lua dist_man_MANS = sile.1 sile-lua.1 +sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli.rs +EXTRA_sile_SOURCES = Cargo.lock .version +nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = core/features.lua core/pathsetup.lua core/version.lua $(LUAMODULES) -dist_man_MANS = sile.1 sile-lua.1 dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE -bin_SCRIPTS = sile-lua -bin_PROGRAMS = sile -sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli.rs -EXTRA_sile_SOURCES = Cargo.lock .version EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh @@ -94,6 +91,10 @@ MLUAVER = lua$(LUA_SHORT_VERSION) endif CARGO_FEATURE_ARGS = --features $(MLUAVER) +DEPDIR := .deps +LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf +SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig + CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target RUST_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) _RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir @@ -184,60 +185,19 @@ dist-hook: $(MANUAL) # Whether to force tests to run from scratch CLEAN ?= -RELTYPE ?= - -.PHONY: tagrelease -tagrelease: - test -z $$($(GIT) tag --points-at HEAD) || exit 0 # end if we are already on a release tag - $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything staged but not committed - $(GIT) diff-files --quiet || exit 1 # die if any tracked files have unstagged changes - npm run release -- $(and $(RELTYPE),--release-as $(RELTYPE)) - -.PHONY: prerelease -prerelease: test docs update_libtexpdf - -.PHONY: release-preview -release-preview: - npm run release -- --dry-run $(and $(RELTYPE),--release-as $(RELTYPE)) - -.PHONY: release -release: tagrelease - dist: sile-$(VERSION).pdf sile-$(VERSION).md sile-$(VERSION).pdf: $(MANUAL) cp $(MANUAL) $@ -sile-%.md: CHANGELOG.md - $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ - $(SED) -e '1,3d;N;$$!P;$$!D;$$d' > $@ - -.PHONY: update_libtexpdf -update_libtexpdf: - $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything already staged - $(GIT) submodule update --init --remote -- libtexpdf - $(NIX) flake lock --override-input libtexpdf-src github:sile-typesetter/libtexpdf/$(shell $(GIT) submodule status -- libtexpdf | awk '{print $$1}') - $(GIT) add -- libtexpdf flake.lock - $(GIT) diff-index --quiet --cached HEAD || $(GIT) commit -m "chore(build): Pin latest libtexpdf library submodule" - -DEPDIR := .deps -REGRESSIONSCRIPT := ./tests/regressions.pl -LOCALTESTFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf -SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig -BUSTEDFLAGS ?= - -TESTPDFS = $(addsuffix .pdf,$(basename $(TESTSRCS))) -EXPECTEDS ?= $(filter $(addsuffix .expected,$(basename $(TESTSRCS))),$(TESTEXPECTS)) -ACTUALS = $(addsuffix .actual,$(basename $(EXPECTEDS))) - check: selfcheck .PHONY: selfcheck -selfcheck: | $(SILE) $(_BUILT_SUBDIRS) +selfcheck: | $(bin_PROGRAMS) $(_BUILT_SUBDIRS) output=$$(mktemp -t selfcheck-XXXXXX.pdf) trap 'rm -f $$output' EXIT HUP TERM export SILE_PATH - echo "foo" | SILE_PATH=$(PWD) ./$(SILE) -o $$output - + echo "foo" | SILE_PATH=$(PWD) ./$(bin_PROGRAMS) -o $$output - $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" .PHONY: docs @@ -247,7 +207,7 @@ docs: $(MANUAL) # garantee the TOC is up to date, simplify when #230 is fixed. hastoc = [ -f $(subst .pdf,.toc,$@) ] && echo true || echo false pages = $(PDFINFO) $@ | $(AWK) '$$1 == "Pages:" {print $$2}' || echo 0 -localsile = $(LOCALTESTFONTS) SILE_PATH=$(PWD) ./$(SILE) $(SILEFLAGS) +localsile = $(LOCALFONTS) SILE_PATH=$(PWD) ./$(bin_PROGRAMS) $(SILEFLAGS) silepass = $(localsile) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false define runsile = set -e @@ -276,7 +236,7 @@ $(_SUBDIR_TELLS): $(MAKE) $(AM_MAKEFLAGS) all-recursive # $(error Running `make install`, `make dist`, or other end-game targets before `make all` unspported.) -patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(SILE) $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) +patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(bin_PROGRAMS) $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) %.pdf: %.sil $$(patterndeps) $(runsile) @@ -299,8 +259,46 @@ PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck rustfmt c if DEVELOPER +RELTYPE ?= + +.PHONY: tagrelease +tagrelease: + test -z $$($(GIT) tag --points-at HEAD) || exit 0 # end if we are already on a release tag + $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything staged but not committed + $(GIT) diff-files --quiet || exit 1 # die if any tracked files have unstagged changes + npm run release -- $(and $(RELTYPE),--release-as $(RELTYPE)) + +.PHONY: prerelease +prerelease: test docs update_libtexpdf + +.PHONY: release-preview +release-preview: + npm run release -- --dry-run $(and $(RELTYPE),--release-as $(RELTYPE)) + +.PHONY: release +release: tagrelease + +sile-%.md: CHANGELOG.md + $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ + $(SED) -e '1,3d;N;$$!P;$$!D;$$d' > $@ + +.PHONY: update_libtexpdf +update_libtexpdf: + $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything already staged + $(GIT) submodule update --init --remote -- libtexpdf + $(NIX) flake lock --override-input libtexpdf-src github:sile-typesetter/libtexpdf/$(shell $(GIT) submodule status -- libtexpdf | awk '{print $$1}') + $(GIT) add -- libtexpdf flake.lock + $(GIT) diff-index --quiet --cached HEAD || $(GIT) commit -m "chore(build): Pin latest libtexpdf library submodule" + +TESTPDFS = $(addsuffix .pdf,$(basename $(TESTSRCS))) +EXPECTEDS ?= $(filter $(addsuffix .expected,$(basename $(TESTSRCS))),$(TESTEXPECTS)) +ACTUALS = $(addsuffix .actual,$(basename $(EXPECTEDS))) + +REGRESSIONSCRIPT := ./tests/regressions.pl +BUSTEDFLAGS ?= + regressions: $(TESTSRCS) $(ACTUALS) - $(LOCALTESTFONTS) $(REGRESSIONSCRIPT) $(TESTSRCS) + $(LOCALFONTS) $(REGRESSIONSCRIPT) $(TESTSRCS) test: regressions busted cargo-test @@ -333,7 +331,7 @@ else packagepath=(./{,lua_modules/share/lua/$(LUA_VERSION)/,lua-libraries/}?{,/init}.lua) endif # Note: use of --lua causes this to be passed back through a shell loosing one layer of quoting. Drop single quotes if removing. - $(LOCALTESTFONTS) $(BUSTED) --lua=$(LUA) --cpath="'$${packagecpath[*]};;'" --lpath="'$${packagepath[*]};;'" $(BUSTEDFLAGS) . + $(LOCALFONTS) $(BUSTED) --lua=$(LUA) --cpath="'$${packagecpath[*]};;'" --lpath="'$${packagepath[*]};;'" $(BUSTEDFLAGS) . coverage: export SILE_COVERAGE=1 coverage: BUSTEDFLAGS += -c @@ -453,9 +451,9 @@ gource.webm: gource -a 0.2 -s 0.2 -i 0 --logo /tmp/sile-logo.jpg -b 000000 --max-file-lag 5 --hide filenames --date-format '%Y-%m-%d' --user-image-dir /tmp/gravatars --user-filter simoncozens --key -1920x1080 -o - | \ ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i - -vcodec libvpx -b 10000K $@ -else +else !DEVELOPER $(PHONY_DEVELOPER_TARGETS): @: $(error "Please reconfigure using --enable-developer to use developer tooling") -endif +endif !DEVELOPER diff --git a/configure.ac b/configure.ac index 98831621e..7b4b3c4af 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([sile], [m4_esyscmd(build-aux/git-version-gen .tarball-version)], [simon@simon-cozens.org]) +AC_INIT([sile], [m4_esyscmd(build-aux/git-version-gen .tarball-version)], [caleb@alerque.com]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign tar-pax dist-xz dist-zip no-dist-gzip color-tests subdir-objects]) @@ -86,6 +86,7 @@ AM_CONDITIONAL([FONT_DOWNLOAD_TOOLS], [test -z ${DEVELOPER_TRUE} || (test -z ${M AC_SUBST([FONT_DOWNLOAD_TOOLS]) AM_COND_IF([DEPENDENCY_CHECKS], [ + AC_MSG_NOTICE([checking for SILE specific build dependencies]) AX_FONT(Gentium Plus) @@ -329,7 +330,8 @@ AX_SUBST_MAN_DATE AC_CONFIG_FILES([build-aux/list-dist-files.sh], [chmod +x build-aux/list-dist-files.sh]) AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/pathsetup.lua core/version.lua]) -AC_CONFIG_FILES([sile-lua:sile.in tests/regressions.pl], [chmod +x sile-lua tests/regressions.pl]) +AC_CONFIG_FILES([sile-lua:sile.in], [chmod +x sile-lua]) +AC_CONFIG_FILES([tests/regressions.pl], [chmod +x tests/regressions.pl]) AC_CONFIG_FILES([sile-dev-1.rockspec:sile.rockspec.in]) AC_ARG_PROGRAM From 08f475598e51ccf60949abadfff1ad59f0bcd43a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 13:10:40 +0300 Subject: [PATCH 077/357] chore(tooling): Extract Git versioning system to re-usable pieces --- Makefile.am | 27 +++++++++------------------ build-aux/ax_git_version.m4 | 9 +++++++++ build-aux/git_version.am | 35 +++++++++++++++++++++++++++++++++++ configure.ac | 6 +++--- 4 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 build-aux/ax_git_version.m4 create mode 100644 build-aux/git_version.am diff --git a/Makefile.am b/Makefile.am index 26bfcf517..0aac17f43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,7 +57,7 @@ bin_PROGRAMS = sile bin_SCRIPTS = sile-lua dist_man_MANS = sile.1 sile-lua.1 sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli.rs -EXTRA_sile_SOURCES = Cargo.lock .version +EXTRA_sile_SOURCES = Cargo.lock nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = core/features.lua core/pathsetup.lua core/version.lua $(LUAMODULES) dist_doc_DATA = README.md CHANGELOG.md @@ -71,9 +71,11 @@ EXTRA_DIST += default.nix flake.nix flake.lock shell.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) -BUILT_SOURCES = .version core/features.lua core/pathsetup.lua core/version.lua Makefile-distfiles +BUILT_SOURCES = core/features.lua core/pathsetup.lua core/version.lua Makefile-distfiles -CLEANFILES = $(bin_SCRIPTS) $(dist_man_MANS) $(BUILT_SOURCES) $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) .version-prev +CLEANFILES = $(bin_SCRIPTS) $(dist_man_MANS) $(BUILT_SOURCES) $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) + +include $(top_srcdir)/build-aux/git_version.am Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ @@ -161,23 +163,12 @@ $(_RUST_OUT) $(RUST_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) -_BRANCH_REF != $(AWK) '{print ".git/" $$2}' .git/HEAD 2>/dev/null ||: - -.version: $(_BRANCH_REF) - @if [ -e "$(srcdir)/.tarball-version" ]; then \ - printf "$(VERSION)" > $@; \ - else \ - touch "$@-prev"; \ - if [ -e "$@" ]; then \ - cp "$@" "$@-prev"; \ - fi; \ - ./build-aux/git-version-gen "$(srcdir)/.tarball-version" > $@; \ - cmp -s "$@" "$@-prev" || ( autoreconf configure.ac --force && build-aux/decore-automake.sh ); \ - fi +dist-hook: $(MANUAL) dist-hook-distfiles + +.PHONY: dist-hook-distfiles -dist-hook: $(MANUAL) +dist-hook-distfiles: cd $(distdir) - printf "$(VERSION)" > .tarball-version $(SED) -i -e '/^LUAMODULES =/s/=.*/=/' Makefile-distfiles $(top_srcdir)/build-aux/decore-automake.sh $(SED) -i -e '/^LUAMODULES/d;/^\tlua_modules/d' Makefile.in diff --git a/build-aux/ax_git_version.m4 b/build-aux/ax_git_version.m4 new file mode 100644 index 000000000..b59807835 --- /dev/null +++ b/build-aux/ax_git_version.m4 @@ -0,0 +1,9 @@ +AC_DEFUN([AX_GIT_VERSION], [ + + AC_PROG_AWK + AC_PROG_GREP + AX_PROGVAR([cmp]) + + AX_TRANSFORM_PACKAGE_NAME + +]) diff --git a/build-aux/git_version.am b/build-aux/git_version.am new file mode 100644 index 000000000..17bbe6659 --- /dev/null +++ b/build-aux/git_version.am @@ -0,0 +1,35 @@ +.SECONDEXPANSION: + +# EXTRA_@PACKAGE_VAR@_SOURCES += .version +EXTRA_DIST += build-aux/git-version-gen +BUILT_SOURCES += .version +CLEANFILES += .version .version-prev + +_BRANCH_REF != $(AWK) '{print ".git/" $$2}' .git/HEAD 2>/dev/null ||: +.version: $(_BRANCH_REF) + @if [ -e "$(srcdir)/.tarball-version" ]; then \ + printf "$(VERSION)" > $@; \ + else \ + touch "$@-prev"; \ + if [ -e "$@" ]; then \ + cp "$@" "$@-prev"; \ + fi; \ + ./build-aux/git-version-gen "$(srcdir)/.tarball-version" > $@; \ + $(CMP) -s "$@" "$@-prev" || autoreconf configure.ac --force; \ + fi + +check-version: check-git-version + +.PHONY: check-git-version +check-git-version: $(PACKAGE_NAME)$(EXEEXT) | .version + $(GREP) -Fx '$(VERSION)' $| + ./$< --version | $(GREP) -Ff $| + +installcheck-local-version: + ./$(TRANSFORMED_PACKAGE_NAME)$(EXEEXT) --version + +dist-hook: dist-tarball-version + +.PHONY: dist-tarball-version +dist-tarball-version: + printf "$(VERSION)" > "$(distdir)/.tarball-version" diff --git a/configure.ac b/configure.ac index 7b4b3c4af..cb1946a12 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,8 @@ AC_CONFIG_MACRO_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign tar-pax dist-xz dist-zip no-dist-gzip color-tests subdir-objects]) AM_SILENT_RULES([yes]) +AX_GIT_VERSION + AM_CONDITIONAL([IS_SDIST], [test ! -e .gitignore]) # Checks for programs. @@ -14,9 +16,6 @@ AC_PROG_OBJC AC_PROG_AWK AC_PROG_GREP AC_PROG_SED - -AX_PROGVAR([cmp]) -AX_PROGVAR([git]) AX_PROGVAR([find]) LT_PREREQ([2.2]) @@ -201,6 +200,7 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ ]) AM_COND_IF([DEVELOPER], [ + AX_PROGVAR([git]) AX_PROGVAR([busted]) AX_PROGVAR([luacheck]) AX_PROGVAR([luarocks]) From 328f88ab109bee6c71ea5a872af9a1ff5158db4f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 13:10:40 +0300 Subject: [PATCH 078/357] chore(tooling): Move package renaming stuff to reusable macro --- build-aux/ax_subst_transformed_package_name.m4 | 5 ----- build-aux/ax_transform_package_name.m4 | 18 ++++++++++++++++++ configure.ac | 3 +-- 3 files changed, 19 insertions(+), 7 deletions(-) delete mode 100644 build-aux/ax_subst_transformed_package_name.m4 create mode 100644 build-aux/ax_transform_package_name.m4 diff --git a/build-aux/ax_subst_transformed_package_name.m4 b/build-aux/ax_subst_transformed_package_name.m4 deleted file mode 100644 index a6ae77472..000000000 --- a/build-aux/ax_subst_transformed_package_name.m4 +++ /dev/null @@ -1,5 +0,0 @@ -AC_DEFUN([AX_SUBST_TRANSFORMED_PACKAGE_NAME], [ - AC_PROG_SED - TRANSFORMED_PACKAGE_NAME="$(printf "$PACKAGE_NAME" | $SED -e "$(printf "$program_transform_name" | $SED -e 's/\$\$/\$/')")" - AC_SUBST([TRANSFORMED_PACKAGE_NAME]) -]) diff --git a/build-aux/ax_transform_package_name.m4 b/build-aux/ax_transform_package_name.m4 new file mode 100644 index 000000000..0ff3298ca --- /dev/null +++ b/build-aux/ax_transform_package_name.m4 @@ -0,0 +1,18 @@ +# The autotools supplied AC_ARG_PROGAM enables renaming operations, but it +# supplies them as a sed operation that can be applied to multiple binaries. +# This isn't convenient to use if we're just renaming the top level package, so +# we go ahead and *do* the transformation and save for use as a substitution. + +AC_DEFUN_ONCE([AX_TRANSFORM_PACKAGE_NAME], [ + + AC_PROG_SED + + TRANSFORMED_PACKAGE_NAME="$(printf "$PACKAGE_NAME" | $SED -e "$(printf "$program_transform_name" | $SED -e 's/\$\$/\$/')")" + AC_SUBST([TRANSFORMED_PACKAGE_NAME]) + + PACKAGE_VAR="$(printf "$PACKAGE_NAME" | $SED -e "s/-/_/g")" + AC_SUBST([PACKAGE_VAR]) + + AC_ARG_PROGRAM + +]) diff --git a/configure.ac b/configure.ac index cb1946a12..13ec34f38 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,7 @@ AM_INIT_AUTOMAKE([foreign tar-pax dist-xz dist-zip no-dist-gzip color-tests subd AM_SILENT_RULES([yes]) AX_GIT_VERSION +AX_TRANSFORM_PACKAGE_NAME AM_CONDITIONAL([IS_SDIST], [test ! -e .gitignore]) @@ -296,8 +297,6 @@ esac AC_SUBST([SHARED_LIB_EXT]) AC_SUBST([LUAROCKSARGS]) -AX_SUBST_TRANSFORMED_PACKAGE_NAME - # Avoid need for `--datarootdir=$(cd ..; pwd)` hack to run locally for # tests/manual build when developer mode is enabled AM_COND_IF([DEVELOPER], [ From 5df7ff8653178b4fbbbfee266e8c3d7b9b2daf2c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 21 Sep 2023 01:50:57 +0300 Subject: [PATCH 079/357] chore(cli): Fall back to build time configured data dir, not SILE_PATH --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 673d458a5..6429ce2c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ pub fn version() -> crate::Result { let lua = unsafe { Lua::unsafe_new() }; let sile_path = match env::var("SILE_PATH") { Ok(val) => val, - Err(_) => env!("SILE_PATH").to_string(), + Err(_) => env!("CONFIGURE_DATADIR").to_string(), }; let sile_path: LuaString = lua.create_string(&sile_path)?; let sile: LuaTable = lua @@ -49,7 +49,7 @@ pub fn run( let lua = unsafe { Lua::unsafe_new() }; let sile_path = match env::var("SILE_PATH") { Ok(val) => val, - Err(_) => env!("SILE_PATH").to_string(), + Err(_) => env!("CONFIGURE_DATADIR").to_string(), }; let sile_path: LuaString = lua.create_string(&sile_path)?; let sile: LuaTable = lua From 7ff19c9d28a1235f4bc780d993270d9c1e7b4b00 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 13 Sep 2023 13:10:40 +0300 Subject: [PATCH 080/357] chore(tooling): Move Rust build tooling that can be shared to build-aux --- Makefile.am | 99 +++------------------------- bootstrap.sh | 7 ++ build-aux/ax_rust_boilerplate.m4 | 92 ++++++++++++++++++++++++++ build-aux/build.rs | 2 +- build-aux/rust_boilerplate.am.in | 107 +++++++++++++++++++++++++++++++ configure.ac | 62 +----------------- 6 files changed, 216 insertions(+), 153 deletions(-) create mode 100644 build-aux/ax_rust_boilerplate.m4 create mode 100644 build-aux/rust_boilerplate.am.in diff --git a/Makefile.am b/Makefile.am index 0aac17f43..11827ebbd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,9 +55,9 @@ $(MANUAL): $(FIGURES) bin_PROGRAMS = sile bin_SCRIPTS = sile-lua -dist_man_MANS = sile.1 sile-lua.1 -sile_SOURCES = Cargo.toml build-aux/build.rs src/bin/sile.rs src/lib.rs src/cli.rs -EXTRA_sile_SOURCES = Cargo.lock +dist_man_MANS = sile-lua.1 +sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs +EXTRA_sile_SOURCES = nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = core/features.lua core/pathsetup.lua core/version.lua $(LUAMODULES) dist_doc_DATA = README.md CHANGELOG.md @@ -73,19 +73,14 @@ EXTRA_DIST += $(MANUAL) $(FIGURES) BUILT_SOURCES = core/features.lua core/pathsetup.lua core/version.lua Makefile-distfiles -CLEANFILES = $(bin_SCRIPTS) $(dist_man_MANS) $(BUILT_SOURCES) $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) +CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) include $(top_srcdir)/build-aux/git_version.am +include $(top_srcdir)/build-aux/rust_boilerplate.am Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ -if DEBUG_RELEASE -CARGO_RELEASE_ARGS = -else -CARGO_RELEASE_ARGS = --release --locked -endif - if LUAJIT MLUAVER = luajit else @@ -97,76 +92,9 @@ DEPDIR := .deps LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig -CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target -RUST_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) -_RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir -COMPLETIONS_OUT_DIR = completions - -if ENABLE_BASH_COMPLETION -bashcompletiondir = $(BASH_COMPLETION_DIR) -nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) -CLEANFILES += $(nodist_bashcompletion_DATA) -endif - -if ENABLE_FISH_COMPLETION -fishcompletiondir = $(FISH_COMPLETION_DIR) -nodist_fishcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish -CLEANFILES += $(nodist_fishcompletion_DATA) -endif - -if ENABLE_ZSH_COMPLETION -zshcompletiondir = $(ZSH_COMPLETION_DIR) -nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) -CLEANFILES += $(nodist_zshcompletion_DATA) -endif - -export SILE_VERSION = v$(VERSION) -SILE := $(PACKAGE_NAME)$(EXEEXT) - -# Leave some tips for cargo to use so CLI knows where it is -export CONFIGURE_PREFIX = $(prefix)/ -export CONFIGURE_DATADIR = $(datadir)/ -export CONFIGURE_BINDIR = $(bindir)/ - -CARGO_VERBOSE = $(cargo_verbose_$(V)) -cargo_verbose_ = $(cargo_verbose_$(AM_DEFAULT_VERBOSITY)) -cargo_verbose_0 = -cargo_verbose_1 = --verbose - -$(COMPLETIONS_OUT_DIR): - $(MKDIR_P) $@ - -$(SILE): $(RUST_BIN) - $(INSTALL) $(RUST_BIN) $@ - -$(PACKAGE_NAME).1: $(RUST_BIN) - $(INSTALL) -m644 $$(cat $(_RUST_OUT))/$@ $@ - -$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).bash $@ - -$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).elv: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).elv $@ - -$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).fish $@ - -$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME).ps1: $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME).ps1 $@ - -$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(RUST_BIN) | $(COMPLETIONS_OUT_DIR) - $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ - -$(_RUST_OUT) $(RUST_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) - cd $(top_srcdir) - $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) - $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | - $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) - dist-hook: $(MANUAL) dist-hook-distfiles .PHONY: dist-hook-distfiles - dist-hook-distfiles: cd $(distdir) $(SED) -i -e '/^LUAMODULES =/s/=.*/=/' Makefile-distfiles @@ -245,7 +173,7 @@ patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(bin_PROGRAMS) $(DEPDIRS .PHONY: force force: ; -PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck rustfmt clippy cargo-test busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm +PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm .PHONY: $(PHONY_DEVELOPER_TARGETS) if DEVELOPER @@ -291,9 +219,9 @@ BUSTEDFLAGS ?= regressions: $(TESTSRCS) $(ACTUALS) $(LOCALFONTS) $(REGRESSIONSCRIPT) $(TESTSRCS) -test: regressions busted cargo-test +test: regressions busted -lint: luacheck luarocks-lint rustfmt clippy +lint: luacheck luarocks-lint luarocks-lint: $(LUAMODSPEC) $(LUAROCKS) lint $(LUAMODSPEC) @@ -301,17 +229,6 @@ luarocks-lint: $(LUAMODSPEC) luacheck: $(LUACHECK) -j$(shell nproc) -q . -rustfmt: - $(GIT) ls-files '*.rs' | $(XARGS) rustfmt --check - -clippy: - cd $(srcdir) - $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clippy $(CARGO_FEATURE_ARGS) -- -D warnings - -cargo-test: $(SILE) - cd $(srcdir) - $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) test $(CARGO_FEATURE_ARGS) --locked - busted: $(SILELUA) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) set -f; IFS=';' if SYSTEM_LUAROCKS diff --git a/bootstrap.sh b/bootstrap.sh index 3e2165b3e..7bc7b1c24 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -35,6 +35,13 @@ else ./build-aux/git-version-gen .tarball-version > .version fi +# Autoreconf uses a perl script to inline includes from Makefile.am into +# Makefile.in before ./configure is even run ... which is where we're going to +# use AC_SUBST to setup project specific build options. We need to pre-seed +# a file to avoid a file not found error on first run. The configure process +# will rebuild this and also re-include it into the final Makefile. +touch build-aux/rust_boilerplate.am + autoreconf --install # See discussion in https://github.com/sile-typesetter/sile/issues/82 and diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 new file mode 100644 index 000000000..46dffdd97 --- /dev/null +++ b/build-aux/ax_rust_boilerplate.m4 @@ -0,0 +1,92 @@ +AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ + + AX_TRANSFORM_PACKAGE_NAME + + AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], + [Build Rust code with debugging information])) + AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"]) + + AC_ARG_ENABLE([dependency-checks], + AS_HELP_STRING([--disable-dependency-checks], + [Disable build tooling dependency checks])) + AM_CONDITIONAL([DEPENDENCY_CHECKS], [test "x$enable_dependency_checks" != "xno"]) + + AC_ARG_ENABLE([developer], + AS_HELP_STRING([--enable-developer], + [Check for and enable tooling required only for developers])) + AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) + + AC_MSG_NOTICE([checking for tools used by automake to build Rust projects]) + AM_COND_IF([DEPENDENCY_CHECKS], [ + AC_PROG_INSTALL + AX_PROGVAR([cargo]) + AX_PROGVAR([jq]) + AX_PROGVAR([rustc]) + AX_PROGVAR([git]) + AX_PROGVAR([cmp]) + AX_PROGVAR([xargs]) + AM_COND_IF([DEVELOPER], [ + AX_PROGVAR([rustfmt]) + ]) + ]) + + AC_MSG_CHECKING([whether to build Rust code with debugging information]) + AM_COND_IF([DEBUG_RELEASE], [ + AC_MSG_RESULT(yes) + RUST_TARGET_SUBDIR=debug + ], [ + AC_MSG_RESULT(no) + RUST_TARGET_SUBDIR=release + ]) + AC_SUBST([RUST_TARGET_SUBDIR]) + + AC_ARG_WITH([bash-completion-dir], + AS_HELP_STRING([--with-bash-completion-dir[=PATH]], + [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_bash_completion_dir=yes]) + AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) + + AM_COND_IF([ENABLE_BASH_COMPLETION], [ + PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], + [BASH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion)"], + [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) + ], [ + BASH_COMPLETION_DIR="$with_bash_completion_dir" + ]) + AC_SUBST([BASH_COMPLETION_DIR]) + + AC_ARG_WITH([fish-completion-dir], + AS_HELP_STRING([--with-fish-completion-dir[=PATH]], + [Install the fish auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_fish_completion_dir=yes]) + AM_CONDITIONAL([ENABLE_FISH_COMPLETION],[test "x$with_fish_completion_dir" != "xno"]) + + AM_COND_IF([ENABLE_FISH_COMPLETION], [ + PKG_CHECK_MODULES([FISH_COMPLETION], [fish >= 3.0], + [FISH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir fish)"], + [FISH_COMPLETION_DIR="$datadir/fish/vendor_completions.d"]) + ], [ + FISH_COMPLETION_DIR="$with_fish_completion_dir" + ]) + AC_SUBST([FISH_COMPLETION_DIR]) + + AC_ARG_WITH([zsh-completion-dir], + AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], + [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_zsh_completion_dir=yes]) + AM_CONDITIONAL([ENABLE_ZSH_COMPLETION],[test "x$with_zsh_completion_dir" != "xno"]) + + AM_COND_IF([ENABLE_ZSH_COMPLETION], [ + ZSH_COMPLETION_DIR="$datadir/zsh/site-functions" + ], [ + ZSH_COMPLETION_DIR="$with_zsh_completion_dir" + ]) + AC_SUBST([ZSH_COMPLETION_DIR]) + + AC_CONFIG_FILES([build-aux/rust_boilerplate.am]) + +]) diff --git a/build-aux/build.rs b/build-aux/build.rs index a698a8166..5b1945085 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -16,7 +16,7 @@ include!("../src/cli.rs"); fn main() { let mut flags = Config::default(); - if let Ok(val) = env::var("SILE_VERSION") { + if let Ok(val) = env::var("VERSION_FROM_AUTOTOOLS") { *flags.git_mut().semver_mut() = false; println!("cargo:rustc-env=VERGEN_GIT_SEMVER={val}") }; diff --git a/build-aux/rust_boilerplate.am.in b/build-aux/rust_boilerplate.am.in new file mode 100644 index 000000000..96ca1fa70 --- /dev/null +++ b/build-aux/rust_boilerplate.am.in @@ -0,0 +1,107 @@ +export VERSION_FROM_AUTOTOOLS = v$(VERSION) + +@PACKAGE_VAR@_SOURCES += Cargo.toml build-aux/build.rs +EXTRA_@PACKAGE_VAR@_SOURCES += Cargo.lock .version +dist_man_MANS += @PACKAGE_NAME@.1 + +CLEANFILES += $(bin_PROGRAMS) $(BUILT_SOURCES) $(dist_man_MANS) + +CARGO_RELEASE_ARGS = +if !DEBUG_RELEASE +CARGO_RELEASE_ARGS += --release --locked +endif + +CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target +CARGO_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) +_RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir +COMPLETIONS_OUT_DIR = completions + +@PACKAGE_NAME@$(EXEEXT): $(CARGO_BIN) + $(INSTALL) $< $@ + +if ENABLE_BASH_COMPLETION +bashcompletiondir = $(BASH_COMPLETION_DIR) +nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_bashcompletion_DATA) +endif + +if ENABLE_FISH_COMPLETION +fishcompletiondir = $(FISH_COMPLETION_DIR) +nodist_fishcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish +CLEANFILES += $(nodist_fishcompletion_DATA) +endif + +if ENABLE_ZSH_COMPLETION +zshcompletiondir = $(ZSH_COMPLETION_DIR) +nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_zshcompletion_DATA) +endif + +# Leave some tips for cargo to use so CLI knows where it is +export CONFIGURE_PREFIX = $(prefix)/ +export CONFIGURE_DATADIR = $(datadir)/ +export CONFIGURE_BINDIR = $(bindir)/ + +CARGO_VERBOSE = $(cargo_verbose_$(V)) +cargo_verbose_ = $(cargo_verbose_$(AM_DEFAULT_VERBOSITY)) +cargo_verbose_0 = +cargo_verbose_1 = --verbose + +$(COMPLETIONS_OUT_DIR): + $(MKDIR_P) $@ + +$(PACKAGE_NAME).1: $(CARGO_BIN) + $(INSTALL) -m644 $$(cat $(_RUST_OUT))/$@ $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME): $(CARGO_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).bash $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).elv: $(CARGO_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).elv $@ + +$(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish: $(CARGO_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/$(PACKAGE_NAME).fish $@ + +$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME).ps1: $(CARGO_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME).ps1 $@ + +$(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(CARGO_BIN) | $(COMPLETIONS_OUT_DIR) + $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ + +$(_RUST_OUT) $(CARGO_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) + cd $(top_srcdir) + $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) + $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | + $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) + +RUST_DEVELOPER_TARGETS = cargo-test clippy installcheck-local-version rustfmt +.PHONY: $(RUST_DEVELOPER_TARGETS) + +if DEVELOPER + +test: cargo-test +lint: rustfmt clippy +clean-local: clean-cargo +check-local: cargo-test + +rustfmt: + $(GIT) ls-files '*.rs' | $(XARGS) $(RUSTFMT) --check + +clippy: + cd $(srcdir) + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clippy $(CARGO_FEATURE_ARGS) -- -D warnings + +clean-cargo: + cd $(top_srcdir) + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clean + +cargo-test: $(PACKAGE_NAME)$(EXEEXT) + cd $(srcdir) + $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) test $(CARGO_FEATURE_ARGS) --locked + +else !DEVELOPER + +$(RUST_DEVELOPER_TARGETS): + @: $(error "Please reconfigure using --enable-developer to use developer tooling") + +endif !DEVELOPER diff --git a/configure.ac b/configure.ac index 13ec34f38..5553ec585 100644 --- a/configure.ac +++ b/configure.ac @@ -24,11 +24,7 @@ LT_INIT([dlopen]) AC_CANONICAL_HOST -AC_ARG_ENABLE(debug, - AS_HELP_STRING([--enable-debug],[Build Rust code with debugging information [default=no]]), - [debug_release=$enableval], - [debug_release=no]) -AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"]) +AX_RUST_BOILERPLATE AC_ARG_ENABLE([dependency-checks], AS_HELP_STRING([--disable-dependency-checks], @@ -209,63 +205,7 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_PROGVAR([perl]) ]) - AX_PROGVAR([cargo]) - AX_PROGVAR([rustc]) - -]) - -AC_MSG_CHECKING(whether to build Rust code with debugging information) -AM_COND_IF([DEBUG_RELEASE], [ - AC_MSG_RESULT(yes) - RUST_TARGET_SUBDIR=debug -], [ - AC_MSG_RESULT(no) - RUST_TARGET_SUBDIR=release ]) -AC_SUBST([RUST_TARGET_SUBDIR]) - -AC_ARG_WITH([bash-completion-dir], - AS_HELP_STRING([--with-bash-completion-dir[=PATH]], - [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), - [], - [with_bash_completion_dir=yes]) -if test "x$with_bash_completion_dir" = "xyes"; then - PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], - [BASH_COMPLETION_DIR="`pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion`"], - [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) - else - BASH_COMPLETION_DIR="$with_bash_completion_dir" -fi -AC_SUBST([BASH_COMPLETION_DIR]) -AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) - -AC_ARG_WITH([fish-completion-dir], - AS_HELP_STRING([--with-fish-completion-dir[=PATH]], - [Install the fish auto-completion script in this directory. @<:@default=yes@:>@]), - [], - [with_fish_completion_dir=yes]) -if test "x$with_fish_completion_dir" = "xyes"; then - PKG_CHECK_MODULES([FISH_COMPLETION], [fish >= 3.0], - [FISH_COMPLETION_DIR="`pkg-config --define-variable=datadir=$datadir --variable=completionsdir fish`"], - [FISH_COMPLETION_DIR="$datadir/fish/vendor_completions.d"]) - else - FISH_COMPLETION_DIR="$with_fish_completion_dir" -fi -AC_SUBST([FISH_COMPLETION_DIR]) -AM_CONDITIONAL([ENABLE_FISH_COMPLETION],[test "x$with_fish_completion_dir" != "xno"]) - -AC_ARG_WITH([zsh-completion-dir], - AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], - [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), - [], - [with_zsh_completion_dir=yes]) -if test "x$with_zsh_completion_dir" = "xyes"; then - ZSH_COMPLETION_DIR="$datadir/zsh/site-functions" -else - ZSH_COMPLETION_DIR="$with_zsh_completion_dir" -fi -AC_SUBST([ZSH_COMPLETION_DIR]) -AM_CONDITIONAL([ENABLE_ZSH_COMPLETION],[test "x$with_zsh_completion_dir" != "xno"]) AM_CONDITIONAL([APPKIT], [test "x$have_appkit" = "xyes"]) AM_CONDITIONAL([ICU], [test "x$with_icu" = "xyes"]) From 8ee4663f8d9bbdefa19991cf2358cc2b8e08f6f2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 21 Sep 2023 14:50:22 +0300 Subject: [PATCH 081/357] refactor(build): Move shell completion configuration to shared macros --- .gitignore | 1 + Makefile.am | 1 - build-aux/ax_rust_boilerplate.m4 | 47 +-------------------------- build-aux/ax_shell_completion_dirs.m4 | 47 +++++++++++++++++++++++++++ build-aux/rust_boilerplate.am.in | 22 ++----------- build-aux/shell_completion_dirs.am | 19 +++++++++++ 6 files changed, 71 insertions(+), 66 deletions(-) create mode 100644 build-aux/ax_shell_completion_dirs.m4 create mode 100644 build-aux/shell_completion_dirs.am diff --git a/.gitignore b/.gitignore index 916392aac..aab2af785 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ build-aux/ltversion.m4 build-aux/lt~obsolete.m4 build-aux/missing build-aux/list-dist-files.sh +build-aux/rust_boilerplate.am tests/regressions.pl # Other autojunk diff --git a/Makefile.am b/Makefile.am index 11827ebbd..e50dc9138 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,7 +75,6 @@ BUILT_SOURCES = core/features.lua core/pathsetup.lua core/version.lua Makefile-d CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) -include $(top_srcdir)/build-aux/git_version.am include $(top_srcdir)/build-aux/rust_boilerplate.am Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 index 46dffdd97..331c979d2 100644 --- a/build-aux/ax_rust_boilerplate.m4 +++ b/build-aux/ax_rust_boilerplate.m4 @@ -1,6 +1,7 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ AX_TRANSFORM_PACKAGE_NAME + AX_SHELL_COMPLETION_DIRS AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], @@ -41,52 +42,6 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ ]) AC_SUBST([RUST_TARGET_SUBDIR]) - AC_ARG_WITH([bash-completion-dir], - AS_HELP_STRING([--with-bash-completion-dir[=PATH]], - [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), - [], - [with_bash_completion_dir=yes]) - AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) - - AM_COND_IF([ENABLE_BASH_COMPLETION], [ - PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], - [BASH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion)"], - [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) - ], [ - BASH_COMPLETION_DIR="$with_bash_completion_dir" - ]) - AC_SUBST([BASH_COMPLETION_DIR]) - - AC_ARG_WITH([fish-completion-dir], - AS_HELP_STRING([--with-fish-completion-dir[=PATH]], - [Install the fish auto-completion script in this directory. @<:@default=yes@:>@]), - [], - [with_fish_completion_dir=yes]) - AM_CONDITIONAL([ENABLE_FISH_COMPLETION],[test "x$with_fish_completion_dir" != "xno"]) - - AM_COND_IF([ENABLE_FISH_COMPLETION], [ - PKG_CHECK_MODULES([FISH_COMPLETION], [fish >= 3.0], - [FISH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir fish)"], - [FISH_COMPLETION_DIR="$datadir/fish/vendor_completions.d"]) - ], [ - FISH_COMPLETION_DIR="$with_fish_completion_dir" - ]) - AC_SUBST([FISH_COMPLETION_DIR]) - - AC_ARG_WITH([zsh-completion-dir], - AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], - [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), - [], - [with_zsh_completion_dir=yes]) - AM_CONDITIONAL([ENABLE_ZSH_COMPLETION],[test "x$with_zsh_completion_dir" != "xno"]) - - AM_COND_IF([ENABLE_ZSH_COMPLETION], [ - ZSH_COMPLETION_DIR="$datadir/zsh/site-functions" - ], [ - ZSH_COMPLETION_DIR="$with_zsh_completion_dir" - ]) - AC_SUBST([ZSH_COMPLETION_DIR]) - AC_CONFIG_FILES([build-aux/rust_boilerplate.am]) ]) diff --git a/build-aux/ax_shell_completion_dirs.m4 b/build-aux/ax_shell_completion_dirs.m4 new file mode 100644 index 000000000..1545cfd94 --- /dev/null +++ b/build-aux/ax_shell_completion_dirs.m4 @@ -0,0 +1,47 @@ +AC_DEFUN_ONCE([AX_SHELL_COMPLETION_DIRS], [ + + AX_TRANSFORM_PACKAGE_NAME + + AC_ARG_WITH([bash-completion-dir], + AS_HELP_STRING([--with-bash-completion-dir[=PATH]], + [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_bash_completion_dir=yes]) + AM_CONDITIONAL([ENABLE_BASH_COMPLETION], + [test "x$with_bash_completion_dir" != "xno"]) + + AM_COND_IF([ENABLE_BASH_COMPLETION], + [PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], + [BASH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion)"], + [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"])], + [BASH_COMPLETION_DIR="$with_bash_completion_dir"]) + AC_SUBST([BASH_COMPLETION_DIR]) + + AC_ARG_WITH([fish-completion-dir], + AS_HELP_STRING([--with-fish-completion-dir[=PATH]], + [Install the fish auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_fish_completion_dir=yes]) + AM_CONDITIONAL([ENABLE_FISH_COMPLETION],[test "x$with_fish_completion_dir" != "xno"]) + + AM_COND_IF([ENABLE_FISH_COMPLETION], + [PKG_CHECK_MODULES([FISH_COMPLETION], [fish >= 3.0], + [FISH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir fish)"], + [FISH_COMPLETION_DIR="$datadir/fish/vendor_completions.d"])], + [FISH_COMPLETION_DIR="$with_fish_completion_dir"]) + AC_SUBST([FISH_COMPLETION_DIR]) + + AC_ARG_WITH([zsh-completion-dir], + AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], + [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_zsh_completion_dir=yes]) + AM_CONDITIONAL([ENABLE_ZSH_COMPLETION], + [test "x$with_zsh_completion_dir" != "xno"]) + + AM_COND_IF([ENABLE_ZSH_COMPLETION], + [ZSH_COMPLETION_DIR="$datadir/zsh/site-functions"], + [ZSH_COMPLETION_DIR="$with_zsh_completion_dir"]) + AC_SUBST([ZSH_COMPLETION_DIR]) + +]) diff --git a/build-aux/rust_boilerplate.am.in b/build-aux/rust_boilerplate.am.in index 96ca1fa70..c87ac4164 100644 --- a/build-aux/rust_boilerplate.am.in +++ b/build-aux/rust_boilerplate.am.in @@ -14,29 +14,13 @@ endif CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target CARGO_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) _RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir -COMPLETIONS_OUT_DIR = completions + +include $(top_srcdir)/build-aux/git_version.am +include $(top_srcdir)/build-aux/shell_completion_dirs.am @PACKAGE_NAME@$(EXEEXT): $(CARGO_BIN) $(INSTALL) $< $@ -if ENABLE_BASH_COMPLETION -bashcompletiondir = $(BASH_COMPLETION_DIR) -nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) -CLEANFILES += $(nodist_bashcompletion_DATA) -endif - -if ENABLE_FISH_COMPLETION -fishcompletiondir = $(FISH_COMPLETION_DIR) -nodist_fishcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish -CLEANFILES += $(nodist_fishcompletion_DATA) -endif - -if ENABLE_ZSH_COMPLETION -zshcompletiondir = $(ZSH_COMPLETION_DIR) -nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) -CLEANFILES += $(nodist_zshcompletion_DATA) -endif - # Leave some tips for cargo to use so CLI knows where it is export CONFIGURE_PREFIX = $(prefix)/ export CONFIGURE_DATADIR = $(datadir)/ diff --git a/build-aux/shell_completion_dirs.am b/build-aux/shell_completion_dirs.am new file mode 100644 index 000000000..9f0f0cab7 --- /dev/null +++ b/build-aux/shell_completion_dirs.am @@ -0,0 +1,19 @@ +COMPLETIONS_OUT_DIR = completions + +if ENABLE_BASH_COMPLETION +bashcompletiondir = $(BASH_COMPLETION_DIR) +nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_bashcompletion_DATA) +endif + +if ENABLE_FISH_COMPLETION +fishcompletiondir = $(FISH_COMPLETION_DIR) +nodist_fishcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME).fish +CLEANFILES += $(nodist_fishcompletion_DATA) +endif + +if ENABLE_ZSH_COMPLETION +zshcompletiondir = $(ZSH_COMPLETION_DIR) +nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) +CLEANFILES += $(nodist_zshcompletion_DATA) +endif From c97ead9f8ef66fe3c08defa1ec6d13703ed6b557 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 21 Sep 2023 15:49:10 +0300 Subject: [PATCH 082/357] docs: Format license file with Markdown --- LICENSE | 21 --------------------- LICENSE.md | 25 +++++++++++++++++++++++++ Makefile.am | 4 ++-- 3 files changed, 27 insertions(+), 23 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSE.md diff --git a/LICENSE b/LICENSE deleted file mode 100644 index c1a6832f1..000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012-2022 Simon Cozens, Caleb Maclennan. - -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. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..2b0c94e73 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,25 @@ +The MIT License (MIT) +===================== + +Copyright © `2012-2023` `Simon Cozens, Caleb Maclennan` + +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. diff --git a/Makefile.am b/Makefile.am index e50dc9138..ad39bc1dd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,8 +10,8 @@ if SYSTEM_LIBTEXPDF SUBDIRS += libtexpdf endif -licensedir = $(datarootdir)/licenses/$(TRANSFORMED_PACKAGE_NAME) docdir = $(datarootdir)/doc/$(TRANSFORMED_PACKAGE_NAME) +licensedir = $(datarootdir)/licenses/$(TRANSFORMED_PACKAGE_NAME) datadir = $(datarootdir)/$(TRANSFORMED_PACKAGE_NAME) pkgdatadir = $(datadir) @@ -62,7 +62,7 @@ nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = core/features.lua core/pathsetup.lua core/version.lua $(LUAMODULES) dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) -dist_license_DATA = LICENSE +dist_license_DATA = LICENSE.md EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh From 3bac03ce6382d13e581641c09d357bb6ddd28d28 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 21 Sep 2023 22:55:28 +0300 Subject: [PATCH 083/357] chore(tooling): Use more editor friendly filename patters --- .editorconfig | 6 +++++- .gitignore | 2 +- Makefile.am | 2 +- bootstrap.sh | 2 +- build-aux/ax_rust_boilerplate.m4 | 2 +- build-aux/{git_version.am => git_version.mk} | 2 ++ .../{rust_boilerplate.am.in => rust_boilerplate.mk.in} | 6 ++++-- .../{shell_completion_dirs.am => shell_completion_dirs.mk} | 2 ++ 8 files changed, 17 insertions(+), 7 deletions(-) rename build-aux/{git_version.am => git_version.mk} (97%) rename build-aux/{rust_boilerplate.am.in => rust_boilerplate.mk.in} (96%) rename build-aux/{shell_completion_dirs.am => shell_completion_dirs.mk} (96%) diff --git a/.editorconfig b/.editorconfig index f935e92c5..90fd4bf03 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,6 +15,10 @@ max_line_length = 120 indent_style = space indent_size = 4 -[makefile*] +[*.m4] +indent_style = space +indent_size = 8 + +[{Makefile*,*.mk,*.mk.in] indent_style = tab indent_size = 4 diff --git a/.gitignore b/.gitignore index aab2af785..2ea55fa56 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ build-aux/ltversion.m4 build-aux/lt~obsolete.m4 build-aux/missing build-aux/list-dist-files.sh -build-aux/rust_boilerplate.am +build-aux/rust_boilerplate.mk tests/regressions.pl # Other autojunk diff --git a/Makefile.am b/Makefile.am index ad39bc1dd..252218fbf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,7 +75,7 @@ BUILT_SOURCES = core/features.lua core/pathsetup.lua core/version.lua Makefile-d CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) -include $(top_srcdir)/build-aux/rust_boilerplate.am +include $(top_srcdir)/build-aux/rust_boilerplate.mk Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ diff --git a/bootstrap.sh b/bootstrap.sh index 7bc7b1c24..07eaf4c6a 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -40,7 +40,7 @@ fi # use AC_SUBST to setup project specific build options. We need to pre-seed # a file to avoid a file not found error on first run. The configure process # will rebuild this and also re-include it into the final Makefile. -touch build-aux/rust_boilerplate.am +touch build-aux/rust_boilerplate.mk autoreconf --install diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 index 331c979d2..8ab21fd69 100644 --- a/build-aux/ax_rust_boilerplate.m4 +++ b/build-aux/ax_rust_boilerplate.m4 @@ -42,6 +42,6 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ ]) AC_SUBST([RUST_TARGET_SUBDIR]) - AC_CONFIG_FILES([build-aux/rust_boilerplate.am]) + AC_CONFIG_FILES([build-aux/rust_boilerplate.mk]) ]) diff --git a/build-aux/git_version.am b/build-aux/git_version.mk similarity index 97% rename from build-aux/git_version.am rename to build-aux/git_version.mk index 17bbe6659..58e16119f 100644 --- a/build-aux/git_version.am +++ b/build-aux/git_version.mk @@ -33,3 +33,5 @@ dist-hook: dist-tarball-version .PHONY: dist-tarball-version dist-tarball-version: printf "$(VERSION)" > "$(distdir)/.tarball-version" + +# vim: ft=automake diff --git a/build-aux/rust_boilerplate.am.in b/build-aux/rust_boilerplate.mk.in similarity index 96% rename from build-aux/rust_boilerplate.am.in rename to build-aux/rust_boilerplate.mk.in index c87ac4164..a9c5a8eec 100644 --- a/build-aux/rust_boilerplate.am.in +++ b/build-aux/rust_boilerplate.mk.in @@ -15,8 +15,8 @@ CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target CARGO_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) _RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir -include $(top_srcdir)/build-aux/git_version.am -include $(top_srcdir)/build-aux/shell_completion_dirs.am +include $(top_srcdir)/build-aux/git_version.mk +include $(top_srcdir)/build-aux/shell_completion_dirs.mk @PACKAGE_NAME@$(EXEEXT): $(CARGO_BIN) $(INSTALL) $< $@ @@ -89,3 +89,5 @@ $(RUST_DEVELOPER_TARGETS): @: $(error "Please reconfigure using --enable-developer to use developer tooling") endif !DEVELOPER + +# vim: ft=automake diff --git a/build-aux/shell_completion_dirs.am b/build-aux/shell_completion_dirs.mk similarity index 96% rename from build-aux/shell_completion_dirs.am rename to build-aux/shell_completion_dirs.mk index 9f0f0cab7..5e29abbe7 100644 --- a/build-aux/shell_completion_dirs.am +++ b/build-aux/shell_completion_dirs.mk @@ -17,3 +17,5 @@ zshcompletiondir = $(ZSH_COMPLETION_DIR) nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) CLEANFILES += $(nodist_zshcompletion_DATA) endif + +# vim: ft=automake From 5e587bdb2574f1e385fe24a1826bdbdb2e4c5253 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 22 Sep 2023 23:10:03 +0300 Subject: [PATCH 084/357] fix(build): Move build-time dependency checks out of runtime dep check configure flag --- build-aux/ax_rust_boilerplate.m4 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 index 8ab21fd69..12ccecde4 100644 --- a/build-aux/ax_rust_boilerplate.m4 +++ b/build-aux/ax_rust_boilerplate.m4 @@ -19,15 +19,15 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) AC_MSG_NOTICE([checking for tools used by automake to build Rust projects]) + AC_PROG_INSTALL + AX_PROGVAR([cargo]) + AX_PROGVAR([jq]) + AX_PROGVAR([rustc]) + AX_PROGVAR([cmp]) + AX_PROGVAR([xargs]) AM_COND_IF([DEPENDENCY_CHECKS], [ - AC_PROG_INSTALL - AX_PROGVAR([cargo]) - AX_PROGVAR([jq]) - AX_PROGVAR([rustc]) - AX_PROGVAR([git]) - AX_PROGVAR([cmp]) - AX_PROGVAR([xargs]) AM_COND_IF([DEVELOPER], [ + AX_PROGVAR([git]) AX_PROGVAR([rustfmt]) ]) ]) From 0b29ae9b0f8018c90974746e5fac364b7c846815 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 25 Sep 2023 13:26:33 +0300 Subject: [PATCH 085/357] chore(deps): Document current MSRV in Cargo.toml Documenting it should help in the future analizing what release tags should be and whether or not to dump dependencies. Technically the current limit would be 1.64.0, a limitation inherited from `clap_builder` and `clap`. While we could adapt to support that version, the linting rules we are using require 1.71.0. Since we're just coming out with Rust support I don't feel bad at all about making it a pretty new version. Hopefully that will give us a little breathing room before we have to do major bumps to support MSRV bumps. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5d7a07569..a5c7f04c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "sile" version = "0.14.8" edition = "2021" +rust-version = "1.71.0" description = "Simon’s Improved Layout Engine" authors = [ "Simon Cozens", @@ -9,7 +10,6 @@ authors = [ "Olivier Nicole", "Didier Willis" ] -rust-version = "1.68" homepage = "https://sile-typesetter.org" license = "MIT" build = "build-aux/build.rs" From 9928c5aa87e2625a05b4130746a821ccd43b1f89 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 25 Sep 2023 14:34:33 +0300 Subject: [PATCH 086/357] chore(tooling): Update husky hooks sticking with npm --- .gitignore | 1 - .husky/.gitignore | 1 - .husky/commit-msg | 6 +++--- .husky/pre-commit | 2 -- 4 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 .husky/.gitignore delete mode 100755 .husky/pre-commit diff --git a/.gitignore b/.gitignore index 916392aac..d47ad3f7a 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,6 @@ node_modules lua_modules lua_modules_dist package-lock.json -yarn.lock # Editor entrails .vscode/ diff --git a/.husky/.gitignore b/.husky/.gitignore deleted file mode 100644 index 31354ec13..000000000 --- a/.husky/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_ diff --git a/.husky/commit-msg b/.husky/commit-msg index d71a03b9f..b56767669 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1,4 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" -yarn commitlint --edit $1 +npx --no -- commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 6700f5128..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" From d8d14409a6076f3a765d5bd7be907e47ed0492d9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 22 Sep 2023 00:50:58 +0300 Subject: [PATCH 087/357] chore(tooling): Restyle to cope with editor-config lints --- .editorconfig | 25 +++++++++++++++++-------- build-aux/adl_recursive_eval.m4 | 23 +++++++++++++---------- build-aux/ax_build_date_epoch.m4 | 25 +++++++++++-------------- build-aux/ax_font.m4 | 30 +++++++++++++++--------------- build-aux/ax_progvar.m4 | 6 +++--- build-aux/ax_subst_man_date.m4 | 22 +++++++++++----------- 6 files changed, 70 insertions(+), 61 deletions(-) diff --git a/.editorconfig b/.editorconfig index 90fd4bf03..c8de8f6b5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,19 +6,28 @@ insert_final_newline = true charset = utf-8 trim_trailing_whitespace = true +[{Makefile*,*.mk,*.mk.in}] +indent_style = tab +indent_size = 4 + +[*.m4] +indent_style = space +indent_size = 8 + +[*.md] +trim_trailing_whitespace = false + [{*.lua,*.lua.in,sile.in,*rockspec,.busted,.luacheckrc}] indent_style = space -indent_size = 2 +indent_size = 3 max_line_length = 120 -[*.pl] -indent_style = space -indent_size = 4 +[*rockspec] +max_line_length = 190 -[*.m4] +[*.pl] indent_style = space -indent_size = 8 +indent_size = 2 -[{Makefile*,*.mk,*.mk.in] -indent_style = tab +[*.rs] indent_size = 4 diff --git a/build-aux/adl_recursive_eval.m4 b/build-aux/adl_recursive_eval.m4 index 71f2aeb24..4f9a17a54 100644 --- a/build-aux/adl_recursive_eval.m4 +++ b/build-aux/adl_recursive_eval.m4 @@ -3,13 +3,16 @@ dnl ================================= dnl Interpolate the VALUE in loop until it doesn't change, dnl and set the result to $RESULT. dnl WARNING: It's easy to get an infinite loop with some unsane input. -AC_DEFUN([adl_RECURSIVE_EVAL], -[_lcl_receval="$1" -$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" - test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" - _lcl_receval_old='' - while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do - _lcl_receval_old="[$]_lcl_receval" - eval _lcl_receval="\"[$]_lcl_receval\"" - done - echo "[$]_lcl_receval")`]) \ No newline at end of file +AC_DEFUN([adl_RECURSIVE_EVAL], [ + _lcl_receval="$1" + $2=`( + test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" + _lcl_receval_old='' + while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do + _lcl_receval_old="[$]_lcl_receval" + eval _lcl_receval="\"[$]_lcl_receval\"" + done + echo "[$]_lcl_receval" + )` +]) diff --git a/build-aux/ax_build_date_epoch.m4 b/build-aux/ax_build_date_epoch.m4 index dbecb067a..81ac87c7b 100644 --- a/build-aux/ax_build_date_epoch.m4 +++ b/build-aux/ax_build_date_epoch.m4 @@ -53,18 +53,15 @@ #serial 2 -AC_DEFUN([AX_BUILD_DATE_EPOCH], -[dnl -AC_MSG_CHECKING([for build time]) -ax_date_fmt="m4_default($2,%s)" -AS_IF([test x"$SOURCE_DATE_EPOCH" = x], - [$1=`date "+$ax_date_fmt"`], - [ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \ - || date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null` - AS_IF([test x"$ax_build_date" = x], - [m4_ifval([$3], - [$3], - [AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])], - [$1=$ax_build_date])]) -AC_MSG_RESULT([$$1]) +AC_DEFUN([AX_BUILD_DATE_EPOCH], [dnl + AC_MSG_CHECKING([for build time]) + ax_date_fmt="m4_default($2,%s)" + AS_IF([test x"$SOURCE_DATE_EPOCH" = x], + [$1=`date "+$ax_date_fmt"`], + [ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \ + || date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null` + AS_IF([test x"$ax_build_date" = x], + [m4_ifval([$3], [$3], [AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])], + [$1=$ax_build_date])]) + AC_MSG_RESULT([$$1]) ])dnl AX_BUILD_DATE_EPOCH diff --git a/build-aux/ax_font.m4 b/build-aux/ax_font.m4 index 93b319c5c..c955106ba 100644 --- a/build-aux/ax_font.m4 +++ b/build-aux/ax_font.m4 @@ -1,21 +1,21 @@ AC_DEFUN([AX_FONT], [ - AC_PROG_GREP - if test -z "$FCMATCH"; then - AC_PATH_PROG(FCMATCH, fc-match) + AC_PROG_GREP if test -z "$FCMATCH"; then - AC_MSG_ERROR([can't find fc-match]) + AC_PATH_PROG(FCMATCH, fc-match) + if test -z "$FCMATCH"; then + AC_MSG_ERROR([can't find fc-match]) + fi fi - fi - pushdef([FONT],$1) - AC_MSG_CHECKING(whether font family FONT is available) - AS_IF([test "$FCMATCH" = "true"],[ - AC_MSG_RESULT(skip) - ],[ - AS_IF([$FCMATCH "FONT" family | $GREP -qx "FONT"],[ - AC_MSG_RESULT(yes) + pushdef([FONT],$1) + AC_MSG_CHECKING(whether font family FONT is available) + AS_IF([test "$FCMATCH" = "true"],[ + AC_MSG_RESULT(skip) ],[ - AC_MSG_FAILURE([font family FONT not found]) + AS_IF([$FCMATCH "FONT" family | $GREP -qx "FONT"],[ + AC_MSG_RESULT(yes) + ],[ + AC_MSG_FAILURE([font family FONT not found]) + ]) ]) - ]) - popdef([FONT]) + popdef([FONT]) ])dnl diff --git a/build-aux/ax_progvar.m4 b/build-aux/ax_progvar.m4 index 131c80617..e584ed4aa 100644 --- a/build-aux/ax_progvar.m4 +++ b/build-aux/ax_progvar.m4 @@ -1,5 +1,5 @@ AC_DEFUN([AX_PROGVAR], [ - test -n "$m4_toupper($1)" || { AC_PATH_PROG(m4_toupper($1), m4_default($2,$1)) } - test -n "$m4_toupper($1)" || AC_MSG_ERROR([m4_default($2,$1) is required]) - ]) + test -n "$m4_toupper($1)" || { AC_PATH_PROG(m4_toupper($1), m4_default($2,$1)) } + test -n "$m4_toupper($1)" || AC_MSG_ERROR([m4_default($2,$1) is required]) +]) diff --git a/build-aux/ax_subst_man_date.m4 b/build-aux/ax_subst_man_date.m4 index 3eea16d76..edb697064 100644 --- a/build-aux/ax_subst_man_date.m4 +++ b/build-aux/ax_subst_man_date.m4 @@ -1,13 +1,13 @@ AC_DEFUN([AX_SUBST_MAN_DATE], [ - ax_date_fmt="m4_default($1,%d %B %Y)" - ax_src_file="m4_default($2,*.1.in)" - AS_IF([test ! -e .gitignore], - [ - AX_PROGVAR([date]) - AX_BUILD_DATE_EPOCH(MAN_DATE, "$ax_date_fmt") - ], [ - AX_PROGVAR([git]) - MAN_DATE=$($GIT log -1 --format="%cd" --date=format:"$ax_date_fmt" -- $ax_src_file) - ]) - AC_SUBST([MAN_DATE]) + ax_date_fmt="m4_default($1,%d %B %Y)" + ax_src_file="m4_default($2,*.1.in)" + AS_IF([test ! -e .gitignore], + [ + AX_PROGVAR([date]) + AX_BUILD_DATE_EPOCH(MAN_DATE, "$ax_date_fmt") + ], [ + AX_PROGVAR([git]) + MAN_DATE=$($GIT log -1 --format="%cd" --date=format:"$ax_date_fmt" -- $ax_src_file) + ]) + AC_SUBST([MAN_DATE]) ]) From 16f8fbd7d741c4c032e217742de6229fac61ec4c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 25 Sep 2023 17:02:35 +0300 Subject: [PATCH 088/357] chore(tooling): Backport autoconf-archive 45 ax_lua macros ...as submitted upstream as serial 44 (for Lua 5.4 support) and 45 (for LuaJIT support), minus keeping our AX_LUA_MODULE macro for now. --- build-aux/ax_lua.m4 | 451 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 368 insertions(+), 83 deletions(-) diff --git a/build-aux/ax_lua.m4 b/build-aux/ax_lua.m4 index 085dc49ad..12ce133e6 100644 --- a/build-aux/ax_lua.m4 +++ b/build-aux/ax_lua.m4 @@ -1,30 +1,230 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_lua.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# +# DESCRIPTION +# +# Detect a Lua interpreter, optionally specifying a minimum and maximum +# version number. Set up important Lua paths, such as the directories in +# which to install scripts and modules (shared libraries). +# +# Also detect Lua headers and libraries. The Lua version contained in the +# header is checked to match the Lua interpreter version exactly. When +# searching for Lua libraries, the version number is used as a suffix. +# This is done with the goal of supporting multiple Lua installs (5.1, +# 5.2, 5.3, and 5.4 side-by-side). +# +# A note on compatibility with previous versions: This file has been +# mostly rewritten for serial 18. Most developers should be able to use +# these macros without needing to modify configure.ac. Care has been taken +# to preserve each macro's behavior, but there are some differences: +# +# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as +# AX_PROG_LUA with no arguments. +# +# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h +# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore +# unnecessary, so it is deprecated and does not expand to anything. +# +# 3) The configure flag --with-lua-suffix no longer exists; the user +# should instead specify the LUA precious variable on the command line. +# See the AX_PROG_LUA description for details. +# +# Please read the macro descriptions below for more information. +# +# This file was inspired by Andrew Dalke's and James Henstridge's +# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4 +# (serial 17). Basically, this file is a mash-up of those two files. I +# like to think it combines the best of the two! +# +# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua +# paths. Adds precious variable LUA, which may contain the path of the Lua +# interpreter. If LUA is blank, the user's path is searched for an +# suitable interpreter. +# +# Optionally a LUAJIT option may be set ahead of time to look for and +# validate a LuaJIT install instead of PUC Lua. Usage might look like: +# +# AC_ARG_WITH(luajit, [AS_HELP_STRING([--with-luajit], +# [Prefer LuaJIT over PUC Lua, even if the latter is newer. Default: no]) +# ]) +# AM_CONDITIONAL([LUAJIT], [test "x$with_luajit" != 'xno']) +# +# If MINIMUM-VERSION is supplied, then only Lua interpreters with a +# version number greater or equal to MINIMUM-VERSION will be accepted. If +# TOO-BIG-VERSION is also supplied, then only Lua interpreters with a +# version number greater or equal to MINIMUM-VERSION and less than +# TOO-BIG-VERSION will be accepted. +# +# The Lua version number, LUA_VERSION, is found from the interpreter, and +# substituted. LUA_PLATFORM is also found, but not currently supported (no +# standard representation). +# +# Finally, the macro finds four paths: +# +# luadir Directory to install Lua scripts. +# pkgluadir $luadir/$PACKAGE +# luaexecdir Directory to install Lua modules. +# pkgluaexecdir $luaexecdir/$PACKAGE +# +# These paths are found based on $prefix, $exec_prefix, Lua's +# package.path, and package.cpath. The first path of package.path +# beginning with $prefix is selected as luadir. The first path of +# package.cpath beginning with $exec_prefix is used as luaexecdir. This +# should work on all reasonable Lua installations. If a path cannot be +# determined, a default path is used. Of course, the user can override +# these later when invoking make. +# +# luadir Default: $prefix/share/lua/$LUA_VERSION +# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION +# +# These directories can be used by Automake as install destinations. The +# variable name minus 'dir' needs to be used as a prefix to the +# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES. +# +# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is +# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT- +# FOUND is blank, then it will default to printing an error. To prevent +# the default behavior, give ':' as an action. +# +# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be +# expanded before this macro. Adds precious variable LUA_INCLUDE, which +# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If +# LUA_INCLUDE is blank, then this macro will attempt to find suitable +# flags. +# +# LUA_INCLUDE can be used by Automake to compile Lua modules or +# executables with embedded interpreters. The *_CPPFLAGS variables should +# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE). +# +# This macro searches for the header lua.h (and others). The search is +# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE. +# If the search is unsuccessful, then some common directories are tried. +# If the headers are then found, then LUA_INCLUDE is set accordingly. +# +# The paths automatically searched are: +# +# * /usr/include/luaX.Y +# * /usr/include/lua/X.Y +# * /usr/include/luaXY +# * /usr/local/include/luaX.Y +# * /usr/local/include/lua-X.Y +# * /usr/local/include/lua/X.Y +# * /usr/local/include/luaXY +# +# (Where X.Y is the Lua version number, e.g. 5.1.) +# +# The Lua version number found in the headers is always checked to match +# the Lua interpreter's version number. Lua headers with mismatched +# version numbers are not accepted. +# +# If headers are found, then ACTION-IF-FOUND is performed, otherwise +# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then +# it will default to printing an error. To prevent the default behavior, +# set the action to ':'. +# +# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be +# expanded before this macro. Adds precious variable LUA_LIB, which may +# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank, +# then this macro will attempt to find suitable flags. +# +# LUA_LIB can be used by Automake to link Lua modules or executables with +# embedded interpreters. The *_LIBADD and *_LDADD variables should be used +# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB). +# +# This macro searches for the Lua library. More technically, it searches +# for a library containing the function lua_load. The search is performed +# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB. +# +# If the search determines that some linker flags are missing, then those +# flags will be added to LUA_LIB. +# +# If libraries are found, then ACTION-IF-FOUND is performed, otherwise +# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then +# it will default to printing an error. To prevent the default behavior, +# set the action to ':'. +# +# AX_LUA_READLINE: Search for readline headers and libraries. Requires the +# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the +# Autoconf Archive. +# +# If a readline compatible library is found, then ACTION-IF-FOUND is +# performed, otherwise ACTION-IF-NOT-FOUND is performed. +# +# LICENSE +# +# Copyright (c) 2023 Caleb Maclennan +# Copyright (c) 2015 Reuben Thomas +# Copyright (c) 2014 Tim Perkins +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 45 + dnl ========================================================================= dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION], dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_PROG_LUA], [ + dnl Check for required tools. + AC_REQUIRE([AC_PROG_GREP]) + AC_REQUIRE([AC_PROG_SED]) + dnl Make LUA a precious variable. AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1]) dnl Find a Lua interpreter. AM_COND_IF([LUAJIT], - [_ax_lua_interpreter_list="luajit luajit-2.1.0-beta3 luajit-2.0.5 luajit-2.0.4 luajit-2.0.3"], - [_ax_lua_interpreter_list="lua lua5.4 lua54 lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua5.0 lua50"]) + [_ax_lua_interpreter_list='luajit luajit-2.1.0-beta3 luajit-2.0.5 luajit-2.0.4 luajit-2.0.3'], + [_ax_lua_interpreter_list='lua lua5.4 lua54 lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua5.0 lua50']) m4_if([$1], [], [ dnl No version check is needed. Find any Lua interpreter. AS_IF([test "x$LUA" = 'x'], - [AC_PATH_PROGS([LUA], [_ax_lua_interpreter_list], [:])]) + [AC_PATH_PROGS([LUA], [$_ax_lua_interpreter_list], [:])]) ax_display_LUA='lua' - dnl At least check if this is a Lua interpreter. + AS_IF([test "x$LUA" != 'x:'], + [ dnl At least check if this is a Lua interpreter. AC_MSG_CHECKING([if $LUA is a Lua interpreter]) _AX_LUA_CHK_IS_INTRP([$LUA], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([not a Lua interpreter]) ]) + ]) ], [ dnl A version check is needed. AS_IF([test "x$LUA" != 'x'], @@ -71,8 +271,15 @@ AC_DEFUN([AX_PROG_LUA], m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])]) ], [ dnl Query Lua for its version number. - AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version], - [ ax_cv_lua_version=`$LUA -e 'print(_VERSION:match "(%d+%.%d+)")'` ]) + AC_CACHE_CHECK([for $ax_display_LUA version], + [ax_cv_lua_version], + [ dnl Get the interpreter version in X.Y format. This should work for + dnl interpreters version 5.0 and beyond. + ax_cv_lua_version=[`$LUA -e ' + -- return a version number in X.Y format + local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)") + print(ver or "")'`] + ]) AS_IF([test "x$ax_cv_lua_version" = 'x'], [AC_MSG_ERROR([invalid Lua version number])]) AC_SUBST([LUA_VERSION], [$ax_cv_lua_version]) @@ -80,18 +287,22 @@ AC_DEFUN([AX_PROG_LUA], AM_COND_IF([LUAJIT], [ AC_CACHE_CHECK([for $ax_display_LUA jit version], [ax_cv_luajit_version], - [ ax_cv_luajit_version=`$LUA -e 'print(jit and jit.version:match "(%d+%..+)")'` ]) + [ ax_cv_luajit_version=[`$LUA -e ' + local _, _, ver = string.find(jit and jit.version, "(%d+%..+)") + print(ver or "")'`] + ]) AS_IF([test "x$ax_cv_luajit_version" = 'x'], - [AC_MSG_ERROR([invalid Lua version number])]) + [AC_MSG_ERROR([invalid Lua jit version number])]) AC_SUBST([LUAJIT_VERSION], [$ax_cv_luajit_version]) - AC_SUBST([LUAJIT_SHORT_VERSION], [`echo "$LUAJIT_VERSION" | $SED 's|\.|§|;s|\..*||;s|§|.|'`]) + AC_SUBST([LUAJIT_SHORT_VERSION], [$(echo "$LUAJIT_VERSION" | $SED 's|\.|§|;s|\..*||;s|§|.|')]) ]) dnl The following check is not supported: dnl At times (like when building shared libraries) you may want to know dnl which OS platform Lua thinks this is. - AC_CACHE_CHECK([for $ax_display_LUA platform], [ax_cv_lua_platform], - [ax_cv_lua_platform=`$LUA -e "print('unknown')"`]) + AC_CACHE_CHECK([for $ax_display_LUA platform], + [ax_cv_lua_platform], + [ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]]) AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform]) dnl Use the values of $prefix and $exec_prefix for the corresponding @@ -116,12 +327,12 @@ AC_DEFUN([AX_PROG_LUA], ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION" dnl Try to find a path with the prefix. - _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [package.path]) + _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script]) AS_IF([test "x$ax_lua_prefixed_path" != 'x'], [ dnl Fix the prefix. _ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'` ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \ - $SED "s,^$_ax_strip_prefix,$LUA_PREFIX,"` + $SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"` ]) ]) AC_SUBST([luadir], [$ax_cv_lua_luadir]) @@ -143,12 +354,12 @@ AC_DEFUN([AX_PROG_LUA], dnl Try to find a path with the prefix. _AX_LUA_FND_PRFX_PTH([$LUA], - [$ax_lua_exec_prefix], [package.cpath]) + [$ax_lua_exec_prefix], [module]) AS_IF([test "x$ax_lua_prefixed_path" != 'x'], [ dnl Fix the prefix. _ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'` ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \ - $SED "s,^$_ax_strip_prefix,$LUA_EXEC_PREFIX,"` + $SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"` ]) ]) AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir]) @@ -162,7 +373,7 @@ AC_DEFUN([AX_PROG_LUA], dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA. AC_DEFUN([AX_WITH_LUA], [ - AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA]]) + AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]]) AX_PROG_LUA ]) @@ -172,8 +383,19 @@ dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl ========================================================================= AC_DEFUN([_AX_LUA_CHK_IS_INTRP], [ - dnl Just print _VERSION because all Lua interpreters have this global. - AS_IF([$1 -e "print('Hello ' .. _VERSION .. '!')"], + dnl A minimal Lua factorial to prove this is an interpreter. This should work + dnl for Lua interpreters version 5.0 and beyond. + _ax_lua_factorial=[`$1 2>/dev/null -e ' + -- a simple factorial + function fact (n) + if n == 0 then + return 1 + else + return n * fact(n-1) + end + end + print("fact(5) is " .. fact(5))'`] + AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'], [$2], [$3]) ]) @@ -184,13 +406,28 @@ dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl ========================================================================= AC_DEFUN([_AX_LUA_CHK_VER], [ - AS_IF([$1 2>/dev/null -e ' - function norm (v) - i,j=v:match "(%d+)%.(%d+)" if i then return 100 * i + j end - end - v, toobig=norm (_VERSION), norm "$3" or math.huge - os.exit ((v >= norm ("$2") and v < toobig) and 0 or 1)'], - [$4], [$5]) + dnl Check that the Lua version is within the bounds. Only the major and minor + dnl version numbers are considered. This should work for Lua interpreters + dnl version 5.0 and beyond. + _ax_lua_good_version=[`$1 -e ' + -- a script to compare versions + function verstr2num(verstr) + local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)") + if majorver and minorver then + return tonumber(majorver) * 100 + tonumber(minorver) + end + end + local minver = verstr2num("$2") + local _, _, trimver = string.find(_VERSION, "^Lua (.*)") + local ver = verstr2num(trimver) + local maxver = verstr2num("$3") or 1e9 + if minver <= ver and ver < maxver then + print("yes") + else + print("no") + end'`] + AS_IF([test "x$_ax_lua_good_version" = "xyes"], + [$4], [$5]) ]) AC_DEFUN([_AX_LUAJIT_CHK_VER], @@ -206,25 +443,44 @@ AC_DEFUN([_AX_LUAJIT_CHK_VER], dnl ========================================================================= -dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, LUA-PATH-VARIABLE) +dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR) dnl ========================================================================= AC_DEFUN([_AX_LUA_FND_PRFX_PTH], [ - dnl Invokes the Lua interpreter PROG to print the path variable - dnl LUA-PATH-VARIABLE, usually package.path or package.cpath. Paths are - dnl then matched against PREFIX. Then ax_lua_prefixed_path is set to the - dnl shortest sub path beginning with PREFIX up to the last directory - dnl that does not contain a '?', if any. - - ax_lua_prefixed_path=`$1 2>/dev/null -e ' - $3:gsub ("(@<:@^;@:>@+)", - function (p) - p = p:gsub ("%?.*$", ""):gsub ("/@<:@^/@:>@*$", "") - if p:match ("^$2") and (not shortest or #shortest > #p) then - shortest = p + dnl Get the script or module directory by querying the Lua interpreter, + dnl filtering on the given prefix, and selecting the shallowest path. If no + dnl path is found matching the prefix, the result will be an empty string. + dnl The third argument determines the type of search, it can be 'script' or + dnl 'module'. Supplying 'script' will perform the search with package.path + dnl and LUA_PATH, and supplying 'module' will search with package.cpath and + dnl LUA_CPATH. This is done for compatibility with Lua 5.0. + + ax_lua_prefixed_path=[`$1 -e ' + -- get the path based on search type + local searchtype = "$3" + local paths = "" + if searchtype == "script" then + paths = (package and package.path) or LUA_PATH + elseif searchtype == "module" then + paths = (package and package.cpath) or LUA_CPATH + end + -- search for the prefix + local prefix = "'$2'" + local minpath = "" + local mindepth = 1e9 + string.gsub(paths, "(@<:@^;@:>@+)", + function (path) + path = string.gsub(path, "%?.*$", "") + path = string.gsub(path, "/@<:@^/@:>@*$", "") + if string.find(path, prefix) then + local depth = string.len(string.gsub(path, "@<:@^/@:>@", "")) + if depth < mindepth then + minpath = path + mindepth = depth + end end end) - print (shortest or "")'` + print(minpath)'`] ]) @@ -241,13 +497,35 @@ AC_DEFUN([AX_LUA_HEADERS], AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION]) ]) + AM_COND_IF([LUAJIT],[ + dnl Check for LUAJIT_VERSION. + AC_MSG_CHECKING([if LUAJIT_VERSION is defined]) + AS_IF([test "x$LUAJIT_VERSION" != 'x'], + [AC_MSG_RESULT([yes])], + [ AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot check Lua jit headers without knowing LUAJIT_VERSION]) + ]) + ]) + dnl Make LUA_INCLUDE a precious variable. AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1]) dnl Some default directories to search. AM_COND_IF([LUAJIT], - [_ax_lua_include_list="/usr/include/luajit-$LUAJIT_VERSION /usr/include/luajit-$LUAJIT_SHORT_VERSION /usr/local/include/luajit-$LUAJIT_VERSION /usr/local/include/luajit-$LUAJIT_SHORT_VERSION"], - [_ax_lua_include_list="/usr/include/lua$LUA_VERSION /usr/include/lua/$LUA_VERSION /usr/include/lua$LUA_SHORT_VERSION /usr/local/include/lua$LUA_VERSION /usr/local/include/lua-$LUA_VERSION /usr/local/include/lua/$LUA_VERSION /usr/local/include/lua$LUA_SHORT_VERSION"]) + [_ax_lua_include_list=" + /usr/include/luajit-$LUAJIT_VERSION + /usr/include/luajit-$LUAJIT_SHORT_VERSION + /usr/local/include/luajit-$LUAJIT_VERSION + /usr/local/include/luajit-$LUAJIT_SHORT_VERSION"], + [_ax_lua_include_list=" + /usr/include/lua$LUA_VERSION + /usr/include/lua-$LUA_VERSION + /usr/include/lua/$LUA_VERSION + /usr/include/lua$LUA_SHORT_VERSION + /usr/local/include/lua$LUA_VERSION + /usr/local/include/lua-$LUA_VERSION + /usr/local/include/lua/$LUA_VERSION + /usr/local/include/lua$LUA_SHORT_VERSION"]) dnl Try to find the headers. _ax_lua_saved_cppflags=$CPPFLAGS @@ -258,9 +536,9 @@ AC_DEFUN([AX_LUA_HEADERS], dnl Try some other directories if LUA_INCLUDE was not set. AS_IF([test "x$LUA_INCLUDE" = 'x' && - test "x$ac_cv_header_lua_h" != "xyes" || - test "x$with_luajit" = "xyes" && - test "x$ac_cv_header_luajit_h" != 'xyes'], + test "x$ac_cv_header_lua_h" != 'xyes' || + test "x$with_luajit" != 'xno' && + test "x$ac_cv_header_luajit_h" != 'xyes'], [ dnl Try some common include paths. for _ax_include_path in $_ax_lua_include_list; do test ! -d "$_ax_include_path" && continue @@ -269,10 +547,10 @@ AC_DEFUN([AX_LUA_HEADERS], AC_MSG_RESULT([$_ax_include_path]) AS_UNSET([ac_cv_header_lua_h]) - AS_UNSET([ac_cv_header_luajit_h]) AS_UNSET([ac_cv_header_lualib_h]) AS_UNSET([ac_cv_header_lauxlib_h]) AS_UNSET([ac_cv_header_luaconf_h]) + AS_UNSET([ac_cv_header_luajit_h]) _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I$_ax_include_path" @@ -287,46 +565,44 @@ AC_DEFUN([AX_LUA_HEADERS], done ]) - AS_IF([test "x$ac_cv_header_lua_h" = 'xyes' && test "x$cross_compiling" != 'xyes'], + AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], [ dnl Make a program to print LUA_VERSION defined in the header. - dnl TODO This probably shouldn't be a runtime test. - - AC_CACHE_CHECK([for Lua header version], - [ax_cv_lua_header_version], - [ _ax_lua_saved_cppflags=$CPPFLAGS - CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" - AC_RUN_IFELSE( - [ AC_LANG_SOURCE([[ + dnl TODO It would be really nice if we could do this without compiling a + dnl program, then it would work when cross compiling. But I'm not sure how + dnl to do this reliably. For now, assume versions match when cross compiling. + + AS_IF([test "x$cross_compiling" != 'xyes'], + [ AC_CACHE_CHECK([for Lua header version], + [ax_cv_lua_header_version], + [ _ax_lua_saved_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" + AC_COMPUTE_INT(ax_cv_lua_header_version_major,[LUA_VERSION_NUM/100],[AC_INCLUDES_DEFAULT #include -#include -#include -int main(int argc, char ** argv) -{ - if(argc > 1) printf("%s", LUA_VERSION); - exit(EXIT_SUCCESS); -} -]]) - ], - [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \ - $SED "s|^Lua \(.*\)|\1|" | \ - $GREP -E -o "^@<:@0-9@:>@+\.@<:@0-9@:>@+"` +],[ax_cv_lua_header_version_major=unknown]) + AC_COMPUTE_INT(ax_cv_lua_header_version_minor,[LUA_VERSION_NUM%100],[AC_INCLUDES_DEFAULT +#include +],[ax_cv_lua_header_version_minor=unknown]) + AS_IF([test "x$ax_cv_lua_header_version_major" = xunknown || test "x$ax_cv_lua_header_version_minor" = xunknown],[ + ax_cv_lua_header_version=unknown + ],[ + ax_cv_lua_header_version="$ax_cv_lua_header_version_major.$ax_cv_lua_header_version_minor" + ]) + CPPFLAGS=$_ax_lua_saved_cppflags + ]) + + dnl Compare this to the previously found LUA_VERSION. + AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION]) + AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"], + [ AC_MSG_RESULT([yes]) + ax_header_version_match='yes' ], - [ax_cv_lua_header_version='unknown']) - CPPFLAGS=$_ax_lua_saved_cppflags - ]) - - dnl Compare this to the previously found LUA_VERSION. - AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION]) - AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"], - [ AC_MSG_RESULT([yes]) - ax_header_version_match='yes' + [ AC_MSG_RESULT([no]) + ax_header_version_match='no' + ]) ], - [ AC_MSG_RESULT([no]) - ax_header_version_match='no' + [ AC_MSG_WARN([cross compiling so assuming header version number matches]) + ax_header_version_match='yes' ]) - ], - [ - ax_header_version_match='yes' ]) dnl Was LUA_INCLUDE specified? @@ -342,7 +618,7 @@ int main(int argc, char ** argv) dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS. AC_DEFUN([AX_LUA_HEADERS_VERSION], [ - AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS]]) + AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]]) ]) @@ -399,12 +675,21 @@ AC_DEFUN([AX_LUA_LIBS], LIBS="$LIBS $LUA_LIB" AM_COND_IF([LUAJIT], [AC_SEARCH_LIBS([lua_load], - [luajit$LUA_VERSION luajit$LUA_SHORT_VERSION luajit-$LUA_VERSION luajit-$LUA_SHORT_VERSION luajit], + [ luajit$LUA_VERSION \ + luajit$LUA_SHORT_VERSION \ + luajit-$LUA_VERSION \ + luajit-$LUA_SHORT_VERSION \ + luajit], [_ax_found_lua_libs='yes'], [_ax_found_lua_libs='no'], [$_ax_lua_extra_libs])], [AC_SEARCH_LIBS([lua_load], - [lua$LUA_VERSION lua$LUA_SHORT_VERSION lua-$LUA_VERSION lua-$LUA_SHORT_VERSION lua], + [ lua$LUA_VERSION \ + lua$LUA_SHORT_VERSION \ + lua-$LUA_VERSION \ + lua-$LUA_SHORT_VERSION \ + lua \ + ], [_ax_found_lua_libs='yes'], [_ax_found_lua_libs='no'], [$_ax_lua_extra_libs])]) From 9cc09e73f4dc9183b0cb07905048f53c4455a4d2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 26 Sep 2023 14:46:59 +0300 Subject: [PATCH 089/357] chore(build): Remove variable exports from LuaRocks makefile now always set by configure --- Makefile-luarocks | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile-luarocks b/Makefile-luarocks index c4ded991d..46e5c8ef3 100644 --- a/Makefile-luarocks +++ b/Makefile-luarocks @@ -17,7 +17,4 @@ $(LUAMODLOCK): lua_modules $(LUAMODSPEC) $(genrockslock) > $@ else LUAMODLOCK := -LUA_PATH := $(shell $(LUA) -e 'print(package.path)') -LUA_CPATH := $(shell $(LUA) -e 'print(package.cpath)') -export LUA_PATH LUA_CPATH endif From 7897bc645b4d8631fe92fa67fed48880799a61db Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 26 Sep 2023 15:38:53 +0300 Subject: [PATCH 090/357] chore(cli): Normalize interpreter info in full_version string across VMs --- sile.in | 1 + src/bin/sile.rs | 1 - src/lib.rs | 9 +++++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sile.in b/sile.in index 4a74845e3..6b2cd50f7 100755 --- a/sile.in +++ b/sile.in @@ -16,6 +16,7 @@ end -- This global is set here and *also* in the core library, since this -- effectively passes the same table they are interchangeable (for now). SILE = require("core.sile") +SILE.full_version = SILE.full_version .. " [Lua]" SILE.cli:parseArguments() diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 2df463373..4fa00604f 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -9,7 +9,6 @@ fn main() -> sile::Result<()> { .strip_prefix("SILE ") .unwrap_or("") .to_string(); - let long_version = format!("{} [Rust]", long_version); let app = Cli::command().version(version).long_version(long_version); #[allow(unused_variables)] let matches = app.get_matches(); diff --git a/src/lib.rs b/src/lib.rs index 673d458a5..fc3773fb7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,9 @@ pub fn version() -> crate::Result { return require("core.sile") }) .eval()?; - Ok(sile.get("full_version")?) + let mut full_version: String = sile.get("full_version")?; + full_version.push_str(" [Rust]"); + Ok(full_version) } // Yes I know this should be taking a struct, probably 1 with what ends up being SILE.input and one @@ -61,6 +63,9 @@ pub fn run( return require("core.sile") }) .eval()?; + let mut full_version: String = sile.get("full_version")?; + full_version.push_str(" [Rust]"); + sile.set("full_version", full_version)?; sile.set("traceback", traceback)?; sile.set("quiet", quiet)?; let mut has_input_filename = false; @@ -107,7 +112,7 @@ pub fn run( sile_input.set("use", modules)?; } if !quiet { - eprintln!("{full_version} [Rust]"); + eprintln!("{full_version}"); } let init: LuaFunction = sile.get("init")?; init.call::<_, _>(())?; From 1b42a0ddff84169174869839fa4768ee2a409cb6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 26 Sep 2023 15:54:42 +0300 Subject: [PATCH 091/357] ci(actions): Set some feature args for Clippy linter that skips configure step --- .github/workflows/rust_lint.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml index 25dd6e644..10c01efc8 100644 --- a/.github/workflows/rust_lint.yml +++ b/.github/workflows/rust_lint.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -39,4 +39,4 @@ jobs: - uses: actions-rs/clippy-check@v1 with: token: ${{ github.token }} - args: -- -D warnings + args: --features luajit -- -D warnings From cc490e3beaceafb6be1ad6fac5d5f09d45922d70 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 26 Sep 2023 22:22:28 +0300 Subject: [PATCH 092/357] refactor(build): Un-conflate subdir with C modules from Rust code --- CMakeLists.txt | 12 ++++++------ Makefile.am | 2 +- configure.ac | 2 +- {src => justenough}/Makefile.am | 0 {src => justenough}/fontmetrics.c | 0 {src => justenough}/hb-utils.c | 0 {src => justenough}/hb-utils.h | 0 {src => justenough}/imagebbox.c | 0 {src => justenough}/justenoughfontconfig.c | 0 {src => justenough}/justenoughharfbuzz.c | 0 {src => justenough}/justenoughicu.c | 0 {src => justenough}/justenoughlibtexpdf.c | 0 {src => justenough}/macfonts.m | 0 {src => justenough}/nanosvg.h | 0 {src => justenough}/podofo_wrap.cxx | 0 {src => justenough}/silewin32.h | 0 {src => justenough}/svg.c | 0 17 files changed, 8 insertions(+), 8 deletions(-) rename {src => justenough}/Makefile.am (100%) rename {src => justenough}/fontmetrics.c (100%) rename {src => justenough}/hb-utils.c (100%) rename {src => justenough}/hb-utils.h (100%) rename {src => justenough}/imagebbox.c (100%) rename {src => justenough}/justenoughfontconfig.c (100%) rename {src => justenough}/justenoughharfbuzz.c (100%) rename {src => justenough}/justenoughicu.c (100%) rename {src => justenough}/justenoughlibtexpdf.c (100%) rename {src => justenough}/macfonts.m (100%) rename {src => justenough}/nanosvg.h (100%) rename {src => justenough}/podofo_wrap.cxx (100%) rename {src => justenough}/silewin32.h (100%) rename {src => justenough}/svg.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90373dcb7..1f362b3ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,7 +136,7 @@ if (WIN32) endif() -add_library(justenoughlibtexpdf SHARED src/justenoughlibtexpdf.c src/imagebbox.c) +add_library(justenoughlibtexpdf SHARED justenough/justenoughlibtexpdf.c justenough/imagebbox.c) add_dependencies(justenoughlibtexpdf libtexpdf lua) target_include_directories(justenoughlibtexpdf PUBLIC "${CMAKE_SOURCE_DIR}" @@ -149,7 +149,7 @@ target_link_libraries(justenoughlibtexpdf PUBLIC libtexpdf lua51.lib) target_link_options(justenoughlibtexpdf PUBLIC /EXPORT:luaopen_justenoughlibtexpdf) -add_library(justenoughharfbuzz SHARED src/justenoughharfbuzz.c src/hb-utils.c src/hb-utils.h) +add_library(justenoughharfbuzz SHARED justenough/justenoughharfbuzz.c justenough/hb-utils.c justenough/hb-utils.h) add_dependencies(justenoughharfbuzz harfbuzz lua) target_include_directories(justenoughharfbuzz PUBLIC "${TMP_INSTALL_DIR}/include" @@ -162,7 +162,7 @@ target_compile_definitions(justenoughharfbuzz PUBLIC HAVE_HARFBUZZ_SUBSET) target_link_libraries(justenoughharfbuzz PUBLIC harfbuzz.lib harfbuzz-subset.lib lua51.lib) target_link_options(justenoughharfbuzz PUBLIC /EXPORT:luaopen_justenoughharfbuzz) -add_library(justenoughicu SHARED src/justenoughicu.c) +add_library(justenoughicu SHARED justenough/justenoughicu.c) add_dependencies(justenoughicu icu lua) target_include_directories(justenoughicu PUBLIC "${TMP_INSTALL_DIR}/include" @@ -173,7 +173,7 @@ target_link_directories(justenoughicu PUBLIC target_link_libraries(justenoughicu PUBLIC icuio.lib icuin.lib icuuc.lib icudt.lib lua51.lib) target_link_options(justenoughicu PUBLIC /EXPORT:luaopen_justenoughicu) -add_library(justenoughfontconfig SHARED src/justenoughfontconfig.c) +add_library(justenoughfontconfig SHARED justenough/justenoughfontconfig.c) add_dependencies(justenoughfontconfig fontconfig) target_include_directories(justenoughfontconfig PUBLIC "${TMP_INSTALL_DIR}/include" @@ -184,7 +184,7 @@ target_link_directories(justenoughfontconfig PUBLIC target_link_libraries(justenoughfontconfig PUBLIC fontconfig-static.lib lua51.lib expat.lib freetype.lib libpng16_static.lib zlibstatic.lib) target_link_options(justenoughfontconfig PUBLIC /EXPORT:luaopen_justenoughfontconfig) -add_library(fontmetrics SHARED src/fontmetrics.c src/hb-utils.c src/hb-utils.h) +add_library(fontmetrics SHARED justenough/fontmetrics.c justenough/hb-utils.c justenough/hb-utils.h) add_dependencies(fontmetrics harfbuzz lua) target_include_directories(fontmetrics PUBLIC "${TMP_INSTALL_DIR}/include" @@ -196,7 +196,7 @@ target_link_directories(fontmetrics PUBLIC target_link_libraries(fontmetrics PUBLIC harfbuzz.lib lua51.lib) target_link_options(fontmetrics PUBLIC /EXPORT:luaopen_fontmetrics) -add_library(svg SHARED src/svg.c) +add_library(svg SHARED justenough/svg.c) add_dependencies(svg lua) target_include_directories(svg PUBLIC "${TMP_INSTALL_DIR}/include" diff --git a/Makefile.am b/Makefile.am index 252218fbf..4c3079653 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I build-aux .SECONDEXPANSION: .DELETE_ON_ERROR: -SUBDIRS = src +SUBDIRS = justenough if SYSTEM_LIBTEXPDF SUBDIRS += libtexpdf endif diff --git a/configure.ac b/configure.ac index 5553ec585..cbb701841 100644 --- a/configure.ac +++ b/configure.ac @@ -268,7 +268,7 @@ AC_SUBST([ROCKREV], [1]) AX_SUBST_MAN_DATE AC_CONFIG_FILES([build-aux/list-dist-files.sh], [chmod +x build-aux/list-dist-files.sh]) -AC_CONFIG_FILES([Makefile src/Makefile sile-lua.1 core/features.lua core/pathsetup.lua core/version.lua]) +AC_CONFIG_FILES([Makefile justenough/Makefile sile-lua.1 core/features.lua core/pathsetup.lua core/version.lua]) AC_CONFIG_FILES([sile-lua:sile.in], [chmod +x sile-lua]) AC_CONFIG_FILES([tests/regressions.pl], [chmod +x tests/regressions.pl]) AC_CONFIG_FILES([sile-dev-1.rockspec:sile.rockspec.in]) diff --git a/src/Makefile.am b/justenough/Makefile.am similarity index 100% rename from src/Makefile.am rename to justenough/Makefile.am diff --git a/src/fontmetrics.c b/justenough/fontmetrics.c similarity index 100% rename from src/fontmetrics.c rename to justenough/fontmetrics.c diff --git a/src/hb-utils.c b/justenough/hb-utils.c similarity index 100% rename from src/hb-utils.c rename to justenough/hb-utils.c diff --git a/src/hb-utils.h b/justenough/hb-utils.h similarity index 100% rename from src/hb-utils.h rename to justenough/hb-utils.h diff --git a/src/imagebbox.c b/justenough/imagebbox.c similarity index 100% rename from src/imagebbox.c rename to justenough/imagebbox.c diff --git a/src/justenoughfontconfig.c b/justenough/justenoughfontconfig.c similarity index 100% rename from src/justenoughfontconfig.c rename to justenough/justenoughfontconfig.c diff --git a/src/justenoughharfbuzz.c b/justenough/justenoughharfbuzz.c similarity index 100% rename from src/justenoughharfbuzz.c rename to justenough/justenoughharfbuzz.c diff --git a/src/justenoughicu.c b/justenough/justenoughicu.c similarity index 100% rename from src/justenoughicu.c rename to justenough/justenoughicu.c diff --git a/src/justenoughlibtexpdf.c b/justenough/justenoughlibtexpdf.c similarity index 100% rename from src/justenoughlibtexpdf.c rename to justenough/justenoughlibtexpdf.c diff --git a/src/macfonts.m b/justenough/macfonts.m similarity index 100% rename from src/macfonts.m rename to justenough/macfonts.m diff --git a/src/nanosvg.h b/justenough/nanosvg.h similarity index 100% rename from src/nanosvg.h rename to justenough/nanosvg.h diff --git a/src/podofo_wrap.cxx b/justenough/podofo_wrap.cxx similarity index 100% rename from src/podofo_wrap.cxx rename to justenough/podofo_wrap.cxx diff --git a/src/silewin32.h b/justenough/silewin32.h similarity index 100% rename from src/silewin32.h rename to justenough/silewin32.h diff --git a/src/svg.c b/justenough/svg.c similarity index 100% rename from src/svg.c rename to justenough/svg.c From d22ea347055ae2e183efc617d45a9e09b03b89c0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 26 Sep 2023 23:17:34 +0300 Subject: [PATCH 093/357] fix(build): Fix build configuration for --with-system-libtexpdf --- Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 4c3079653..a373cf5a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ ACLOCAL_AMFLAGS = -I build-aux .DELETE_ON_ERROR: SUBDIRS = justenough -if SYSTEM_LIBTEXPDF +if !SYSTEM_LIBTEXPDF SUBDIRS += libtexpdf endif @@ -152,7 +152,6 @@ $(_BUILT_SUBDIRS): $(_SUBDIR_TELLS) $(_SUBDIR_TELLS): $(MAKE) $(AM_MAKEFLAGS) all-recursive -# $(error Running `make install`, `make dist`, or other end-game targets before `make all` unspported.) patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(bin_PROGRAMS) $(DEPDIRS) $(LUAMODLOCK) $(_BUILT_SUBDIRS) From 68d900804ada4b9dceefe36604b2b22ccfaaffd4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 27 Sep 2023 00:17:07 +0300 Subject: [PATCH 094/357] fix(build): Stop copying libraries places autotools doesn't normaly handle them --- core/pathsetup.lua.in | 5 +++++ justenough/Makefile.am | 12 ++---------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index 413d3ce65..bb3193076 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -4,6 +4,11 @@ if "@LUA_PATH@" ~= "" then package.cpath = "@LUA_CPATH@" end +if "@DEVELOPER_FALSE@" ~= "" then + package.cpath = package.cpath .. ";./libtexpdf/.libs/?.so" + package.cpath = package.cpath .. ";./justenough/.libs/?.so" + end + local executable = debug.getinfo(3, "S").source local luaversion = _VERSION:match("%d+%.%d+") diff --git a/justenough/Makefile.am b/justenough/Makefile.am index 70f72913c..0de136e56 100644 --- a/justenough/Makefile.am +++ b/justenough/Makefile.am @@ -12,6 +12,8 @@ if SYSTEM_LIBTEXPDF LIBTEXPDF_LIB=-ltexpdf else LIBTEXPDF_LIB=../libtexpdf/libtexpdf.la +$(LIBTEXPDF_LIB): + make -C ../libtexpdf all endif pkglib_LTLIBRARIES = justenoughharfbuzz.la justenoughlibtexpdf.la justenoughfontconfig.la fontmetrics.la svg.la @@ -19,13 +21,11 @@ justenoughharfbuzz_la_SOURCES = justenoughharfbuzz.c hb-utils.c hb-utils.h justenoughharfbuzz_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughharfbuzz_la_CFLAGS = $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) justenoughharfbuzz_la_LIBADD = $(HARFBUZZ_LIBS) $(HARFBUZZ_SUBSET_LIBS) $(MY_LUA_LIB) -to_copy = .libs/justenoughharfbuzz.@SHARED_LIB_EXT@ justenoughfontconfig_la_SOURCES = justenoughfontconfig.c silewin32.h justenoughfontconfig_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughfontconfig_la_CFLAGS = $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) justenoughfontconfig_la_LIBADD = $(FONTCONFIG_LIBS) $(MY_LUA_LIB) -to_copy += .libs/justenoughfontconfig.@SHARED_LIB_EXT@ if APPKIT pkglib_LTLIBRARIES += macfonts.la @@ -33,26 +33,22 @@ macfonts_la_SOURCES = macfonts.m macfonts_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) macfonts_la_OBJCFLAGS = -U VERSION $(HARFBUZZ_CFLAGS) $(LUA_INCLUDE) -fmodules macfonts_la_LIBADD = $(HARFBUZZ_LIBS) $(MY_LUA_LIB) -to_copy += .libs/macfonts.@SHARED_LIB_EXT@ endif justenoughlibtexpdf_la_SOURCES = justenoughlibtexpdf.c imagebbox.c justenoughlibtexpdf_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughlibtexpdf_la_CFLAGS = -I.. $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) justenoughlibtexpdf_la_LIBADD = $(LIBTEXPDF_LIB) $(LIBPNG_LIBS) $(ZLIB_LIBS) $(LIBPAPER_LIBS) $(MY_LUA_LIB) -to_copy += .libs/justenoughlibtexpdf.@SHARED_LIB_EXT@ fontmetrics_la_SOURCES = fontmetrics.c hb-utils.c hb-utils.h fontmetrics_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) fontmetrics_la_CFLAGS = $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) fontmetrics_la_LIBADD = $(MY_LUA_LIB) $(HARFBUZZ_LIBS) -to_copy += .libs/fontmetrics.@SHARED_LIB_EXT@ svg_la_SOURCES = svg.c nanosvg.h svg_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) svg_la_CFLAGS = $(LUA_INCLUDE) svg_la_LIBADD = $(MY_LUA_LIB) -to_copy += .libs/svg.@SHARED_LIB_EXT@ if ICU pkglib_LTLIBRARIES += justenoughicu.la @@ -60,8 +56,4 @@ justenoughicu_la_SOURCES = justenoughicu.c justenoughicu_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughicu_la_CFLAGS = -I.. $(ICU_CFLAGS) $(LUA_INCLUDE) justenoughicu_la_LIBADD = $(ICU_LIBS) $(MY_LUA_LIB) -to_copy += .libs/justenoughicu.@SHARED_LIB_EXT@ endif - -all-local: $(pkglib_LTLIBRARIES) - cp $(to_copy) .. From 3e3086ddb1080209ea63dab5062e17421f009c09 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 27 Sep 2023 10:41:44 +0300 Subject: [PATCH 095/357] chore(tooling): Fixup busted runner to use developer paths --- Makefile.am | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index a373cf5a5..3858278e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -229,15 +229,14 @@ luacheck: busted: $(SILELUA) $(addprefix .fonts/,$(TESTFONTFILES)) $(BUSTEDSPECS) set -f; IFS=';' -if SYSTEM_LUAROCKS - packagecpath=(./{,core/}?.$(SHARED_LIB_EXT)) packagepath=(./{,lua-libraries/}?{,/init}.lua) -else - packagecpath=(./{,core/,lua_modules/lib/lua/$(LUA_VERSION)/}?.$(SHARED_LIB_EXT)) - packagepath=(./{,lua_modules/share/lua/$(LUA_VERSION)/,lua-libraries/}?{,/init}.lua) + packagecpath=(./{,core/,{libtexpdf,justenough}/.libs/}?.$(SHARED_LIB_EXT)) +if !SYSTEM_LUAROCKS + packagepath+=(./lua_modules/share/lua/$(LUA_VERSION)/?{,/init}.lua) + packagecpath+=(./lua_modules/lib/lua/$(LUA_VERSION)/?.$(SHARED_LIB_EXT)) endif # Note: use of --lua causes this to be passed back through a shell loosing one layer of quoting. Drop single quotes if removing. - $(LOCALFONTS) $(BUSTED) --lua=$(LUA) --cpath="'$${packagecpath[*]};;'" --lpath="'$${packagepath[*]};;'" $(BUSTEDFLAGS) . + $(LOCALFONTS) $(BUSTED) --lua=$(LUA) --lpath="'$${packagepath[*]};;'" --cpath="'$${packagecpath[*]};;'" $(BUSTEDFLAGS) . coverage: export SILE_COVERAGE=1 coverage: BUSTEDFLAGS += -c From 9d8635e5725aa25f0b7ade379e081b20911b4a69 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 27 Sep 2023 16:02:59 +0300 Subject: [PATCH 096/357] chore(tooling): Allow clippy to run outside of autotools --- .cargo/config.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 96522a110..a253042ba 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -5,10 +5,12 @@ rustflags = ["-C", "link-args=-rdynamic"] rustflags = ["-C", "link-args=-rdynamic"] # Since autotools sets these and we are *not* forcing them here, this will not -# affect release builds. It will affect `cargo run` and make it easier to test -# locally since the Lua loader path will be relative to the current sources. +# affect release builds. It will affect `cargo run`, `cargo clippy` and others +# making it easier to test locally since the Lua loader path and other +# resources will be relative to the current sources. [env] SILE_PATH = { value = "", relative = true } +CONFIGURE_DATADIR = { value = "", relative = true } [target.'cfg(all())'] rustflags = [ From 17d1691e4b1df7484aeae9adaea7e959d84d4095 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 27 Sep 2023 17:44:28 +0300 Subject: [PATCH 097/357] chore(tooling): Facilitate selfcheck and manual builds without developer mode biraries --- Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3858278e2..4c9515568 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,6 +89,7 @@ CARGO_FEATURE_ARGS = --features $(MLUAVER) DEPDIR := .deps LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf +LOCALPATHS := SILE_PATH="$(PWD);libtexpdf/.libs;justenough/.libs" SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig dist-hook: $(MANUAL) dist-hook-distfiles @@ -114,8 +115,7 @@ check: selfcheck selfcheck: | $(bin_PROGRAMS) $(_BUILT_SUBDIRS) output=$$(mktemp -t selfcheck-XXXXXX.pdf) trap 'rm -f $$output' EXIT HUP TERM - export SILE_PATH - echo "foo" | SILE_PATH=$(PWD) ./$(bin_PROGRAMS) -o $$output - + echo "foo" | $(LOCALPATHS) ./$(bin_PROGRAMS) -o $$output - $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" .PHONY: docs @@ -125,7 +125,7 @@ docs: $(MANUAL) # garantee the TOC is up to date, simplify when #230 is fixed. hastoc = [ -f $(subst .pdf,.toc,$@) ] && echo true || echo false pages = $(PDFINFO) $@ | $(AWK) '$$1 == "Pages:" {print $$2}' || echo 0 -localsile = $(LOCALFONTS) SILE_PATH=$(PWD) ./$(bin_PROGRAMS) $(SILEFLAGS) +localsile = $(LOCALFONTS) $(LOCALPATHS) ./$(bin_PROGRAMS) $(SILEFLAGS) silepass = $(localsile) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false define runsile = set -e From c2fc1909e999dbd0c86aa3ff40bfea7c81812827 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 27 Sep 2023 18:16:17 +0300 Subject: [PATCH 098/357] chore(build): Explictly specify order of library builds to avoid races --- Makefile.am | 3 ++- justenough/Makefile.am | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 4c9515568..5cbd02b16 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,10 +5,11 @@ ACLOCAL_AMFLAGS = -I build-aux .SECONDEXPANSION: .DELETE_ON_ERROR: -SUBDIRS = justenough +SUBDIRS = if !SYSTEM_LIBTEXPDF SUBDIRS += libtexpdf endif +SUBDIRS += justenough . docdir = $(datarootdir)/doc/$(TRANSFORMED_PACKAGE_NAME) licensedir = $(datarootdir)/licenses/$(TRANSFORMED_PACKAGE_NAME) diff --git a/justenough/Makefile.am b/justenough/Makefile.am index 0de136e56..e8fdbc217 100644 --- a/justenough/Makefile.am +++ b/justenough/Makefile.am @@ -12,16 +12,15 @@ if SYSTEM_LIBTEXPDF LIBTEXPDF_LIB=-ltexpdf else LIBTEXPDF_LIB=../libtexpdf/libtexpdf.la -$(LIBTEXPDF_LIB): - make -C ../libtexpdf all endif -pkglib_LTLIBRARIES = justenoughharfbuzz.la justenoughlibtexpdf.la justenoughfontconfig.la fontmetrics.la svg.la +pkglib_LTLIBRARIES = justenoughharfbuzz.la justenoughharfbuzz_la_SOURCES = justenoughharfbuzz.c hb-utils.c hb-utils.h justenoughharfbuzz_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughharfbuzz_la_CFLAGS = $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) justenoughharfbuzz_la_LIBADD = $(HARFBUZZ_LIBS) $(HARFBUZZ_SUBSET_LIBS) $(MY_LUA_LIB) +pkglib_LTLIBRARIES += justenoughfontconfig.la justenoughfontconfig_la_SOURCES = justenoughfontconfig.c silewin32.h justenoughfontconfig_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughfontconfig_la_CFLAGS = $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) @@ -35,16 +34,19 @@ macfonts_la_OBJCFLAGS = -U VERSION $(HARFBUZZ_CFLAGS) $(LUA_INCLUDE) -fmodules macfonts_la_LIBADD = $(HARFBUZZ_LIBS) $(MY_LUA_LIB) endif +pkglib_LTLIBRARIES += justenoughlibtexpdf.la justenoughlibtexpdf_la_SOURCES = justenoughlibtexpdf.c imagebbox.c justenoughlibtexpdf_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) justenoughlibtexpdf_la_CFLAGS = -I.. $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) justenoughlibtexpdf_la_LIBADD = $(LIBTEXPDF_LIB) $(LIBPNG_LIBS) $(ZLIB_LIBS) $(LIBPAPER_LIBS) $(MY_LUA_LIB) +pkglib_LTLIBRARIES += fontmetrics.la fontmetrics_la_SOURCES = fontmetrics.c hb-utils.c hb-utils.h fontmetrics_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) fontmetrics_la_CFLAGS = $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) fontmetrics_la_LIBADD = $(MY_LUA_LIB) $(HARFBUZZ_LIBS) +pkglib_LTLIBRARIES += svg.la svg_la_SOURCES = svg.c nanosvg.h svg_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) svg_la_CFLAGS = $(LUA_INCLUDE) From e31c196169e2bfc146d0a96f834a2a0ae75b6c67 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 2 Oct 2023 09:43:29 +0300 Subject: [PATCH 099/357] refactor(build): Touchup developer mode path handling --- configure.ac | 12 ++++++------ core/pathsetup.lua.in | 9 ++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index cbb701841..ffc0ddd7e 100644 --- a/configure.ac +++ b/configure.ac @@ -240,13 +240,12 @@ AC_SUBST([LUAROCKSARGS]) # Avoid need for `--datarootdir=$(cd ..; pwd)` hack to run locally for # tests/manual build when developer mode is enabled AM_COND_IF([DEVELOPER], [ - adl_RECURSIVE_EVAL(["$(pwd)"], [SILE_PATH]) - AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) - ],[ - adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) - AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) + adl_RECURSIVE_EVAL(["$(pwd)"], [SILE_PATH]) + datarootdir="$(cd ..; pwd)" +],[ + adl_RECURSIVE_EVAL(["${datadir}/${TRANSFORMED_PACKAGE_NAME}"], [SILE_PATH]) ]) - +AC_DEFINE_UNQUOTED([SILE_PATH], ["${SILE_PATH}"], [Path for SILE packages and classes]) AC_SUBST([SILE_PATH]) # In order for our Rust CLI binary to use the same default package.path as the system Lua, @@ -254,6 +253,7 @@ AC_SUBST([SILE_PATH]) adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.path)')"], [LUA_PATH]) AC_DEFINE_UNQUOTED([LUA_PATH], ["${LUA_PATH}"],[System Lua package path]) AC_SUBST([LUA_PATH]) + adl_RECURSIVE_EVAL(["$(${LUA} -e 'print(package.cpath)')"], [LUA_CPATH]) AC_DEFINE_UNQUOTED([LUA_CPATH], ["${LUA_CPATH}"], [System Lua package cpath]) AC_SUBST([LUA_CPATH]) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index bb3193076..b0994d4f2 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -4,11 +4,6 @@ if "@LUA_PATH@" ~= "" then package.cpath = "@LUA_CPATH@" end -if "@DEVELOPER_FALSE@" ~= "" then - package.cpath = package.cpath .. ";./libtexpdf/.libs/?.so" - package.cpath = package.cpath .. ";./justenough/.libs/?.so" - end - local executable = debug.getinfo(3, "S").source local luaversion = _VERSION:match("%d+%.%d+") @@ -36,6 +31,10 @@ local function extendPaths (path, ours) prependCPath(path) prependPath(path) if ours then + if "@DEVELOPER_FALSE@" ~= "" then -- see ./configure --(en|dis)able-developer + prependCPath(path .. "/libtexpdf/.libs") + prependCPath(path .. "/justenough/.libs") + end prependPath(path .. "/lua-libraries") if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks prependCPath(path .. "/lua_modules/lib/lua/" .. luaversion) From b3299239f608fea68d7b9c491e6f25e7abc889c0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 2 Oct 2023 11:00:11 +0300 Subject: [PATCH 100/357] feat(core): Allow multiple runtime SILE_PATH segments --- src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 49939e863..c19ab2d55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,11 @@ pub fn version() -> crate::Result { let sile_path: LuaString = lua.create_string(&sile_path)?; let sile: LuaTable = lua .load(chunk! { - local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") + local status + for path in string.gmatch($sile_path, "[^;]+") do + status = pcall(dofile, path .. "/core/pathsetup.lua") + if status then break end + end if not status then dofile("./core/pathsetup.lua") end @@ -56,7 +60,11 @@ pub fn run( let sile_path: LuaString = lua.create_string(&sile_path)?; let sile: LuaTable = lua .load(chunk! { - local status = pcall(dofile, $sile_path .. "/core/pathsetup.lua") + local status + for path in string.gmatch($sile_path, "[^;]+") do + status = pcall(dofile, path .. "/core/pathsetup.lua") + if status then break end + end if not status then dofile("./core/pathsetup.lua") end From d65adf50d10a792848df96034659126f3e5d6ad6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 2 Oct 2023 16:36:32 +0300 Subject: [PATCH 101/357] refactor(cli): Use consistent plural variables for tables/Vecs --- src/bin/sile.rs | 4 ++-- src/cli.rs | 4 ++-- src/lib.rs | 28 ++++++++++++++-------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 4fa00604f..0b5e957a7 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -14,7 +14,7 @@ fn main() -> sile::Result<()> { let matches = app.get_matches(); let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments"); sile::run( - args.inputs, + args.input, args.backend, args.class, args.debug, @@ -23,7 +23,7 @@ fn main() -> sile::Result<()> { args.fontmanager, args.makedeps, args.output, - args.options, + args.option, args.preamble, args.postamble, args.r#use, diff --git a/src/cli.rs b/src/cli.rs index 758374113..3eda24b05 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; #[clap(author, name = "SILE", bin_name = "sile")] pub struct Cli { /// Input document, by default in SIL or XML format - pub inputs: Option>, + pub input: Option>, /// Choose an alternative output backend #[clap(short, long, value_name = "BACKEND")] @@ -46,7 +46,7 @@ pub struct Cli { /// Set document class options #[clap(short = 'O', long)] - pub options: Option>, + pub option: Option>, /// Process SIL, XML, or other content before the input document #[clap(short, long, value_name = "FILE")] diff --git a/src/lib.rs b/src/lib.rs index c19ab2d55..fd32d909a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,16 +39,16 @@ pub fn run( inputs: Option>, backend: Option, class: Option, - debug: Option>, - evaluate: Option>, - evaluate_after: Option>, + debugs: Option>, + evaluates: Option>, + evaluate_afters: Option>, fontmanager: Option, makedeps: Option, output: Option, options: Option>, - preamble: Option>, - postamble: Option>, - r#use: Option>, + preambles: Option>, + postambles: Option>, + uses: Option>, quiet: bool, traceback: bool, ) -> crate::Result<()> { @@ -77,7 +77,7 @@ pub fn run( sile.set("traceback", traceback)?; sile.set("quiet", quiet)?; let mut has_input_filename = false; - if let Some(flags) = debug { + if let Some(flags) = debugs { let debug_flags: LuaTable = sile.get("debugFlags")?; for flag in flags { debug_flags.set(flag, true)?; @@ -85,10 +85,10 @@ pub fn run( } let full_version: String = sile.get("full_version")?; let sile_input: LuaTable = sile.get("input")?; - if let Some(expressions) = evaluate { + if let Some(expressions) = evaluates { sile_input.set("evaluates", expressions)?; } - if let Some(expressions) = evaluate_after { + if let Some(expressions) = evaluate_afters { sile_input.set("evaluateAfters", expressions)?; } if let Some(backend) = backend { @@ -100,11 +100,11 @@ pub fn run( if let Some(class) = class { sile_input.set("class", class)?; } - if let Some(paths) = preamble { + if let Some(paths) = preambles { sile_input.set("preambles", paths_to_strings(paths))?; } - if let Some(paths) = postamble { - sile_input.set("postamble", paths_to_strings(paths))?; + if let Some(paths) = postambles { + sile_input.set("postambles", paths_to_strings(paths))?; } if let Some(path) = makedeps { sile_input.set("makedeps", path_to_string(&path))?; @@ -116,8 +116,8 @@ pub fn run( if let Some(options) = options { sile_input.set("options", options)?; } - if let Some(modules) = r#use { - sile_input.set("use", modules)?; + if let Some(modules) = uses { + sile_input.set("uses", modules)?; } if !quiet { eprintln!("{full_version}"); From 83f93ce787cf77f7ce13471aac846c6bd1aca5c0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 3 Oct 2023 00:10:26 +0300 Subject: [PATCH 102/357] chore(cli): Implement SILE.use() from CLI args in Rust wrapper --- src/lib.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index fd32d909a..82754be26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,7 +117,18 @@ pub fn run( sile_input.set("options", options)?; } if let Some(modules) = uses { - sile_input.set("uses", modules)?; + // let parser_bits: LuaTable = sile.get("parserBits")?; + // let cliuse: LuaAnyUserData = parser_bits.get("cliuse")?; + // sile_input.get("uses")?; + for module in modules.iter() { + let module = lua.create_string(module)?; + lua.load(chunk! { + local spec = SILE.parserBits.cliuse:match($module); + table.insert(SILE.input.uses, spec) + }) + .eval()?; + // let spec = cliuse.call_function::<_, _, _>("match", module); + } } if !quiet { eprintln!("{full_version}"); @@ -139,6 +150,14 @@ pub fn run( ); } sile_input.set("filenames", input_filenames)?; + let input_uses: LuaTable = sile_input.get("uses")?; + let r#use: LuaFunction = sile.get("use")?; + for spec in input_uses.sequence_values::() { + let spec = spec?; + let module: LuaString = spec.get("module")?; + let options: LuaTable = spec.get("options")?; + r#use.call::<(LuaString, LuaTable), _>((module, options))?; + } let input_filenames: LuaTable = sile_input.get("filenames")?; let process_file: LuaFunction = sile.get("processFile")?; for file in input_filenames.sequence_values::() { From 796b344e557895c5448e552898a808750d382835 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 3 Oct 2023 02:49:21 +0300 Subject: [PATCH 103/357] feat(core): Make it easier to add project-specific LuaRocks trees as dependencies --- core/pathsetup.lua.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index b0994d4f2..1c2e0f59c 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -36,10 +36,8 @@ local function extendPaths (path, ours) prependCPath(path .. "/justenough/.libs") end prependPath(path .. "/lua-libraries") - if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks - prependCPath(path .. "/lua_modules/lib/lua/" .. luaversion) - prependPath(path .. "/lua_modules/share/lua/" .. luaversion) - end + prependCPath(path .. "/lib/lua/" .. luaversion) + prependPath(path .. "/share/lua/" .. luaversion) else prependCPath(path .. "/sile") prependPath(path .. "/sile") @@ -58,6 +56,9 @@ package.path = table.concat(luapath, ";") extendPaths("@SILE_PATH@", true) extendPaths("@SILE_LIB_PATH@", true) +if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks + extendPaths("@SILE_PATH@/lua_modules") +end package.path = table.concat(extpath, ";") .. ";" .. package.path From 133567e5bb208cce52f748ee6d530d04774c0caa Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 3 Oct 2023 03:22:08 +0300 Subject: [PATCH 104/357] chore(classes)!: Remove obsolete/broken native markdown class Drop the markdown parser based on a Lunamark fork. 3rd party packages now support Markdown parsing in a more robust way than the vendered fork of a Lua parser ever did. Previously implemented in 5f462836f, but not marked as breaking. This commit is to get the change to show up in breaking changes. From fd940a9e0a8d2f813c04c80d408755a28957dcea Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 5 Oct 2023 13:58:14 +0300 Subject: [PATCH 105/357] feat(core): Automaticalyl include project-local lua_modules in module loader path --- core/pathsetup.lua.in | 1 + 1 file changed, 1 insertion(+) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index 1c2e0f59c..ced6f6332 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -77,6 +77,7 @@ if cwd:match("^@") then -- Consider "ours" for the sake of Nix Flake else if cwd ~= "./" then extendPaths(cwd) end extendPaths(".") + extendPaths("./lua_modules") end _G.extendSilePath = extendPaths From 52df41f931141cfc32afaf50733a5e07be7e10fc Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 23 Aug 2023 01:31:12 +0200 Subject: [PATCH 106/357] refactor(packages,outputters): Move pdf:bookmark and pdf:metadata logic to the outputter --- outputters/base.lua | 4 +++ outputters/libtexpdf.lua | 37 ++++++++++++++++++++++ packages/pdf/init.lua | 67 +++++++++------------------------------- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/outputters/base.lua b/outputters/base.lua index 30fd6d75b..2dfe4ae4a 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -40,6 +40,10 @@ function outputter.enterLinkTarget (_, _, _) end function outputter.leaveLinkTarget (_, _, _, _, _, _, _) end +function outputter.setMetadata (_, _, _) end + +function outputter.setBookmark (_, _, _) end + function outputter:getOutputFilename () local fname if SILE.outputFilename then diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index 35a29dec9..0c0c811ab 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -342,4 +342,41 @@ function outputter.leaveLinkTarget (_, x0, y0, x1, y1, dest, opts) trueXCoord(x1), trueYCoord(y1 + opts.borderoffset)) end +-- Bookmarks and metadata + +local function validate_date (date) + return string.match(date, [[^D:%d+%s*-%s*%d%d%s*'%s*%d%d%s*'?$]]) ~= nil +end + +function outputter:setMetadata (key, value) + if key == "Trapped" then + SU.warn("Skipping special metadata key \\Trapped") + return + end + + if key == "ModDate" or key == "CreationDate" then + if not validate_date(value) then + SU.warn("Invalid date: " .. value) + return + end + else + -- see comment in on bookmark + value = SU.utf8_to_utf16be(value) + end + self:_ensureInit() + pdf.metadata(key, value) +end + +function outputter:setBookmark (dest, title, level) + -- Added UTF8 to UTF16-BE conversion + -- For annotations and bookmarks, text strings must be encoded using + -- either PDFDocEncoding or UTF16-BE with a leading byte-order marker. + -- As PDFDocEncoding supports only limited character repertoire for + -- European languages, we use UTF-16BE for internationalization. + local ustr = SU.utf8_to_utf16be_hexencoded(title) + local d = "</A<>>>" + self:_ensureInit() + pdf.bookmark(d, level) +end + return outputter diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index c31d4e624..9a9e2f394 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -1,22 +1,13 @@ +-- +-- This package and its commands are perhaps ill-named: +-- Exception made of the pdf:literal command below, the concepts of links +-- (anchor, target), bookmarks, and metadata are not specific to PDF. +-- local base = require("packages.base") local package = pl.class(base) package._name = "pdf" -local pdf - -local function validate_date (date) - return string.match(date, [[^D:%d+%s*-%s*%d%d%s*'%s*%d%d%s*'?$]]) ~= nil -end - -function package:_init () - base._init(self) - pdf = require("justenoughlibtexpdf") - if SILE.outputter._name ~= "libtexpdf" then - SU.error("pdf package requires libtexpdf backend") - end -end - function package:registerCommands () self:registerCommand("pdf:destination", function (options, _) @@ -36,29 +27,26 @@ function package:registerCommands () self:registerCommand("pdf:bookmark", function (options, _) local dest = SU.required(options, "dest", "pdf:bookmark") local title = SU.required(options, "title", "pdf:bookmark") - local level = options.level or 1 - -- Added UTF8 to UTF16-BE conversion - -- For annotations and bookmarks, text strings must be encoded using - -- either PDFDocEncoding or UTF16-BE with a leading byte-order marker. - -- As PDFDocEncoding supports only limited character repertoire for - -- European languages, we use UTF-16BE for internationalization. - local ustr = SU.utf8_to_utf16be_hexencoded(title) - if type(SILE.outputter._ensureInit) == "function" then - SILE.outputter:_ensureInit() - end + local level = SU.cast("integer", options.level or 1) SILE.typesetter:pushHbox({ value = nil, height = SILE.measurement(0), width = SILE.measurement(0), depth = SILE.measurement(0), outputYourself = function () - local d = "</A<>>>" - pdf.bookmark(d, level) + SILE.outputter:setBookmark(dest, title, level) end }) end) self:registerCommand("pdf:literal", function (_, content) + -- NOTE: This method is used by the pdfstructure package and should + -- probably be moved elsewhere, so there's no attempt here to delegate + -- the low-level libtexpdf call to te outputter. + if SILE.outputter._name ~= "libtexpdf" then + SU.error("pdf package requires libtexpdf backend") + end + local pdf = require("justenoughlibtexpdf") if type(SILE.outputter._ensureInit) == "function" then SILE.outputter:_ensureInit() end @@ -122,32 +110,7 @@ function package:registerCommands () end local value = SU.required(options, "value", "pdf:metadata") - if key == "Trapped" then - SU.warn("Skipping special metadata key \\Trapped") - return - end - - if key == "ModDate" or key == "CreationDate" then - if not validate_date(value) then - SU.warn("Invalid date: " .. value) - return - end - else - -- see comment in pdf:bookmark - value = SU.utf8_to_utf16be(value) - end - if type(SILE.outputter._ensureInit) == "function" then - SILE.outputter:_ensureInit() - end - SILE.typesetter:pushHbox({ - value = nil, - height = SILE.measurement(0), - width = SILE.measurement(0), - depth = SILE.measurement(0), - outputYourself = function (_, _, _) - pdf.metadata(key, value) - end - }) + SILE.outputter:setMetadata(key, value) end) end From 697188bb0a8af0c9ba3938583c2f5cc570a8b380 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 23 Aug 2023 13:16:34 +0200 Subject: [PATCH 107/357] refactor(packages,outputters): Code-cleanup in cropmarks, background and outputters --- outputters/libtexpdf.lua | 29 +++++++++++++++-------------- packages/background/init.lua | 19 ++++++++----------- packages/cropmarks/init.lua | 6 ++---- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index 0c0c811ab..e49b773f4 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -22,20 +22,21 @@ local outputter = pl.class(base) outputter._name = "libtexpdf" outputter.extension = "pdf" --- Sometimes setCoord is called before the outputter has ensure initialization! +-- N.B. Sometimes setCoord is called before the outputter has ensured initialization. +-- This ok for coordinates manipulation, at these points we know the page size. local deltaX local deltaY local function trueXCoord (x) if not deltaX then - deltaX = SILE.documentState.sheetSize[1] - SILE.documentState.paperSize[1] + deltaX = (SILE.documentState.sheetSize[1] - SILE.documentState.paperSize[1]) / 2 end - return x + deltaX / 2 + return x + deltaX end local function trueYCoord (y) if not deltaY then - deltaY = SILE.documentState.sheetSize[2] - SILE.documentState.paperSize[2] + deltaY = (SILE.documentState.sheetSize[2] - SILE.documentState.paperSize[2]) / 2 end - return y + deltaY / 2 + return y + deltaY end -- The outputter init can't actually initialize output (as logical as it might @@ -368,15 +369,15 @@ function outputter:setMetadata (key, value) end function outputter:setBookmark (dest, title, level) - -- Added UTF8 to UTF16-BE conversion - -- For annotations and bookmarks, text strings must be encoded using - -- either PDFDocEncoding or UTF16-BE with a leading byte-order marker. - -- As PDFDocEncoding supports only limited character repertoire for - -- European languages, we use UTF-16BE for internationalization. - local ustr = SU.utf8_to_utf16be_hexencoded(title) - local d = "</A<>>>" - self:_ensureInit() - pdf.bookmark(d, level) + -- Added UTF8 to UTF16-BE conversion + -- For annotations and bookmarks, text strings must be encoded using + -- either PDFDocEncoding or UTF16-BE with a leading byte-order marker. + -- As PDFDocEncoding supports only limited character repertoire for + -- European languages, we use UTF-16BE for internationalization. + local ustr = SU.utf8_to_utf16be_hexencoded(title) + local d = "</A<>>>" + self:_ensureInit() + pdf.bookmark(d, level) end return outputter diff --git a/packages/background/init.lua b/packages/background/init.lua index 00740bae9..10e7a7117 100644 --- a/packages/background/init.lua +++ b/packages/background/init.lua @@ -3,11 +3,12 @@ local base = require("packages.base") local package = pl.class(base) package._name = "background" -local outputBackground = function (background) +local background = {} + +local outputBackground = function () local pagea = SILE.getFrame("page") local offset = SILE.documentState.bleed / 2 if type(background.bg) == "string" then - -- FIXME SILE.outputter:drawImage(background.bg, pagea:left() - offset, pagea:top() - offset, pagea:width() + 2 * offset, pagea:height() + 2 * offset) @@ -23,13 +24,9 @@ local outputBackground = function (background) end end -SILE.scratch.background = SILE.scratch.background or {} - function package:_init () base._init(self) - self.class:registerHook("newpage", function (_) - outputBackground(SILE.scratch.background) - end ) + self.class:registerHook("newpage", outputBackground) end function package:registerCommands () @@ -37,18 +34,18 @@ function package:registerCommands () self:registerCommand("background", function (options, _) if SU.boolean(options.disable, false) then -- This option is certainly better than enforcing a white color. - SILE.scratch.background.bg = nil + background.bg = nil return end local allpages = SU.boolean(options.allpages, true) - SILE.scratch.background.allpages = allpages + background.allpages = allpages local color = options.color and SILE.color(options.color) local src = options.src if src then - SILE.scratch.background.bg = src and SILE.resolveFile(src) or SU.error("Couldn't find file "..src) + background.bg = src and SILE.resolveFile(src) or SU.error("Couldn't find file "..src) elseif color then - SILE.scratch.background.bg = color + background.bg = color else SU.error("background requires a color or an image src parameter") end diff --git a/packages/cropmarks/init.lua b/packages/cropmarks/init.lua index 8c7c65c91..87148ee9f 100644 --- a/packages/cropmarks/init.lua +++ b/packages/cropmarks/init.lua @@ -28,7 +28,7 @@ local function outputMarks () if SILE.Commands["crop:header"] then -- Deprecation shim: -- If user redefined this command, still use it with a warning... - SU.deprecated("crop:header", "cropmarks:header", "0.14.0", "0.16.0") + SU.deprecated("crop:header", "cropmarks:header", "0.15.0", "0.16.0") SILE.call("crop:header") else SILE.call("cropmarks:header") @@ -66,9 +66,7 @@ function package:registerCommands () end) self:registerCommand("cropmarks:setup", function (_, _) - self.class:registerHook("endpage", function (_) - outputMarks() - end ) + self.class:registerHook("endpage", outputMarks) end) self:registerCommand("crop:setup", function (_, _) From 3aecb459b9a34c4660f69cf6c9fabe1b5c610149 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 23 Aug 2023 20:17:21 +0200 Subject: [PATCH 108/357] refactor(packages): Let url package always load the pdf package --- packages/url/init.lua | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/packages/url/init.lua b/packages/url/init.lua index f30259445..b754595cc 100644 --- a/packages/url/init.lua +++ b/packages/url/init.lua @@ -3,8 +3,6 @@ local base = require("packages.base") local package = pl.class(base) package._name = "url" -local pdf - -- URL escape sequence, URL fragment: local preferBreakBefore = "%#" -- URL path elements, URL query arguments, acceptable extras: @@ -23,8 +21,7 @@ function package:_init () base._init(self) self:loadPackage("verbatim") self:loadPackage("inputfilter") - pdf = SILE.outputter._name == "libtexpdf" - if pdf then self:loadPackage("pdf") end + self:loadPackage("pdf") end function package.declareSettings (_) @@ -48,15 +45,6 @@ end function package:registerCommands () self:registerCommand("href", function (options, content) - if not pdf then - if options.src then - SILE.process(content) - else - SILE.call("url", { language = options.language }, content) - end - return -- DONE. - end - if options.src then SILE.call("pdf:link", { dest = options.src, external = true, borderwidth = options.borderwidth, From 89fb72c886941c194e81513f0de6b138098d5675 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 23 Aug 2023 20:36:52 +0200 Subject: [PATCH 109/357] test(packages): Update bug-337 and bug-353 to load the color package --- tests/bug-337.sil | 1 + tests/bug-353.sil | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/bug-337.sil b/tests/bug-337.sil index 66a746aa1..6f71122e1 100644 --- a/tests/bug-337.sil +++ b/tests/bug-337.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.color] \script[src=inc.bug-337] \define[command=crop:header]{tests/bug-337.sil} \crop:setup[papersize=a6] diff --git a/tests/bug-353.sil b/tests/bug-353.sil index 636cb60e5..b564c40ca 100644 --- a/tests/bug-353.sil +++ b/tests/bug-353.sil @@ -1,5 +1,6 @@ \begin[papersize=a5]{document} \use[module=packages.background] +\use[module=packages.color] \nofolios \background[color=#e9d8ba] \color[color=#5a4129]{Sepia baby.} From 67bfcaeca57d8d584aa5c13a2eeefd5198aa20c2 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 23 Aug 2023 21:13:16 +0200 Subject: [PATCH 110/357] test(packages): Update cropmarks bug-337 and expectations --- tests/bug-337.expected | 81 +++++++++++++++++++++--------------------- tests/bug-337.sil | 6 ++-- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/tests/bug-337.expected b/tests/bug-337.expected index a21541759..ed8b90595 100644 --- a/tests/bug-337.expected +++ b/tests/bug-337.expected @@ -1,69 +1,68 @@ -Set paper size 297.6377985 419.5275636 +Set paper size 209.7637818 297.6377985 Begin page -Mx 43.9370 -My 67.1949 +My 6.2500 Set font Gentium Plus;10;400;;normal;;;LTR T 21 20 19 83 87 w=22.8174 (210pt) -Mx 69.4140 +Mx 25.4770 T 2258 w=4.1016 (×) -Mx 76.1752 +Mx 32.2382 T 21 28 27 83 87 w=22.8174 (298pt) -Draw line 33.9370 60.9449 -10.0000 0.5000 -Draw line 43.9370 50.9449 0.5000 -10.0000 -Draw line 263.7008 60.9449 10.0000 0.5000 -Draw line 253.7008 50.9449 0.5000 -10.0000 -Draw line 33.9370 358.5827 -10.0000 0.5000 -Draw line 43.9370 368.5827 0.5000 10.0000 -Draw line 263.7008 358.5827 10.0000 0.5000 -Draw line 253.7008 368.5827 0.5000 10.0000 -Mx 53.9370 -My 47.9449 +Draw line -10.0000 0.0000 -20.0000 0.5000 +Draw line 0.0000 -10.0000 0.5000 -20.0000 +Draw line 219.7638 0.0000 20.0000 0.5000 +Draw line 209.7638 -10.0000 0.5000 -20.0000 +Draw line -10.0000 297.6378 -20.0000 0.5000 +Draw line 0.0000 307.6378 0.5000 20.0000 +Draw line 219.7638 297.6378 20.0000 0.5000 +Draw line 209.7638 307.6378 0.5000 20.0000 +Mx 10.0000 +My -14.0000 Set font Gentium Plus;6;400;;normal;;;LTR T 87 72 86 87 86 w=11.5371 (tests) -Mx 65.4741 +Mx 21.5371 T 18 w=2.8154 (/) -Mx 68.2895 +Mx 24.3525 T 69 88 74 w=9.1523 (bug) -Mx 77.4419 +Mx 33.5049 T 16 w=2.0215 (-) -Mx 79.4634 +Mx 35.5264 T 22 22 26 w=8.4463 (337) -Mx 87.9097 +Mx 43.9727 T 17 w=1.3740 (.) -Mx 89.2837 +Mx 45.3467 T 86 76 79 w=5.5693 (sil) New page -Mx 43.9370 -My 67.1949 +Mx 0.0000 +My 6.2500 Set font Gentium Plus;10;400;;normal;;;LTR T 21 20 19 83 87 w=22.8174 (210pt) -Mx 69.4140 +Mx 25.4770 T 2258 w=4.1016 (×) -Mx 76.1752 +Mx 32.2382 T 21 28 27 83 87 w=22.8174 (298pt) -Draw line 33.9370 60.9449 -10.0000 0.5000 -Draw line 43.9370 50.9449 0.5000 -10.0000 -Draw line 263.7008 60.9449 10.0000 0.5000 -Draw line 253.7008 50.9449 0.5000 -10.0000 -Draw line 33.9370 358.5827 -10.0000 0.5000 -Draw line 43.9370 368.5827 0.5000 10.0000 -Draw line 263.7008 358.5827 10.0000 0.5000 -Draw line 253.7008 368.5827 0.5000 10.0000 -Mx 53.9370 -My 47.9449 +Draw line -10.0000 0.0000 -20.0000 0.5000 +Draw line 0.0000 -10.0000 0.5000 -20.0000 +Draw line 219.7638 0.0000 20.0000 0.5000 +Draw line 209.7638 -10.0000 0.5000 -20.0000 +Draw line -10.0000 297.6378 -20.0000 0.5000 +Draw line 0.0000 307.6378 0.5000 20.0000 +Draw line 219.7638 297.6378 20.0000 0.5000 +Draw line 209.7638 307.6378 0.5000 20.0000 +Mx 10.0000 +My -14.0000 Set font Gentium Plus;6;400;;normal;;;LTR T 87 72 86 87 86 w=11.5371 (tests) -Mx 65.4741 +Mx 21.5371 T 18 w=2.8154 (/) -Mx 68.2895 +Mx 24.3525 T 69 88 74 w=9.1523 (bug) -Mx 77.4419 +Mx 33.5049 T 16 w=2.0215 (-) -Mx 79.4634 +Mx 35.5264 T 22 22 26 w=8.4463 (337) -Mx 87.9097 +Mx 43.9727 T 17 w=1.3740 (.) -Mx 89.2837 +Mx 45.3467 T 86 76 79 w=5.5693 (sil) End page Finish diff --git a/tests/bug-337.sil b/tests/bug-337.sil index 6f71122e1..54ca7a454 100644 --- a/tests/bug-337.sil +++ b/tests/bug-337.sil @@ -1,8 +1,8 @@ -\begin[papersize=a7,class=book]{document} +\begin[papersize=a7,class=book, sheetsize=a6]{document} \use[module=packages.color] \script[src=inc.bug-337] -\define[command=crop:header]{tests/bug-337.sil} -\crop:setup[papersize=a6] +\define[command=cropmarks:header]{tests/bug-337.sil} +\cropmarks:setup \nofolios \set[parameter=document.parindent,value=0] From 2049745f85a05c3b6740faa0c8d9cd2525893854 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Thu, 24 Aug 2023 00:25:41 +0200 Subject: [PATCH 111/357] docs(manual): Document new full bleed printing and sheet size options --- documentation/c03-input.sil | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/documentation/c03-input.sil b/documentation/c03-input.sil index 051635cb4..2894ffdbb 100644 --- a/documentation/c03-input.sil +++ b/documentation/c03-input.sil @@ -61,6 +61,25 @@ Once some of the basic document properties have been set up using these fixed si For example, once the paper size is set, percentage of page width (\code{\%pw}) and height(\code{\%ph}) become valid units. In Chapter 4 we will meet more of these relative units, and in Chapter 7 we will meet some other ways of specifying lengths to make them stretchable or shrinkable. +When preparing a book for press printing, you may be asked by the professional printer to output the document on a larger sheet than your target paper, and to reserve a trim area around it. +This trick is often called “full bleed printing”. +Your document will be printed on an oversized sheet that will then be mechanically cut down to the target size. +You can specify the expected “trim” (or “bleed”) dimension, to be distributed evenly on all sides +of the document: + +\code{papersize=\em{}, bleed=\em{}}. + +For instance, a US trade book with an extra 0.125 inch bleed area can be specified by \code{papersize=6in x 9in, bleed=0.25in}. +The output paper size is then 6.25 per 9.25 inches, with the actual 6 per 9 inches inner content centered. + +Some packages, such as \autodoc:package{background} and \autodoc:package{cropmarks}, ensure their content extends over the trim area and thus indeed “bleeds” off the sides of the page, so that artifacts such as blank lines are avoided when the sheets are cut, would they be trimmed slightly differently for some assembling or technical reasons. + +Finally, there is also the case when the actual paper sheets available to you are larger than your target paper size, and yet you would want the output document to show properly centered: + +\code{papersize=\em{}, sheetsize=\em{}}. + +For instance, \code{papersize=6in x 9in, sheetsize=a4} produces an A4-dimensioned document, but with you content formatted as a 6 per 9 inches US trade book. You may, obviously, combine these options and also specify a bleed area. + \section{Ordinary text} On the whole, ordinary text isn’t particularly interesting—it’s just typeset. From 6f8a0224974eb92661b569da6c8bffa3b8a2e3a8 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Thu, 24 Aug 2023 01:00:50 +0200 Subject: [PATCH 112/357] chore(typesetters,outputters,packages): Clean in-code comments No code change --- outputters/base.lua | 6 +++--- outputters/libtexpdf.lua | 2 ++ packages/cropmarks/init.lua | 2 +- typesetters/base.lua | 4 +--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/outputters/base.lua b/outputters/base.lua index 2dfe4ae4a..4888a0605 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -34,11 +34,11 @@ function outputter.debugFrame (_, _, _) end function outputter.debugHbox (_, _, _) end -function outputter.linkAnchor (_, _, _) end +function outputter.linkAnchor (_, _, _) end -- Unstable API -function outputter.enterLinkTarget (_, _, _) end +function outputter.enterLinkTarget (_, _, _) end -- Unstable API -function outputter.leaveLinkTarget (_, _, _, _, _, _, _) end +function outputter.leaveLinkTarget (_, _, _, _, _, _, _) end -- Unstable API function outputter.setMetadata (_, _, _) end diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index e49b773f4..2c6387719 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -47,6 +47,8 @@ function outputter:_ensureInit () if not started then local w, h = SILE.documentState.sheetSize[1], SILE.documentState.sheetSize[2] local fname = self:getOutputFilename() + -- Ideally we could want to set the PDF CropBox, BleedBox, TrimBox... + -- Our wrapper only manages the MediaBox at this point. pdf.init(fname == "-" and "/dev/stdout" or fname, w, h, SILE.full_version) pdf.beginpage() started = true diff --git a/packages/cropmarks/init.lua b/packages/cropmarks/init.lua index 87148ee9f..5135faef9 100644 --- a/packages/cropmarks/init.lua +++ b/packages/cropmarks/init.lua @@ -7,7 +7,7 @@ local outcounter = 1 local function outputMarks () local page = SILE.getFrame("page") - -- Length of cromark bars + -- Length of crop mark bars local cropsz = 20 -- Ensure the crop marks stay outside the bleed area local offset = math.max(10, SILE.documentState.bleed / 2) diff --git a/typesetters/base.lua b/typesetters/base.lua index f086cbcd5..e30748b01 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -940,14 +940,12 @@ function typesetter:makeHbox (content) local ox = atypesetter.frame.state.cursorX local oy = atypesetter.frame.state.cursorY SILE.outputter:setCursor(atypesetter.frame.state.cursorX, atypesetter.frame.state.cursorY) - -- BEGIN SILEX FIX DEBUG SU.debug("hboxes", function () - -- setCursor also invoked by the internal hboxes etc. + -- setCursor is also invoked by the internal (wrapped) hboxes etc. -- so we must show our debug box before outputting its content. SILE.outputter:debugHbox(box, box:scaledWidth(line)) return "Drew debug outline around hbox" end) - -- END SILEX FIX DEBUG for _, node in ipairs(box.value) do node:outputYourself(atypesetter, line) end From 14d27a7b36fbda180ee4a1576e00f479db201902 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 5 Oct 2023 23:26:56 +0300 Subject: [PATCH 113/357] docs(manpage): Normalize summary across man pages and help flags --- core/cli.lua | 10 +++++----- sile-lua.1.in | 6 +++--- src/cli.rs | 9 +++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/cli.lua b/core/cli.lua index 884f0780d..3d847bda5 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -9,11 +9,11 @@ cli.parseArguments = function () cliargs:set_colsz(0, 120) cliargs:set_name("sile") cliargs:set_description([[ - The SILE typesetter reads a single input file, by default in either SIL or XML format, - and processes it to generate a single output file, by default in PDF format. The - output file will be written to the same name as the input file with the extension - changed to .pdf. Additional input or output formats can be handled by requiring a - module that adds support for them first. + The SILE typesetter reads an input file(s), by default in either SIL or XML format, and + processes them to generate an output file, by default in PDF format. The output will be written + to a file with the same name as the first input file with the extension changed to .pdf unless + the `--output` argument is used. Additional input or output formats can be handled by loading + a module with the `--use` argument to add support for them first. ]]) cliargs:splat("INPUTS", "input document(s), by default in SIL or XML format", nil, 999) cliargs:option("-b, --backend=VALUE", "choose an alternative output backend") diff --git a/sile-lua.1.in b/sile-lua.1.in index 69626942a..322f9aa45 100644 --- a/sile-lua.1.in +++ b/sile-lua.1.in @@ -10,9 +10,9 @@ .I filename.xml .B ] .SH DESCRIPTION -The SILE typesetter reads a single input file, by default in either SIL or XML format, and processes it to generate a single output file, by default in PDF format. -The output will be written to the same name as the input file with the extension changed to .pdf unless the \fB\-\-output\fR flag is used. -Additional input or output formats can be handled by loading a module with \fB\-\-use\fR to add support for them first. +The SILE typesetter reads an input file(s), by default in either SIL or XML format, and processes them to generate an output file, by default in PDF format. +The output will be written to a file with the same name as the first input file with the extension changed to .pdf unless the \fB\-\-output\fR argument is used. +Additional input or output formats can be handled by loading a module with the \fB\-\-use\fR argument to add support for them first. .SH OPTIONS .B @TRANSFORMED_PACKAGE_NAME@ accepts the following feature flags: .TP diff --git a/src/cli.rs b/src/cli.rs index 3eda24b05..24e1e7af8 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,10 +1,11 @@ use clap::Parser; use std::path::PathBuf; -/// The SILE typesetter reads a single input file, by default in either SIL or XML format, and -/// processes it to generate a single output file, by default in PDF format. The output file will -/// be written to the same name as the input file with the extension changed to .pdf. Additional -/// input or output formats can be handled by requiring a module that adds support for them first. +/// The SILE typesetter reads an input file(s), by default in either SIL or XML format, and +/// processes them to generate an output file, by default in PDF format. The output will be written +/// to a file with the same name as the first input file with the extension changed to .pdf unless +/// the `--output` argument is used. Additional input or output formats can be handled by loading +/// a module with the `--use` argument to add support for them first. #[derive(Parser, Debug)] #[clap(author, name = "SILE", bin_name = "sile")] pub struct Cli { From da588c3500d7c66559599027a17813536dddc988 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 00:01:32 +0300 Subject: [PATCH 114/357] chore(deps): Bump minor version updates to crates --- Cargo.lock | 426 ++++++++++++++++++++++++----------------------------- Cargo.toml | 6 +- 2 files changed, 196 insertions(+), 236 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61cf64834..3d7d050e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,58 +4,66 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.2.6" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", + "anstyle-query", "anstyle-wincon", - "concolor-override", - "concolor-query", - "is-terminal", + "colorchoice", "utf8parse", ] [[package]] name = "anstyle" -version = "0.3.5" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.1.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + [[package]] name = "anstyle-wincon" -version = "0.2.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "autocfg" @@ -69,6 +77,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "bstr" version = "0.2.17" @@ -80,11 +94,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -95,24 +110,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.2.1" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.2.1" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", "terminal_size", @@ -120,91 +133,88 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.2.0" +version = "4.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c22dcfb410883764b29953103d9ef7bb8fe21b3fa1158bc99986c2067294bd" +checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.38", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "clap_mangen" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4237e29de9c6949982ba87d51709204504fb8ed2fd38232fcb1e5bf7d4ba48c8" +checksum = "b44f35c514163027542f7147797ff930523eea288e03642727348ef1a9666f6b" dependencies = [ "clap", "roff", ] [[package]] -name = "concolor-override" +name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] -name = "concolor-query" -version = "0.3.3" +name = "deranged" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" -dependencies = [ - "windows-sys 0.45.0", -] +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "enum-iterator" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706d9e7cf1c7664859d79cd524e4e53ea2b67ea03c98cc2870c5e539695d597e" +checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355f93763ef7b0ae1c43c4d8eccc9d5848d84ad1a1d8ce61c421d1ac85a19d05" +checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "errno" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -219,9 +229,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -244,7 +254,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -258,44 +268,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" -version = "0.3.1" +name = "home" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", ] -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "is-terminal" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" -dependencies = [ - "hermit-abi", - "io-lifetimes", - "rustix", - "windows-sys 0.45.0", -] - [[package]] name = "itertools" version = "0.10.5" @@ -307,9 +297,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -322,9 +312,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.141" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libgit2-sys" @@ -340,9 +330,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" dependencies = [ "cc", "libc", @@ -352,48 +342,46 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.1" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lua-src" -version = "544.0.1" +version = "546.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708ba3c844d5e9d38def4a09dd871c17c370f519b3c4b7261fbabe4a613a814c" +checksum = "7c26d4af78361e025a3d03a2b964cd1592aff7495f4d4f7947218c084c6fdca8" dependencies = [ "cc", ] [[package]] name = "luajit-src" -version = "210.4.5+resty2cf5186" +version = "210.4.8+resty107baaf" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b7992a40e602786272d84c6f2beca44a588ededcfd57b48ec6f82008a7cb97" +checksum = "e05167e8b2a2185758d83ed23541e5bd8bce37072e4204e0ef2c9b322bc87c4e" dependencies = [ "cc", + "which", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mlua" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8ce6788556a67d90567809c7de94dfef2ff1f47ff897aeee935bcfbcdf5735" +checksum = "0bb37b0ba91f017aa7ca2b98ef99496827770cd635b4a932a6047c5b4bbe678e" dependencies = [ "bstr", "cc", @@ -423,30 +411,30 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "proc-macro-error" @@ -474,27 +462,39 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.8.1" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "roff" @@ -521,29 +521,42 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.37.7" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] [[package]] name = "sile" @@ -576,9 +589,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.13" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -587,40 +600,41 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.38", ] [[package]] name = "time" -version = "0.3.20" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ + "deranged", "itoa", "serde", "time-core", @@ -629,15 +643,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -665,9 +679,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -680,9 +694,9 @@ dependencies = [ [[package]] name = "url" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -724,12 +738,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "windows-sys" -version = "0.45.0" +name = "which" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ - "windows-targets 0.42.2", + "either", + "home", + "once_cell", + "rustix", ] [[package]] @@ -738,119 +755,62 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index a5c7f04c9..733eb3c68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ required-features = ["cli"] version = "1.0" [dependencies.clap] - version = "4.2" + version = "4.4" optional = true features = [ "derive", "string", "wrap_help" ] @@ -35,7 +35,7 @@ required-features = ["cli"] [build-dependencies] [build-dependencies.clap_complete] - version = "4.2" + version = "4.4" optional = true [build-dependencies.clap_mangen] @@ -43,7 +43,7 @@ required-features = ["cli"] optional = true [build-dependencies.clap] - version = "4.0" + version = "4.4" optional = true features = [ "derive" ] From 0a72a9e2417ff0723e9c57db2d64c7ff16efa64e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 00:08:43 +0300 Subject: [PATCH 115/357] chore(deps): Bump major version of mlua crate --- Cargo.lock | 37 ++++++++++++++++++++++++------------- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d7d050e6..3e1d405ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,11 +85,12 @@ checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "bstr" -version = "0.2.17" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", + "serde", ] [[package]] @@ -288,9 +289,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] @@ -379,26 +380,36 @@ checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mlua" -version = "0.8.10" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb37b0ba91f017aa7ca2b98ef99496827770cd635b4a932a6047c5b4bbe678e" +checksum = "6c3a7a7ff4481ec91b951a733390211a8ace1caba57266ccb5f4d4966704e560" dependencies = [ "bstr", - "cc", - "lua-src", - "luajit-src", + "mlua-sys", "mlua_derive", "num-traits", "once_cell", - "pkg-config", "rustc-hash", ] +[[package]] +name = "mlua-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec8b54eddb76093069cce9eeffb4c7b3a1a0fe66962d7bd44c4867928149ca3" +dependencies = [ + "cc", + "cfg-if", + "lua-src", + "luajit-src", + "pkg-config", +] + [[package]] name = "mlua_derive" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9214e60d3cf1643013b107330fcd374ccec1e4ba1eef76e7e5da5e8202e71c0" +checksum = "0f359220f24e6452dd82a3f50d7242d4aab822b5594798048e953d7a9e0314c6" dependencies = [ "itertools", "once_cell", @@ -406,7 +417,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 733eb3c68..6e42acc5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ required-features = ["cli"] features = [ "derive", "string", "wrap_help" ] [dependencies.mlua] - version = "0.8" + version = "0.9" features = [ "macros", "vendored" ] [build-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 82754be26..34c79e93f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,7 +167,7 @@ pub fn run( finish.call::<_, _>(())?; } else { let repl: LuaTable = sile.get("repl")?; - repl.call_method::<_, _, _>("enter", ())?; + repl.call_method::<_, _>("enter", ())?; } Ok(()) } From 39f7b5c49f953113c5e29b01d87f7376eaff2d91 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 00:16:08 +0300 Subject: [PATCH 116/357] chore(deps): Bump major version of vergen crate --- Cargo.lock | 849 ++++++++++++++++++++++++++++++++++++++++----- Cargo.toml | 4 +- build-aux/build.rs | 32 +- src/bin/sile.rs | 5 +- 4 files changed, 795 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e1d405ac..71e602828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "1.1.1" @@ -65,6 +71,12 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + [[package]] name = "autocfg" version = "1.1.0" @@ -90,16 +102,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", + "regex-automata", "serde", ] +[[package]] +name = "btoi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad" +dependencies = [ + "num-traits", +] + [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ - "jobserver", "libc", ] @@ -169,18 +190,39 @@ dependencies = [ "roff", ] +[[package]] +name = "clru" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" + [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "deranged" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "either" version = "1.9.0" @@ -188,44 +230,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] -name = "enum-iterator" -version = "1.4.1" +name = "errno" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7add3873b5dd076766ee79c8e406ad1a472c385476b9e38849f8eec24f1be689" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ - "enum-iterator-derive", + "errno-dragonfly", + "libc", + "windows-sys", ] [[package]] -name = "enum-iterator-derive" -version = "1.2.1" +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", + "cc", + "libc", ] [[package]] -name = "errno" -version = "0.3.4" +name = "faster-hex" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +checksum = "239f7bfb930f820ab16a9cd95afc26f88264cf6905c960b340a615384aa3338a" dependencies = [ - "errno-dragonfly", + "serde", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +dependencies = [ + "cfg-if", "libc", + "redox_syscall", "windows-sys", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "flate2" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ - "cc", - "libc", + "crc32fast", + "miniz_oxide", ] [[package]] @@ -238,30 +297,507 @@ dependencies = [ ] [[package]] -name = "getset" -version = "0.1.2" +name = "gix" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +checksum = "06a8c9f9452078f474fecd2880de84819b8c77224ab62273275b646bf785f906" +dependencies = [ + "gix-actor", + "gix-commitgraph", + "gix-config", + "gix-date", + "gix-diff", + "gix-discover", + "gix-features", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-hashtable", + "gix-index", + "gix-lock", + "gix-macros", + "gix-object", + "gix-odb", + "gix-pack", + "gix-path", + "gix-ref", + "gix-refspec", + "gix-revision", + "gix-revwalk", + "gix-sec", + "gix-tempfile", + "gix-trace", + "gix-traverse", + "gix-url", + "gix-utils", + "gix-validate", + "once_cell", + "parking_lot", + "signal-hook", + "smallvec", + "thiserror", + "unicode-normalization", +] + +[[package]] +name = "gix-actor" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8c6778cc03bca978b2575a03e04e5ba6f430a9dd9b0f1259f0a8a9a5e5cc66" +dependencies = [ + "bstr", + "btoi", + "gix-date", + "itoa", + "thiserror", + "winnow", +] + +[[package]] +name = "gix-bitmap" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ccab4bc576844ddb51b78d81b4a42d73e6229660fa614dfc3d3999c874d1959" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gix-chunk" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b42ea64420f7994000130328f3c7a2038f639120518870436d31b8bde704493" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gix-commitgraph" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676ede3a7d37e7028e2889830349a6aca22efc1d2f2dd9fa3351c1a8ddb0c6a" +dependencies = [ + "bstr", + "gix-chunk", + "gix-features", + "gix-hash", + "memmap2", + "thiserror", +] + +[[package]] +name = "gix-config" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1108c4ac88248dd25cc8ab0d0dae796e619fb72d92f88e30e00b29d61bb93cc4" +dependencies = [ + "bstr", + "gix-config-value", + "gix-features", + "gix-glob", + "gix-path", + "gix-ref", + "gix-sec", + "memchr", + "once_cell", + "smallvec", + "thiserror", + "unicode-bom", + "winnow", +] + +[[package]] +name = "gix-config-value" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea7505b97f4d8e7933e29735a568ba2f86d8de466669d9f0e8321384f9972f47" +dependencies = [ + "bitflags 2.4.0", + "bstr", + "gix-path", + "libc", + "thiserror", +] + +[[package]] +name = "gix-date" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7df669639582dc7c02737642f76890b03b5544e141caba68a7d6b4eb551e0d" +dependencies = [ + "bstr", + "itoa", + "thiserror", + "time", +] + +[[package]] +name = "gix-diff" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45e342d148373bd9070d557e6fb1280aeae29a3e05e32506682d027278501eb" +dependencies = [ + "gix-hash", + "gix-object", + "thiserror", +] + +[[package]] +name = "gix-discover" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4cacda5ee9dd1b38b0e2506834e40e66c08cf050ef55c344334c76745f277b" +dependencies = [ + "bstr", + "dunce", + "gix-hash", + "gix-path", + "gix-ref", + "gix-sec", + "thiserror", +] + +[[package]] +name = "gix-features" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f414c99e1a7abc69b21f3225a6539d203b0513f1d1d448607c4ea81cdcf9ee59" +dependencies = [ + "crc32fast", + "flate2", + "gix-hash", + "gix-trace", + "libc", + "once_cell", + "prodash", + "sha1_smol", + "thiserror", + "walkdir", +] + +[[package]] +name = "gix-fs" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404795da3d4c660c9ab6c3b2ad76d459636d1e1e4b37b0c7ff68eee898c298d4" +dependencies = [ + "gix-features", +] + +[[package]] +name = "gix-glob" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ac79c444193b0660fe0c0925d338bd338bd643e32138784dccfb12c628b892" +dependencies = [ + "bitflags 2.4.0", + "bstr", + "gix-features", + "gix-path", +] + +[[package]] +name = "gix-hash" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ccf425543779cddaa4a7c62aba3fa9d90ea135b160be0a72dd93c063121ad4a" +dependencies = [ + "faster-hex", + "thiserror", +] + +[[package]] +name = "gix-hashtable" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "409268480841ad008e81c17ca5a293393fbf9f2b6c2f85b8ab9de1f0c5176a16" +dependencies = [ + "gix-hash", + "hashbrown", + "parking_lot", +] + +[[package]] +name = "gix-index" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9599fc30b3d6aad231687a403f85dfa36ae37ccf1b68ee1f621ad5b7fc7a0d" +dependencies = [ + "bitflags 2.4.0", + "bstr", + "btoi", + "filetime", + "gix-bitmap", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-traverse", + "itoa", + "memmap2", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-lock" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1568c3d90594c60d52670f325f5db88c2d572e85c8dd45fabc23d91cadb0fd52" +dependencies = [ + "gix-tempfile", + "gix-utils", + "thiserror", +] + +[[package]] +name = "gix-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8acb5ee668d55f0f2d19a320a3f9ef67a6999ad483e11135abcc2464ed18b6" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] -name = "git2" -version = "0.16.1" +name = "gix-object" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" +checksum = "3e5528d5b2c984044d547e696e44a8c45fa122e83cd8c2ac1da69bd474336be8" dependencies = [ - "bitflags 1.3.2", + "bstr", + "btoi", + "gix-actor", + "gix-date", + "gix-features", + "gix-hash", + "gix-validate", + "itoa", + "smallvec", + "thiserror", + "winnow", +] + +[[package]] +name = "gix-odb" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0446eca295459deb3d6dd6ed7d44a631479f1b7381d8087166605c7a9f717c6" +dependencies = [ + "arc-swap", + "gix-date", + "gix-features", + "gix-hash", + "gix-object", + "gix-pack", + "gix-path", + "gix-quote", + "parking_lot", + "tempfile", + "thiserror", +] + +[[package]] +name = "gix-pack" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be19ee650300d7cbac5829b637685ec44a8d921a7c2eaff8a245d8f2f008870c" +dependencies = [ + "clru", + "gix-chunk", + "gix-features", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-path", + "gix-tempfile", + "memmap2", + "parking_lot", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-path" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1d370115171e3ae03c5c6d4f7d096f2981a40ddccb98dfd704c773530ba73b" +dependencies = [ + "bstr", + "gix-trace", + "home", + "once_cell", + "thiserror", +] + +[[package]] +name = "gix-quote" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "475c86a97dd0127ba4465fbb239abac9ea10e68301470c9791a6dd5351cdc905" +dependencies = [ + "bstr", + "btoi", + "thiserror", +] + +[[package]] +name = "gix-ref" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cccbfa8d5cd9b86465f27a521e0c017de54b92d9fd37c143e49c658a2f04f3a" +dependencies = [ + "gix-actor", + "gix-date", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-validate", + "memmap2", + "thiserror", + "winnow", +] + +[[package]] +name = "gix-refspec" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678ba30d95baa5462df9875628ed40655d5f5b8aba7028de86ed57f36e762c6c" +dependencies = [ + "bstr", + "gix-hash", + "gix-revision", + "gix-validate", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-revision" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e80a5992ae446fe1745dd26523b86084e3f1b6b3e35377fe09b4f35ac8f151" +dependencies = [ + "bstr", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "gix-trace", + "thiserror", +] + +[[package]] +name = "gix-revwalk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b806349bc1f668e09035800e07ac8045da4e39a8925a245d93142c4802224ec1" +dependencies = [ + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-sec" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92b9542ac025a8c02ed5d17b3fc031a111a384e859d0be3532ec4d58c40a0f28" +dependencies = [ + "bitflags 2.4.0", + "gix-path", + "libc", + "windows", +] + +[[package]] +name = "gix-tempfile" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2762b91ff95e27ff3ea95758c0d4efacd7435a1be3629622928b8276de0f72a8" +dependencies = [ + "gix-fs", "libc", - "libgit2-sys", - "log", + "once_cell", + "parking_lot", + "signal-hook", + "signal-hook-registry", + "tempfile", +] + +[[package]] +name = "gix-trace" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b6d623a1152c3facb79067d6e2ecdae48130030cf27d6eb21109f13bd7b836" + +[[package]] +name = "gix-traverse" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec6358f8373fb018af8fc96c9d2ec6a5b66999e2377dc40b7801351fec409ed" +dependencies = [ + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-url" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c79d595b99a6c7ab274f3c991735a0c0f5a816a3da460f513c48edf1c7bf2cc" +dependencies = [ + "bstr", + "gix-features", + "gix-path", + "home", + "thiserror", "url", ] +[[package]] +name = "gix-utils" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b85d89dc728613e26e0ed952a19583744e7f5240fcd4aa30d6c824ffd8b52f0f" +dependencies = [ + "fastrand", +] + +[[package]] +name = "gix-validate" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05cab2b03a45b866156e052aa38619f4ece4adcb2f79978bfc249bc3b21b8c5" +dependencies = [ + "bstr", + "thiserror", +] + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" + [[package]] name = "heck" version = "0.4.1" @@ -302,45 +838,12 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - [[package]] name = "libc" version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" -[[package]] -name = "libgit2-sys" -version = "0.14.2+1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libz-sys" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "linux-raw-sys" version = "0.4.8" @@ -348,10 +851,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] -name = "log" -version = "0.4.20" +name = "lock_api" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "lua-src" @@ -378,6 +885,24 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memmap2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" +dependencies = [ + "libc", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mlua" version = "0.9.1" @@ -429,12 +954,44 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + [[package]] name = "percent-encoding" version = "2.3.0" @@ -480,6 +1037,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prodash" +version = "26.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf" + [[package]] name = "quote" version = "1.0.33" @@ -489,6 +1052,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.9.6" @@ -549,6 +1121,21 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.188" @@ -569,6 +1156,31 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "sile" version = "0.14.8" @@ -581,6 +1193,12 @@ dependencies = [ "vergen", ] +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + [[package]] name = "strsim" version = "0.10.0" @@ -594,7 +1212,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", "unicode-ident", ] @@ -609,6 +1226,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + [[package]] name = "terminal_size" version = "0.3.0" @@ -647,6 +1277,8 @@ checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ "deranged", "itoa", + "libc", + "num_threads", "serde", "time-core", "time-macros", @@ -688,6 +1320,12 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +[[package]] +name = "unicode-bom" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -720,25 +1358,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "vergen" -version = "7.5.1" +version = "8.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" +checksum = "85e7dc29b3c54a2ea67ef4f953d5ec0c4085035c0ae2d325be1c0d2144bd9f16" dependencies = [ "anyhow", - "cfg-if", - "enum-iterator", - "getset", - "git2", + "gix", "rustversion", - "thiserror", "time", ] @@ -748,6 +1376,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "which" version = "4.4.2" @@ -760,6 +1398,46 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -825,3 +1503,12 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index 6e42acc5b..08d78f2c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ required-features = ["cli"] features = [ "derive" ] [build-dependencies.vergen] - version = "7.4" + version = "8.2" default-features = false - features = [ "build", "git" ] + features = [ "build", "cargo", "git", "gitoxide" ] [features] default = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"] diff --git a/build-aux/build.rs b/build-aux/build.rs index 5b1945085..f90e33049 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -6,25 +6,24 @@ use clap_complete::generator::generate_to; use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; #[cfg(feature = "manpage")] use clap_mangen::Man; -use std::env; +use std::{collections, env}; #[cfg(feature = "completions")] use std::{fs, path}; -use vergen::{vergen, Config}; +use vergen::EmitBuilder; #[cfg(feature = "completions")] include!("../src/cli.rs"); fn main() { - let mut flags = Config::default(); + let mut builder = EmitBuilder::builder(); + // If passed a version from automake, use that instead of vergen's formatting if let Ok(val) = env::var("VERSION_FROM_AUTOTOOLS") { - *flags.git_mut().semver_mut() = false; - println!("cargo:rustc-env=VERGEN_GIT_SEMVER={val}") + println!("cargo:rustc-env=VERGEN_GIT_DESCRIBE={val}") + } else { + builder = *builder.git_describe(true, true, None); }; - if vergen(flags).is_err() { - let mut flags = Config::default(); - *flags.git_mut().enabled_mut() = false; - vergen(flags).expect("Unable to generate the cargo keys!"); - } + builder.emit().expect("Unable to generate the cargo keys!"); + pass_on_configure_details(); #[cfg(feature = "manpage")] generate_manpage(); #[cfg(feature = "completions")] @@ -84,3 +83,16 @@ fn generate_shell_completions() { generate_to(Zsh, &mut app, bin_name, &completions_dir) .expect("Unable to generate zsh completions"); } + +/// Pass through some variables set by autoconf/automake about where we're installed to cargo for +/// use in finding resources at runtime +fn pass_on_configure_details() { + let mut autoconf_vars = collections::HashMap::new(); + autoconf_vars.insert("CONFIGURE_PREFIX", String::from("./")); + autoconf_vars.insert("CONFIGURE_BINDIR", String::from("./")); + autoconf_vars.insert("CONFIGURE_DATADIR", String::from("./")); + for (var, default) in autoconf_vars { + let val = env::var(var).unwrap_or(default); + println!("cargo:rustc-env={var}={val}"); + } +} diff --git a/src/bin/sile.rs b/src/bin/sile.rs index 0b5e957a7..146f4e7cc 100644 --- a/src/bin/sile.rs +++ b/src/bin/sile.rs @@ -1,9 +1,10 @@ use clap::{CommandFactory, FromArgMatches}; use sile::cli::Cli; +use sile::Result; -fn main() -> sile::Result<()> { - let version = option_env!("VERGEN_GIT_SEMVER").unwrap_or_else(|| env!("VERGEN_BUILD_SEMVER")); +fn main() -> Result<()> { + let version = option_env!("VERGEN_GIT_DESCRIBE").unwrap_or_else(|| env!("CARGO_PKG_VERSION")); let version = version.replacen('-', ".r", 1); let long_version = sile::version()? .strip_prefix("SILE ") From 7af400d8ce2e78f727da8a7a9afce8a98f68dc2d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 00:21:54 +0300 Subject: [PATCH 117/357] chore(deps): Bump LuaRocks dependencies to latest versions --- sile.rockspec.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sile.rockspec.in b/sile.rockspec.in index 3a62a55e0..b3c7b3613 100644 --- a/sile.rockspec.in +++ b/sile.rockspec.in @@ -32,16 +32,16 @@ dependencies = { "fluent == 0.2.0-0", "linenoise == 0.9-1", "loadkit == 1.1.0-1", - "lpeg == 1.0.2-1", + "lpeg == 1.1.0-1", "lua-zlib == 1.2-2", "lua_cliargs == 3.0-2", "luaepnf == 0.3-2", "luaexpat == 1.5.1-1", "luafilesystem == 1.8.0-1", "luarepl == 0.10-1", - "luasec == 1.3.1-1", + "luasec == 1.3.2-1", "luasocket == 3.1.0-1", - "luautf8 == 0.1.5-1", + "luautf8 == 0.1.5-2", "penlight == 1.13.1-1", "vstruct == 2.1.1-1" } From ed688796c6a1cc7f4b8ef2f7e96465e0c7af9618 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 00:54:58 +0300 Subject: [PATCH 118/357] chore(deps): Bump developer tooling --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 2cd7b2b73..5e286ebbf 100644 --- a/package.json +++ b/package.json @@ -19,11 +19,11 @@ }, "homepage": "https://sile-typesetter.org", "devDependencies": { - "@commitlint/cli": "^17.6", - "@commitlint/config-conventional": "^17.6", - "@commitlint/prompt": "^17.6", + "@commitlint/cli": "^17.7", + "@commitlint/config-conventional": "^17.7", + "@commitlint/prompt": "^17.7", "commitizen": "^4.3", - "conventional-changelog-cli": "^4.0", + "conventional-changelog-cli": "^4.1", "husky": "^8.0", "standard-version": "^9.5", "yaml": "^2.3" From ffff1c0131c3015956b64939caf9b2f5812326e0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 01:05:13 +0300 Subject: [PATCH 119/357] chore(tooling): Fixup Flake details, flesh out comments --- Makefile.am | 2 +- pkg.nix => build-aux/pkg.nix | 29 +++++++++++++++++++++++------ flake.nix | 2 +- 3 files changed, 25 insertions(+), 8 deletions(-) rename pkg.nix => build-aux/pkg.nix (78%) diff --git a/Makefile.am b/Makefile.am index 5cbd02b16..52988e6af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,7 +68,7 @@ EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh EXTRA_DIST += Dockerfile build-aux/docker-bootstrap.sh build-aux/docker-fontconfig.conf hooks/build -EXTRA_DIST += default.nix flake.nix flake.lock shell.nix +EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) diff --git a/pkg.nix b/build-aux/pkg.nix similarity index 78% rename from pkg.nix rename to build-aux/pkg.nix index 5d87bfc96..0951c40e8 100644 --- a/pkg.nix +++ b/build-aux/pkg.nix @@ -29,7 +29,6 @@ let luaEnv = lua.withPackages(ps: with ps; [ cassowary cldr - cosmo fluent linenoise loadkit @@ -84,7 +83,7 @@ in stdenv.mkDerivation (finalAttrs: { # derivation). `nix-update` and `nixpkgs-update` should be able to catch that # hash and update it as well when performing updates. cargoDeps = rustPlatform.importCargoLock { - lockFile = ./Cargo.lock; + lockFile = ../Cargo.lock; }; buildInputs = [ @@ -98,16 +97,26 @@ in stdenv.mkDerivation (finalAttrs: { ]; configureFlags = [ + # Nix will supply all the Lua dependencies, so stop the build system from + # bundling vendored copies of them. "--with-system-luarocks" - # TODO: Explain this flag + # The automake check target uses pdfinfo to confirm the output of a test + # run, and uses autotools to discover it. This flake build eschews that + # test because it is run from the source directory but the binary is + # already built with system paths, so it can't be checked under Nix until + # after install. After install the Makefile isn't available of course, so + # we have our own copy of it with a hard coded path to `pdfinfo`. By + # specifying some binary here we skip the configure time test for + # `pdfinfo`, by using `false` we make sure that if it is expected during + # build time we would fail to build since we only provide it at test time. "PDFINFO=false" #"--with-manual" In Nixpkgs we add this flag, here its not important enough - ] ++ lib.optionals lua.pkgs.isLuaJIT [ - "--with-luajit" + ] ++ lib.optionals (!lua.pkgs.isLuaJIT) [ + "--without-luajit" ]; postPatch = '' - patchShebangs build-aux/*.sh + patchShebangs build-aux/*.sh build-aux/git-version-gen '' + lib.optionalString stdenv.isDarwin '' sed -i -e 's|@import AppKit;|#import |' src/macfonts.m ''; @@ -122,6 +131,14 @@ in stdenv.mkDerivation (finalAttrs: { enableParallelBuilding = true; + # Autoconf wants to check that Makefile imports are valid files even before + # it potentially generates said files from substitution templates. The + # upstream project uses a bootstrap.sh to create this. Since we skip that, we + # have to fix this race condition ourselves. + postUnpack = '' + touch source/build-aux/rust_boilerplate.mk + ''; + preBuild = lib.optionalString stdenv.cc.isClang '' substituteInPlace libtexpdf/dpxutil.c \ --replace "ASSERT(ht && ht->table && iter);" "ASSERT(ht && iter);" diff --git a/flake.nix b/flake.nix index 5a1bb103a..6ce0061af 100644 --- a/flake.nix +++ b/flake.nix @@ -37,7 +37,7 @@ inherit (gitignore.lib) gitignoreSource; # https://discourse.nixos.org/t/passing-git-commit-hash-and-tag-to-build-with-flakes/11355/2 version_rev = if (self ? rev) then (builtins.substring 0 7 self.rev) else "dirty"; - sile = pkgs.callPackage ./pkg.nix { + sile = pkgs.callPackage ./build-aux/pkg.nix { version = "${(pkgs.lib.importJSON ./package.json).version}-${version_rev}-flake"; src = pkgs.lib.cleanSourceWith { # Ignore many files that gitignoreSource doesn't ignore, see: From 5fb45f8b61d1ba17a4b76f7e86298030cce9e974 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 22:20:57 +0300 Subject: [PATCH 120/357] chore(tooling): Set default Lua for Flake to LuaJIT --- flake.lock | 18 +++++++++--------- flake.nix | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index e1f2d0d37..0dca04683 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -21,11 +21,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1692799911, - "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -72,11 +72,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694343207, - "narHash": "sha256-jWi7OwFxU5Owi4k2JmiL1sa/OuBCQtpaAesuj5LXC8w=", + "lastModified": 1696577711, + "narHash": "sha256-94VRjvClIKDym1QRqPkX5LTQoAwZ1E6QE/3dWtOXSIQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "78058d810644f5ed276804ce7ea9e82d92bee293", + "rev": "a2eb207f45e4a14a1e3019d9e3863d1e208e2295", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 6ce0061af..52addc5bb 100644 --- a/flake.nix +++ b/flake.nix @@ -97,7 +97,7 @@ lua = pkgs.luajit; }; }; - defaultPackage = sile; + defaultPackage = packages.sile-luajit; apps = rec { default = sile; sile = { From bd2c6f35aaaa2a3739e5e65adb39b3868b87c2a1 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 23:27:48 +0300 Subject: [PATCH 121/357] feat(docker): Deploy upcoming major version branches to a `develop` tag on GHCR --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cd11234a8..cdaa8290b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - develop - rel* tags: - latest From 82c7ba6720bba965518fbc457a7cf60dac469e94 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 23:31:46 +0300 Subject: [PATCH 122/357] chore(deps): Target develop branch from Lua Rockspec --- sile.rockspec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sile.rockspec.in b/sile.rockspec.in index b3c7b3613..9cf849739 100644 --- a/sile.rockspec.in +++ b/sile.rockspec.in @@ -5,7 +5,7 @@ version = "dev-@ROCKREV@" source = { url = "git+https://github.com/sile-typesetter/sile.git", - branch = "master" + branch = "develop" } description = { From 45332d8fecc878c9cc0143d90b4d4ec253bc9d12 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 23:49:05 +0300 Subject: [PATCH 123/357] chore(docker): Update containerized build with development dependencies --- hooks/build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/build b/hooks/build index 44325bff4..d08cb6adf 100755 --- a/hooks/build +++ b/hooks/build @@ -5,8 +5,8 @@ set -e REVISION=$(git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g') -RUNTIME_DEPS='fontconfig gentium-plus-font libpng harfbuzz icu lua zlib' -BUILD_DEPS='git luarocks poppler' +RUNTIME_DEPS='fontconfig freetype2 gentium-plus-font glibc harfbuzz icu libpng luajit zlib' +BUILD_DEPS='cargo git jq lua51 luarocks poppler' : "${DOCKER_BUILDKIT:=1}" export DOCKER_BUILDKIT From 6bd5dc03ff930e881e7d4fe1d9287a8a22f93ef9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 6 Oct 2023 23:49:38 +0300 Subject: [PATCH 124/357] feat(docker): Add all default fonts and package management tooling to container --- hooks/build | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hooks/build b/hooks/build index d08cb6adf..065a6024b 100755 --- a/hooks/build +++ b/hooks/build @@ -5,8 +5,9 @@ set -e REVISION=$(git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g') -RUNTIME_DEPS='fontconfig freetype2 gentium-plus-font glibc harfbuzz icu libpng luajit zlib' -BUILD_DEPS='cargo git jq lua51 luarocks poppler' +RUNTIME_DEPS='fontconfig freetype2 gentium-plus-font glibc harfbuzz icu libpng luajit zlib'\ +' libertinus-font luarocks noto-fonts-cjk ttf-hack' +BUILD_DEPS='cargo git jq lua51 poppler' : "${DOCKER_BUILDKIT:=1}" export DOCKER_BUILDKIT From eca0383524d44f3185ec230e5fa063727d2f47af Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 7 Oct 2023 01:10:39 +0300 Subject: [PATCH 125/357] chore(core): Correct project-local and --without-system-luarocks paths from Rust --- core/pathsetup.lua.in | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index ced6f6332..d9b4b8dcb 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -27,17 +27,19 @@ local function prependCPath (path) package.cpath = prepend_and_dedup(path .. "/?.@SHARED_LIB_EXT@", package.cpath) end -local function extendPaths (path, ours) +local function extendPaths (path, luarocks_tree) prependCPath(path) prependPath(path) - if ours then + if luarocks_tree then if "@DEVELOPER_FALSE@" ~= "" then -- see ./configure --(en|dis)able-developer prependCPath(path .. "/libtexpdf/.libs") prependCPath(path .. "/justenough/.libs") end prependPath(path .. "/lua-libraries") prependCPath(path .. "/lib/lua/" .. luaversion) + prependCPath(path .. "/lib/lua/" .. luaversion .. "/sile") prependPath(path .. "/share/lua/" .. luaversion) + prependPath(path .. "/share/lua/" .. luaversion .. "/sile") else prependCPath(path .. "/sile") prependPath(path .. "/sile") @@ -57,7 +59,7 @@ package.path = table.concat(luapath, ";") extendPaths("@SILE_PATH@", true) extendPaths("@SILE_LIB_PATH@", true) if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks - extendPaths("@SILE_PATH@/lua_modules") + extendPaths("@SILE_PATH@/lua_modules", true) end package.path = table.concat(extpath, ";") .. ";" .. package.path @@ -72,12 +74,12 @@ if pathvar then end local cwd = executable:gsub("(.*)(/.*)", "%1") -if cwd:match("^@") then -- Consider "ours" for the sake of Nix Flake +if cwd:match("^@") then -- Nix Flake root path extendPaths(".", true) else if cwd ~= "./" then extendPaths(cwd) end extendPaths(".") - extendPaths("./lua_modules") + extendPaths("./lua_modules", true) end _G.extendSilePath = extendPaths From b17cb546982d06896dc46fd09fb3aa7943c39025 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 7 Oct 2023 01:44:33 +0300 Subject: [PATCH 126/357] docs(readme): Update Arch Linux notes since they default to LuaJIT now --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9f76fecb6..166c97304 100644 --- a/README.md +++ b/README.md @@ -65,9 +65,8 @@ Arch Linux has a prebuilt [SILE package][arch-sile] in the official package repo $ pacman -S sile ``` -The official package uses Lua 5.4. -Alternatively, a package that uses LuaJIT may be built manually from the [Arch User Repository][aur] using [sile-luajit][aur-sile-luajit]. -A VCS package is also available as [sile-git][aur-sile-git] to build from the latest Git commit. +The official package uses LuaJIT. +If you install LuaRocks for use with SILE via `pacman`, use the `lua51-*` variants to match LuaJIT. #### Fedora @@ -197,7 +196,7 @@ If you try to `brew link` and you get a series of messages including something l export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig" Optionally you may install the Lua libraries listed in the [rockspec][] to your system (using either your system's package manager or [luarocks][] (`luarocks install --only-deps sile-dev-1.rockspec`). -By default all the required Lua libraries will be downloaded and bundled alongside the SILE the instalation. +By default all the required Lua libraries will be downloaded and bundled alongside the SILE the installation. If you downloaded a source tarball these dependencies are included, if you are using a git clone of the source repository the build system will require `luarocks` to fetch them during build. Note that OpenSSL development headers will be required for one of the Lua modules to compile¹. If your system has all the required packages already you may add `--with-system-luarocks` to the `./configure` command to avoid bundling them. @@ -353,8 +352,6 @@ SILE is distributed under the [MIT licence][license]. [libtexpdf]: https://github.com/sile-typesetter/libtexpdf [arch-sile]: https://archlinux.org/packages/community/x86_64/sile/ [aur]: https://wiki.archlinux.org/index.php/Arch_User_Repository - [aur-sile-luajit]: https://aur.archlinux.org/packages/sile-luajit/ - [aur-sile-git]: https://aur.archlinux.org/packages/sile-git/ [typesetting]: https://en.wikipedia.org/wiki/Typesetting [tex]: https://en.wikipedia.org/wiki/TeX [indesign]: https://en.wikipedia.org/wiki/Adobe_InDesign From 624137fc0aaad08794a41c12dfbea2db64cff066 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sat, 7 Oct 2023 12:13:35 +0300 Subject: [PATCH 127/357] fix(tooling): Add npx to nix' devShell --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 52addc5bb..c020740f6 100644 --- a/flake.nix +++ b/flake.nix @@ -82,6 +82,8 @@ pkgs.luarocks # For commitlint git hook pkgs.yarn + # For npx + pkgs.nodejs ]; }; }; From 5b30695f4d5618e24aa9af2fbf5ea1b297ffadc5 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sat, 7 Oct 2023 12:13:04 +0300 Subject: [PATCH 128/357] feat(tooling): Add nix packages building sile with clang Co-authored-by: Caleb Maclennan --- build-aux/pkg.nix | 5 ----- flake.nix | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build-aux/pkg.nix b/build-aux/pkg.nix index 0951c40e8..f2ac5fa7f 100644 --- a/build-aux/pkg.nix +++ b/build-aux/pkg.nix @@ -139,11 +139,6 @@ in stdenv.mkDerivation (finalAttrs: { touch source/build-aux/rust_boilerplate.mk ''; - preBuild = lib.optionalString stdenv.cc.isClang '' - substituteInPlace libtexpdf/dpxutil.c \ - --replace "ASSERT(ht && ht->table && iter);" "ASSERT(ht && iter);" - ''; - # remove forbidden references to $TMPDIR preFixup = lib.optionalString stdenv.isLinux '' for f in "$out"/bin/*; do diff --git a/flake.nix b/flake.nix index c020740f6..77b8d1461 100644 --- a/flake.nix +++ b/flake.nix @@ -98,6 +98,11 @@ sile-luajit = sile.override { lua = pkgs.luajit; }; + sile-clang = sile.override { + lua = pkgs.luajit; + # Use the same clang version as Nixpkgs' rust clang stdenv + stdenv = pkgs.rustc.llvmPackages.stdenv; + }; }; defaultPackage = packages.sile-luajit; apps = rec { From a9296ed846acd7e826d0bfdd0f73946d6a4692c9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 11 Oct 2023 23:19:36 +0300 Subject: [PATCH 129/357] ci(actions): Disable testing on OpenResty, not currently enabled in mlua --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6d549d0b1..d844714c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: - '5.2' - '5.1' - 'luajit' - - 'luajit-openresty' + # - 'luajit-openresty' runs-on: ubuntu-22.04 name: Test on Lua ${{ matrix.luaVersion }} steps: From 5e05fa918cbb3a1c3be496dcb1bc06d86bcfec6c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 11 Oct 2023 23:30:08 +0300 Subject: [PATCH 130/357] feat(core): Allow multiple runtime SILE_PATH segments in Lua binary as well as Rust --- sile.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sile.in b/sile.in index 6b2cd50f7..54ad51a60 100755 --- a/sile.in +++ b/sile.in @@ -2,7 +2,11 @@ -- At this point at run time we may or may not have anything useful in package.path, -- so require() isn't something we can rely on. -local status = pcall(dofile, "@SILE_PATH@/core/pathsetup.lua") +local status +for path in string.gmatch("@SILE_PATH@", "[^;]+") do + status = pcall(dofile, path .. "/core/pathsetup.lua") + if status then break end +end if not status then dofile("./core/pathsetup.lua") end From f05d8a677ad7fb84179143ff97a01367536f3c6c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 11 Oct 2023 23:35:05 +0300 Subject: [PATCH 131/357] style(build): Normalize TOML formatting --- Cargo.toml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 08d78f2c7..fe9839d35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ build = "build-aux/build.rs" [[bin]] name = "sile" -required-features = ["cli"] +required-features = [ "cli" ] [dependencies] @@ -53,20 +53,20 @@ required-features = ["cli"] features = [ "build", "cargo", "git", "gitoxide" ] [features] -default = ["cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh"] -lua54 = ["mlua/lua54"] -lua53 = ["mlua/lua53"] -lua52 = ["mlua/lua52"] -lua51 = ["mlua/lua51"] -luajit = ["mlua/luajit"] -completions = ["cli", "clap_complete"] -cli = ["clap"] -bash = ["completions"] -elvish = ["completions"] -fish = ["completions"] -manpage = ["clap_mangen"] -powershell = ["completions"] -zsh = ["completions"] +default = [ "cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh" ] +lua54 = [ "mlua/lua54" ] +lua53 = [ "mlua/lua53" ] +lua52 = [ "mlua/lua52" ] +lua51 = [ "mlua/lua51" ] +luajit = [ "mlua/luajit" ] +completions = [ "cli", "clap_complete" ] +cli = [ "clap" ] +bash = [ "completions" ] +elvish = [ "completions" ] +fish = [ "completions" ] +manpage = [ "clap_mangen" ] +powershell = [ "completions" ] +zsh = [ "completions" ] [profile.release] lto = true From 773245b8dcb8df1bc983c7320cb1ad2cdd46784d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 11 Oct 2023 23:37:47 +0300 Subject: [PATCH 132/357] feat(build): Make vendoring Lua sources controlable at build time --- Cargo.toml | 3 ++- Dockerfile | 2 +- Makefile.am | 4 ++++ build-aux/pkg.nix | 1 + configure.ac | 6 ++++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fe9839d35..0353e418f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ required-features = [ "cli" ] [dependencies.mlua] version = "0.9" - features = [ "macros", "vendored" ] + features = [ "macros" ] [build-dependencies] @@ -59,6 +59,7 @@ lua53 = [ "mlua/lua53" ] lua52 = [ "mlua/lua52" ] lua51 = [ "mlua/lua51" ] luajit = [ "mlua/luajit" ] +vendored = [ "mlua/vendored" ] completions = [ "cli", "clap_complete" ] cli = [ "clap" ] bash = [ "completions" ] diff --git a/Dockerfile b/Dockerfile index cab044aab..335d543d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ WORKDIR /src RUN build-aux/docker-bootstrap.sh RUN ./bootstrap.sh -RUN ./configure --without-manual +RUN ./configure --with-system-lua-sources --without-manual RUN make RUN make check RUN make install DESTDIR=/pkgdir diff --git a/Makefile.am b/Makefile.am index 52988e6af..e822bbbb4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -88,6 +88,10 @@ MLUAVER = lua$(LUA_SHORT_VERSION) endif CARGO_FEATURE_ARGS = --features $(MLUAVER) +if !SYSTEM_LUA_SOURCES +CARGO_FEATURE_ARGS += --features vendored +endif + DEPDIR := .deps LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf LOCALPATHS := SILE_PATH="$(PWD);libtexpdf/.libs;justenough/.libs" diff --git a/build-aux/pkg.nix b/build-aux/pkg.nix index f2ac5fa7f..2b53be20d 100644 --- a/build-aux/pkg.nix +++ b/build-aux/pkg.nix @@ -99,6 +99,7 @@ in stdenv.mkDerivation (finalAttrs: { configureFlags = [ # Nix will supply all the Lua dependencies, so stop the build system from # bundling vendored copies of them. + "--with-system-lua-sources" "--with-system-luarocks" # The automake check target uses pdfinfo to confirm the output of a test # run, and uses autotools to discover it. This flake build eschews that diff --git a/configure.ac b/configure.ac index ffc0ddd7e..40fc7c722 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,12 @@ AC_ARG_WITH([system-luarocks], AM_CONDITIONAL([SYSTEM_LUAROCKS], [test "x$with_system_luarocks" = "xyes"]) AC_SUBST([SYSTEM_LUAROCKS]) +AC_ARG_WITH([system-lua-sources], + AS_HELP_STRING([--with-system-lua-sources], + [Don’t compile against vendored Lua sources, use system headers])) +AM_CONDITIONAL([SYSTEM_LUA_SOURCES], [test "x$with_system_lua_sources" = "xyes"]) +AC_SUBST([SYSTEM_LUA_SOURCES]) + AC_ARG_WITH([luajit], AS_HELP_STRING([--without-luajit], [Prefer LuaJIT over PUC Lua, even if the latter is newer])) From b134ca67e577b64b55f694a0d59aae916e063af9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 00:22:01 +0300 Subject: [PATCH 133/357] chore(tooling): Add tools to Nix develop environment needed for manual --- flake.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flake.nix b/flake.nix index 77b8d1461..756e3dbc4 100644 --- a/flake.nix +++ b/flake.nix @@ -84,6 +84,10 @@ pkgs.yarn # For npx pkgs.nodejs + # For gs, dot, and bsdtar used in building the manual + pkgs.ghostscript + pkgs.graphviz + pkgs.libarchive ]; }; }; From d2ad044494454258b1c913c86d523fb24bca27c4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 00:35:32 +0300 Subject: [PATCH 134/357] ci(actions): Use vendored Lua sources for Rust lint purposes --- .github/workflows/rust_lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml index 10c01efc8..ac1174c4a 100644 --- a/.github/workflows/rust_lint.yml +++ b/.github/workflows/rust_lint.yml @@ -39,4 +39,4 @@ jobs: - uses: actions-rs/clippy-check@v1 with: token: ${{ github.token }} - args: --features luajit -- -D warnings + args: --features luajit,vendored -- -D warnings From 28ab320669177f2056d520984adcd2afbabd4fda Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 01:03:29 +0300 Subject: [PATCH 135/357] chore(build): Add Crate meta-data and move features above dependencies --- Cargo.toml | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0353e418f..71c77fcbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,9 @@ authors = [ "Olivier Nicole", "Didier Willis" ] +readme = "README.md" homepage = "https://sile-typesetter.org" +repository = "https://github.com/sile-typesetter/sile" license = "MIT" build = "build-aux/build.rs" @@ -18,6 +20,26 @@ build = "build-aux/build.rs" name = "sile" required-features = [ "cli" ] +[features] +default = [ "cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh" ] +lua54 = [ "mlua/lua54" ] +lua53 = [ "mlua/lua53" ] +lua52 = [ "mlua/lua52" ] +lua51 = [ "mlua/lua51" ] +luajit = [ "mlua/luajit" ] +vendored = [ "mlua/vendored" ] +completions = [ "cli", "clap_complete" ] +cli = [ "clap" ] +bash = [ "completions" ] +elvish = [ "completions" ] +fish = [ "completions" ] +manpage = [ "clap_mangen" ] +powershell = [ "completions" ] +zsh = [ "completions" ] + +[profile.release] +lto = true + [dependencies] [dependencies.anyhow] @@ -51,23 +73,3 @@ required-features = [ "cli" ] version = "8.2" default-features = false features = [ "build", "cargo", "git", "gitoxide" ] - -[features] -default = [ "cli", "bash", "elvish", "fish", "manpage", "powershell", "zsh" ] -lua54 = [ "mlua/lua54" ] -lua53 = [ "mlua/lua53" ] -lua52 = [ "mlua/lua52" ] -lua51 = [ "mlua/lua51" ] -luajit = [ "mlua/luajit" ] -vendored = [ "mlua/vendored" ] -completions = [ "cli", "clap_complete" ] -cli = [ "clap" ] -bash = [ "completions" ] -elvish = [ "completions" ] -fish = [ "completions" ] -manpage = [ "clap_mangen" ] -powershell = [ "completions" ] -zsh = [ "completions" ] - -[profile.release] -lto = true From 4df14760b7c09b0df58faebe701c790911b2652f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 01:11:49 +0300 Subject: [PATCH 136/357] ci(actions): Use extrenal Cargo, Ubuntu LTS is lower than our MSRV --- .github/workflows/build.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04a28c3b7..9e0146bf9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,10 +28,14 @@ jobs: path: | lua_modules key: luarocks-${{ hashFiles('Makefile-luarocks', 'sile.rockspec.in') }} + - name: Cache Rust + uses: Swatinem/rust-cache@v2 - name: Install system dependencies run: | sudo apt-get update - sudo apt-get install cargo fonts-sil-gentiumplus ghostscript graphviz jq libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev libluajit-5.1-dev libpng-dev luajit lua-sec lua-socket lua-zlib-dev luarocks poppler-utils + sudo apt-get install fonts-sil-gentiumplus ghostscript graphviz jq libarchive-tools libfontconfig1-dev libharfbuzz-dev libicu-dev libluajit-5.1-dev libpng-dev luajit lua-sec lua-socket lua-zlib-dev luarocks poppler-utils + - name: Setup ‘cargo’ + uses: actions-rs/toolchain@v1 - name: Configure run: | ./bootstrap.sh From 0837ba8a5badef4fa2f456f4534e7c2abe7e9247 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 01:11:49 +0300 Subject: [PATCH 137/357] ci(actions): Drop configure flags that are the default --- .github/workflows/build.yml | 2 -- .github/workflows/coverage.yml | 2 -- .github/workflows/test.yml | 1 - 3 files changed, 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e0146bf9..b5bcc1c59 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,9 +40,7 @@ jobs: run: | ./bootstrap.sh ./configure \ - --with-luajit \ --disable-font-variations \ - --without-system-luarocks \ --with-manual echo "VERSION=$(./build-aux/git-version-gen .tarball-version)" >> $GITHUB_ENV echo "MAKEFLAGS=-j$(nproc) -Otarget" >> $GITHUB_ENV diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 675dbbb1c..527cdff82 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -62,8 +62,6 @@ jobs: ./configure \ --enable-developer LUACHECK=false NIX=false \ --disable-font-variations \ - --without-system-luarocks \ - --with-luajit \ --without-manual - name: Make run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d844714c9..ad83696e7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,6 @@ jobs: ./configure \ --enable-developer LUACHECK=false NIX=false \ --disable-font-variations \ - --without-system-luarocks \ --with${{ !startsWith(matrix.luaVersion, 'luajit') && 'out' || '' }}-luajit \ --without-manual - name: Make From d032a6a237d22eeae4834fd330f68724c9323776 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 16:08:18 +0300 Subject: [PATCH 138/357] chore(build): Make sure all .PHONY declarations are outside of conditionals --- Makefile-fonts | 3 ++- Makefile-luarocks | 1 + Makefile.am | 10 ++++------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile-fonts b/Makefile-fonts index dcb7c15c6..57cb88644 100644 --- a/Makefile-fonts +++ b/Makefile-fonts @@ -1,3 +1,5 @@ +.PHONY: fonttooling + if FONT_DOWNLOAD_TOOLS .fonts: fonttooling @@ -6,7 +8,6 @@ if FONT_DOWNLOAD_TOOLS .sources: fonttooling [ -h .sources ] || mkdir -p $@ -.PHONY: fonttooling fonttooling: $(if $(BSDTAR),,$(error Please set BSDTAR with path or `./configure --enable-developer`)) $(if $(CURL),,$(error Please set CURL with path or `./configure --enable-developer`)) diff --git a/Makefile-luarocks b/Makefile-luarocks index 54387731d..6042815d9 100644 --- a/Makefile-luarocks +++ b/Makefile-luarocks @@ -1,4 +1,5 @@ .PHONY: installrocks + LUAMODSPEC := sile-dev-1.rockspec if !SYSTEM_LUAROCKS LUAMODLOCK := sile-dev-1.rockslock diff --git a/Makefile.am b/Makefile.am index e822bbbb4..62cb28487 100644 --- a/Makefile.am +++ b/Makefile.am @@ -176,35 +176,33 @@ patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(bin_PROGRAMS) $(DEPDIRS .PHONY: force force: ; -PHONY_DEVELOPER_TARGETS = regressions test lint luarocks-lint luacheck busted coverage benchmark compare update_expecteds regression_previews docker docker-dep-check docker-ghcr-to-hub docker-build-push gource.webm +PHONY_DEVELOPER_TARGETS = benchmark busted compare coverage docker docker-build-push \ + docker-dep-check docker-ghcr-to-hub gource.webm lint luacheck luarocks-lint \ + prerelease regression_previews regressions release release-preview tagrelease \ + test update_expecteds update_libtexpdf .PHONY: $(PHONY_DEVELOPER_TARGETS) if DEVELOPER RELTYPE ?= -.PHONY: tagrelease tagrelease: test -z $$($(GIT) tag --points-at HEAD) || exit 0 # end if we are already on a release tag $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything staged but not committed $(GIT) diff-files --quiet || exit 1 # die if any tracked files have unstagged changes npm run release -- $(and $(RELTYPE),--release-as $(RELTYPE)) -.PHONY: prerelease prerelease: test docs update_libtexpdf -.PHONY: release-preview release-preview: npm run release -- --dry-run $(and $(RELTYPE),--release-as $(RELTYPE)) -.PHONY: release release: tagrelease sile-%.md: CHANGELOG.md $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ $(SED) -e '1,3d;N;$$!P;$$!D;$$d' > $@ -.PHONY: update_libtexpdf update_libtexpdf: $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything already staged $(GIT) submodule update --init --remote -- libtexpdf From 48f731220ada284ecf748212211b7f7d9794dab6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 16:20:14 +0300 Subject: [PATCH 139/357] chore(tooling): Drop install time version checking that won't work in all scenarios --- build-aux/git_version.mk | 3 --- build-aux/rust_boilerplate.mk.in | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build-aux/git_version.mk b/build-aux/git_version.mk index 58e16119f..97a35ad8b 100644 --- a/build-aux/git_version.mk +++ b/build-aux/git_version.mk @@ -25,9 +25,6 @@ check-git-version: $(PACKAGE_NAME)$(EXEEXT) | .version $(GREP) -Fx '$(VERSION)' $| ./$< --version | $(GREP) -Ff $| -installcheck-local-version: - ./$(TRANSFORMED_PACKAGE_NAME)$(EXEEXT) --version - dist-hook: dist-tarball-version .PHONY: dist-tarball-version diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index a9c5a8eec..a8d39cb4b 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -58,7 +58,7 @@ $(_RUST_OUT) $(CARGO_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) -RUST_DEVELOPER_TARGETS = cargo-test clippy installcheck-local-version rustfmt +RUST_DEVELOPER_TARGETS = cargo-test clippy rustfmt .PHONY: $(RUST_DEVELOPER_TARGETS) if DEVELOPER From 707da2314be6478c59bc3f0de4022604b192794c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 14 Oct 2023 13:56:37 +0300 Subject: [PATCH 140/357] docs(manpage): Sync Rust & Lua man pages and help output --- core/cli.lua | 54 +++++++++++++++++++---------- sile-lua.1.in | 96 ++++++++++++++++++++++++++++++++------------------- src/cli.rs | 87 ++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 168 insertions(+), 69 deletions(-) diff --git a/core/cli.lua b/core/cli.lua index 3d847bda5..474076d00 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -15,24 +15,42 @@ cli.parseArguments = function () the `--output` argument is used. Additional input or output formats can be handled by loading a module with the `--use` argument to add support for them first. ]]) - cliargs:splat("INPUTS", "input document(s), by default in SIL or XML format", nil, 999) - cliargs:option("-b, --backend=VALUE", "choose an alternative output backend") - cliargs:option("-c, --class=VALUE", "override default document class") - cliargs:option("-d, --debug=VALUE", "show debug information for tagged aspects of SILE’s operation", {}) - cliargs:option("-e, --evaluate=VALUE", "evaluate Lua expression before processing input", {}) - cliargs:option("-E, --evaluate-after=VALUE", "evaluate Lua expression after processing input", {}) - cliargs:option("-f, --fontmanager=VALUE", "choose an alternative font manager") - cliargs:option("-I, --include=FILE", "deprecated, see --use, --preamble, or --postamble", {}) - cliargs:option("-m, --makedeps=FILE", "generate a list of dependencies in Makefile format") - cliargs:option("-o, --output=FILE", "explicitly set output file name") - cliargs:option("-O, --options=PARAMETER=VALUE[,PARAMETER=VALUE]", "set document class options", {}) - cliargs:option("-p, --preamble=FILE", "process SIL, XML, or other content before the input document", {}) - cliargs:option("-P, --postamble=FILE", "process SIL, XML, or other content after the input document", {}) - cliargs:option("-u, --use=MODULE[[PARAMETER=VALUE][,PARAMETER=VALUE]]", "load and initialize a module before processing input", {}) - cliargs:flag("-q, --quiet", "suppress warnings and informational messages during processing") - cliargs:flag("-t, --traceback", "display detailed location trace on errors and warnings") - cliargs:flag("-h, --help", "display this help, then exit") - cliargs:flag("-V, --version", "display version information, then exit", print_version) + cliargs:splat("INPUTS", + "Input document filename(s), by default in SIL, XML, or Lua formats.", nil, 999) + cliargs:option("-b, --backend=VALUE", + "Specify the output backend") + cliargs:option("-c, --class=VALUE", + "Override the default or specified document class") + cliargs:option("-d, --debug=VALUE", + "Show debug information for tagged aspects of SILE’s operation", {}) + cliargs:option("-e, --evaluate=VALUE", + "Evaluate Lua expression before processing input", {}) + cliargs:option("-E, --evaluate-after=VALUE", + "Evaluate Lua expression after processing input", {}) + cliargs:option("-f, --fontmanager=VALUE", + "Specify which font manager to use") + cliargs:option("-I, --include=FILE", + "Deprecated, see --use, --preamble, --postamble, or multiple input files", {}) + cliargs:option("-m, --makedeps=FILE", + "Generate a Makefile format list of dependencies and white them to a file") + cliargs:option("-o, --output=FILE", + "Explicitly set output file name") + cliargs:option("-O, --options=PARAMETER=VALUE[,PARAMETER=VALUE]", + "Set or override document class options", {}) + cliargs:option("-p, --preamble=FILE", + "Include the contents of a SIL, XML, or other resource file before the input document content", {}) + cliargs:option("-P, --postamble=FILE", + "Include the contents of a SIL, XML, or other resource file after the input document content", {}) + cliargs:option("-u, --use=MODULE[[PARAMETER=VALUE][,PARAMETER=VALUE]]", + "Load and initialize a class, inputter, shaper, or other module before processing the main input", {}) + cliargs:flag("-q, --quiet", + "Suppress warnings and informational messages during processing") + cliargs:flag("-t, --traceback", + "Display detailed location trace on errors and warnings") + cliargs:flag("-h, --help", + "Display this help, then exit") + cliargs:flag("-V, --version", + "Print version", print_version) -- Work around cliargs not processing - as an alias for STDIO streams: -- https://github.com/amireh/lua_cliargs/issues/67 local _arg = pl.tablex.imap(luautf8.gsub, _G.arg, "^-$", "STDIO") diff --git a/sile-lua.1.in b/sile-lua.1.in index 322f9aa45..b5375705a 100644 --- a/sile-lua.1.in +++ b/sile-lua.1.in @@ -1,94 +1,118 @@ .TH @TRANSFORMED_PACKAGE_NAME@ 1 "@MAN_DATE@" "version v@VERSION@" .SH NAME -@TRANSFORMED_PACKAGE_NAME@ \- Simon's Improved Layout Engine +@TRANSFORMED_PACKAGE_NAME@ \- Simon’s Improved Layout Engine .SH SYNOPSIS -.B @TRANSFORMED_PACKAGE_NAME@ [ -.I options -.B ] [ -.I filename.sil -.B | -.I filename.xml -.B ] +.B @TRANSFORMED_PACKAGE_NAME@ +.B [\fIoptions\fR] +.B [\fIINPUT\fR] .SH DESCRIPTION The SILE typesetter reads an input file(s), by default in either SIL or XML format, and processes them to generate an output file, by default in PDF format. The output will be written to a file with the same name as the first input file with the extension changed to .pdf unless the \fB\-\-output\fR argument is used. Additional input or output formats can be handled by loading a module with the \fB\-\-use\fR argument to add support for them first. .SH OPTIONS -.B @TRANSFORMED_PACKAGE_NAME@ accepts the following feature flags: -.TP -.BR \-t ", " \-\-traceback -Display detailed location trace on errors and warnings. -.TP -.BR \-h ", " \-\-help -Print help message and exit. -.TP -.BR \-v ", " \-\-version -Print version information and exit. -.TP -.B @TRANSFORMED_PACKAGE_NAME@ accepts the following options with values: .TP .BR \-b ", " \-\-backend= \fIvalue\fR -Choose an alternative output backend. -The default backend for producing PDF files is \fIlibtexpdf\fR. -Other available backends include \fIcairo\fR, \fIdebug\fR, \fItext\fR, and \fIdummy\fR. +Specify the output backend. +.IP +The default is \fIlibtexpdf\fR and suitible for most PDF output. +Alternatives supported out of the box include \fItext\fR, \fIdebug\fR, \fIdummy\fR, \fIcairo\fR, and \fIpodofo\fR. +Other outputters may be enabled via \fI--use\fR. .TP .BR \-c ", " \-\-class= \fIvalue\fR -Set the document class. -The default for documents that do not specify is \fIplain\fR. -Can be used to either change the default class or to override the class specified in a document. -Other default classes include \fIbase\fR, \fIbible\fR, \fIbook\fR, \fIdiglot\fR, \fIdocbook\fR, \fIdocbook.sil \fIjbook\fR, \fIjplain\fR, \fIletter\fR, \fIpecha\fR, \fItbook\fR, \fItplain\fR, and \fItriglot\fR. +Override the default or specified document class. +.IP +The default class for documents that do not specify one in the root tag is \fIplain\fR. +This can be used to either change the default class or to override the class actually specified in a document. +Other bundled classes include \fIbase\fR, \fIbible\fR, \fIbook\fR, \fIdiglot\fR, \fIdocbook\fR, \fIdocbook\fR, \fIjbook\fR, \fIjplain\fR, \fIletter\fR, \fIpecha\fR, \fItbook\fR, \fItplain\fR, and \fItriglot\fR. +Others will be loaded dynamically from the module path. .TP .BR \-d ", " \-\-debug= \fIvalue\fR[,\fIvalue\fR] -Debug SILE's operation. +Show debug information for tagged aspects of SILE’s operation. +.IP Multiple debug flags may be given as a comma separated list. While packages may define their own debug flags, the most commonly used ones are \fItypesetter\fR, \fIpagebuilder\fR, \fIvboxes\fR, \fIbreak\fR, \fIframes\fR, \fIprofile\fR, and \fIversions\fR. May be specified more than once. .TP .BR \-e ", " \-\-evaluate= \fIvalue\fR Evaluate Lua expression before processing input. +.IP May be specified more than once. .TP .BR \-E ", " \-\-evaluate-after= \fIvalue\fR Evaluate Lua expression after processing input. +.IP May be specified more than once. .TP .BR \-f ", " \-\-fontmanager= \fIvalue\fR -Choose an alternative font manager. +Specify which font manager to use. +.IP The font manager is responsible for discovering the locations on font files on the system given a font name. The default font manager is \fIfontconfig\fR on non-macOS systems and \fImacfonts\fR on macOS. .TP .BR \-m ", " \-\-makedeps \fIfile\fR Generate a list of dependencies in Makefile format. +.IP +This tracks all the files (input files, Lua libraries, fonts, images, etc.) use during the typesetting process. +After completion, the list is written to FILE in the format of a dependency list for a target in a Makefile. +This can be used later to determine if a PDF needs re-rendering based on whether any inputs have changed. .TP .BR \-o ", " \-\-output= \fIfile\fR Explicitly set the output file name. +.IP +By default the basename of the first input file will be used as the output filename. +An extension will be chosen based on the output backend, typically .pdf. +With this option any arbitrary name and path can be given. +Additionally \fI-\fR can be used to write the output to STDOUT. .TP .BR \-O ", " \-\-options= \fIparameter=value\fR[,\fIparameter=value\fR] -Set document class options. +Set or override document class options. +.IP Can be used to change default options or override the ones specified in a document. -For example setting \fB\-\-options papersize=letter\fR would override both the default \fIpapersize\fR of A4 and any specific one set in the document's options. +For example setting \fB\-\-options papersize=letter\fR would override both the default \fIpapersize\fR of A4 and any specific one set in the document’s options. May be specified more than once. .TP .BR \-I ", " \-\-include= \fIfilename\fR -Deprecated, will be removed. -Please use \-\-use, \-\-preamble, or \-\-postamble. +Deprecated, use \-\-use, \-\-preamble, \-\-postamble, or multiple input files. .TP .BR \-p ", " \-\-preamble= \fIfilename\fR -Include an SIL, XML, or other content resource before the input document. +Include the contents of a SIL, XML, or other resource file before the input document content. +.IP The value should be a full filename with a path relative to PWD or an absolute path. May be specified more than once. .TP .BR \-P ", " \-\-postamble= \fIfilename\fR -Include an SIL, XML, or other content resource after the input document. +Include the contents of a SIL, XML, or other resource file after the input document content. +.IP The value should be a full filename with a path relative to PWD or an absolute path. May be specified more than once. .TP .BR \-u ", " \-\-use= \fImodule\fR [[\fIparameter=value[,parameter=value]]]\fR Load and initialize a class, inputter, shaper, or other module before processing the main input. -The value should be a loadable module name (with no extension, using \fI'.'\fR as a path separator) and will be loaded using SILE's module search path. +.IP +The value should be a loadable module name (with no extension, using \fI'.'\fR as a path separator) and will be loaded using SILE’s module search path. Options may be passed to the module by enclosing \fIkey=value\fR pairs in square brackets following the module name. This is particularly useful when the input document is not SIL or a natively recognized XML scheme and SILE needs to be taught new tricks before even trying to read the input file. If the module is a document class, it will replace \fIplain\fR as the default class for processing documents that do not specifically identify one to use. Because this executes before loading the document, it may even add an input parser or modify an existing one to support new file formats. Package modules will be added to the preamble to be loaded after the class is initialized. May be specified more than once. +.TP +.BR \-q ", " \-\-quiet +Suppress warnings and informational messages during processing. +.TP +.BR \-t ", " \-\-traceback +Display detailed location trace on errors and warnings. +.TP +.BR [INPUT] +Input document filename(s), by default in SIL, XML, or Lua formats. +.IP +One or more input files from which to process content. +The first listed file is considered the master document, others are procced in sequence. +Other inputter formats may be enabled via \fI--use\fR. +Use \fI-\fR to read a content stream from STDIN. +.TP +.BR \-h ", " \-\-help +Print help message and exit. +.TP +.BR \-v ", " \-\-version +Print version. diff --git a/src/cli.rs b/src/cli.rs index 24e1e7af8..9af8b7142 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -9,55 +9,112 @@ use std::path::PathBuf; #[derive(Parser, Debug)] #[clap(author, name = "SILE", bin_name = "sile")] pub struct Cli { - /// Input document, by default in SIL or XML format + /// Input document filename(s), by default in SIL, XML, or Lua formats. + /// + /// One or more input files from which to process content. + /// The first listed file is considered the master document, others are procced in sequence. + /// Other inputter formats may be enabled via`--use`. + /// Use `-` to read a content stream from STDIN. pub input: Option>, - /// Choose an alternative output backend + /// Specify the output backend. + /// + /// The default is `libtexpdf` and suitible for most PDF output. + /// Alternatives supported out of the box include `text`, `debug`, `dummy`, `cairo`, and `podofo`. + /// Other outputters may be enabled via `--use`. #[clap(short, long, value_name = "BACKEND")] pub backend: Option, - /// Override default document class + /// Override the default or specified document class. + /// + /// The default class for documents that do not specify one in the root tag is `plain`. + /// This can be used to either change the default class or to override the class actually specified in a document. + /// Other bundled classes include `base`, `bible`, `book`, `diglot`, `docbook`, `docbook`, `jbook`, `jplain`, `letter`, `pecha`, `tbook`, `tplain`, and `triglot`. + /// Others will be loaded dynamically from the module path. #[clap(short, long)] pub class: Option, - /// Show debug information for tagged aspects of SILE’s operation + /// Show debug information for tagged aspects of SILE’s operation. + /// + /// Multiple debug flags may be given as a comma separated list. + /// While packages may define their own debug flags, the most commonly used ones are `typesetter`, `pagebuilder`, `vboxes`, `break`, `frames`, `profile`, and `versions`. + /// May be specified more than once. #[clap(short, long, value_name = "DEBUGFLAG[,DEBUGFLAG]")] // TODO: switch to num_args(0..) to allow space separated inputs pub debug: Option>, - /// Evaluate Lua expression before processing input + /// Evaluate Lua expression before processing input. + /// + /// May be specified more than once. #[clap(short, long, value_name = "EXRPESION")] pub evaluate: Option>, - /// Evaluate Lua expression after processing input + /// Evaluate Lua expression after processing input. + /// + /// May be specified more than once. #[clap(short = 'E', long, value_name = "EXRPESION")] pub evaluate_after: Option>, - /// Choose an alternative font manager + /// Specify which font manager to use. + /// + /// The font manager is responsible for discovering the locations on font files on the system given a font name. + /// The default font manager is `fontconfig` on non-macOS systems and `macfonts` on macOS. #[clap(short, long, value_name = "FONTMANAGER")] pub fontmanager: Option, - /// Generate a list of dependencies in Makefile format + /// Generate a Makefile format list of dependencies and white them to a file. + /// + /// This tracks all the files (input files, Lua libraries, fonts, images, etc.) use during the + /// typesetting process. + /// After completion, the list is written to FILE in the format of a dependency list for + /// a target in a Makefile. + /// This can be used later to determine if a PDF needs re-rendering based on whether any inputs + /// have changed. #[clap(short, long, value_name = "FILE")] pub makedeps: Option, - /// Explicitly set output file name + /// Explicitly set the output file name. + /// + /// By default the basename of the first input file will be used as the output filename. + /// An extension will be chosen based on the output backend, typically .pdf. + /// With this option any arbitrary name and path can be given. + /// Additionally `-` can be used to write the output to STDOUT. #[clap(short, long, value_name = "FILE")] pub output: Option, - /// Set document class options + /// Set or override document class options. + /// + /// Can be used to change default options or override the ones specified in a document. + /// For example setting `--options papersize=letter` would override both the default `papersize` of A4 and any specific one set in the document’s options. + /// May be specified more than once. #[clap(short = 'O', long)] pub option: Option>, - /// Process SIL, XML, or other content before the input document + /// Include the contents of a SIL, XML, or other resource file before the input document content. + /// + /// The value should be a full filename with a path relative to PWD or an absolute path. + /// May be specified more than once. #[clap(short, long, value_name = "FILE")] pub preamble: Option>, - /// Process SIL, XML, or other content after the input document + /// Include the contents of a SIL, XML, or other resource file after the input document content. + /// + /// The value should be a full filename with a path relative to PWD or an absolute path. + /// May be specified more than once. #[clap(short = 'P', long, value_name = "FILE")] pub postamble: Option>, - /// Load and initialize a module before processing input + /// Load and initialize a class, inputter, shaper, or other module before processing the main input. + /// + /// The value should be a loadable module name (with no extension, using `.` as a path separator) and will be loaded using SILE’s module search path. + /// Options may be passed to the module by enclosing `key=value` pairs in square brackets following the module name. + /// This is particularly useful when the input document is not SIL or a natively recognized XML scheme + /// and SILE needs to be taught new tricks before even trying to read the input file. + /// If the module is a document class, it will replace `plain` as the default class for processing + /// documents that do not specifically identify one to use. + /// Because this executes before loading the document, it may even add an input parser or modify an existing one to support new file formats. + /// Package modules will be added to the preamble to be loaded after the class is initialized. + /// May be specified more than once. #[clap( short, long, @@ -65,11 +122,11 @@ pub struct Cli { )] pub r#use: Option>, - /// Discard all non-error output messages + /// Suppress warnings and informational messages during processing. #[clap(short, long)] pub quiet: bool, - /// Display detailed location trace on errors and warnings + /// Display detailed location trace on errors and warnings. #[clap(short, long)] pub traceback: bool, } From 5248b0ca2fe9fc90e3b7344543c1855ad3b72748 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 14 Oct 2023 21:29:34 +0300 Subject: [PATCH 141/357] chore(build): Fix recursion in dependency tree --- Makefile.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 62cb28487..1582f4afd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -151,7 +151,11 @@ _DOCS_DEPS = $(and $$(filter documentation/%,$@),$(addprefix .fonts/,$(DOCSFONTF # TODO: remove _BUILT_SUBDIRS hack and replace it with something sensible when # these subdirs don't do crazy things like copying files outside of their own trees! _BUILT_SUBDIRS = .built-subdirs -_SUBDIR_TELLS = justenoughfontconfig.so justenoughharfbuzz.so justenoughicu.so justenoughlibtexpdf.so libtexpdf/.libs/libtexpdf.so.0.0.0 +_SUBDIR_TELLS = justenough/.libs/justenoughfontconfig.so \ + justenough/.libs/justenoughharfbuzz.so \ + justenough/.libs/justenoughicu.so \ + justenough/.libs/justenoughlibtexpdf.so \ + libtexpdf/.libs/libtexpdf.so.0.0.0 $(_BUILT_SUBDIRS): $(_SUBDIR_TELLS) touch $@ From 42b64bbb2ae193b1962eb728159f0db58a899c72 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 14 Oct 2023 21:46:08 +0300 Subject: [PATCH 142/357] chore(build): Fixup `make dist` to run configured without developer mode --- Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1582f4afd..e46199b57 100644 --- a/Makefile.am +++ b/Makefile.am @@ -114,6 +114,10 @@ dist: sile-$(VERSION).pdf sile-$(VERSION).md sile-$(VERSION).pdf: $(MANUAL) cp $(MANUAL) $@ +sile-%.md: CHANGELOG.md + $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ + $(SED) -e '1,3d;N;$$!P;$$!D;$$d' > $@ + check: selfcheck .PHONY: selfcheck @@ -203,10 +207,6 @@ release-preview: release: tagrelease -sile-%.md: CHANGELOG.md - $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ - $(SED) -e '1,3d;N;$$!P;$$!D;$$d' > $@ - update_libtexpdf: $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything already staged $(GIT) submodule update --init --remote -- libtexpdf From 8825b5b55acb119485ef3e980826fc6f61d1f72a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 30 Oct 2023 15:50:10 +0300 Subject: [PATCH 143/357] chore(build): Correct Rust dependency calculations in make target --- build-aux/rust_boilerplate.mk.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index a8d39cb4b..77524437e 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -52,7 +52,7 @@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME).ps1: $(CARGO_BIN) | $(COMPLE $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(CARGO_BIN) | $(COMPLETIONS_OUT_DIR) $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ -$(_RUST_OUT) $(CARGO_BIN): $(sile_SOURCES) $(EXTRA_sile_SOURCES) +$(_RUST_OUT) $(CARGO_BIN): $(@PACKAGE_VAR@_SOURCES) $(EXTRA_@PACKAGE_VAR@_SOURCES) cd $(top_srcdir) $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | From 93d5bf49e3be6b73c9840e7aea43893c84b5303a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 30 Oct 2023 15:50:34 +0300 Subject: [PATCH 144/357] chore(build): Force rebuild of CLI if Git version description changes --- build-aux/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build-aux/build.rs b/build-aux/build.rs index f90e33049..739ea2f7c 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -15,6 +15,7 @@ use vergen::EmitBuilder; include!("../src/cli.rs"); fn main() { + println!("cargo:rerun-if-changed=.version"); let mut builder = EmitBuilder::builder(); // If passed a version from automake, use that instead of vergen's formatting if let Ok(val) = env::var("VERSION_FROM_AUTOTOOLS") { From e318eb13653ee26133ff3f7df07446183b38b562 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 20 Oct 2023 12:18:30 +0300 Subject: [PATCH 145/357] chore(tooling): Make sure make fails if cargo build fails --- build-aux/rust_boilerplate.mk.in | 1 + 1 file changed, 1 insertion(+) diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index 77524437e..32623cb31 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -54,6 +54,7 @@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(CARGO_BIN) | $(COMPLETION $(_RUST_OUT) $(CARGO_BIN): $(@PACKAGE_VAR@_SOURCES) $(EXTRA_@PACKAGE_VAR@_SOURCES) cd $(top_srcdir) + set -e $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) From c01245292df9a9102787e07ad882864750109fdf Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 19 Oct 2023 01:28:31 +0300 Subject: [PATCH 146/357] chore(deps): Depend on rust-embed crate --- Cargo.lock | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +++ 2 files changed, 104 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 71e602828..f0ecec724 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bstr" version = "1.6.2" @@ -202,6 +211,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -211,12 +229,32 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "deranged" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dunce" version = "1.0.4" @@ -296,6 +334,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gix" version = "0.53.1" @@ -1096,6 +1144,40 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" +[[package]] +name = "rust-embed" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.38", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1162,6 +1244,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "signal-hook" version = "0.3.17" @@ -1190,6 +1283,7 @@ dependencies = [ "clap_complete", "clap_mangen", "mlua", + "rust-embed", "vergen", ] @@ -1314,6 +1408,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-bidi" version = "0.3.13" diff --git a/Cargo.toml b/Cargo.toml index 71c77fcbc..4b5012907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,10 @@ lto = true version = "0.9" features = [ "macros" ] + [dependencies.rust-embed] + version = "8.0" + optional = true + [build-dependencies] [build-dependencies.clap_complete] From 9f1110049a25bb59de6d2c9aef6b5945b58ec8b0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 19 Oct 2023 01:28:31 +0300 Subject: [PATCH 147/357] feat(cli): Add configure time option to embed Lua resources in binary --- Cargo.toml | 1 + Makefile.am | 14 ++++++++++++-- configure.ac | 5 +++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4b5012907..4bb775c02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ lua52 = [ "mlua/lua52" ] lua51 = [ "mlua/lua51" ] luajit = [ "mlua/luajit" ] vendored = [ "mlua/vendored" ] +embed = [ "rust-embed" ] completions = [ "cli", "clap_complete" ] cli = [ "clap" ] bash = [ "completions" ] diff --git a/Makefile.am b/Makefile.am index e46199b57..53a851d56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,13 +54,19 @@ endif $(MANUAL): $(FIGURES) +BUILT_LUA_SOURCES = core/features.lua core/pathsetup.lua core/version.lua + bin_PROGRAMS = sile bin_SCRIPTS = sile-lua dist_man_MANS = sile-lua.1 sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs EXTRA_sile_SOURCES = +if EMBEDED_RESOURCES +export EMBEDED_LUA_RESOURCES = $(SILEDATA) $(LUALIBRARIES) $(BUILT_LUA_SOURCES) $(LUAMODULES) +else nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) -nobase_nodist_pkgdata_DATA = core/features.lua core/pathsetup.lua core/version.lua $(LUAMODULES) +nobase_nodist_pkgdata_DATA = $(BUILT_LUA_SOURCES) $(LUAMODULES) +endif dist_doc_DATA = README.md CHANGELOG.md dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE.md @@ -72,7 +78,7 @@ EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) -BUILT_SOURCES = core/features.lua core/pathsetup.lua core/version.lua Makefile-distfiles +BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) @@ -92,6 +98,10 @@ if !SYSTEM_LUA_SOURCES CARGO_FEATURE_ARGS += --features vendored endif +if EMBEDED_RESOURCES +CARGO_FEATURE_ARGS += --features embed +endif + DEPDIR := .deps LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf LOCALPATHS := SILE_PATH="$(PWD);libtexpdf/.libs;justenough/.libs" diff --git a/configure.ac b/configure.ac index 40fc7c722..51446e1d8 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,11 @@ AC_ARG_ENABLE([developer], [Check for and enable tooling required only for developers])) AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) +AC_ARG_ENABLE([embeded], + AS_HELP_STRING([--enable-embeded-resources], + [Compile resources such as Lua module files directly into the Rust CLI binary])) +AM_CONDITIONAL([EMBEDED_RESOURCES], [test "x$enable_embeded_resources" = "xyes"]) + AC_ARG_ENABLE([font-variations], AS_HELP_STRING([--disable-font-variations], [Disable support for OpenType variations and variable fonts that requires HarfBuzz subsetter library])) From 6461c4dc53d9ba058c9dbe54e29bb9417356916d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 31 Oct 2023 00:03:42 +0300 Subject: [PATCH 148/357] refactor(build): Overhaul paths again, fixing conflation of developer mode and luarocks trees --- core/pathsetup.lua.in | 68 +++++++++++++++++++++++++++++++------------ core/sile.lua | 1 + 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/core/pathsetup.lua.in b/core/pathsetup.lua.in index d9b4b8dcb..3a5f482bb 100644 --- a/core/pathsetup.lua.in +++ b/core/pathsetup.lua.in @@ -8,46 +8,59 @@ local executable = debug.getinfo(3, "S").source local luaversion = _VERSION:match("%d+%.%d+") -- Normalize possibly dirty Lua path formatting shortcut: /./ → / --- Even leafo/gh-actions-luarocks takes this shortcut which inhibits duplicate cleanup +-- Even leafo/gh-actions-luarocks takes this shortcut which inhibits duplicate cleanup. package.path = package.path:gsub("/%./", "/") package.cpath = package.cpath:gsub("/%./", "/") +-- Utility function so that last-added paths take precidence and are not duplicated. local function prepend_and_dedup (segment, path) local escaped = segment:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1') -- copied from pl.utils.escape() which we can't load yet local striped = path:gsub(("^%s"):format(escaped), ""):gsub((";%s"):format(escaped), "") return ("%s;%s"):format(segment, striped) end +-- Prepend paths specifically for Lua module.s local function prependPath (path) package.path = prepend_and_dedup(path .. "/?/init.lua", package.path) package.path = prepend_and_dedup(path .. "/?.lua", package.path) end +-- Prepand paths specifically for C modules. local function prependCPath (path) package.cpath = prepend_and_dedup(path .. "/?.@SHARED_LIB_EXT@", package.cpath) end -local function extendPaths (path, luarocks_tree) +-- Take a given path and iterate over permutations of paths that LuaRocks might have installed a rock to that are +-- specific to a given Lua version version +local function extendPathsRocks (path) + prependCPath(path .. "/lib/lua/" .. luaversion) + prependCPath(path .. "/lib/lua/" .. luaversion .. "/sile") + prependPath(path .. "/share/lua/" .. luaversion) + prependPath(path .. "/share/lua/" .. luaversion .. "/sile") +end + +-- Take a given path and iterate over the permutations of subdirectories we expect to finde SILE/Lua/C modules under. +-- The second argument enables extra paths that we *only* expect to find in SILE source checkouts, and should not be +-- found in system, user, toolkit, or project level paths. +local function extendPaths (path, silesourcedir) + extendPathsRocks(path .. "/lua_modules") prependCPath(path) prependPath(path) - if luarocks_tree then - if "@DEVELOPER_FALSE@" ~= "" then -- see ./configure --(en|dis)able-developer - prependCPath(path .. "/libtexpdf/.libs") - prependCPath(path .. "/justenough/.libs") - end + if silesourcedir then prependPath(path .. "/lua-libraries") - prependCPath(path .. "/lib/lua/" .. luaversion) - prependCPath(path .. "/lib/lua/" .. luaversion .. "/sile") - prependPath(path .. "/share/lua/" .. luaversion) - prependPath(path .. "/share/lua/" .. luaversion .. "/sile") else prependCPath(path .. "/sile") prependPath(path .. "/sile") end + -- These paths are *only* used in developer mode for build testing + if "@DEVELOPER_FALSE@" ~= "" then -- see ./configure --(en|dis)able-developer + prependCPath(path .. "/libtexpdf/.libs") + prependCPath(path .. "/justenough/.libs") + end end --- Facilitate loading SILE classes & packages from system LuaRocks --- Also weed out CWD relative paths, we add them in a different order later +-- Facilitate loading SILE classes & packages from system LuaRocks by adding variants of the default Lua paths with sile +-- appended, stashed to be prepended later. Also weed out CWD relative paths, we add them in a different order later. local luapath = {} local extpath = {} for path in package.path:gmatch("[^;]+") do @@ -56,14 +69,23 @@ for path in package.path:gmatch("[^;]+") do end package.path = table.concat(luapath, ";") +-- This path is set by autoconf at configure time, and could be the full path to the source directory if in developer +-- mode or the expeted system istalation location otherwise. extendPaths("@SILE_PATH@", true) extendPaths("@SILE_LIB_PATH@", true) + +-- If the configure time option to use system luarocks is disabled, use ones local to the source (again could be the +-- development mode source directory or expected system instalation location). if "@SYSTEM_LUAROCKS_FALSE@" == "" then -- see ./configure --with[out]-system-luarocks - extendPaths("@SILE_PATH@/lua_modules", true) + extendPathsRocks("@SILE_PATH@/lua_modules") end +-- Stuff the variants of system Lua Rocks paths with sile suffixes added back at higher priority that regular paths. package.path = table.concat(extpath, ";") .. ";" .. package.path +-- Deal with the *run time* variant of SILE_PATH, which may be more than one path. This could be references to a source +-- tree for development work, a fork of some SILE core libraries, or just a way to stuff toolkits into the path besides +-- the default project local or system paths without exporting Lua environment variables. local pathvar = os.getenv("SILE_PATH") if pathvar then for path in string.gmatch(pathvar, "[^;]+") do @@ -73,14 +95,22 @@ if pathvar then end end -local cwd = executable:gsub("(.*)(/.*)", "%1") -if cwd:match("^@") then -- Nix Flake root path - extendPaths(".", true) +-- Add the current working directory, presumably a local project, as one of the highest priority paths. +local executable_dir = executable:gsub("(.*)(/.*)", "%1") +if executable_dir:match("^@") then + -- Running from a nix flake reports this, but we don't want anything special to get added. + extendPaths(".") else - if cwd ~= "./" then extendPaths(cwd) end + -- If executable_dir is just an alternate name of PWD, we don't need to duplicate it. + -- Also ignore Rust binary thinking its executable_dir is in its source directory. + if executable_dir ~= "./" and executable_dir ~= "src" then + extendPaths(executable_dir) + end + extendPathsRocks("./lua_modules") extendPaths(".") - extendPaths("./lua_modules", true) end +-- Stuff internal utility features into the global namespace so they could be manipulated externally (undocumented). _G.extendSilePath = extendPaths +_G.extendSilePathRocks = extendPathsRocks _G.executablePath = executable diff --git a/core/sile.lua b/core/sile.lua index 40719b859..8dfd51404 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -329,6 +329,7 @@ function SILE.processFile (filename, format, options) end if SILE.masterDir and SILE.masterDir:len() >= 1 then _G.extendSilePath(SILE.masterDir) + _G.extendSilePathRocks(SILE.masterDir .. "/lua_modules") end filename = SILE.resolveFile(filename) or SU.error("Could not find file") local mode = lfs.attributes(filename).mode From d0a2a1ee9645ee357fd8efa3e6b9406aad7ddf1c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 31 Oct 2023 22:55:24 +0300 Subject: [PATCH 149/357] fix(backends): Fix plain text backend to work in LuaJIT/Lua 5.1 --- outputters/text.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outputters/text.lua b/outputters/text.lua index 2898cff25..661635c0e 100644 --- a/outputters/text.lua +++ b/outputters/text.lua @@ -59,7 +59,7 @@ function outputter:setCursor (x, y, relative) outfile:write("‫") end elseif newx > cursorX then - if newx - cursorX > spc then + if newx:tonumber() - cursorX:tonumber() > spc then outfile:write(" ") else outfile:write("‫") From 2c980c210c847b3b9c8026daadf73dab9e017d82 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 2 Nov 2023 17:01:29 +0300 Subject: [PATCH 150/357] chore(build): Tell Cargo about all the things autotools consideres dependencies Among other things this will trigger rebuilds after commits so that the embeded version string is actually kept up to date. --- build-aux/build.rs | 6 +++++- build-aux/rust_boilerplate.mk.in | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/build-aux/build.rs b/build-aux/build.rs index 739ea2f7c..7e9156853 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -15,7 +15,11 @@ use vergen::EmitBuilder; include!("../src/cli.rs"); fn main() { - println!("cargo:rerun-if-changed=.version"); + if let Ok(val) = env::var("AUTOTOOLS_DEPENDENCIES") { + for dependency in val.split(' ') { + println!("cargo:rerun-if-changed={dependency}"); + } + } let mut builder = EmitBuilder::builder(); // If passed a version from automake, use that instead of vergen's formatting if let Ok(val) = env::var("VERSION_FROM_AUTOTOOLS") { diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index 32623cb31..e324bea41 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -55,6 +55,7 @@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(CARGO_BIN) | $(COMPLETION $(_RUST_OUT) $(CARGO_BIN): $(@PACKAGE_VAR@_SOURCES) $(EXTRA_@PACKAGE_VAR@_SOURCES) cd $(top_srcdir) set -e + export AUTOTOOLS_DEPENDENCIES="$^" $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) From bff44d595d60a4e171830a491b54a0f880639cc3 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 4 Nov 2023 07:00:54 +0300 Subject: [PATCH 151/357] chore(tooling): Lint source file generation templates but don't recurse modules --- .github/workflows/rust_lint.yml | 2 +- build-aux/rust_boilerplate.mk.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml index ac1174c4a..8c315d67f 100644 --- a/.github/workflows/rust_lint.yml +++ b/.github/workflows/rust_lint.yml @@ -20,7 +20,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run rustfmt run: | - git ls-files '*.rs' | xargs rustfmt --check + git ls-files '*.rs' '*.rs.in' | xargs rustfmt --check --config skip_children=true clippy: strategy: diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index e324bea41..fc61df56d 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -71,7 +71,7 @@ clean-local: clean-cargo check-local: cargo-test rustfmt: - $(GIT) ls-files '*.rs' | $(XARGS) $(RUSTFMT) --check + $(GIT) ls-files '*.rs' '*.rs.in' | $(XARGS) $(RUSTFMT) --check --config skip_children=true clippy: cd $(srcdir) From 3224243e2f163b5111928bf2f4601ee292cdf6fc Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 4 Nov 2023 10:24:46 +0300 Subject: [PATCH 152/357] chore(packages): Tweak pandoc list functions to pass through to lists package --- packages/lists/init.lua | 6 +++--- packages/pandoc/init.lua | 41 +++++++++++++--------------------------- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/packages/lists/init.lua b/packages/lists/init.lua index b2082af0f..29db687a2 100644 --- a/packages/lists/init.lua +++ b/packages/lists/init.lua @@ -72,8 +72,8 @@ local trim = function (str) end local enforceListType = function (cmd) - if cmd ~= "enumerate" and cmd ~= "itemize" then - SU.error("Only 'enumerate', 'itemize' or 'item' are accepted in lists, found '"..cmd.."'") + if cmd ~= "enumerate" and cmd ~= "itemize" and cmd ~= "BulletedList" and cmd ~= "OrderedList" then + SU.error("Only items or lists are allowed as content in lists, found '"..cmd.."'") end end @@ -165,7 +165,7 @@ function package.doNestedList (_, listType, options, content) local counter = options.start and (SU.cast("integer", options.start) - 1) or 0 for i = 1, #content do if type(content[i]) == "table" then - if content[i].command == "item" then + if content[i].command == "item" or content[i].command == "ListItem" then counter = counter + 1 -- Enrich the node with internal properties content[i]._lists_ = { diff --git a/packages/pandoc/init.lua b/packages/pandoc/init.lua index c3fc868d4..24356f1bc 100644 --- a/packages/pandoc/init.lua +++ b/packages/pandoc/init.lua @@ -49,6 +49,7 @@ function package:_init () base._init(self) self:loadPackage("footnotes") self:loadPackage("image") + self:loadPackage("lists") self:loadPackage("pdf") self:loadPackage("raiselower") self:loadPackage("rules") @@ -67,15 +68,11 @@ function package:registerCommands () SILE.typesetter:leaveHmode() end) - self:registerCommand("BulletList", function (_, content) - -- luacheck: ignore pandocListType - local pandocListType = "bullet" - SILE.settings:temporarily(function () - SILE.settings:set("document.rskip","10pt") - SILE.settings:set("document.lskip","20pt") - SILE.process(content) + self:registerCommand("BulletList", function (options, content) + local wrapper, args = handlePandocArgs(options) + wrapper(function () + SILE.call("itemize", args, content) end) - SILE.typesetter:leaveHmode() end) self:registerCommand("CodeBlock", function (options, content) @@ -128,14 +125,11 @@ function package:registerCommands () SILE.typesetter:leaveHmode() end) - self:registerCommand("OrderedList", function (_, content) - -- TODO: handle listAttributes - SILE.settings:temporarily(function () - SILE.settings:set("document.rskip","10pt") - SILE.settings:set("document.lskip","20pt") - SILE.process(content) + self:registerCommand("OrderedList", function (options, content) + local wrapper, args = handlePandocArgs(options) + wrapper(function () + SILE.call("enumerate", args, content) end) - SILE.typesetter:leaveHmode() end) self:registerCommand("Para", function (_, content) @@ -277,20 +271,11 @@ function package:registerCommands () -- Non native types - self:registerCommand("ListItem", function (_, content) - SILE.call("smallskip") - SILE.call("glue", { width = "-1em"}) - SILE.call("rebox", { width = "1em" }, function () - -- Note: Relies on Lua scope shadowing to find immediate parent list type - -- luacheck: ignore pandocListType - if pandocListType == "bullet" then - SILE.typesetter:typeset("•") - else - SILE.typesetter:typeset("-") - end + self:registerCommand("ListItem", function (options, content) + local wrapper, args = handlePandocArgs(options) + wrapper(function () + SILE.call("item", args, content) end) - SILE.process(content) - SILE.call("smallskip") end) self:registerCommand("ListItemTerm", function (_, content) From 3177bafad35d57d89104bd89cb61415f96630c7c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 11 Nov 2023 10:33:14 +0300 Subject: [PATCH 153/357] ci(cirrus): Switch Cirrus builder to LuaJIT per defaults --- .cirrus.yml | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index b18f51e71..ab336409b 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,7 +3,7 @@ task: freebsd_instance: matrix: - image_family: freebsd-13-2 - - image_family: freebsd-12-3 + - image_family: freebsd-12-4 env: MAKEFLAGS: -j$(nproc) -Otarget CFLAGS: -I/usr/local/include -fPIC @@ -24,20 +24,20 @@ task: fingerprint_script: cat sile.rockspec.in dependencies_script: - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz jq libtool pkgconf png rust - - pkg install -y lua54 lua54-luaexpat lua54-lpeg lua54-luafilesystem lua54-luarocks lua54-luasec lua54-luasocket - - luarocks54 install cassowary - - luarocks54 install cldr - - luarocks54 install compat53 - - luarocks54 install fluent - - luarocks54 install linenoise - - luarocks54 install loadkit - - luarocks54 install lua-zlib - - luarocks54 install lua_cliargs - - luarocks54 install luaepnf - - luarocks54 install luarepl - - luarocks54 install luautf8 - - luarocks54 install penlight - - luarocks54 install vstruct + - pkg install -y luajit lua51-luaexpat lua51-lpeg lua51-luafilesystem lua51-luarocks lua51-luasec lua51-luasocket + - luarocks51 install cassowary + - luarocks51 install cldr + - luarocks51 install compat53 + - luarocks51 install fluent + - luarocks51 install linenoise + - luarocks51 install loadkit + - luarocks51 install lua-zlib + - luarocks51 install lua_cliargs + - luarocks51 install luaepnf + - luarocks51 install luarepl + - luarocks51 install luautf8 + - luarocks51 install penlight + - luarocks51 install vstruct bootstrap_script: - git fetch --prune --tags ||: - ./bootstrap.sh @@ -45,6 +45,7 @@ task: ./configure MAKE=gmake \ --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false PDFINFO=false NIX=false \ --disable-font-variations \ + --with-system-lua-sources \ --with-system-luarocks \ --without-manual make_script: From 3f298143457d0cd4c178096a5e5ecb54d5eb50a3 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 11 Nov 2023 11:37:34 +0300 Subject: [PATCH 154/357] chore(core): Remove shims for APIs marked deprecated in 0.15.0 --- core/cli.lua | 3 +-- core/deprecations.lua | 3 +-- core/pagebuilder.lua | 2 -- core/settings.lua | 19 +++++++++---------- core/sile.lua | 1 - core/typesetter.lua | 2 -- packages/counters/init.lua | 6 ++---- packages/infonode/init.lua | 3 +-- packages/masters/init.lua | 4 +--- packages/rules/init.lua | 23 ----------------------- packages/twoside/init.lua | 3 +-- 11 files changed, 16 insertions(+), 53 deletions(-) diff --git a/core/cli.lua b/core/cli.lua index 474076d00..2226f9896 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -119,9 +119,8 @@ cli.parseArguments = function () for _, path in ipairs(opts.postamble) do table.insert(SILE.input.postambles, path) end - for _, path in ipairs(opts.include) do + if opts.include then SU.deprecated("-I/--include", "-u/--use or -p/--preamble", "0.14.0", "0.15.0") - table.insert(SILE.input.includes, path) end -- http://lua-users.org/wiki/VarargTheSecondClassCitizen local summary = function (...) diff --git a/core/deprecations.lua b/core/deprecations.lua index 73f050dee..204baa9cc 100644 --- a/core/deprecations.lua +++ b/core/deprecations.lua @@ -49,9 +49,8 @@ SILE.baseClass = setmetatable({}, { __index = nobaseclass }) -SILE.defaultTypesetter = function (frame) +SILE.defaultTypesetter = function () SU.deprecated("SILE.defaultTypesetter", "SILE.typesetters.base", "0.14.6", "0.15.0") - return SILE.typesetters.base(frame) end SILE.toPoints = function (_, _) diff --git a/core/pagebuilder.lua b/core/pagebuilder.lua index 36b68f159..c0e904fc3 100644 --- a/core/pagebuilder.lua +++ b/core/pagebuilder.lua @@ -1,3 +1 @@ SU.deprecated("core.pagebuilder", "pagebuilder.base", "0.14.6", "0.15.0") - -return require("pagebuilders.base") diff --git a/core/settings.lua b/core/settings.lua index 4db053fdc..ac3b200cf 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -1,6 +1,5 @@ local deprecator = function () SU.deprecated("SILE.settings.*", "SILE.settings:*", "0.13.0", "0.15.0") - return SILE.settings end local settings = pl.class() @@ -96,18 +95,18 @@ function settings:_init() end function settings:pushState () - if not self then self = deprecator() end + if not self then return deprecator() end table.insert(self.stateQueue, self.state) self.state = pl.tablex.copy(self.state) end function settings:popState () - if not self then self = deprecator() end + if not self then return deprecator() end self.state = table.remove(self.stateQueue) end function settings:declare (spec) - if not spec then self, spec = deprecator(), self end + if not spec then return deprecator() end if spec.name then SU.deprecated("'name' argument of SILE.settings:declare", "'parameter' argument of SILE.settings:declare", "0.10.10", "0.11.0") end @@ -121,7 +120,7 @@ end --- Reset all settings to their default value. function settings:reset () - if not self then self = deprecator() end + if not self then return deprecator() end for k,_ in pairs(self.state) do self:set(k, self.defaults[k]) end @@ -131,7 +130,7 @@ end -- that is at the head of the settings stack (normally the document -- level). function settings:toplevelState () - if not self then self = deprecator() end + if not self then return deprecator() end if #self.stateQueue ~= 0 then for parameter, _ in pairs(self.state) do -- Bypass self:set() as the latter performs some tests and a cast, @@ -148,7 +147,7 @@ function settings:get (parameter) if parameter == "current.parindent" then return SILE.typesetter and SILE.typesetter.state.parindent end - if not parameter then self, parameter = deprecator(), self end + if not parameter then return deprecator() end if not self.declarations[parameter] then SU.error("Undefined setting '"..parameter.."'") end @@ -184,7 +183,7 @@ function settings:set (parameter, value, makedefault, reset) end return end - if type(self) ~= "table" then self, parameter, value, makedefault, reset = deprecator(), self, parameter, value, makedefault end + if type(self) ~= "table" then return deprecator() end if not self.declarations[parameter] then SU.error("Undefined setting '"..parameter.."'") end @@ -203,14 +202,14 @@ function settings:set (parameter, value, makedefault, reset) end function settings:temporarily (func) - if not func then self, func = deprecator(), self end + if not func then return deprecator() end self:pushState() func() self:popState() end function settings:wrap () -- Returns a closure which applies the current state, later - if not self then self = deprecator() end + if not self then return deprecator() end local clSettings = pl.tablex.copy(self.state) return function(content) table.insert(self.stateQueue, self.state) diff --git a/core/sile.lua b/core/sile.lua index 8dfd51404..99e320727 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -65,7 +65,6 @@ SILE.input = { filenames = {}, evaluates = {}, evaluateAfters = {}, - includes = {}, uses = {}, options = {}, preambles = {}, diff --git a/core/typesetter.lua b/core/typesetter.lua index cf7ca1a52..d2d35c79a 100644 --- a/core/typesetter.lua +++ b/core/typesetter.lua @@ -1,3 +1 @@ SU.deprecated("core.typesetter", "typesetters.base", "0.14.0", "0.15.0") - -return require("typesetters.base") diff --git a/packages/counters/init.lua b/packages/counters/init.lua index 7df646d24..9f8b57c5f 100644 --- a/packages/counters/init.lua +++ b/packages/counters/init.lua @@ -3,14 +3,12 @@ local base = require("packages.base") local package = pl.class(base) package._name = "counters" -SILE.formatCounter = function (counter) +SILE.formatCounter = function () SU.deprecated("SILE.formatCounter", "class:formatCounter", "0.13.0", "0.15.0") - return package.formatCounter(nil, counter) end -SILE.formatMultilevelCounter = function (counter, options) +SILE.formatMultilevelCounter = function () SU.deprecated("SILE.formatMultilevelCounter", "class:formatMultilevelCounter", "0.13.0", "0.15.0") - return package.formatMultilevelCounter(nil, counter, options) end local function getCounter (_, id) diff --git a/packages/infonode/init.lua b/packages/infonode/init.lua index c53fce99f..40f65ff5e 100644 --- a/packages/infonode/init.lua +++ b/packages/infonode/init.lua @@ -43,9 +43,8 @@ function package:_init () SILE.scratch.info = { thispage = {} } end self.class:registerHook("newpage", newPageInfo) - self:deprecatedExport("newPageInfo", function (class) + self:deprecatedExport("newPageInfo", function () SU.deprecated("class:newPageInfo", nil, "0.13.0", "0.15.0", _deprecate) - return class:newPageInfo() end) end diff --git a/packages/masters/init.lua b/packages/masters/init.lua index 664c7b3fa..e00806776 100644 --- a/packages/masters/init.lua +++ b/packages/masters/init.lua @@ -37,9 +37,8 @@ local function doswitch (frames) end end -local function switchMasterOnePage (class, id) +local function switchMasterOnePage (_, id) if not id then - id = class SU.deprecated("class.switchMasterOnePage", "class:switchMasterOnePage", "0.13.0", "0.15.0") end if not SILE.scratch.masters[id] then @@ -53,7 +52,6 @@ end local function switchMaster (class, id) if not id then - id, class = class, SILE.documentState.documentClass SU.deprecated("class.switchMaster", "class:switchMaster", "0.13.0", "0.15.0") end _currentMaster = id diff --git a/packages/rules/init.lua b/packages/rules/init.lua index 22f68851b..b6efbc3a7 100644 --- a/packages/rules/init.lua +++ b/packages/rules/init.lua @@ -107,38 +107,15 @@ function package:registerCommands () local thickness = SU.cast("measurement", options.thickness or "0.2pt") local raise = SU.cast("measurement", options.raise or "0.5em") - -- BEGIN DEPRECATION COMPATIBILITY if options.height then SU.deprecated("\\fullrule[…, height=…]", "\\fullrule[…, thickness=…]", "0.13.1", "0.15.0") - thickness = SU.cast("measurement", options.height) end if not SILE.typesetter:vmode() then SU.deprecated("\\fullrule in horizontal mode", "\\hrule or \\hrulefill", "0.13.1", "0.15.0") - if options.width then - SU.deprecated("\\fullrule with width", "\\hrule and \\raise", "0.13.1", "0.15.0") - SILE.call("raise", { height = raise }, function () - SILE.call("hrule", { - height = thickness, - width = options.width - }) - end) - else - -- This was very broken anyway, as it was overflowing the line. - -- At least we try better... - SILE.call("hrulefill", { raise = raise, thickness = thickness }) - end - return end if options.width then SU.deprecated("\\fullrule with width", "\\hrule and \\raise", "0.13.1 ", "0.15.0") - SILE.call("raise", { height = raise }, function () - SILE.call("hrule", { - height = thickness, - width = options.width - }) - end) end - -- END DEPRECATION COMPATIBILITY SILE.typesetter:leaveHmode() SILE.call("noindent") diff --git a/packages/twoside/init.lua b/packages/twoside/init.lua index 4f90ceb75..4e81ef16b 100644 --- a/packages/twoside/init.lua +++ b/packages/twoside/init.lua @@ -57,9 +57,8 @@ function package:_init (options) end self:export("oddPage", self.oddPage) self:export("mirrorMaster", mirrorMaster) - self:export("switchPage", function (class) + self:export("switchPage", function () SU.deprecated("class:switchPage", nil, "0.13.0", "0.15.0", _deprecate) - return class:switchPage() end) self.class.oddPageMaster = options.oddPageMaster self.class.evenPageMaster = options.evenPageMaster From 730150f9b7a759b2564461b95778bdd27df20b2e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 11 Nov 2023 21:21:30 +0300 Subject: [PATCH 155/357] fix(packages): Use current pagebuilder API not deprecatod one internaly --- packages/balanced-frames/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/balanced-frames/init.lua b/packages/balanced-frames/init.lua index 97619d38a..644c1a175 100644 --- a/packages/balanced-frames/init.lua +++ b/packages/balanced-frames/init.lua @@ -55,7 +55,7 @@ local function buildPage (typesetter, independent) end typesetter.state.lastPenalty = 0 local oldPageBuilder = SILE.pagebuilder - SILE.pagebuilder = require("core.pagebuilder")() + SILE.pagebuilder = SILE.pagebuilders.base() while typesetter.frame and typesetter.frame.balanced do unbalanced_buildPage(typesetter, true) if typesetter.frame.next and SILE.getFrame(typesetter.frame.next).balanced == true then From 5e097d354e710a2b34eafc0d4c6e02592904da62 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 11 Nov 2023 21:32:48 +0300 Subject: [PATCH 156/357] chore(packages): Remove shims for APIs marked deprecated in 0.14.0 --- packages/bibtex/init.lua | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/bibtex/init.lua b/packages/bibtex/init.lua index 134ee3301..373b619c1 100644 --- a/packages/bibtex/init.lua +++ b/packages/bibtex/init.lua @@ -81,12 +81,6 @@ function package:registerCommands () self:registerCommand("bibstyle", function (_, content) SU.deprecated("\\bibstyle", '\\set[parameter=bibtex.style]', "0.13.2", "0.14.0") - if type(content) == "table" then - content = content[1] - end - if type(content) == "string" then - SILE.settings:set("bibtex.style", content) - end end) self:registerCommand("cite", function (options, content) From ed3331af4b9ed60a0010b7f8b617135e1323f5e6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 4 Nov 2023 12:10:43 +0300 Subject: [PATCH 157/357] feat(packages)!: Make most package _init() actions run only once BREAKING CHANGE: The current (pseudo) idempotent behaviour when loading a package potentially clobbers anything that has been modified since the last load. Loading a package, then modifiying a function it provides, then loading the same package again will clobber the modifiecation. This is good for idempotency but not very good for user experience when you may not be modifiying all aspects of a document render pipeline at once, as in when using templates. This change makes the default behaviour to run setting, raw handler, and command registrations only once. An altertanive to :loadpackage() called :reloadpackage() can be used to force all these registrations to be rerun when the goal is to make sure of a specific state. --- classes/base.lua | 8 ++++++-- packages/base.lua | 33 +++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 0d469006a..7c7768bd3 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -150,15 +150,19 @@ function class.declareSettings (_) }) end -function class:loadPackage (packname, options) +function class:loadPackage (packname, options, reload) local pack = require(("packages.%s"):format(packname)) if type(pack) == "table" and pack.type == "package" then -- new package - self.packages[pack._name] = pack(options) + self.packages[pack._name] = pack(options, reload) else -- legacy package self:initPackage(pack, options) end end +function class:reloadPackage (packname, options) + return self:loadPackage(packname, options, true) +end + function class:initPackage (pack, options) SU.deprecated("class:initPackage(options)", "package(options)", "0.14.0", "0.16.0", [[ This package appears to be a legacy format package. It returns a table diff --git a/packages/base.lua b/packages/base.lua index d7f5a1f27..ae1534b92 100644 --- a/packages/base.lua +++ b/packages/base.lua @@ -14,15 +14,32 @@ local function script_path () return base end -function package:_init (_) +local settingDeclarations = { } +local rawhandlerRegistrations = {} +local commandRegistrations = { } + +function package:_init (_, reload) self.class = SILE.scratch.half_initialized_class or SILE.documentState.documentClass if not self.class then SU.error("Attempted to initialize package before class, should have been queued in the preamble", true) end self.basedir = script_path() - self:declareSettings() - self:registerRawHandlers() - self:registerCommands() + -- Note string.format(%p) would be nicer than tostring() but only LuaJIT and Lua 5.4 support it + local settingsDeclarator = tostring(self.declareSettings) + if reload or not settingDeclarations[settingsDeclarator] then + settingDeclarations[settingsDeclarator] = true + self:declareSettings() + end + local rawhandlerRegistrator = tostring(self.registerRawHandlers) + if reload or not rawhandlerRegistrations[rawhandlerRegistrator] then + rawhandlerRegistrations[rawhandlerRegistrator] = true + self:registerRawHandlers() + end + local commandRegistrator = tostring(self.registerCommands) + if reload or not commandRegistrations[commandRegistrator] then + commandRegistrations[commandRegistrator] = true + self:registerCommands() + end end function package:_post_init () @@ -33,8 +50,12 @@ function package.declareSettings (_) end function package.registerRawHandlers (_) end -function package:loadPackage (packname) - return self.class:loadPackage(packname) +function package:loadPackage (packname, options, reload) + return self.class:loadPackage(packname, options, reload) +end + +function package:reloadPackage (packname, options) + return self.class:reloadPackage(packname, options) end function package.registerCommands (_) end From 2b85318eae44719652d98eab55b0521f987a3fe4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 15 Nov 2023 14:45:20 +0300 Subject: [PATCH 158/357] chore(packages): Fix lint issue, unused var because of deprected API --- packages/bibtex/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bibtex/init.lua b/packages/bibtex/init.lua index 373b619c1..d4b77a6b5 100644 --- a/packages/bibtex/init.lua +++ b/packages/bibtex/init.lua @@ -79,7 +79,7 @@ function package:registerCommands () SILE.scratch.bibtex.bib = parseBibtex(file) -- Later we'll do multiple bibliogs, but not now end) - self:registerCommand("bibstyle", function (_, content) + self:registerCommand("bibstyle", function (_, _) SU.deprecated("\\bibstyle", '\\set[parameter=bibtex.style]', "0.13.2", "0.14.0") end) From dc6b0642dcfdb336be499bd26783a7fa0efe4b01 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 19 Oct 2023 14:27:41 +0300 Subject: [PATCH 159/357] chore(cli): Add plumbing to embed things otherwise installed to datadir --- .gitignore | 3 +++ Cargo.lock | 26 ++++++++++++++++++++++++++ Cargo.toml | 1 + Makefile.am | 24 +++++++++++++++++++----- src/embed.rs.in | 40 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 7 +++++++ 6 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 src/embed.rs.in diff --git a/.gitignore b/.gitignore index d243ce5c6..674cc4563 100644 --- a/.gitignore +++ b/.gitignore @@ -88,11 +88,14 @@ sile-lua.1 .tarball-version .built-subdirs *.so +*.o core/version.lua core/features.lua target/ completions/ core/pathsetup.lua +src/embed.rs +src/embed-includes.rs # Nix symlink to builds result diff --git a/Cargo.lock b/Cargo.lock index f0ecec724..75d896044 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -325,6 +325,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -840,6 +846,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "globset" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "hashbrown" version = "0.14.1" @@ -908,6 +927,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + [[package]] name = "lua-src" version = "546.0.1" @@ -1174,6 +1199,7 @@ version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" dependencies = [ + "globset", "sha2", "walkdir", ] diff --git a/Cargo.toml b/Cargo.toml index 4bb775c02..11fc040bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,7 @@ lto = true [dependencies.rust-embed] version = "8.0" optional = true + features = [ "include-exclude" ] [build-dependencies] diff --git a/Makefile.am b/Makefile.am index 53a851d56..92fc477c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,11 +59,9 @@ BUILT_LUA_SOURCES = core/features.lua core/pathsetup.lua core/version.lua bin_PROGRAMS = sile bin_SCRIPTS = sile-lua dist_man_MANS = sile-lua.1 -sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs +sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs src/embed.rs src/embed-includes.rs EXTRA_sile_SOURCES = -if EMBEDED_RESOURCES -export EMBEDED_LUA_RESOURCES = $(SILEDATA) $(LUALIBRARIES) $(BUILT_LUA_SOURCES) $(LUAMODULES) -else +if !EMBEDED_RESOURCES nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = $(BUILT_LUA_SOURCES) $(LUAMODULES) endif @@ -78,7 +76,7 @@ EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) -BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles +BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles src/embed-includes.rs src/embed.rs CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) @@ -87,6 +85,22 @@ include $(top_srcdir)/build-aux/rust_boilerplate.mk Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ +if EMBEDED_RESOURCES +export EMBEDED_LUA_RESOURCES = $(SILEDATA) $(LUALIBRARIES) $(BUILT_LUA_SOURCES) $(LUAMODULES) + +src/embed-includes.rs: Makefile-distfiles + cat << EOF | sed -e '/^$$/d' > $@ + $(foreach FILE,$(EMBEDED_LUA_RESOURCES),#[include = "$(FILE)"] + ) + EOF + +src/embed.rs: src/embed.rs.in src/embed-includes.rs + $(SED) \ + -e '/@INCLUDE_EMDED_INCLUDES@/r $(word 2,$^)' \ + -e '/@INCLUDE_EMDED_INCLUDES@/d' \ + $< > $@ +endif EMBEDED_RESOURCES + if LUAJIT MLUAVER = luajit else diff --git a/src/embed.rs.in b/src/embed.rs.in new file mode 100644 index 000000000..58a1fce12 --- /dev/null +++ b/src/embed.rs.in @@ -0,0 +1,40 @@ +use mlua::prelude::*; +use rust_embed::RustEmbed; +use std::str; + +/// Embed everything that would otherwise be installed to datadir +#[derive(RustEmbed)] +#[folder = "."] +// @INCLUDE_EMDED_INCLUDES@ -- this marker line gets replaced by a list of includes +#[exclude = "*"] +pub struct SileModules; + +pub fn gmod (lua: &Lua) { + let package: LuaTable = lua.globals().get("package").unwrap(); + + let loaders: LuaValue = package.get("loaders").unwrap(); + if let LuaValue::Table(loaders) = loaders { + dbg!(loaders.clone()); + + loaders.push(LuaFunction::wrap(|lua, path: String| { + dbg!(path.clone()); + let embeded = SileModules::get(&path); + match embeded { + Some(module) => { + return LuaFunction::wrap(move |lua, ()| { + let data = str::from_utf8(module.data.as_ref()).expect("Embeded content is not valid UTF-8"); + lua.create_string(data) + }).into_lua(lua) + }, + None => format!("Module {path} is not embeded in Rust binary").into_lua(lua) + } + })).unwrap(); + + lua.load(r#"print("fizzle", require("core.version"))"#).exec().unwrap(); + } + + let searchers: LuaValue = package.get("searchers").unwrap(); + if let LuaValue::Table(searchers) = searchers { + dbg!(searchers); + } +} diff --git a/src/lib.rs b/src/lib.rs index 34c79e93f..83ebb560b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,15 @@ +// rust-embed include attributes have issues with lots of matches... +#![recursion_limit = "2048"] + use mlua::chunk; use mlua::prelude::*; use std::{env, path::PathBuf}; #[cfg(feature = "cli")] pub mod cli; +#[cfg(feature = "embed")] +pub mod embed; + pub type Result = anyhow::Result; pub fn version() -> crate::Result { @@ -53,6 +59,7 @@ pub fn run( traceback: bool, ) -> crate::Result<()> { let lua = unsafe { Lua::unsafe_new() }; + crate::embed::gmod(&lua); let sile_path = match env::var("SILE_PATH") { Ok(val) => val, Err(_) => env!("CONFIGURE_DATADIR").to_string(), From 62851af7e9290ed1adbeb9926d1ee485d9353006 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 20 Oct 2023 15:27:01 +0300 Subject: [PATCH 160/357] refactor(cli): Reuse Lua VM instead across invocation functions --- src/embed.rs.in | 14 +++++---- src/lib.rs | 75 ++++++++++++++++++++++++------------------------- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/embed.rs.in b/src/embed.rs.in index 58a1fce12..ad4f9f785 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -9,16 +9,16 @@ use std::str; #[exclude = "*"] pub struct SileModules; -pub fn gmod (lua: &Lua) { +pub fn inject_embeded_loader (lua: &Lua) { let package: LuaTable = lua.globals().get("package").unwrap(); let loaders: LuaValue = package.get("loaders").unwrap(); if let LuaValue::Table(loaders) = loaders { dbg!(loaders.clone()); - loaders.push(LuaFunction::wrap(|lua, path: String| { - dbg!(path.clone()); - let embeded = SileModules::get(&path); + loaders.push(LuaFunction::wrap(|lua, module: String| { + dbg!(module.clone()); + let embeded = SileModules::get(&module); match embeded { Some(module) => { return LuaFunction::wrap(move |lua, ()| { @@ -26,11 +26,13 @@ pub fn gmod (lua: &Lua) { lua.create_string(data) }).into_lua(lua) }, - None => format!("Module {path} is not embeded in Rust binary").into_lua(lua) + None => format!("Module {module} is not embeded in Rust binary").into_lua(lua) } })).unwrap(); - lua.load(r#"print("fizzle", require("core.version"))"#).exec().unwrap(); + dbg!(loaders.clone()); + + lua.load(r#"print("fizzle", require("core/version.lua"))"#).exec().unwrap(); } let searchers: LuaValue = package.get("searchers").unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 83ebb560b..f73007df2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,27 +12,45 @@ pub mod embed; pub type Result = anyhow::Result; -pub fn version() -> crate::Result { +pub fn start_luavm() -> crate::Result { let lua = unsafe { Lua::unsafe_new() }; + #[cfg(feature = "embed")] + crate::embed::inject_embeded_loader(&lua); + inject_paths(&lua); + inject_version(&lua); + Ok(lua) +} + +pub fn inject_paths(lua: &Lua) { let sile_path = match env::var("SILE_PATH") { Ok(val) => val, Err(_) => env!("CONFIGURE_DATADIR").to_string(), }; - let sile_path: LuaString = lua.create_string(&sile_path)?; - let sile: LuaTable = lua - .load(chunk! { - local status - for path in string.gmatch($sile_path, "[^;]+") do - status = pcall(dofile, path .. "/core/pathsetup.lua") - if status then break end - end - if not status then - dofile("./core/pathsetup.lua") - end - return require("core.sile") - }) - .eval()?; - let mut full_version: String = sile.get("full_version")?; + let sile_path: LuaString = lua.create_string(&sile_path).unwrap(); + lua.load(chunk! { + local status + for path in string.gmatch($sile_path, "[^;]+") do + status = pcall(dofile, path .. "/core/pathsetup.lua") + if status then break end + end + if not status then + dofile("./core/pathsetup.lua") + end + }) + .exec() + .unwrap(); +} + +pub fn inject_version(lua: &Lua) { + let sile: LuaTable = lua.globals().get("SILE").unwrap(); + let mut full_version: String = sile.get("full_version").unwrap(); + full_version.push_str(" [Rust]"); +} + +pub fn version() -> crate::Result { + let lua = start_luavm()?; + let sile: LuaTable = lua.globals().get("SILE").unwrap(); + let mut full_version: String = sile.get("full_version").unwrap(); full_version.push_str(" [Rust]"); Ok(full_version) } @@ -58,29 +76,8 @@ pub fn run( quiet: bool, traceback: bool, ) -> crate::Result<()> { - let lua = unsafe { Lua::unsafe_new() }; - crate::embed::gmod(&lua); - let sile_path = match env::var("SILE_PATH") { - Ok(val) => val, - Err(_) => env!("CONFIGURE_DATADIR").to_string(), - }; - let sile_path: LuaString = lua.create_string(&sile_path)?; - let sile: LuaTable = lua - .load(chunk! { - local status - for path in string.gmatch($sile_path, "[^;]+") do - status = pcall(dofile, path .. "/core/pathsetup.lua") - if status then break end - end - if not status then - dofile("./core/pathsetup.lua") - end - return require("core.sile") - }) - .eval()?; - let mut full_version: String = sile.get("full_version")?; - full_version.push_str(" [Rust]"); - sile.set("full_version", full_version)?; + let lua = start_luavm()?; + let sile: LuaTable = lua.globals().get("SILE")?; sile.set("traceback", traceback)?; sile.set("quiet", quiet)?; let mut has_input_filename = false; From 2c892941d16a35fc64275fe8621a7a3b1e4a04ca Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 20 Oct 2023 18:55:55 +0300 Subject: [PATCH 161/357] chore(cli): Add plumbing so Lua require can find embeded resources Co-authored-by: Alex Orlenko --- src/embed.rs.in | 74 ++++++++++++++++++++++++++++++------------------- src/lib.rs | 7 +++++ 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/embed.rs.in b/src/embed.rs.in index ad4f9f785..0e736056f 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -1,5 +1,6 @@ +use mlua::chunk; use mlua::prelude::*; -use rust_embed::RustEmbed; +use rust_embed::{RustEmbed, EmbeddedFile}; use std::str; /// Embed everything that would otherwise be installed to datadir @@ -11,32 +12,49 @@ pub struct SileModules; pub fn inject_embeded_loader (lua: &Lua) { let package: LuaTable = lua.globals().get("package").unwrap(); - - let loaders: LuaValue = package.get("loaders").unwrap(); - if let LuaValue::Table(loaders) = loaders { - dbg!(loaders.clone()); - - loaders.push(LuaFunction::wrap(|lua, module: String| { - dbg!(module.clone()); - let embeded = SileModules::get(&module); - match embeded { - Some(module) => { - return LuaFunction::wrap(move |lua, ()| { - let data = str::from_utf8(module.data.as_ref()).expect("Embeded content is not valid UTF-8"); - lua.create_string(data) - }).into_lua(lua) - }, - None => format!("Module {module} is not embeded in Rust binary").into_lua(lua) + let loaders: LuaTable = match package.get("loaders").unwrap() { + LuaValue::Table(loaders) => loaders, + LuaValue::Nil => { + let loaders: LuaTable = package.get("searchers").unwrap(); + loaders + }, + _ => panic!("Unable to find approprate interface to inject embeded loader"), + }; + loaders.push(LuaFunction::wrap(|lua, module: String| { + let luaversion: LuaString = lua.load(chunk! { + return _VERSION:match("%d+%.%d+") + }).eval().unwrap(); + let luaversion: &str = luaversion.to_str().unwrap(); + let mut package_epath: Vec<&str> = vec![ + "?/init.lua", + "?.lua", + "lua-libraries/?.lua" + ]; + let path = format!("lua_modules/lib/lua/{}/?/init.lua", luaversion); + package_epath.push(&path); + let path = format!("lua_modules/lib/lua/{}/?.lua", luaversion); + package_epath.push(&path); + let path = format!("lua_modules/share/lua/{}/?/init.lua", luaversion); + package_epath.push(&path); + let path = format!("lua_modules/share/lua/{}/?.lua", luaversion); + package_epath.push(&path); + let mut resource_option: Option = None; + for pattern in &package_epath { + let path = pattern.replace('?', &module); + let embeded = SileModules::get(&path); + if embeded.is_some() { + resource_option = embeded; + break; } - })).unwrap(); - - dbg!(loaders.clone()); - - lua.load(r#"print("fizzle", require("core/version.lua"))"#).exec().unwrap(); - } - - let searchers: LuaValue = package.get("searchers").unwrap(); - if let LuaValue::Table(searchers) = searchers { - dbg!(searchers); - } + } + match resource_option { + Some(module) => { + return LuaFunction::wrap(move |lua, ()| { + let data = str::from_utf8(module.data.as_ref()).expect("Embeded content is not valid UTF-8"); + lua.load(data).call::<_, LuaValue>(()) + }).into_lua(lua) + }, + None => format!("Module {module} is not embeded in Rust binary").into_lua(lua) + } + })).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index f73007df2..48acde43f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ pub fn start_luavm() -> crate::Result { #[cfg(feature = "embed")] crate::embed::inject_embeded_loader(&lua); inject_paths(&lua); + load_sile(&lua); inject_version(&lua); Ok(lua) } @@ -47,6 +48,12 @@ pub fn inject_version(lua: &Lua) { full_version.push_str(" [Rust]"); } +pub fn load_sile(lua: &Lua) { + let entry: LuaString = lua.create_string("core.sile").unwrap(); + let r#require: LuaFunction = lua.globals().get("require").unwrap(); + r#require.call::(entry).unwrap(); +} + pub fn version() -> crate::Result { let lua = start_luavm()?; let sile: LuaTable = lua.globals().get("SILE").unwrap(); From 5823fa15f0f911732a42c97a6a503e5cad265d88 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 21 Oct 2023 12:47:44 +0300 Subject: [PATCH 162/357] chore(cli): Round out asset embedding more cases --- src/embed.rs.in | 5 +++-- src/lib.rs | 39 +++++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/embed.rs.in b/src/embed.rs.in index 0e736056f..00d86cc88 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -21,6 +21,7 @@ pub fn inject_embeded_loader (lua: &Lua) { _ => panic!("Unable to find approprate interface to inject embeded loader"), }; loaders.push(LuaFunction::wrap(|lua, module: String| { + let module_path = module.replace('.', "/"); let luaversion: LuaString = lua.load(chunk! { return _VERSION:match("%d+%.%d+") }).eval().unwrap(); @@ -40,7 +41,7 @@ pub fn inject_embeded_loader (lua: &Lua) { package_epath.push(&path); let mut resource_option: Option = None; for pattern in &package_epath { - let path = pattern.replace('?', &module); + let path = pattern.replace('?', &module_path); let embeded = SileModules::get(&path); if embeded.is_some() { resource_option = embeded; @@ -54,7 +55,7 @@ pub fn inject_embeded_loader (lua: &Lua) { lua.load(data).call::<_, LuaValue>(()) }).into_lua(lua) }, - None => format!("Module {module} is not embeded in Rust binary").into_lua(lua) + None => format!("Module '{module}' is not embeded in Rust binary").into_lua(lua) } })).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index 48acde43f..79a2ee1ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,9 @@ use mlua::chunk; use mlua::prelude::*; -use std::{env, path::PathBuf}; +#[cfg(not(feature = "embed"))] +use std::env; +use std::path::PathBuf; #[cfg(feature = "cli")] pub mod cli; @@ -23,23 +25,32 @@ pub fn start_luavm() -> crate::Result { } pub fn inject_paths(lua: &Lua) { - let sile_path = match env::var("SILE_PATH") { - Ok(val) => val, - Err(_) => env!("CONFIGURE_DATADIR").to_string(), - }; - let sile_path: LuaString = lua.create_string(&sile_path).unwrap(); + #[cfg(feature = "embed")] lua.load(chunk! { - local status - for path in string.gmatch($sile_path, "[^;]+") do - status = pcall(dofile, path .. "/core/pathsetup.lua") - if status then break end - end - if not status then - dofile("./core/pathsetup.lua") - end + require("core.pathsetup") }) .exec() .unwrap(); + #[cfg(not(feature = "embed"))] + { + let sile_path = match env::var("SILE_PATH") { + Ok(val) => val, + Err(_) => env!("CONFIGURE_DATADIR").to_string(), + }; + let sile_path: LuaString = lua.create_string(&sile_path).unwrap(); + lua.load(chunk! { + local status + for path in string.gmatch($sile_path, "[^;]+") do + status = pcall(dofile, path .. "/core/pathsetup.lua") + if status then break end + end + if not status then + dofile("./core/pathsetup.lua") + end + }) + .exec() + .unwrap(); + } } pub fn inject_version(lua: &Lua) { From e34ea3907d67fb16b7a2d215e11a12718b824899 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 21 Oct 2023 14:29:07 +0300 Subject: [PATCH 163/357] chore(cli): Also embed C modules, not just Lua ones --- src/embed.rs.in | 19 +++++++++++++++++++ src/lib.rs | 6 +----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/embed.rs.in b/src/embed.rs.in index 00d86cc88..6c1b9178c 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -3,6 +3,13 @@ use mlua::prelude::*; use rust_embed::{RustEmbed, EmbeddedFile}; use std::str; +/// Embed C modules +#[derive(RustEmbed)] +#[folder = "./justenough/.libs/"] +#[include = "*.so"] +#[exclude = "*"] +pub struct SileCModules; + /// Embed everything that would otherwise be installed to datadir #[derive(RustEmbed)] #[folder = "."] @@ -20,6 +27,18 @@ pub fn inject_embeded_loader (lua: &Lua) { }, _ => panic!("Unable to find approprate interface to inject embeded loader"), }; + loaders.push(LuaFunction::wrap(|lua, module: String| { + let embeded = SileCModules::get(&module); + match embeded { + Some(module) => { + return LuaFunction::wrap(move |lua, ()| { + let data = module.data.as_ref(); + lua.create_string(data) + }).into_lua(lua) + }, + None => format!("C Module '{module}' is not embeded in Rust binary").into_lua(lua) + } + })).unwrap(); loaders.push(LuaFunction::wrap(|lua, module: String| { let module_path = module.replace('.', "/"); let luaversion: LuaString = lua.load(chunk! { diff --git a/src/lib.rs b/src/lib.rs index 79a2ee1ff..77a1d7e9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,11 +26,7 @@ pub fn start_luavm() -> crate::Result { pub fn inject_paths(lua: &Lua) { #[cfg(feature = "embed")] - lua.load(chunk! { - require("core.pathsetup") - }) - .exec() - .unwrap(); + lua.load(r#"require("core.pathsetup")"#).exec().unwrap(); #[cfg(not(feature = "embed"))] { let sile_path = match env::var("SILE_PATH") { From 88fd2307420b13fb5a8598ae2740d289a1287972 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 21 Oct 2023 21:37:50 +0300 Subject: [PATCH 164/357] chore(cli): Handle C modules via linking not embedding --- Cargo.lock | 112 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 7 +++ Makefile.am | 9 ++-- build-aux/build.rs | 34 +++++++++++-- justenough/Makefile.am | 20 ++++---- src/embed.rs.in | 70 ++++++++++++++++++++------ 6 files changed, 222 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75d896044..9159408f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -205,12 +205,73 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "core-text" +version = "19.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +dependencies = [ + "core-foundation", + "core-graphics", + "foreign-types", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.9" @@ -331,6 +392,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -340,6 +416,27 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "freetype" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +dependencies = [ + "freetype-sys", + "libc", +] + +[[package]] +name = "freetype-sys" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +dependencies = [ + "cmake", + "libc", + "pkg-config", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -859,6 +956,20 @@ dependencies = [ "regex", ] +[[package]] +name = "harfbuzz-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf8c27ca13930dc4ffe474880040fe9e0f03c2121600dc9c95423624cab3e467" +dependencies = [ + "cc", + "core-graphics", + "core-text", + "foreign-types", + "freetype", + "pkg-config", +] + [[package]] name = "hashbrown" version = "0.14.1" @@ -1308,6 +1419,7 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", + "harfbuzz-sys", "mlua", "rust-embed", "vergen", diff --git a/Cargo.toml b/Cargo.toml index 11fc040bd..f9c41bb11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ homepage = "https://sile-typesetter.org" repository = "https://github.com/sile-typesetter/sile" license = "MIT" build = "build-aux/build.rs" +# links = "svg" [[bin]] name = "sile" @@ -29,6 +30,8 @@ lua51 = [ "mlua/lua51" ] luajit = [ "mlua/luajit" ] vendored = [ "mlua/vendored" ] embed = [ "rust-embed" ] +static = [ "embed" ] +dynamic = [] completions = [ "cli", "clap_complete" ] cli = [ "clap" ] bash = [ "completions" ] @@ -60,6 +63,10 @@ lto = true optional = true features = [ "include-exclude" ] + [dependencies.harfbuzz-sys] + version = "0.5" + optional = true + [build-dependencies] [build-dependencies.clap_complete] diff --git a/Makefile.am b/Makefile.am index 92fc477c5..eb95d48f5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,7 +59,7 @@ BUILT_LUA_SOURCES = core/features.lua core/pathsetup.lua core/version.lua bin_PROGRAMS = sile bin_SCRIPTS = sile-lua dist_man_MANS = sile-lua.1 -sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs src/embed.rs src/embed-includes.rs +sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs EXTRA_sile_SOURCES = if !EMBEDED_RESOURCES nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) @@ -76,7 +76,7 @@ EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) -BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles src/embed-includes.rs src/embed.rs +BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) @@ -86,6 +86,9 @@ Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ if EMBEDED_RESOURCES +sile_SOURCES += src/embed.rs src/embed-includes.rs +BUILT_SOURCES += src/embed.rs src/embed-includes.rs + export EMBEDED_LUA_RESOURCES = $(SILEDATA) $(LUALIBRARIES) $(BUILT_LUA_SOURCES) $(LUAMODULES) src/embed-includes.rs: Makefile-distfiles @@ -113,7 +116,7 @@ CARGO_FEATURE_ARGS += --features vendored endif if EMBEDED_RESOURCES -CARGO_FEATURE_ARGS += --features embed +CARGO_FEATURE_ARGS += --features static endif DEPDIR := .deps diff --git a/build-aux/build.rs b/build-aux/build.rs index f90e33049..4b592324c 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -6,9 +6,11 @@ use clap_complete::generator::generate_to; use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; #[cfg(feature = "manpage")] use clap_mangen::Man; -use std::{collections, env}; #[cfg(feature = "completions")] -use std::{fs, path}; +use std::fs; +#[cfg(any(feature = "embed", feature = "completions"))] +use std::path::Path; +use std::{collections, env}; use vergen::EmitBuilder; #[cfg(feature = "completions")] @@ -28,6 +30,30 @@ fn main() { generate_manpage(); #[cfg(feature = "completions")] generate_shell_completions(); + #[cfg(feature = "embed")] + { + let dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + println!( + "cargo:rustc-link-search=native={}", + Path::new(&dir).join("justenough").join(".libs").display() + ); + println!("cargo:rustc-link-arg=-l:fontmetrics.a"); + println!("cargo:rustc-link-arg=-l:justenoughfontconfig.a"); + println!("cargo:rustc-link-arg=-l:justenoughharfbuzz.a"); + println!("cargo:rustc-link-arg=-l:justenoughicu.a"); + println!("cargo:rustc-link-arg=-l:justenoughlibtexpdf.a"); + println!("cargo:rustc-link-arg=-l:svg.a"); + println!("cargo:rustc-link-arg=-lharfbuzz"); + println!("cargo:rustc-link-arg=-lharfbuzz-subset"); + println!("cargo:rustc-link-arg=-lfontconfig"); + println!("cargo:rustc-link-arg=-licui18n"); + println!("cargo:rustc-link-arg=-licuuc"); + println!( + "cargo:rustc-link-search=native={}", + Path::new(&dir).join("libtexpdf").join(".libs").display() + ); + println!("cargo:rustc-link-arg=-ltexpdf"); + } } /// Generate man page @@ -37,7 +63,7 @@ fn generate_manpage() { None => return, Some(out_dir) => out_dir, }; - let manpage_dir = path::Path::new(&out_dir); + let manpage_dir = Path::new(&out_dir); fs::create_dir_all(manpage_dir).expect("Unable to create directory for generated manpages"); let app = Cli::command(); let bin_name: &str = app @@ -59,7 +85,7 @@ fn generate_shell_completions() { None => return, Some(out_dir) => out_dir, }; - let completions_dir = path::Path::new(&out_dir).join("completions"); + let completions_dir = Path::new(&out_dir).join("completions"); fs::create_dir_all(&completions_dir) .expect("Could not create directory in which to place completions"); let app = Cli::command(); diff --git a/justenough/Makefile.am b/justenough/Makefile.am index e8fdbc217..4aa4a1229 100644 --- a/justenough/Makefile.am +++ b/justenough/Makefile.am @@ -14,48 +14,50 @@ else LIBTEXPDF_LIB=../libtexpdf/libtexpdf.la endif +AM_CFLAGS = $(WARNING_CFLAGS) -I.. + pkglib_LTLIBRARIES = justenoughharfbuzz.la justenoughharfbuzz_la_SOURCES = justenoughharfbuzz.c hb-utils.c hb-utils.h -justenoughharfbuzz_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) +justenoughharfbuzz_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^hb_' justenoughharfbuzz_la_CFLAGS = $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) justenoughharfbuzz_la_LIBADD = $(HARFBUZZ_LIBS) $(HARFBUZZ_SUBSET_LIBS) $(MY_LUA_LIB) pkglib_LTLIBRARIES += justenoughfontconfig.la justenoughfontconfig_la_SOURCES = justenoughfontconfig.c silewin32.h -justenoughfontconfig_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) +justenoughfontconfig_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^fontconfig_' justenoughfontconfig_la_CFLAGS = $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) justenoughfontconfig_la_LIBADD = $(FONTCONFIG_LIBS) $(MY_LUA_LIB) if APPKIT pkglib_LTLIBRARIES += macfonts.la macfonts_la_SOURCES = macfonts.m -macfonts_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) +macfonts_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^macfonts_' macfonts_la_OBJCFLAGS = -U VERSION $(HARFBUZZ_CFLAGS) $(LUA_INCLUDE) -fmodules macfonts_la_LIBADD = $(HARFBUZZ_LIBS) $(MY_LUA_LIB) endif pkglib_LTLIBRARIES += justenoughlibtexpdf.la justenoughlibtexpdf_la_SOURCES = justenoughlibtexpdf.c imagebbox.c -justenoughlibtexpdf_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) -justenoughlibtexpdf_la_CFLAGS = -I.. $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) +justenoughlibtexpdf_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^libtexpdf_' +justenoughlibtexpdf_la_CFLAGS = $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) justenoughlibtexpdf_la_LIBADD = $(LIBTEXPDF_LIB) $(LIBPNG_LIBS) $(ZLIB_LIBS) $(LIBPAPER_LIBS) $(MY_LUA_LIB) pkglib_LTLIBRARIES += fontmetrics.la fontmetrics_la_SOURCES = fontmetrics.c hb-utils.c hb-utils.h -fontmetrics_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) +fontmetrics_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^fontmetrics_' fontmetrics_la_CFLAGS = $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) fontmetrics_la_LIBADD = $(MY_LUA_LIB) $(HARFBUZZ_LIBS) pkglib_LTLIBRARIES += svg.la svg_la_SOURCES = svg.c nanosvg.h -svg_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) +svg_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^svg_' svg_la_CFLAGS = $(LUA_INCLUDE) svg_la_LIBADD = $(MY_LUA_LIB) if ICU pkglib_LTLIBRARIES += justenoughicu.la justenoughicu_la_SOURCES = justenoughicu.c -justenoughicu_la_LDFLAGS = -module -avoid-version -shared $(UNDEFINED) -justenoughicu_la_CFLAGS = -I.. $(ICU_CFLAGS) $(LUA_INCLUDE) +justenoughicu_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^icu_' +justenoughicu_la_CFLAGS = $(ICU_CFLAGS) $(LUA_INCLUDE) justenoughicu_la_LIBADD = $(ICU_LIBS) $(MY_LUA_LIB) endif diff --git a/src/embed.rs.in b/src/embed.rs.in index 6c1b9178c..18691afc7 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -3,13 +3,6 @@ use mlua::prelude::*; use rust_embed::{RustEmbed, EmbeddedFile}; use std::str; -/// Embed C modules -#[derive(RustEmbed)] -#[folder = "./justenough/.libs/"] -#[include = "*.so"] -#[exclude = "*"] -pub struct SileCModules; - /// Embed everything that would otherwise be installed to datadir #[derive(RustEmbed)] #[folder = "."] @@ -17,6 +10,20 @@ pub struct SileCModules; #[exclude = "*"] pub struct SileModules; +// Link Lua loader functions from C modules that Lua would otherwise be loading externally that +// we've linked into the CLI binary. Linking happens in build-aux/build.rs. +extern "C-unwind" { + fn luaopen_fontmetrics(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughfontconfig(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughharfbuzz(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughicu(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughlibtexpdf(lua: *mut mlua::lua_State) -> i32; + fn luaopen_svg(lua: *mut mlua::lua_State) -> i32; +} + +/// Register a Lua function in the loaders/searchers table to return C modules linked into the CLI +/// binary and another to return embeded Lua resources as Lua modules. See discussion in mlua: +/// https://github.com/khvzak/mlua/discussions/322 pub fn inject_embeded_loader (lua: &Lua) { let package: LuaTable = lua.globals().get("package").unwrap(); let loaders: LuaTable = match package.get("loaders").unwrap() { @@ -28,15 +35,50 @@ pub fn inject_embeded_loader (lua: &Lua) { _ => panic!("Unable to find approprate interface to inject embeded loader"), }; loaders.push(LuaFunction::wrap(|lua, module: String| { - let embeded = SileCModules::get(&module); - match embeded { - Some(module) => { - return LuaFunction::wrap(move |lua, ()| { - let data = module.data.as_ref(); - lua.create_string(data) + match module.as_str() { + "fontmetrics" => { + LuaFunction::wrap(move |lua, ()| { + let loader = unsafe { lua.create_c_function(luaopen_fontmetrics).unwrap() }; + let module: LuaTable = loader.call(()).unwrap(); + Ok(module) + }).into_lua(lua) + }, + "justenoughfontconfig" => { + LuaFunction::wrap(move |lua, ()| { + let loader = unsafe { lua.create_c_function(luaopen_justenoughfontconfig).unwrap() }; + let module: LuaTable = loader.call(()).unwrap(); + Ok(module) + }).into_lua(lua) + }, + "justenoughharfbuzz" => { + LuaFunction::wrap(move |lua, ()| { + let loader = unsafe { lua.create_c_function(luaopen_justenoughharfbuzz).unwrap() }; + let module: LuaTable = loader.call(()).unwrap(); + Ok(module) + }).into_lua(lua) + }, + "justenoughicu" => { + LuaFunction::wrap(move |lua, ()| { + let loader = unsafe { lua.create_c_function(luaopen_justenoughicu).unwrap() }; + let module: LuaTable = loader.call(()).unwrap(); + Ok(module) + }).into_lua(lua) + }, + "justenoughlibtexpdf" => { + LuaFunction::wrap(move |lua, ()| { + let loader = unsafe { lua.create_c_function(luaopen_justenoughlibtexpdf).unwrap() }; + let module: LuaTable = loader.call(()).unwrap(); + Ok(module) + }).into_lua(lua) + }, + "svg" => { + LuaFunction::wrap(move |lua, ()| { + let loader = unsafe { lua.create_c_function(luaopen_svg).unwrap() }; + let module: LuaTable = loader.call(()).unwrap(); + Ok(module) }).into_lua(lua) }, - None => format!("C Module '{module}' is not embeded in Rust binary").into_lua(lua) + _ => format!("C Module '{module}' is not linked in Rust binary").into_lua(lua) } })).unwrap(); loaders.push(LuaFunction::wrap(|lua, module: String| { From ccdb8a2d873e45fa3c703fa2a5ab87c628078248 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 23 Oct 2023 16:30:04 +0300 Subject: [PATCH 165/357] fix(core): Use unique function name so static linking doesn't clobber Lua-5.1 --- justenough/fontmetrics.c | 4 ++-- justenough/justenoughfontconfig.c | 4 ++-- justenough/justenoughharfbuzz.c | 4 ++-- justenough/justenoughicu.c | 4 ++-- justenough/justenoughlibtexpdf.c | 4 ++-- justenough/macfonts.m | 4 ++-- justenough/svg.c | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/justenough/fontmetrics.c b/justenough/fontmetrics.c index 0d7396d98..547a90ebf 100644 --- a/justenough/fontmetrics.c +++ b/justenough/fontmetrics.c @@ -54,7 +54,7 @@ int glyphwidth (lua_State* L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs_fontmetrics (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -76,6 +76,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_fontmetrics (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_fontmetrics(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughfontconfig.c b/justenough/justenoughfontconfig.c index aa7b069fc..8c43007b9 100644 --- a/justenough/justenoughfontconfig.c +++ b/justenough/justenoughfontconfig.c @@ -165,7 +165,7 @@ int face_from_options(lua_State* L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs_fontconfig (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -186,7 +186,7 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughfontconfig (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_fontconfig(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughharfbuzz.c b/justenough/justenoughharfbuzz.c index a576da9c3..16bf39e90 100644 --- a/justenough/justenoughharfbuzz.c +++ b/justenough/justenoughharfbuzz.c @@ -457,7 +457,7 @@ int get_table (lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs_harfbuzz (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -484,7 +484,7 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughharfbuzz (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_harfbuzz(L, lib_table, 0); //lua_setglobal(L, "harfbuzz"); return 1; } diff --git a/justenough/justenoughicu.c b/justenough/justenoughicu.c index b5da54190..c0345df5f 100644 --- a/justenough/justenoughicu.c +++ b/justenough/justenoughicu.c @@ -504,7 +504,7 @@ int icu_version(lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs_icu (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -533,6 +533,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughicu (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_icu(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughlibtexpdf.c b/justenough/justenoughlibtexpdf.c index 0ef178f26..926fa45b6 100644 --- a/justenough/justenoughlibtexpdf.c +++ b/justenough/justenoughlibtexpdf.c @@ -551,7 +551,7 @@ int pdf_version(lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs_libtexpdf (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -609,6 +609,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughlibtexpdf (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_libtexpdf(L, lib_table, 0); return 1; } diff --git a/justenough/macfonts.m b/justenough/macfonts.m index 479999aa5..23daa34c3 100644 --- a/justenough/macfonts.m +++ b/justenough/macfonts.m @@ -17,7 +17,7 @@ /* ** Adapted from Lua 5.2.0 */ -static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +static void luaL_setfuncs_macfonts (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -211,7 +211,7 @@ int face_from_options(lua_State* L) { int luaopen_macfonts (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_macfonts(L, lib_table, 0); return 1; } diff --git a/justenough/svg.c b/justenough/svg.c index fd3406efa..265eca58c 100644 --- a/justenough/svg.c +++ b/justenough/svg.c @@ -107,7 +107,7 @@ int svg_to_ps(lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs_svg (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -128,6 +128,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_svg (lua_State *L) { lua_newtable(L); - luaL_setfuncs(L, lib_table, 0); + luaL_setfuncs_svg(L, lib_table, 0); return 1; } From 45c1dc2d3a5fee77c288107d75a169e36cd76658 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 27 Oct 2023 16:05:59 +0300 Subject: [PATCH 166/357] chore(build): Tweak C modules so static builds work without previously building dynamic --- build-aux/build.rs | 1 + justenough/Makefile.am | 29 +++--- justenough/fontmetrics.c | 8 +- justenough/hb-utils.c | 2 - justenough/imagebbox.c | 5 +- justenough/justenoughfontconfig.c | 5 +- justenough/justenoughharfbuzz.c | 30 +++--- justenough/justenoughicu.c | 36 +++---- justenough/justenoughlibtexpdf.c | 155 +++++++++++++++--------------- justenough/macfonts.m | 4 +- 10 files changed, 136 insertions(+), 139 deletions(-) diff --git a/build-aux/build.rs b/build-aux/build.rs index 4b592324c..586688d38 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -53,6 +53,7 @@ fn main() { Path::new(&dir).join("libtexpdf").join(".libs").display() ); println!("cargo:rustc-link-arg=-ltexpdf"); + println!("cargo:rustc-link-arg=-lm"); } } diff --git a/justenough/Makefile.am b/justenough/Makefile.am index 4aa4a1229..2137d5a5c 100644 --- a/justenough/Makefile.am +++ b/justenough/Makefile.am @@ -14,50 +14,51 @@ else LIBTEXPDF_LIB=../libtexpdf/libtexpdf.la endif -AM_CFLAGS = $(WARNING_CFLAGS) -I.. +AM_CFLAGS = $(WARNING_CFLAGS) -I../libtexpdf +AM_LDFLAGS = -module -avoid-version $(UNDEFINED) pkglib_LTLIBRARIES = justenoughharfbuzz.la justenoughharfbuzz_la_SOURCES = justenoughharfbuzz.c hb-utils.c hb-utils.h -justenoughharfbuzz_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^hb_' -justenoughharfbuzz_la_CFLAGS = $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) +justenoughharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) +justenoughharfbuzz_la_CFLAGS = $(AM_CFLAGS) $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) justenoughharfbuzz_la_LIBADD = $(HARFBUZZ_LIBS) $(HARFBUZZ_SUBSET_LIBS) $(MY_LUA_LIB) pkglib_LTLIBRARIES += justenoughfontconfig.la justenoughfontconfig_la_SOURCES = justenoughfontconfig.c silewin32.h -justenoughfontconfig_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^fontconfig_' -justenoughfontconfig_la_CFLAGS = $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) +justenoughfontconfig_la_LDFLAGS = $(AM_LDFLAGS) +justenoughfontconfig_la_CFLAGS = $(AM_CFLAGS) $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) justenoughfontconfig_la_LIBADD = $(FONTCONFIG_LIBS) $(MY_LUA_LIB) if APPKIT pkglib_LTLIBRARIES += macfonts.la macfonts_la_SOURCES = macfonts.m -macfonts_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^macfonts_' +macfonts_la_LDFLAGS = $(AM_LDFLAGS) macfonts_la_OBJCFLAGS = -U VERSION $(HARFBUZZ_CFLAGS) $(LUA_INCLUDE) -fmodules macfonts_la_LIBADD = $(HARFBUZZ_LIBS) $(MY_LUA_LIB) endif pkglib_LTLIBRARIES += justenoughlibtexpdf.la justenoughlibtexpdf_la_SOURCES = justenoughlibtexpdf.c imagebbox.c -justenoughlibtexpdf_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^libtexpdf_' -justenoughlibtexpdf_la_CFLAGS = $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) +justenoughlibtexpdf_la_LDFLAGS = $(AM_LDFLAGS) +justenoughlibtexpdf_la_CFLAGS = $(AM_CFLAGS) $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) justenoughlibtexpdf_la_LIBADD = $(LIBTEXPDF_LIB) $(LIBPNG_LIBS) $(ZLIB_LIBS) $(LIBPAPER_LIBS) $(MY_LUA_LIB) pkglib_LTLIBRARIES += fontmetrics.la fontmetrics_la_SOURCES = fontmetrics.c hb-utils.c hb-utils.h -fontmetrics_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^fontmetrics_' -fontmetrics_la_CFLAGS = $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) +fontmetrics_la_LDFLAGS = $(AM_LDFLAGS) +fontmetrics_la_CFLAGS = $(AM_CFLAGS) $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) fontmetrics_la_LIBADD = $(MY_LUA_LIB) $(HARFBUZZ_LIBS) pkglib_LTLIBRARIES += svg.la svg_la_SOURCES = svg.c nanosvg.h -svg_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^svg_' -svg_la_CFLAGS = $(LUA_INCLUDE) +svg_la_LDFLAGS = $(AM_LDFLAGS) +svg_la_CFLAGS = $(AM_CFLAGS) $(LUA_INCLUDE) svg_la_LIBADD = $(MY_LUA_LIB) if ICU pkglib_LTLIBRARIES += justenoughicu.la justenoughicu_la_SOURCES = justenoughicu.c -justenoughicu_la_LDFLAGS = -module -avoid-version $(UNDEFINED) -export-symbols-regex '^icu_' -justenoughicu_la_CFLAGS = $(ICU_CFLAGS) $(LUA_INCLUDE) +justenoughicu_la_LDFLAGS = $(AM_LDFLAGS) +justenoughicu_la_CFLAGS = $(AM_CFLAGS) $(ICU_CFLAGS) $(LUA_INCLUDE) justenoughicu_la_LIBADD = $(ICU_LIBS) $(MY_LUA_LIB) endif diff --git a/justenough/fontmetrics.c b/justenough/fontmetrics.c index 547a90ebf..317521d7d 100644 --- a/justenough/fontmetrics.c +++ b/justenough/fontmetrics.c @@ -7,7 +7,7 @@ #include "hb-utils.h" -int get_typographic_extents (lua_State *L) { +int fm_get_typographic_extents (lua_State *L) { double upem; double ascender; double descender; @@ -35,7 +35,7 @@ int get_typographic_extents (lua_State *L) { } -int glyphwidth (lua_State* L) { +int fm_glyphwidth (lua_State* L) { size_t font_l; unsigned int gid = luaL_checknumber(L, 1); hb_font_t* hbFont = get_hb_font(L, 2); @@ -69,8 +69,8 @@ void luaL_setfuncs_fontmetrics (lua_State *L, const luaL_Reg *l, int nup) { #endif static const struct luaL_Reg lib_table [] = { - {"get_typographic_extents", get_typographic_extents}, - {"glyphwidth", glyphwidth}, + {"get_typographic_extents", fm_get_typographic_extents}, + {"glyphwidth", fm_glyphwidth}, {NULL, NULL} }; diff --git a/justenough/hb-utils.c b/justenough/hb-utils.c index 024fe4595..8c294ddbb 100644 --- a/justenough/hb-utils.c +++ b/justenough/hb-utils.c @@ -148,5 +148,3 @@ hb_font_t* get_hb_font(lua_State *L, int index) { return font; } - - diff --git a/justenough/imagebbox.c b/justenough/imagebbox.c index 60c159b15..51acb1f26 100644 --- a/justenough/imagebbox.c +++ b/justenough/imagebbox.c @@ -1,6 +1,7 @@ #include #include -#include "libtexpdf/libtexpdf.h" + +#include int get_pdf_bbox(FILE* f, long page_no, double* llx, double* lly, double* urx, double* ury) { pdf_obj* page; @@ -68,5 +69,3 @@ int get_image_bbox(FILE* f, long page_no, double* llx, double* lly, double* urx, *yresol = ydensity != 0 ? 72 / ydensity : 0; return 0; } - - diff --git a/justenough/justenoughfontconfig.c b/justenough/justenoughfontconfig.c index 8c43007b9..11ee559f0 100644 --- a/justenough/justenoughfontconfig.c +++ b/justenough/justenoughfontconfig.c @@ -9,7 +9,7 @@ #include "silewin32.h" -int face_from_options(lua_State* L) { +int je_face_from_options(lua_State* L) { FcChar8 * font_path, * fullname, * familyname; FcPattern* p; FcPattern* matched; @@ -180,7 +180,7 @@ void luaL_setfuncs_fontconfig (lua_State *L, const luaL_Reg *l, int nup) { #endif static const struct luaL_Reg lib_table [] = { - {"_face", face_from_options}, + {"_face", je_face_from_options}, {NULL, NULL} }; @@ -189,4 +189,3 @@ int luaopen_justenoughfontconfig (lua_State *L) { luaL_setfuncs_fontconfig(L, lib_table, 0); return 1; } - diff --git a/justenough/justenoughharfbuzz.c b/justenough/justenoughharfbuzz.c index 16bf39e90..85bc01835 100644 --- a/justenough/justenoughharfbuzz.c +++ b/justenough/justenoughharfbuzz.c @@ -135,7 +135,7 @@ static char** scan_shaper_list(char* cp1) { return res; } -int shape (lua_State *L) { +int je_hb_shape (lua_State *L) { size_t font_l; const char * text = luaL_checkstring(L, 1); hb_font_t * hbFont = get_hb_font(L, 2); @@ -277,7 +277,7 @@ static int has_table(hb_face_t* face, hb_tag_t tag) { return ret; } -int instanciate(lua_State *L) { +int je_hb_instanciate(lua_State *L) { unsigned int data_l = 0; const char * data_s = NULL; #ifdef HAVE_HARFBUZZ_SUBSET @@ -367,7 +367,7 @@ int instanciate(lua_State *L) { return 1; } -int get_glyph_dimensions(lua_State *L) { +int je_hb_get_glyph_dimensions(lua_State *L) { hb_font_t* hbFont = get_hb_font(L, 1); double point_size = (unsigned int)luaL_checknumber(L, 2); hb_codepoint_t glyphId = (hb_codepoint_t)luaL_checknumber(L, 3); @@ -402,7 +402,7 @@ int get_glyph_dimensions(lua_State *L) { return 1; } -int get_harfbuzz_version (lua_State *L) { +int je_hb_get_harfbuzz_version (lua_State *L) { unsigned int major; unsigned int minor; unsigned int micro; @@ -413,7 +413,7 @@ int get_harfbuzz_version (lua_State *L) { return 1; } -int version_lessthan (lua_State *L) { +int je_hb_version_lessthan (lua_State *L) { unsigned int major = luaL_checknumber(L, 1); unsigned int minor = luaL_checknumber(L, 2); unsigned int micro = luaL_checknumber(L, 3); @@ -421,7 +421,7 @@ int version_lessthan (lua_State *L) { return 1; } -int list_shapers (lua_State *L) { +int je_hb_list_shapers (lua_State *L) { const char **shaper_list = hb_shape_list_shapers (); int i = 0; @@ -432,7 +432,7 @@ int list_shapers (lua_State *L) { return i; } -int get_table (lua_State *L) { +int je_hb_get_table (lua_State *L) { size_t tag_l; hb_face_t * face = hb_font_get_face(get_hb_font(L, 1)); const char * tag_s = luaL_checklstring(L, 2, &tag_l); @@ -472,20 +472,18 @@ void luaL_setfuncs_harfbuzz (lua_State *L, const luaL_Reg *l, int nup) { #endif static const struct luaL_Reg lib_table [] = { - {"_shape", shape}, - {"get_glyph_dimensions", get_glyph_dimensions}, - {"version", get_harfbuzz_version}, - {"shapers", list_shapers}, - {"get_table", get_table}, - {"instanciate", instanciate}, - {"version_lessthan", version_lessthan}, + {"_shape", je_hb_shape}, + {"get_glyph_dimensions", je_hb_get_glyph_dimensions}, + {"version", je_hb_get_harfbuzz_version}, + {"shapers", je_hb_list_shapers}, + {"get_table", je_hb_get_table}, + {"instanciate", je_hb_instanciate}, + {"version_lessthan", je_hb_version_lessthan}, {NULL, NULL} }; int luaopen_justenoughharfbuzz (lua_State *L) { lua_newtable(L); luaL_setfuncs_harfbuzz(L, lib_table, 0); - //lua_setglobal(L, "harfbuzz"); return 1; } - diff --git a/justenough/justenoughicu.c b/justenough/justenoughicu.c index c0345df5f..71176c358 100644 --- a/justenough/justenoughicu.c +++ b/justenough/justenoughicu.c @@ -27,7 +27,7 @@ typedef int32_t (*conversion_function_t)(UChar *dest, int32_t destCapacity, cons u_strFromUTF8(out, out_l, &out_l, in, in_l, &err); \ } -int icu_case(lua_State *L) { +int je_icu_case(lua_State *L) { size_t input_l; const char* input = luaL_checklstring(L, 1, &input_l); @@ -96,7 +96,7 @@ int icu_case(lua_State *L) { return luaL_error(L, "Error in UTF8 conversion %s", u_errorName(err)); } -int icu_breakpoints(lua_State *L) { +int je_icu_breakpoints(lua_State *L) { const char* input = luaL_checkstring(L, 1); int input_l = strlen(input); const char* locale = luaL_checkstring(L, 2); @@ -168,7 +168,7 @@ int icu_breakpoints(lua_State *L) { return breakcount; } -int icu_canonicalize_language(lua_State *L) { +int je_icu_canonicalize_language(lua_State *L) { const char* lang = luaL_checkstring(L, 1); char locale[200], minimized[200], result[200]; UErrorCode error = 0; @@ -190,7 +190,7 @@ int icu_canonicalize_language(lua_State *L) { #define MAX_ICU_FORMATTED_NUMBER_STRING 512 -int icu_format_number(lua_State *L) { +int je_icu_format_number(lua_State *L) { double a = luaL_checknumber(L, 1); const char* locale = luaL_checkstring(L, 2); UNumberFormatStyle numFormatStyle = luaL_checkinteger(L, 3); @@ -213,7 +213,7 @@ int icu_format_number(lua_State *L) { return 1; } -int icu_bidi_runs(lua_State *L) { +int je_icu_bidi_runs(lua_State *L) { size_t input_l; const char* input = luaL_checklstring(L, 1, &input_l); const char* direction = luaL_checkstring(L, 2); @@ -292,7 +292,7 @@ int icu_bidi_runs(lua_State *L) { return count; } -int icu_collation_create(lua_State *L) { +int je_icu_collation_create(lua_State *L) { int nargs = lua_gettop(L); const char* locale = luaL_checkstring(L, 1); @@ -452,7 +452,7 @@ int icu_collation_create(lua_State *L) { return 1; } -int icu_collation_destroy(lua_State *L) { +int je_icu_collation_destroy(lua_State *L) { UCollator *collator = (UCollator *)lua_touserdata(L, 1); if (!collator) { return luaL_error(L, "Collation cleanup called with invalid input"); @@ -461,7 +461,7 @@ int icu_collation_destroy(lua_State *L) { return 0; } -int icu_compare(lua_State *L) { +int je_icu_compare(lua_State *L) { UCollator *collator = (UCollator *)lua_touserdata(L, 1); if (!collator) { return luaL_error(L, "Comparison called with invalid first argument (collator)"); @@ -490,7 +490,7 @@ int icu_compare(lua_State *L) { // UCollationResult result = ucol_strcollIter(collation, &s1iter, &s2iter, &status); } -int icu_version(lua_State *L) { +int je_icu_version(lua_State *L) { lua_pushstring(L, U_ICU_VERSION); return 1; } @@ -519,15 +519,15 @@ void luaL_setfuncs_icu (lua_State *L, const luaL_Reg *l, int nup) { #endif static const struct luaL_Reg lib_table [] = { - {"breakpoints", icu_breakpoints}, - {"case", icu_case}, - {"bidi_runs", icu_bidi_runs}, - {"canonicalize_language", icu_canonicalize_language}, - {"format_number", icu_format_number}, - {"collation_create", icu_collation_create}, - {"collation_destroy", icu_collation_destroy}, - {"compare", icu_compare}, - {"version", icu_version}, + {"breakpoints", je_icu_breakpoints}, + {"case", je_icu_case}, + {"bidi_runs", je_icu_bidi_runs}, + {"canonicalize_language", je_icu_canonicalize_language}, + {"format_number", je_icu_format_number}, + {"collation_create", je_icu_collation_create}, + {"collation_destroy", je_icu_collation_destroy}, + {"compare", je_icu_compare}, + {"version", je_icu_version}, {NULL, NULL} }; diff --git a/justenough/justenoughlibtexpdf.c b/justenough/justenoughlibtexpdf.c index 926fa45b6..71b25abac 100644 --- a/justenough/justenoughlibtexpdf.c +++ b/justenough/justenoughlibtexpdf.c @@ -1,12 +1,13 @@ #include #include #include -#include #include #include #include +#include + #if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 #define lua_rawlen lua_strlen #endif @@ -22,7 +23,7 @@ char* producer = "SILE"; return 0; \ } -int pdf_init (lua_State *L) { +int je_pdf_init (lua_State *L) { pdf_rect mediabox; const char* fn = luaL_checkstring(L, 1); double w = luaL_checknumber(L, 2); @@ -46,19 +47,19 @@ int pdf_init (lua_State *L) { return 0; } -int pdf_endpage(lua_State *L) { +int je_pdf_endpage(lua_State *L) { ASSERT_PDF_OPENED(p); texpdf_doc_end_page(p); return 0; }; -int pdf_beginpage(lua_State *L) { +int je_pdf_beginpage(lua_State *L) { ASSERT_PDF_OPENED(p); texpdf_doc_begin_page(p, 1,0,height); return 0; } -int pdf_changepagesize(lua_State *L) { +int je_pdf_changepagesize(lua_State *L) { pdf_rect mediabox; double pageno = luaL_checknumber(L, 1); @@ -73,7 +74,7 @@ int pdf_changepagesize(lua_State *L) { return 0; } -int pdf_finish(lua_State *L) { +int je_pdf_finish(lua_State *L) { ASSERT_PDF_OPENED(p); texpdf_files_close(); texpdf_close_device (); @@ -82,7 +83,7 @@ int pdf_finish(lua_State *L) { return 0; } -int pdf_loadfont(lua_State *L) { +int je_pdf_loadfont(lua_State *L) { const char * filename; int index = 0; double ptsize; @@ -144,13 +145,13 @@ int pdf_loadfont(lua_State *L) { return 1; } -int pdf_setdirmode(lua_State *L) { +int je_pdf_setdirmode(lua_State *L) { int layout_dir = luaL_checkinteger(L,1); texpdf_dev_set_dirmode(layout_dir); return 0; } -int pdf_setstring(lua_State *L) { +int je_pdf_setstring(lua_State *L) { double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); const char* s = luaL_checkstring(L, 3); @@ -162,7 +163,7 @@ int pdf_setstring(lua_State *L) { return 0; } -int pdf_setrule(lua_State *L) { +int je_pdf_setrule(lua_State *L) { double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); double w = luaL_checknumber(L, 3); @@ -174,7 +175,7 @@ int pdf_setrule(lua_State *L) { /* Colors */ -int pdf_colorpush_rgb(lua_State *L) { +int je_pdf_colorpush_rgb(lua_State *L) { double r = luaL_checknumber(L, 1); double g = luaL_checknumber(L, 2); double b = luaL_checknumber(L, 3); @@ -186,7 +187,7 @@ int pdf_colorpush_rgb(lua_State *L) { return 0; } -int pdf_colorpush_cmyk(lua_State *L) { +int je_pdf_colorpush_cmyk(lua_State *L) { double c = luaL_checknumber(L, 1); double m = luaL_checknumber(L, 2); double y = luaL_checknumber(L, 3); @@ -200,7 +201,7 @@ int pdf_colorpush_cmyk(lua_State *L) { return 0; } -int pdf_colorpush_gray(lua_State *L) { +int je_pdf_colorpush_gray(lua_State *L) { double l = luaL_checknumber(L, 1); pdf_color color; @@ -211,7 +212,7 @@ int pdf_colorpush_gray(lua_State *L) { return 0; } -int pdf_setcolor_rgb(lua_State *L) { +int je_pdf_setcolor_rgb(lua_State *L) { double r = luaL_checknumber(L, 1); double g = luaL_checknumber(L, 2); double b = luaL_checknumber(L, 3); @@ -224,7 +225,7 @@ int pdf_setcolor_rgb(lua_State *L) { return 0; } -int pdf_setcolor_cmyk(lua_State *L) { +int je_pdf_setcolor_cmyk(lua_State *L) { double c = luaL_checknumber(L, 1); double m = luaL_checknumber(L, 2); double y = luaL_checknumber(L, 3); @@ -238,7 +239,7 @@ int pdf_setcolor_cmyk(lua_State *L) { return 0; } -int pdf_setcolor_gray(lua_State *L) { +int je_pdf_setcolor_gray(lua_State *L) { double l = luaL_checknumber(L, 1); pdf_color color; @@ -249,7 +250,7 @@ int pdf_setcolor_gray(lua_State *L) { return 0; } -int pdf_colorpop(lua_State *L) { +int je_pdf_colorpop(lua_State *L) { ASSERT_PDF_OPENED(p); texpdf_color_pop(p); return 0; @@ -257,7 +258,7 @@ int pdf_colorpop(lua_State *L) { /* PDF "specials" */ -int pdf_destination(lua_State *L) { +int je_pdf_destination(lua_State *L) { pdf_obj* array = texpdf_new_array(); const char* name = luaL_checkstring(L, 1); double x = luaL_checknumber(L, 2); @@ -277,7 +278,7 @@ int pdf_destination(lua_State *L) { return 0; } -int pdf_bookmark(lua_State *L) { +int je_pdf_bookmark(lua_State *L) { const char* dictionary = luaL_checkstring(L, 1); int level = luaL_checknumber(L, 2); pdf_obj* dict = texpdf_parse_pdf_dict(&dictionary, dictionary + strlen(dictionary), NULL); @@ -299,12 +300,12 @@ int pdf_bookmark(lua_State *L) { return 0; } -int pdf_begin_annotation(lua_State *L) { +int je_pdf_begin_annotation(lua_State *L) { // In theory we should track boxes and breaking state and etc. return 0; } -int pdf_end_annotation(lua_State *L) { +int je_pdf_end_annotation(lua_State *L) { const char* dictionary = luaL_checkstring(L, 1); pdf_rect rect; pdf_obj* dict; @@ -325,7 +326,7 @@ int pdf_end_annotation(lua_State *L) { return 0; } -int pdf_metadata(lua_State *L) { +int je_pdf_metadata(lua_State *L) { const char* key = luaL_checkstring(L, 1); const char* value = luaL_checkstring(L, 2); int len = lua_rawlen(L, 2); @@ -339,7 +340,7 @@ int pdf_metadata(lua_State *L) { } /* Images */ -int pdf_drawimage(lua_State *L) { +int je_pdf_drawimage(lua_State *L) { const char* filename = luaL_checkstring(L, 1); transform_info ti; double x = luaL_checknumber(L, 2); @@ -361,7 +362,7 @@ int pdf_drawimage(lua_State *L) { extern int get_image_bbox(FILE* f, long page_no, double* llx, double* lly, double* urx, double* ury, double* xresol, double* yresol); -int pdf_imagebbox(lua_State *L) { +int je_pdf_imagebbox(lua_State *L) { const char* filename = luaL_checkstring(L, 1); long page_no = (long)luaL_checkinteger(L, 2); double llx = 0; @@ -400,7 +401,7 @@ int pdf_imagebbox(lua_State *L) { return 6; } -int pdf_transform(lua_State *L) { +int je_pdf_transform(lua_State *L) { pdf_tmatrix matrix; double a = luaL_checknumber(L, 1); double b = luaL_checknumber(L, 2); @@ -415,21 +416,21 @@ int pdf_transform(lua_State *L) { return 0; } -int pdf_gsave(lua_State *L) { +int je_pdf_gsave(lua_State *L) { ASSERT_PDF_OPENED(p); texpdf_graphics_mode(p); texpdf_dev_gsave(p); return 0; } -int pdf_grestore(lua_State *L) { +int je_pdf_grestore(lua_State *L) { ASSERT_PDF_OPENED(p); texpdf_graphics_mode(p); texpdf_dev_grestore(p); return 0; } -int pdf_add_content(lua_State *L) { +int je_pdf_add_content(lua_State *L) { const char* input = luaL_checkstring(L, 1); int input_l = lua_rawlen(L, 1); ASSERT_PDF_OPENED(p); @@ -440,7 +441,7 @@ int pdf_add_content(lua_State *L) { return 0; } -int pdf_parse(lua_State *L) { +int je_pdf_parse(lua_State *L) { const char* input = luaL_checkstring(L, 1); int input_l = lua_rawlen(L, 1); pdf_obj* o = texpdf_parse_pdf_object(&input, input+input_l, NULL); @@ -452,7 +453,7 @@ int pdf_parse(lua_State *L) { } } -int pdf_add_dict(lua_State *L) { +int je_pdf_add_dict(lua_State *L) { pdf_obj* dict = lua_touserdata(L, 1); pdf_obj* key = lua_touserdata(L, 2); pdf_obj* value = lua_touserdata(L, 3); @@ -460,20 +461,20 @@ int pdf_add_dict(lua_State *L) { return 0; } -int pdf_reference(lua_State *L) { +int je_pdf_reference(lua_State *L) { pdf_obj* o1 = lua_touserdata(L, 1); pdf_obj* o2 = texpdf_ref_obj(o1); lua_pushlightuserdata(L, o2); return 1; } -int pdf_release(lua_State *L) { +int je_pdf_release(lua_State *L) { pdf_obj* o1 = lua_touserdata(L, 1); texpdf_release_obj(o1); return 0; } -int pdf_get_dictionary(lua_State *L) { +int je_pdf_get_dictionary(lua_State *L) { const char* dict = luaL_checkstring(L, 1); pdf_obj *o = texpdf_doc_get_dictionary(p, dict); if (o) { @@ -484,7 +485,7 @@ int pdf_get_dictionary(lua_State *L) { } } -int pdf_lookup_dictionary(lua_State *L) { +int je_pdf_lookup_dictionary(lua_State *L) { pdf_obj* dict = lua_touserdata(L, 1); const char* key = luaL_checkstring(L, 2); pdf_obj *o = texpdf_lookup_dict(dict, key); @@ -496,7 +497,7 @@ int pdf_lookup_dictionary(lua_State *L) { } } -int pdf_push_array(lua_State *L) { +int je_pdf_push_array(lua_State *L) { pdf_obj* array = lua_touserdata(L, 1); if (!PDF_OBJ_ARRAYTYPE(array)) { return luaL_error(L, "push_array called on non-array"); @@ -506,7 +507,7 @@ int pdf_push_array(lua_State *L) { return 0; } -int pdf_get_array(lua_State *L) { +int je_pdf_get_array(lua_State *L) { pdf_obj* array = lua_touserdata(L, 1); if (!PDF_OBJ_ARRAYTYPE(array)) { return luaL_error(L, "push_array called on non-array"); @@ -521,7 +522,7 @@ int pdf_get_array(lua_State *L) { } } -int pdf_array_length(lua_State *L) { +int je_pdf_array_length(lua_State *L) { pdf_obj* array = lua_touserdata(L, 1); if (!PDF_OBJ_ARRAYTYPE(array)) { return luaL_error(L, "push_array called on non-array"); @@ -530,14 +531,14 @@ int pdf_array_length(lua_State *L) { return 1; } -int pdf_new_string(lua_State *L) { +int je_pdf_new_string(lua_State *L) { const char* s = luaL_checkstring(L, 1); int l = lua_rawlen(L, 1); lua_pushlightuserdata(L, texpdf_new_string(s, l)); return 1; } -int pdf_version(lua_State *L) { +int je_pdf_version(lua_State *L) { lua_pushstring(L, texpdf_library_version()); return 1; } @@ -566,44 +567,44 @@ void luaL_setfuncs_libtexpdf (lua_State *L, const luaL_Reg *l, int nup) { #endif static const struct luaL_Reg lib_table [] = { - {"init", pdf_init}, - {"beginpage", pdf_beginpage}, - {"change_page_size", pdf_changepagesize}, - {"endpage", pdf_endpage}, - {"finish", pdf_finish}, - {"loadfont", pdf_loadfont}, - {"setdirmode", pdf_setdirmode}, - {"setstring", pdf_setstring}, - {"setrule", pdf_setrule}, - {"setcolor_rgb", pdf_setcolor_rgb}, - {"setcolor_cmyk", pdf_setcolor_cmyk}, - {"setcolor_gray", pdf_setcolor_gray}, - {"drawimage", pdf_drawimage}, - {"imagebbox", pdf_imagebbox}, - {"colorpop", pdf_colorpop}, - {"colorpush_rgb", pdf_colorpush_rgb}, - {"colorpush_cmyk", pdf_colorpush_cmyk}, - {"colorpush_gray", pdf_colorpush_gray}, - {"setmatrix", pdf_transform}, - {"gsave", pdf_gsave}, - {"grestore", pdf_grestore}, - {"destination", pdf_destination}, - {"bookmark", pdf_bookmark}, - {"begin_annotation", pdf_begin_annotation}, - {"end_annotation", pdf_end_annotation}, - {"metadata", pdf_metadata}, - {"version", pdf_version}, - {"add_content", pdf_add_content}, - {"get_dictionary", pdf_get_dictionary}, - {"parse", pdf_parse}, - {"add_dict", pdf_add_dict}, - {"lookup_dictionary", pdf_lookup_dictionary}, - {"reference", pdf_reference}, - {"release", pdf_release}, - {"push_array", pdf_push_array}, - {"get_array", pdf_get_array}, - {"array_length", pdf_array_length}, - {"string", pdf_new_string}, + {"init", je_pdf_init}, + {"beginpage", je_pdf_beginpage}, + {"change_page_size", je_pdf_changepagesize}, + {"endpage", je_pdf_endpage}, + {"finish", je_pdf_finish}, + {"loadfont", je_pdf_loadfont}, + {"setdirmode", je_pdf_setdirmode}, + {"setstring", je_pdf_setstring}, + {"setrule", je_pdf_setrule}, + {"setcolor_rgb", je_pdf_setcolor_rgb}, + {"setcolor_cmyk", je_pdf_setcolor_cmyk}, + {"setcolor_gray", je_pdf_setcolor_gray}, + {"drawimage", je_pdf_drawimage}, + {"imagebbox", je_pdf_imagebbox}, + {"colorpop", je_pdf_colorpop}, + {"colorpush_rgb", je_pdf_colorpush_rgb}, + {"colorpush_cmyk", je_pdf_colorpush_cmyk}, + {"colorpush_gray", je_pdf_colorpush_gray}, + {"setmatrix", je_pdf_transform}, + {"gsave", je_pdf_gsave}, + {"grestore", je_pdf_grestore}, + {"destination", je_pdf_destination}, + {"bookmark", je_pdf_bookmark}, + {"begin_annotation", je_pdf_begin_annotation}, + {"end_annotation", je_pdf_end_annotation}, + {"metadata", je_pdf_metadata}, + {"version", je_pdf_version}, + {"add_content", je_pdf_add_content}, + {"get_dictionary", je_pdf_get_dictionary}, + {"parse", je_pdf_parse}, + {"add_dict", je_pdf_add_dict}, + {"lookup_dictionary", je_pdf_lookup_dictionary}, + {"reference", je_pdf_reference}, + {"release", je_pdf_release}, + {"push_array", je_pdf_push_array}, + {"get_array", je_pdf_get_array}, + {"array_length", je_pdf_array_length}, + {"string", je_pdf_new_string}, {NULL, NULL} }; diff --git a/justenough/macfonts.m b/justenough/macfonts.m index 23daa34c3..99b880e03 100644 --- a/justenough/macfonts.m +++ b/justenough/macfonts.m @@ -119,7 +119,7 @@ static void luaL_setfuncs_macfonts (lua_State *L, const luaL_Reg *l, int nup) { } -int face_from_options(lua_State* L) { +int je_face_from_options(lua_State* L) { uint32_t index = 0; const char *family = "Gentium"; char * font_path; @@ -204,7 +204,7 @@ int face_from_options(lua_State* L) { static const struct luaL_Reg lib_table [] = { - {"_face", face_from_options}, + {"_face", je_face_from_options}, {NULL, NULL} }; From 05864d135465a22b889b8943de41c098cd7752af Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 27 Oct 2023 23:33:24 +0300 Subject: [PATCH 167/357] chore(cli): Fixup static linking of libtexpdf --- build-aux/build.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/build-aux/build.rs b/build-aux/build.rs index 586688d38..65c572825 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -37,23 +37,27 @@ fn main() { "cargo:rustc-link-search=native={}", Path::new(&dir).join("justenough").join(".libs").display() ); + println!( + "cargo:rustc-link-search=native={}", + Path::new(&dir).join("libtexpdf").join(".libs").display() + ); println!("cargo:rustc-link-arg=-l:fontmetrics.a"); println!("cargo:rustc-link-arg=-l:justenoughfontconfig.a"); println!("cargo:rustc-link-arg=-l:justenoughharfbuzz.a"); println!("cargo:rustc-link-arg=-l:justenoughicu.a"); println!("cargo:rustc-link-arg=-l:justenoughlibtexpdf.a"); println!("cargo:rustc-link-arg=-l:svg.a"); - println!("cargo:rustc-link-arg=-lharfbuzz"); - println!("cargo:rustc-link-arg=-lharfbuzz-subset"); - println!("cargo:rustc-link-arg=-lfontconfig"); - println!("cargo:rustc-link-arg=-licui18n"); - println!("cargo:rustc-link-arg=-licuuc"); - println!( - "cargo:rustc-link-search=native={}", - Path::new(&dir).join("libtexpdf").join(".libs").display() - ); - println!("cargo:rustc-link-arg=-ltexpdf"); - println!("cargo:rustc-link-arg=-lm"); + println!("cargo:rustc-link-arg=-l:libtexpdf.a"); + + // These are automatically linked by Cargo, but sadly *previous* to our links above + println!("cargo:rustc-link-arg=-lharfbuzz"); // needed by justenoughharfbuzz + println!("cargo:rustc-link-arg=-lharfbuzz-subset"); // needed by justenoughharfbuzz + println!("cargo:rustc-link-arg=-lfontconfig"); // needed by justenoughfontconfig + println!("cargo:rustc-link-arg=-licui18n"); // needed by justenoughicu + println!("cargo:rustc-link-arg=-licuuc"); // needed by justenoughicu + println!("cargo:rustc-link-arg=-lm"); // needed by svg + println!("cargo:rustc-link-arg=-lz"); // needed by libtexpdf + println!("cargo:rustc-link-arg=-lpng"); // needed by libtexpdf } } From 4f5623602a987e65e28e77eb3acd5cb0d5c8e927 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 28 Oct 2023 01:03:16 +0300 Subject: [PATCH 168/357] chore(cli): Work around rust-embed limitations --- Cargo.toml | 4 +--- build-aux/build.rs | 4 ++-- src/embed.rs.in | 20 +++++++++++++++++++- src/lib.rs | 10 +++++----- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f9c41bb11..daba63adb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,7 @@ lua52 = [ "mlua/lua52" ] lua51 = [ "mlua/lua51" ] luajit = [ "mlua/luajit" ] vendored = [ "mlua/vendored" ] -embed = [ "rust-embed" ] -static = [ "embed" ] -dynamic = [] +static = [ "rust-embed" ] completions = [ "cli", "clap_complete" ] cli = [ "clap" ] bash = [ "completions" ] diff --git a/build-aux/build.rs b/build-aux/build.rs index 65c572825..da3f2895f 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -8,7 +8,7 @@ use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; use clap_mangen::Man; #[cfg(feature = "completions")] use std::fs; -#[cfg(any(feature = "embed", feature = "completions"))] +#[cfg(any(feature = "static", feature = "completions"))] use std::path::Path; use std::{collections, env}; use vergen::EmitBuilder; @@ -30,7 +30,7 @@ fn main() { generate_manpage(); #[cfg(feature = "completions")] generate_shell_completions(); - #[cfg(feature = "embed")] + #[cfg(feature = "static")] { let dir = env::var("CARGO_MANIFEST_DIR").unwrap(); println!( diff --git a/src/embed.rs.in b/src/embed.rs.in index 18691afc7..127b9bb62 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -6,8 +6,26 @@ use std::str; /// Embed everything that would otherwise be installed to datadir #[derive(RustEmbed)] #[folder = "."] +#[exclude = ".*"] +#[exclude = "*~"] +#[exclude = "*.in"] +#[exclude = "Make*"] +#[exclude = "autom4te.cache/*"] +#[exclude = "build-aux/*"] +#[exclude = "cmake/*"] +#[exclude = "completions/*"] +#[exclude = "documentation/*"] +#[exclude = "justenough/*"] +#[exclude = "libtexpdf/*"] +#[exclude = "libtexpdf/*"] +#[exclude = "libtool"] +#[exclude = "node_modules/*"] +#[exclude = "rust-toolchain"] +#[exclude = "sile*"] +#[exclude = "src/*"] +#[exclude = "target/*"] +#[exclude = "tests/*"] // @INCLUDE_EMDED_INCLUDES@ -- this marker line gets replaced by a list of includes -#[exclude = "*"] pub struct SileModules; // Link Lua loader functions from C modules that Lua would otherwise be loading externally that diff --git a/src/lib.rs b/src/lib.rs index 77a1d7e9e..e77d704f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,20 +3,20 @@ use mlua::chunk; use mlua::prelude::*; -#[cfg(not(feature = "embed"))] +#[cfg(not(feature = "static"))] use std::env; use std::path::PathBuf; #[cfg(feature = "cli")] pub mod cli; -#[cfg(feature = "embed")] +#[cfg(feature = "static")] pub mod embed; pub type Result = anyhow::Result; pub fn start_luavm() -> crate::Result { let lua = unsafe { Lua::unsafe_new() }; - #[cfg(feature = "embed")] + #[cfg(feature = "static")] crate::embed::inject_embeded_loader(&lua); inject_paths(&lua); load_sile(&lua); @@ -25,9 +25,9 @@ pub fn start_luavm() -> crate::Result { } pub fn inject_paths(lua: &Lua) { - #[cfg(feature = "embed")] + #[cfg(feature = "static")] lua.load(r#"require("core.pathsetup")"#).exec().unwrap(); - #[cfg(not(feature = "embed"))] + #[cfg(not(feature = "static"))] { let sile_path = match env::var("SILE_PATH") { Ok(val) => val, From 16194ec246451eb2fba86b3557c827a513e97030 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 30 Oct 2023 10:46:33 +0300 Subject: [PATCH 169/357] refactor(cli): Simplify Lua C module loading Co-authored-by: Alex Orlenko --- src/embed.rs.in | 50 +++++++------------------------------------------ 1 file changed, 7 insertions(+), 43 deletions(-) diff --git a/src/embed.rs.in b/src/embed.rs.in index 127b9bb62..f98141c4e 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -52,50 +52,14 @@ pub fn inject_embeded_loader (lua: &Lua) { }, _ => panic!("Unable to find approprate interface to inject embeded loader"), }; - loaders.push(LuaFunction::wrap(|lua, module: String| { + loaders.push(LuaFunction::wrap(|lua, module: String| unsafe { match module.as_str() { - "fontmetrics" => { - LuaFunction::wrap(move |lua, ()| { - let loader = unsafe { lua.create_c_function(luaopen_fontmetrics).unwrap() }; - let module: LuaTable = loader.call(()).unwrap(); - Ok(module) - }).into_lua(lua) - }, - "justenoughfontconfig" => { - LuaFunction::wrap(move |lua, ()| { - let loader = unsafe { lua.create_c_function(luaopen_justenoughfontconfig).unwrap() }; - let module: LuaTable = loader.call(()).unwrap(); - Ok(module) - }).into_lua(lua) - }, - "justenoughharfbuzz" => { - LuaFunction::wrap(move |lua, ()| { - let loader = unsafe { lua.create_c_function(luaopen_justenoughharfbuzz).unwrap() }; - let module: LuaTable = loader.call(()).unwrap(); - Ok(module) - }).into_lua(lua) - }, - "justenoughicu" => { - LuaFunction::wrap(move |lua, ()| { - let loader = unsafe { lua.create_c_function(luaopen_justenoughicu).unwrap() }; - let module: LuaTable = loader.call(()).unwrap(); - Ok(module) - }).into_lua(lua) - }, - "justenoughlibtexpdf" => { - LuaFunction::wrap(move |lua, ()| { - let loader = unsafe { lua.create_c_function(luaopen_justenoughlibtexpdf).unwrap() }; - let module: LuaTable = loader.call(()).unwrap(); - Ok(module) - }).into_lua(lua) - }, - "svg" => { - LuaFunction::wrap(move |lua, ()| { - let loader = unsafe { lua.create_c_function(luaopen_svg).unwrap() }; - let module: LuaTable = loader.call(()).unwrap(); - Ok(module) - }).into_lua(lua) - }, + "fontmetrics" => lua.create_c_function(luaopen_fontmetrics).map(LuaValue::Function), + "justenoughfontconfig" => lua.create_c_function(luaopen_justenoughfontconfig).map(LuaValue::Function), + "justenoughharfbuzz" => lua.create_c_function(luaopen_justenoughharfbuzz).map(LuaValue::Function), + "justenoughicu" => lua.create_c_function(luaopen_justenoughicu).map(LuaValue::Function), + "justenoughlibtexpdf" => lua.create_c_function(luaopen_justenoughlibtexpdf).map(LuaValue::Function), + "svg" => lua.create_c_function(luaopen_svg).map(LuaValue::Function), _ => format!("C Module '{module}' is not linked in Rust binary").into_lua(lua) } })).unwrap(); From 89a2b2338149282ad7588fbec9ea2eb2917304f2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 30 Oct 2023 23:57:58 +0300 Subject: [PATCH 170/357] chore(cli): Always embed if static feature is enabled, don't short-circuit in debug builds --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index daba63adb..04ed08bdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ lto = true [dependencies.rust-embed] version = "8.0" optional = true - features = [ "include-exclude" ] + features = [ "include-exclude", "debug-embed" ] [dependencies.harfbuzz-sys] version = "0.5" From 61eae75e4cdedf09c1edc45be185c4be3ba11f5f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 31 Oct 2023 22:17:17 +0300 Subject: [PATCH 171/357] style(cli): Format generated file to rustfmt specs --- .github/workflows/rust_lint.yml | 2 +- build-aux/rust_boilerplate.mk.in | 2 +- src/embed.rs.in | 147 +++++++++++++++++-------------- 3 files changed, 83 insertions(+), 68 deletions(-) diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml index ac1174c4a..8c315d67f 100644 --- a/.github/workflows/rust_lint.yml +++ b/.github/workflows/rust_lint.yml @@ -20,7 +20,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run rustfmt run: | - git ls-files '*.rs' | xargs rustfmt --check + git ls-files '*.rs' '*.rs.in' | xargs rustfmt --check --config skip_children=true clippy: strategy: diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index a8d39cb4b..9036a06ea 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -69,7 +69,7 @@ clean-local: clean-cargo check-local: cargo-test rustfmt: - $(GIT) ls-files '*.rs' | $(XARGS) $(RUSTFMT) --check + $(GIT) ls-files '*.rs' '*.rs.in' | $(XARGS) $(RUSTFMT) --check --config skip_children=true clippy: cd $(srcdir) diff --git a/src/embed.rs.in b/src/embed.rs.in index f98141c4e..ba4a56b36 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -1,6 +1,6 @@ use mlua::chunk; use mlua::prelude::*; -use rust_embed::{RustEmbed, EmbeddedFile}; +use rust_embed::{EmbeddedFile, RustEmbed}; use std::str; /// Embed everything that would otherwise be installed to datadir @@ -31,74 +31,89 @@ pub struct SileModules; // Link Lua loader functions from C modules that Lua would otherwise be loading externally that // we've linked into the CLI binary. Linking happens in build-aux/build.rs. extern "C-unwind" { - fn luaopen_fontmetrics(lua: *mut mlua::lua_State) -> i32; - fn luaopen_justenoughfontconfig(lua: *mut mlua::lua_State) -> i32; - fn luaopen_justenoughharfbuzz(lua: *mut mlua::lua_State) -> i32; - fn luaopen_justenoughicu(lua: *mut mlua::lua_State) -> i32; - fn luaopen_justenoughlibtexpdf(lua: *mut mlua::lua_State) -> i32; - fn luaopen_svg(lua: *mut mlua::lua_State) -> i32; + fn luaopen_fontmetrics(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughfontconfig(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughharfbuzz(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughicu(lua: *mut mlua::lua_State) -> i32; + fn luaopen_justenoughlibtexpdf(lua: *mut mlua::lua_State) -> i32; + fn luaopen_svg(lua: *mut mlua::lua_State) -> i32; } /// Register a Lua function in the loaders/searchers table to return C modules linked into the CLI /// binary and another to return embeded Lua resources as Lua modules. See discussion in mlua: /// https://github.com/khvzak/mlua/discussions/322 -pub fn inject_embeded_loader (lua: &Lua) { - let package: LuaTable = lua.globals().get("package").unwrap(); - let loaders: LuaTable = match package.get("loaders").unwrap() { - LuaValue::Table(loaders) => loaders, - LuaValue::Nil => { - let loaders: LuaTable = package.get("searchers").unwrap(); - loaders - }, - _ => panic!("Unable to find approprate interface to inject embeded loader"), - }; - loaders.push(LuaFunction::wrap(|lua, module: String| unsafe { - match module.as_str() { - "fontmetrics" => lua.create_c_function(luaopen_fontmetrics).map(LuaValue::Function), - "justenoughfontconfig" => lua.create_c_function(luaopen_justenoughfontconfig).map(LuaValue::Function), - "justenoughharfbuzz" => lua.create_c_function(luaopen_justenoughharfbuzz).map(LuaValue::Function), - "justenoughicu" => lua.create_c_function(luaopen_justenoughicu).map(LuaValue::Function), - "justenoughlibtexpdf" => lua.create_c_function(luaopen_justenoughlibtexpdf).map(LuaValue::Function), - "svg" => lua.create_c_function(luaopen_svg).map(LuaValue::Function), - _ => format!("C Module '{module}' is not linked in Rust binary").into_lua(lua) - } - })).unwrap(); - loaders.push(LuaFunction::wrap(|lua, module: String| { - let module_path = module.replace('.', "/"); - let luaversion: LuaString = lua.load(chunk! { - return _VERSION:match("%d+%.%d+") - }).eval().unwrap(); - let luaversion: &str = luaversion.to_str().unwrap(); - let mut package_epath: Vec<&str> = vec![ - "?/init.lua", - "?.lua", - "lua-libraries/?.lua" - ]; - let path = format!("lua_modules/lib/lua/{}/?/init.lua", luaversion); - package_epath.push(&path); - let path = format!("lua_modules/lib/lua/{}/?.lua", luaversion); - package_epath.push(&path); - let path = format!("lua_modules/share/lua/{}/?/init.lua", luaversion); - package_epath.push(&path); - let path = format!("lua_modules/share/lua/{}/?.lua", luaversion); - package_epath.push(&path); - let mut resource_option: Option = None; - for pattern in &package_epath { - let path = pattern.replace('?', &module_path); - let embeded = SileModules::get(&path); - if embeded.is_some() { - resource_option = embeded; - break; - } - } - match resource_option { - Some(module) => { - return LuaFunction::wrap(move |lua, ()| { - let data = str::from_utf8(module.data.as_ref()).expect("Embeded content is not valid UTF-8"); - lua.load(data).call::<_, LuaValue>(()) - }).into_lua(lua) - }, - None => format!("Module '{module}' is not embeded in Rust binary").into_lua(lua) - } - })).unwrap(); +pub fn inject_embeded_loader(lua: &Lua) { + let package: LuaTable = lua.globals().get("package").unwrap(); + let loaders: LuaTable = match package.get("loaders").unwrap() { + LuaValue::Table(loaders) => loaders, + LuaValue::Nil => { + let loaders: LuaTable = package.get("searchers").unwrap(); + loaders + } + _ => panic!("Unable to find approprate interface to inject embeded loader"), + }; + loaders + .push(LuaFunction::wrap(|lua, module: String| unsafe { + match module.as_str() { + "fontmetrics" => lua + .create_c_function(luaopen_fontmetrics) + .map(LuaValue::Function), + "justenoughfontconfig" => lua + .create_c_function(luaopen_justenoughfontconfig) + .map(LuaValue::Function), + "justenoughharfbuzz" => lua + .create_c_function(luaopen_justenoughharfbuzz) + .map(LuaValue::Function), + "justenoughicu" => lua + .create_c_function(luaopen_justenoughicu) + .map(LuaValue::Function), + "justenoughlibtexpdf" => lua + .create_c_function(luaopen_justenoughlibtexpdf) + .map(LuaValue::Function), + "svg" => lua.create_c_function(luaopen_svg).map(LuaValue::Function), + _ => format!("C Module '{module}' is not linked in Rust binary").into_lua(lua), + } + })) + .unwrap(); + loaders + .push(LuaFunction::wrap(|lua, module: String| { + let module_path = module.replace('.', "/"); + let luaversion: LuaString = lua + .load(chunk! { + return _VERSION:match("%d+%.%d+") + }) + .eval() + .unwrap(); + let luaversion: &str = luaversion.to_str().unwrap(); + let mut package_epath: Vec<&str> = vec!["?/init.lua", "?.lua", "lua-libraries/?.lua"]; + let path = format!("lua_modules/lib/lua/{}/?/init.lua", luaversion); + package_epath.push(&path); + let path = format!("lua_modules/lib/lua/{}/?.lua", luaversion); + package_epath.push(&path); + let path = format!("lua_modules/share/lua/{}/?/init.lua", luaversion); + package_epath.push(&path); + let path = format!("lua_modules/share/lua/{}/?.lua", luaversion); + package_epath.push(&path); + let mut resource_option: Option = None; + for pattern in &package_epath { + let path = pattern.replace('?', &module_path); + let embeded = SileModules::get(&path); + if embeded.is_some() { + resource_option = embeded; + break; + } + } + match resource_option { + Some(module) => { + return LuaFunction::wrap(move |lua, ()| { + let data = str::from_utf8(module.data.as_ref()) + .expect("Embeded content is not valid UTF-8"); + lua.load(data).call::<_, LuaValue>(()) + }) + .into_lua(lua) + } + None => format!("Module '{module}' is not embeded in Rust binary").into_lua(lua), + } + })) + .unwrap(); } From 420564a40b3fc7ae3a82b5f5a001387e624a1c06 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 1 Nov 2023 01:06:51 +0300 Subject: [PATCH 172/357] chore(cli): Give Fluent access to embeded default FTL files --- src/embed.rs.in | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/embed.rs.in b/src/embed.rs.in index ba4a56b36..1a7cb4c2a 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -116,4 +116,23 @@ pub fn inject_embeded_loader(lua: &Lua) { } })) .unwrap(); + loaders + .push(LuaFunction::wrap(|lua, module: String| { + let module_path = module.replace('.', "/"); + let pattern = "?.ftl"; + let path = pattern.replace('?', &module_path); + match SileModules::get(&path) { + Some(module) => + LuaFunction::wrap(move |lua, ()| { + let data = str::from_utf8(module.data.as_ref()) + .expect("Embeded content is not valid UTF-8"); + lua.load(chunk!{ + return assert(fluent:add_messages($data)) + }).call::<_, LuaValue>(()) + }) + .into_lua(lua), + None => format!("FTL resource '{module_path}' is not embeded in Rust binary").into_lua(lua) + } + })) + .unwrap(); } From 02388f96a0f26c63460471316341bfb2ccfd1d2c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 1 Nov 2023 14:39:41 +0300 Subject: [PATCH 173/357] chore(build): Avoid race condition when using generated sources --- Makefile.am | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index eb95d48f5..b8d715efb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,13 +89,15 @@ if EMBEDED_RESOURCES sile_SOURCES += src/embed.rs src/embed-includes.rs BUILT_SOURCES += src/embed.rs src/embed-includes.rs -export EMBEDED_LUA_RESOURCES = $(SILEDATA) $(LUALIBRARIES) $(BUILT_LUA_SOURCES) $(LUAMODULES) - src/embed-includes.rs: Makefile-distfiles - cat << EOF | sed -e '/^$$/d' > $@ - $(foreach FILE,$(EMBEDED_LUA_RESOURCES),#[include = "$(FILE)"] - ) - EOF + { + echo $(BUILT_LUA_SOURCES) + $(GREP) -E '^(SILEDATA|LUALIBRARIES|LUAMODULES) = ' $< + } | + $(SED) -E -e 's/^.* = //;s/ /\n/g' | + while read file; do + echo "#[include = \"$${file}\"]" + done > $@ src/embed.rs: src/embed.rs.in src/embed-includes.rs $(SED) \ From 906ce8083387578c64aed828226a4093b7a57dc7 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 1 Nov 2023 15:36:36 +0300 Subject: [PATCH 174/357] chore(build): Fixup non-LuaJIT builds with embedded resources --- justenough/fontmetrics.c | 4 ++-- justenough/justenoughfontconfig.c | 4 ++-- justenough/justenoughharfbuzz.c | 4 ++-- justenough/justenoughicu.c | 4 ++-- justenough/justenoughlibtexpdf.c | 4 ++-- justenough/macfonts.m | 4 ++-- justenough/svg.c | 4 ++-- src/embed.rs.in | 3 +-- 8 files changed, 15 insertions(+), 16 deletions(-) diff --git a/justenough/fontmetrics.c b/justenough/fontmetrics.c index 317521d7d..4c74999db 100644 --- a/justenough/fontmetrics.c +++ b/justenough/fontmetrics.c @@ -54,7 +54,7 @@ int fm_glyphwidth (lua_State* L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs_fontmetrics (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -76,6 +76,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_fontmetrics (lua_State *L) { lua_newtable(L); - luaL_setfuncs_fontmetrics(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughfontconfig.c b/justenough/justenoughfontconfig.c index 11ee559f0..71153a9d7 100644 --- a/justenough/justenoughfontconfig.c +++ b/justenough/justenoughfontconfig.c @@ -165,7 +165,7 @@ int je_face_from_options(lua_State* L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs_fontconfig (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -186,6 +186,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughfontconfig (lua_State *L) { lua_newtable(L); - luaL_setfuncs_fontconfig(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughharfbuzz.c b/justenough/justenoughharfbuzz.c index 85bc01835..b534a7abb 100644 --- a/justenough/justenoughharfbuzz.c +++ b/justenough/justenoughharfbuzz.c @@ -457,7 +457,7 @@ int je_hb_get_table (lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs_harfbuzz (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -484,6 +484,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughharfbuzz (lua_State *L) { lua_newtable(L); - luaL_setfuncs_harfbuzz(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughicu.c b/justenough/justenoughicu.c index 71176c358..f4be6b405 100644 --- a/justenough/justenoughicu.c +++ b/justenough/justenoughicu.c @@ -504,7 +504,7 @@ int je_icu_version(lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs_icu (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -533,6 +533,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughicu (lua_State *L) { lua_newtable(L); - luaL_setfuncs_icu(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/justenough/justenoughlibtexpdf.c b/justenough/justenoughlibtexpdf.c index 71b25abac..a63674ae0 100644 --- a/justenough/justenoughlibtexpdf.c +++ b/justenough/justenoughlibtexpdf.c @@ -552,7 +552,7 @@ int je_pdf_version(lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs_libtexpdf (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -610,6 +610,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_justenoughlibtexpdf (lua_State *L) { lua_newtable(L); - luaL_setfuncs_libtexpdf(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/justenough/macfonts.m b/justenough/macfonts.m index 99b880e03..a64831299 100644 --- a/justenough/macfonts.m +++ b/justenough/macfonts.m @@ -17,7 +17,7 @@ /* ** Adapted from Lua 5.2.0 */ -static void luaL_setfuncs_macfonts (lua_State *L, const luaL_Reg *l, int nup) { +static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -211,7 +211,7 @@ int je_face_from_options(lua_State* L) { int luaopen_macfonts (lua_State *L) { lua_newtable(L); - luaL_setfuncs_macfonts(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/justenough/svg.c b/justenough/svg.c index 265eca58c..fd3406efa 100644 --- a/justenough/svg.c +++ b/justenough/svg.c @@ -107,7 +107,7 @@ int svg_to_ps(lua_State *L) { /* ** Adapted from Lua 5.2.0 */ -void luaL_setfuncs_svg (lua_State *L, const luaL_Reg *l, int nup) { +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -128,6 +128,6 @@ static const struct luaL_Reg lib_table [] = { int luaopen_svg (lua_State *L) { lua_newtable(L); - luaL_setfuncs_svg(L, lib_table, 0); + luaL_setfuncs(L, lib_table, 0); return 1; } diff --git a/src/embed.rs.in b/src/embed.rs.in index 1a7cb4c2a..2cbfc4e81 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -47,8 +47,7 @@ pub fn inject_embeded_loader(lua: &Lua) { let loaders: LuaTable = match package.get("loaders").unwrap() { LuaValue::Table(loaders) => loaders, LuaValue::Nil => { - let loaders: LuaTable = package.get("searchers").unwrap(); - loaders + package.get("searchers").unwrap() } _ => panic!("Unable to find approprate interface to inject embeded loader"), }; From 375a6491213e861dcf661f1dc9ab61472aa214f5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 1 Nov 2023 16:14:49 +0300 Subject: [PATCH 175/357] refactor(build): Move repeated Lua module code into common library --- justenough/compat-5.2.c | 21 +++++++++++++++++++++ justenough/compat-5.2.h | 7 +++++++ justenough/fontmetrics.c | 25 +++---------------------- justenough/hb-utils.c | 3 +-- justenough/justenoughfontconfig.c | 25 ++----------------------- justenough/justenoughharfbuzz.c | 26 ++------------------------ justenough/justenoughicu.c | 27 ++++----------------------- justenough/justenoughlibtexpdf.c | 27 +-------------------------- justenough/macfonts.m | 24 +----------------------- justenough/svg.c | 30 +++++------------------------- 10 files changed, 47 insertions(+), 168 deletions(-) create mode 100644 justenough/compat-5.2.c create mode 100644 justenough/compat-5.2.h diff --git a/justenough/compat-5.2.c b/justenough/compat-5.2.c new file mode 100644 index 000000000..e2f63a3bd --- /dev/null +++ b/justenough/compat-5.2.c @@ -0,0 +1,21 @@ +#if LUA_VERSION_NUM == 501 + +#include "compat-5.2.h" + +void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup + 1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable( + L, + -(nup + + 3)); /* table must be below the upvalues, the name and the closure */ + } + lua_pop(L, nup); /* remove upvalues */ +} + +#endif diff --git a/justenough/compat-5.2.h b/justenough/compat-5.2.h new file mode 100644 index 000000000..cb8231c94 --- /dev/null +++ b/justenough/compat-5.2.h @@ -0,0 +1,7 @@ +#if LUA_VERSION_NUM==501 + +#define lua_rawlen lua_objlen + +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); + +#endif diff --git a/justenough/fontmetrics.c b/justenough/fontmetrics.c index 4c74999db..064f5efae 100644 --- a/justenough/fontmetrics.c +++ b/justenough/fontmetrics.c @@ -6,6 +6,8 @@ #include "hb-utils.h" +#include "compat-5.2.c" + int fm_get_typographic_extents (lua_State *L) { double upem; @@ -45,28 +47,6 @@ int fm_glyphwidth (lua_State* L) { return 1; } -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif static const struct luaL_Reg lib_table [] = { {"get_typographic_extents", fm_get_typographic_extents}, @@ -74,6 +54,7 @@ static const struct luaL_Reg lib_table [] = { {NULL, NULL} }; + int luaopen_fontmetrics (lua_State *L) { lua_newtable(L); luaL_setfuncs(L, lib_table, 0); diff --git a/justenough/hb-utils.c b/justenough/hb-utils.c index 8c294ddbb..7a79111fa 100644 --- a/justenough/hb-utils.c +++ b/justenough/hb-utils.c @@ -1,9 +1,8 @@ -#include "hb-utils.h" - #include #include #include +#include "hb-utils.h" #include "silewin32.h" static hb_variation_t* scan_variation_string(const char* cp1, unsigned int* ret) { diff --git a/justenough/justenoughfontconfig.c b/justenough/justenoughfontconfig.c index 71153a9d7..50c520612 100644 --- a/justenough/justenoughfontconfig.c +++ b/justenough/justenoughfontconfig.c @@ -9,6 +9,8 @@ #include "silewin32.h" +#include "compat-5.2.c" + int je_face_from_options(lua_State* L) { FcChar8 * font_path, * fullname, * familyname; FcPattern* p; @@ -156,29 +158,6 @@ int je_face_from_options(lua_State* L) { return 1; } -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif - static const struct luaL_Reg lib_table [] = { {"_face", je_face_from_options}, {NULL, NULL} diff --git a/justenough/justenoughharfbuzz.c b/justenough/justenoughharfbuzz.c index b534a7abb..2066d917d 100644 --- a/justenough/justenoughharfbuzz.c +++ b/justenough/justenoughharfbuzz.c @@ -12,9 +12,10 @@ #include #include +#include "hb-utils.h" #include "silewin32.h" -#include "hb-utils.h" +#include "compat-5.2.c" /* The following function stolen from XeTeX_ext.c */ static hb_tag_t @@ -448,29 +449,6 @@ int je_hb_get_table (lua_State *L) { return 1; } -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif - static const struct luaL_Reg lib_table [] = { {"_shape", je_hb_shape}, {"get_glyph_dimensions", je_hb_get_glyph_dimensions}, diff --git a/justenough/justenoughicu.c b/justenough/justenoughicu.c index f4be6b405..249fb622e 100644 --- a/justenough/justenoughicu.c +++ b/justenough/justenoughicu.c @@ -2,6 +2,7 @@ #include #include #include + #include #include #include @@ -9,12 +10,15 @@ #include #include #include + #include #include #include #include "silewin32.h" +#include "compat-5.2.c" + typedef int32_t (*conversion_function_t)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode); #define utf8_to_uchar(in, in_l, out, out_l) { \ @@ -495,29 +499,6 @@ int je_icu_version(lua_State *L) { return 1; } -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 && !LUAJIT -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif - static const struct luaL_Reg lib_table [] = { {"breakpoints", je_icu_breakpoints}, {"case", je_icu_case}, diff --git a/justenough/justenoughlibtexpdf.c b/justenough/justenoughlibtexpdf.c index a63674ae0..95fdbf418 100644 --- a/justenough/justenoughlibtexpdf.c +++ b/justenough/justenoughlibtexpdf.c @@ -8,9 +8,7 @@ #include -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -#define lua_rawlen lua_strlen -#endif +#include "compat-5.2.c" pdf_doc *p = NULL; double height = 0.0; @@ -543,29 +541,6 @@ int je_pdf_version(lua_State *L) { return 1; } -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif - static const struct luaL_Reg lib_table [] = { {"init", je_pdf_init}, {"beginpage", je_pdf_beginpage}, diff --git a/justenough/macfonts.m b/justenough/macfonts.m index a64831299..2bca54aec 100644 --- a/justenough/macfonts.m +++ b/justenough/macfonts.m @@ -7,29 +7,7 @@ #include #include - -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif +#include "compat-5.2.c" #define MAX_NAME_LEN 512 diff --git a/justenough/svg.c b/justenough/svg.c index fd3406efa..a8f0e6ebb 100644 --- a/justenough/svg.c +++ b/justenough/svg.c @@ -1,13 +1,16 @@ #include #include #include -#define NANOSVG_IMPLEMENTATION // Expands implementation -#include "nanosvg.h" #include #include #include +#define NANOSVG_IMPLEMENTATION // Expands implementation +#include "nanosvg.h" + +#include "compat-5.2.c" + static char* safe_append(char* output, int* output_l, int* max_output, char* s2) { int append_len = strlen(s2) + 1; // strlen doesn't count \0 if (*output_l + append_len > *max_output) { @@ -98,29 +101,6 @@ int svg_to_ps(lua_State *L) { return 3; } -#if !defined LUA_VERSION_NUM -/* Lua 5.0 */ -#define luaL_Reg luaL_reg -#endif - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup+1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif - static const struct luaL_Reg lib_table [] = { {"svg_to_ps", svg_to_ps}, {NULL, NULL} From 876a90b41a8254a63b47e5a973ef9eaa6e0ab876 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 1 Nov 2023 21:05:47 +0300 Subject: [PATCH 176/357] style(core): Run generated code template through Rust formatter --- src/embed.rs.in | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/embed.rs.in b/src/embed.rs.in index 2cbfc4e81..f787d7347 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -46,9 +46,7 @@ pub fn inject_embeded_loader(lua: &Lua) { let package: LuaTable = lua.globals().get("package").unwrap(); let loaders: LuaTable = match package.get("loaders").unwrap() { LuaValue::Table(loaders) => loaders, - LuaValue::Nil => { - package.get("searchers").unwrap() - } + LuaValue::Nil => package.get("searchers").unwrap(), _ => panic!("Unable to find approprate interface to inject embeded loader"), }; loaders @@ -121,16 +119,17 @@ pub fn inject_embeded_loader(lua: &Lua) { let pattern = "?.ftl"; let path = pattern.replace('?', &module_path); match SileModules::get(&path) { - Some(module) => - LuaFunction::wrap(move |lua, ()| { - let data = str::from_utf8(module.data.as_ref()) - .expect("Embeded content is not valid UTF-8"); - lua.load(chunk!{ - return assert(fluent:add_messages($data)) - }).call::<_, LuaValue>(()) + Some(module) => LuaFunction::wrap(move |lua, ()| { + let data = str::from_utf8(module.data.as_ref()) + .expect("Embeded content is not valid UTF-8"); + lua.load(chunk! { + return assert(fluent:add_messages($data)) }) + .call::<_, LuaValue>(()) + }) .into_lua(lua), - None => format!("FTL resource '{module_path}' is not embeded in Rust binary").into_lua(lua) + None => format!("FTL resource '{module_path}' is not embeded in Rust binary") + .into_lua(lua), } })) .unwrap(); From 978f0d6175c55ef77f5a7da04501fd1aef7ac7c6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 1 Nov 2023 21:11:27 +0300 Subject: [PATCH 177/357] chore(build): Build Lua C modules with position independent code flag Backtraking, but yes we need these flags and we need the ability to tweak them on a per-lua basis too. Yuck but... --- .github/workflows/test.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ad83696e7..6393d6469 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,14 +13,14 @@ jobs: fail-fast: false matrix: luaVersion: - - '5.4' - - '5.3' - - '5.2' - - '5.1' - - 'luajit' - # - 'luajit-openresty' + - [ '5.4', 'MYCFLAGS=-fPIC' ] + - [ '5.3', 'MYCFLAGS=-fPIC' ] + - [ '5.2', 'MYCFLAGS=-fPIC' ] + - [ '5.1', 'CFLAGS="-O2 -Wall -DLUA_USE_LINUX -fPIC"' ] + - [ 'luajit', 'XCFLAGS=-fPIC' ] + # - [ 'luajit-openresty', 'XCFLAGS=-fPIC' ] runs-on: ubuntu-22.04 - name: Test on Lua ${{ matrix.luaVersion }} + name: Test on Lua ${{ matrix.luaVersion[0] }} steps: - name: Checkout uses: actions/checkout@v4 @@ -38,7 +38,7 @@ jobs: with: path: | lua_modules - key: luarocks-${{ matrix.luaVersion }}-${{ hashFiles('Makefile-luarocks', 'sile.rockspec.in') }} + key: luarocks-${{ matrix.luaVersion[0] }}-${{ hashFiles('Makefile-luarocks', 'sile.rockspec.in') }} - name: Cache Rust uses: Swatinem/rust-cache@v2 - name: Install system dependencies @@ -48,7 +48,8 @@ jobs: - name: Setup ‘lua’ uses: leafo/gh-actions-lua@v10 with: - luaVersion: ${{ matrix.luaVersion }} + luaVersion: ${{ matrix.luaVersion[0] }} + luaCompileFlags: ${{ matrix.luaVersion[1] }} - name: Setup ‘cargo’ uses: actions-rs/toolchain@v1 - name: Setup ‘luarocks’ @@ -69,9 +70,10 @@ jobs: run: | ./bootstrap.sh ./configure \ + ${{ matrix.luaVersion[1] }} \ --enable-developer LUACHECK=false NIX=false \ --disable-font-variations \ - --with${{ !startsWith(matrix.luaVersion, 'luajit') && 'out' || '' }}-luajit \ + --with${{ !startsWith(matrix.luaVersion[0], 'luajit') && 'out' || '' }}-luajit \ --without-manual - name: Make run: | @@ -80,7 +82,7 @@ jobs: run: | make selfcheck - name: Test Busted - continue-on-error: ${{ matrix.luaVersion == '5.1' }} + continue-on-error: ${{ matrix.luaVersion[0] == '5.1' }} timeout-minutes: ${{ runner.debug && 20 || 2 }} run: | make busted @@ -95,5 +97,5 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: test-${{ matrix.luaVersion }}-actuals + name: test-${{ matrix.luaVersion[0] }}-actuals path: tests/*.actual From 42939b717c1cc9fc9aab7aa66738ca101189ae30 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 2 Nov 2023 16:43:09 +0300 Subject: [PATCH 178/357] chore(build): Inform Cargo of what autotools knows about needing rebuilds after commits --- build-aux/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build-aux/build.rs b/build-aux/build.rs index da3f2895f..55e7f33cb 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -17,6 +17,7 @@ use vergen::EmitBuilder; include!("../src/cli.rs"); fn main() { + println!("cargo:rerun-if-changed=.version"); let mut builder = EmitBuilder::builder(); // If passed a version from automake, use that instead of vergen's formatting if let Ok(val) = env::var("VERSION_FROM_AUTOTOOLS") { From 79d7e47027985e672ab9bc08670625a213e77238 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 2 Nov 2023 22:57:40 +0300 Subject: [PATCH 179/357] chore(deps): Include compat53 sources (0.12) --- justenough/compat-5.3.c | 957 ++++++++++++++++++++++++++++++++++++++++ justenough/compat-5.3.h | 421 ++++++++++++++++++ 2 files changed, 1378 insertions(+) create mode 100644 justenough/compat-5.3.c create mode 100644 justenough/compat-5.3.h diff --git a/justenough/compat-5.3.c b/justenough/compat-5.3.c new file mode 100644 index 000000000..1901a8267 --- /dev/null +++ b/justenough/compat-5.3.c @@ -0,0 +1,957 @@ +#include +#include +#include +#include +#include +#include +#include "compat-5.3.h" + +/* don't compile it again if it already is included via compat53.h */ +#ifndef COMPAT53_C_ +#define COMPAT53_C_ + + + +/* definitions for Lua 5.1 only */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 + +#ifndef COMPAT53_FOPEN_NO_LOCK +# if defined(_MSC_VER) +# define COMPAT53_FOPEN_NO_LOCK 1 +# else /* otherwise */ +# define COMPAT53_FOPEN_NO_LOCK 0 +# endif /* VC++ only so far */ +#endif /* No-lock fopen_s usage if possible */ + +#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK +# include +#endif /* VC++ _fsopen for share-allowed file read */ + +#ifndef COMPAT53_HAVE_STRERROR_R +# if (!defined(_WIN32)) && \ + ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ + (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \ + defined(__APPLE__)) +# define COMPAT53_HAVE_STRERROR_R 1 +# else /* none of the defines matched: define to 0 */ +# define COMPAT53_HAVE_STRERROR_R 0 +# endif /* have strerror_r of some form */ +#endif /* strerror_r */ + +#ifndef COMPAT53_HAVE_STRERROR_S +# if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \ + defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) +# define COMPAT53_HAVE_STRERROR_S 1 +# else /* not VC++ or C11 */ +# define COMPAT53_HAVE_STRERROR_S 0 +# endif /* strerror_s from VC++ or C11 */ +#endif /* strerror_s */ + +#ifndef COMPAT53_LUA_FILE_BUFFER_SIZE +# define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 +#endif /* Lua File Buffer Size */ + + +static char* compat53_strerror (int en, char* buff, size_t sz) { +#if COMPAT53_HAVE_STRERROR_R + /* use strerror_r here, because it's available on these specific platforms */ + if (sz > 0) { + buff[0] = '\0'; + /* we don't care whether the GNU version or the XSI version is used: */ + if (strerror_r(en, buff, sz)) { + /* Yes, we really DO want to ignore the return value! + * GCC makes that extra hard, not even a (void) cast will do. */ + } + if (buff[0] == '\0') { + /* Buffer is unchanged, so we probably have called GNU strerror_r which + * returned a static constant string. Chances are that strerror will + * return the same static constant string and therefore be thread-safe. */ + return strerror(en); + } + } + return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ +#elif COMPAT53_HAVE_STRERROR_S + /* for MSVC and other C11 implementations, use strerror_s since it's + * provided by default by the libraries */ + strerror_s(buff, sz, en); + return buff; +#else + /* fallback, but strerror is not guaranteed to be threadsafe due to modifying + * errno itself and some impls not locking a static buffer for it ... but most + * known systems have threadsafe errno: this might only change if the locale + * is changed out from under someone while this function is being called */ + (void)buff; + (void)sz; + return strerror(en); +#endif +} + + +COMPAT53_API int lua_absindex (lua_State *L, int i) { + if (i < 0 && i > LUA_REGISTRYINDEX) + i += lua_gettop(L) + 1; + return i; +} + + +static void compat53_call_lua (lua_State *L, char const code[], size_t len, + int nargs, int nret) { + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, code, len, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); + } + lua_insert(L, -nargs-1); + lua_call(L, nargs, nret); +} + + +static const char compat53_arith_code[] = + "local op,a,b=...\n" + "if op==0 then return a+b\n" + "elseif op==1 then return a-b\n" + "elseif op==2 then return a*b\n" + "elseif op==3 then return a/b\n" + "elseif op==4 then return a%b\n" + "elseif op==5 then return a^b\n" + "elseif op==6 then return -a\n" + "end\n"; + +COMPAT53_API void lua_arith (lua_State *L, int op) { + if (op < LUA_OPADD || op > LUA_OPUNM) + luaL_error(L, "invalid 'op' argument for lua_arith"); + luaL_checkstack(L, 5, "not enough stack slots"); + if (op == LUA_OPUNM) + lua_pushvalue(L, -1); + lua_pushnumber(L, op); + lua_insert(L, -3); + compat53_call_lua(L, compat53_arith_code, + sizeof(compat53_arith_code)-1, 3, 1); +} + + +static const char compat53_compare_code[] = + "local a,b=...\n" + "return a<=b\n"; + +COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) { + int result = 0; + switch (op) { + case LUA_OPEQ: + return lua_equal(L, idx1, idx2); + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + case LUA_OPLE: + luaL_checkstack(L, 5, "not enough stack slots"); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + compat53_call_lua(L, compat53_compare_code, + sizeof(compat53_compare_code)-1, 2, 1); + result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + default: + luaL_error(L, "invalid 'op' argument for lua_compare"); + } + return 0; +} + + +COMPAT53_API void lua_copy (lua_State *L, int from, int to) { + int abs_to = lua_absindex(L, to); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, from); + lua_replace(L, abs_to); +} + + +COMPAT53_API void lua_len (lua_State *L, int i) { + switch (lua_type(L, i)) { + case LUA_TSTRING: + lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); + break; + case LUA_TTABLE: + if (!luaL_callmeta(L, i, "__len")) + lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); + break; + case LUA_TUSERDATA: + if (luaL_callmeta(L, i, "__len")) + break; + /* FALLTHROUGH */ + default: + luaL_error(L, "attempt to get length of a %s value", + lua_typename(L, lua_type(L, i))); + } +} + + +COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + lua_pushlightuserdata(L, (void*)p); + lua_rawget(L, abs_i); + return lua_type(L, -1); +} + +COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, (void*)p); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + + +COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) { + lua_Number n = lua_tonumber(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + + +COMPAT53_API void luaL_checkversion (lua_State *L) { + (void)L; +} + + +COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) { + if (!lua_checkstack(L, sp+LUA_MINSTACK)) { + if (msg != NULL) + luaL_error(L, "stack overflow (%s)", msg); + else { + lua_pushliteral(L, "stack overflow"); + lua_error(L); + } + } +} + + +COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushstring(L, name); + lua_gettable(L, abs_i); + if (lua_istable(L, -1)) + return 1; + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + + +COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) { + lua_Integer res = 0; + int isnum = 0; + luaL_checkstack(L, 1, "not enough stack slots"); + lua_len(L, i); + res = lua_tointegerx(L, -1, &isnum); + lua_pop(L, 1); + if (!isnum) + luaL_error(L, "object length is not an integer"); + return res; +} + + +COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup+1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ + } + lua_pop(L, nup); /* remove upvalues */ +} + + +COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) { + luaL_checkstack(L, 1, "not enough stack slots"); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) { + void *p = lua_touserdata(L, i); + luaL_checkstack(L, 2, "not enough stack slots"); + if (p == NULL || !lua_getmetatable(L, i)) + return NULL; + else { + int res = 0; + luaL_getmetatable(L, tname); + res = lua_rawequal(L, -1, -2); + lua_pop(L, 2); + if (!res) + p = NULL; + } + return p; +} + + +static int compat53_countlevels (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + +static int compat53_findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + +static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (compat53_findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (compat53_pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + +#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ +#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ + +COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = compat53_countlevels(L1); + int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + compat53_pushfuncname(L, &ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + + +COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + const char *serr = NULL; + int en = errno; /* calls to Lua API may change this value */ + char buf[512] = { 0 }; + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + serr = compat53_strerror(en, buf, sizeof(buf)); + if (fname) + lua_pushfstring(L, "%s: %s", fname, serr); + else + lua_pushstring(L, serr); + lua_pushnumber(L, (lua_Number)en); + return 3; + } +} + + +static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { + if (mode && strchr(mode, modename[0]) == NULL) { + lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); + return err; + } + return LUA_OK; +} + + +typedef struct { + lua_Reader reader; + void *ud; + int has_peeked_data; + const char *peeked_data; + size_t peeked_data_size; +} compat53_reader_data; + + +static const char *compat53_reader (lua_State *L, void *ud, size_t *size) { + compat53_reader_data *data = (compat53_reader_data *)ud; + if (data->has_peeked_data) { + data->has_peeked_data = 0; + *size = data->peeked_data_size; + return data->peeked_data; + } else + return data->reader(L, data->ud, size); +} + + +COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { + int status = LUA_OK; + compat53_reader_data compat53_data = { 0, NULL, 1, 0, 0 }; + compat53_data.reader = reader; + compat53_data.ud = data; + compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); + if (compat53_data.peeked_data && compat53_data.peeked_data_size && + compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ + status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); + else + status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); + if (status != LUA_OK) + return status; + /* we need to call the original 5.1 version of lua_load! */ +#undef lua_load + return lua_load(L, compat53_reader, &compat53_data, source); +#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) +} + + +typedef struct { + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ +} compat53_LoadF; + + +static const char *compat53_getF (lua_State *L, void *ud, size_t *size) { + compat53_LoadF *lf = (compat53_LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'compat53_getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + + +static int compat53_errfile (lua_State *L, const char *what, int fnameindex) { + char buf[512] = {0}; + const char *serr = compat53_strerror(errno, buf, sizeof(buf)); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +static int compat53_skipBOM (compat53_LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = (char)c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int compat53_skipcomment (compat53_LoadF *lf, int *cp) { + int c = *cp = compat53_skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { + compat53_LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); +#if defined(_MSC_VER) + /* This code is here to stop a deprecation error that stops builds + * if a certain macro is defined. While normally not caring would + * be best, some header-only libraries and builds can't afford to + * dictate this to the user. A quick check shows that fopen_s this + * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, + * possibly even before that so we don't need to do any version + * number checks, since this has been there since forever. */ + + /* TO USER: if you want the behavior of typical fopen_s/fopen, + * which does lock the file on VC++, define the macro used below to 0 */ +#if COMPAT53_FOPEN_NO_LOCK + lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ + if (lf.f == NULL) + return compat53_errfile(L, "open", fnameindex); +#else /* use default locking version */ + if (fopen_s(&lf.f, filename, "r") != 0) + return compat53_errfile(L, "open", fnameindex); +#endif /* Locking vs. No-locking fopen variants */ +#else + lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ + if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); +#endif + } + if (compat53_skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ +#if defined(_MSC_VER) + if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) + return compat53_errfile(L, "reopen", fnameindex); +#else + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); +#endif + compat53_skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */ + status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return compat53_errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { + int status = LUA_OK; + if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { + status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); + } + else { + status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); + } + if (status != LUA_OK) + return status; + return luaL_loadbuffer(L, buff, sz, name); +} + + +#if !defined(l_inspectstat) && \ + (defined(unix) || defined(__unix) || defined(__unix__) || \ + defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ + (defined(__APPLE__) && defined(__MACH__))) +/* some form of unix; check feature macros in unistd.h for details */ +# include +/* check posix version; the relevant include files and macros probably + * were available before 2001, but I'm not sure */ +# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# include +# define l_inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } +# endif +#endif + +/* provide default (no-op) version */ +#if !defined(l_inspectstat) +# define l_inspectstat(stat,what) ((void)0) +#endif + + +COMPAT53_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; + if (stat == -1) + return luaL_fileresult(L, 0, NULL); + else { + l_inspectstat(stat, what); + if (*what == 'e' && stat == 0) + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; + } +} + + +COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) { + /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ + B->b.p = NULL; + B->b.L = NULL; + B->b.lvl = 0; + /* reuse the buffer from the 5.1-style luaL_Buffer though! */ + B->ptr = B->b.buffer; + B->capacity = LUAL_BUFFERSIZE; + B->nelems = 0; + B->L2 = L; +} + + +COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) { + if (B->capacity - B->nelems < s) { /* needs to grow */ + char* newptr = NULL; + size_t newcap = B->capacity * 2; + if (newcap - B->nelems < s) + newcap = B->nelems + s; + if (newcap < B->capacity) /* overflow */ + luaL_error(B->L2, "buffer too large"); + newptr = (char*)lua_newuserdata(B->L2, newcap); + memcpy(newptr, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove old buffer */ + B->ptr = newptr; + B->capacity = newcap; + } + return B->ptr+B->nelems; +} + + +COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) { + memcpy(luaL_prepbuffsize(B, l), s, l); + luaL_addsize(B, l); +} + + +COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) { + size_t len = 0; + const char *s = lua_tolstring(B->L2, -1, &len); + if (!s) + luaL_error(B->L2, "cannot convert value to string"); + if (B->ptr != B->b.buffer) + lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ + luaL_addlstring(B, s, len); + lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); +} + + +void luaL_pushresult (luaL_Buffer_53 *B) { + lua_pushlstring(B->L2, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove userdata buffer */ +} + + +#endif /* Lua 5.1 */ + + + +/* definitions for Lua 5.1 and Lua 5.2 */ +#if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502 + + +COMPAT53_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { +#undef lua_pushlstring + lua_pushlstring(L, len > 0 ? s : "", len); +#define lua_pushlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _pushlstring_53) + return lua_tostring(L, -1); +} + + +COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) { + index = lua_absindex(L, index); + lua_pushinteger(L, i); + lua_gettable(L, index); + return lua_type(L, -1); +} + + +#ifndef LUA_EXTRASPACE +#define LUA_EXTRASPACE (sizeof(void*)) +#endif + +COMPAT53_API void *lua_getextraspace (lua_State *L) { + int is_main = 0; + void *ptr = NULL; + luaL_checkstack(L, 4, "not enough stack slots available"); + lua_pushliteral(L, "__compat53_extraspace"); + lua_pushvalue(L, -1); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_createtable(L, 0, 2); + lua_createtable(L, 0, 1); + lua_pushliteral(L, "k"); + lua_setfield(L, -2, "__mode"); + lua_setmetatable(L, -2); + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + lua_replace(L, -2); + is_main = lua_pushthread(L); + lua_rawget(L, -2); + ptr = lua_touserdata(L, -1); + if (!ptr) { + lua_pop(L, 1); + ptr = lua_newuserdata(L, LUA_EXTRASPACE); + if (is_main) { + memset(ptr, '\0', LUA_EXTRASPACE); + lua_pushthread(L); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + lua_pushboolean(L, 1); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } else { + void* mptr = NULL; + lua_pushboolean(L, 1); + lua_rawget(L, -3); + mptr = lua_touserdata(L, -1); + if (mptr) + memcpy(ptr, mptr, LUA_EXTRASPACE); + else + memset(ptr, '\0', LUA_EXTRASPACE); + lua_pop(L, 1); + lua_pushthread(L); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } + } + lua_pop(L, 2); + return ptr; +} + + +COMPAT53_API int lua_isinteger (lua_State *L, int index) { + if (lua_type(L, index) == LUA_TNUMBER) { + lua_Number n = lua_tonumber(L, index); + lua_Integer i = lua_tointeger(L, index); + if (i == n) + return 1; + } + return 0; +} + + +COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) { + int ok = 0; + lua_Number n = lua_tonumberx(L, i, &ok); + if (ok) { + if (n == (lua_Integer)n) { + if (isnum) + *isnum = 1; + return (lua_Integer)n; + } + } + if (isnum) + *isnum = 0; + return 0; +} + + +static void compat53_reverse (lua_State *L, int a, int b) { + for (; a < b; ++a, --b) { + lua_pushvalue(L, a); + lua_pushvalue(L, b); + lua_replace(L, a); + lua_replace(L, b); + } +} + + +COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) { + int n_elems = 0; + idx = lua_absindex(L, idx); + n_elems = lua_gettop(L)-idx+1; + if (n < 0) + n += n_elems; + if ( n > 0 && n < n_elems) { + luaL_checkstack(L, 2, "not enough stack slots available"); + n = n_elems - n; + compat53_reverse(L, idx, idx+n-1); + compat53_reverse(L, idx+n, idx+n_elems-1); + compat53_reverse(L, idx, idx+n_elems-1); + } +} + + +COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) { + luaL_checkstack(L, 1, "not enough stack slots available"); + index = lua_absindex(L, index); + lua_pushinteger(L, i); + lua_insert(L, -2); + lua_settable(L, index); +} + + +#if !defined(lua_str2number) +# define lua_str2number(s, p) strtod((s), (p)) +#endif + +COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) { + char* endptr; + lua_Number n = lua_str2number(s, &endptr); + if (endptr != s) { + while (*endptr != '\0' && isspace((unsigned char)*endptr)) + ++endptr; + if (*endptr == '\0') { + lua_pushnumber(L, n); + return endptr - s + 1; + } + } + return 0; +} + + +COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { + int t = lua_type(L, idx), tt = 0; + char const* name = NULL; + switch (t) { + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + case LUA_TSTRING: + case LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + if (lua_toboolean(L, idx)) + lua_pushliteral(L, "true"); + else + lua_pushliteral(L, "false"); + break; + default: + tt = luaL_getmetafield(L, idx, "__name"); + name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); + lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_replace(L, -2); + break; + } + } else { + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + return lua_tolstring(L, -1, len); +} + + +COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + luaL_checkstack(L, 3, "not enough stack slots available"); + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + if (lua_getfield(L, -1, modname) == LUA_TNIL) { + lua_pop(L, 1); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); + } + if (glb) { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } + lua_replace(L, -2); +} + + +#endif /* Lua 5.1 and 5.2 */ + + +#endif /* COMPAT53_C_ */ + + +/********************************************************************* +* This file contains parts of Lua 5.2's and Lua 5.3's source code: +* +* Copyright (C) 1994-2014 Lua.org, PUC-Rio. +* +* 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. +*********************************************************************/ + diff --git a/justenough/compat-5.3.h b/justenough/compat-5.3.h new file mode 100644 index 000000000..6f66dadb9 --- /dev/null +++ b/justenough/compat-5.3.h @@ -0,0 +1,421 @@ +#ifndef COMPAT53_H_ +#define COMPAT53_H_ + +#include +#include +#include +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +extern "C" { +#endif +#include +#include +#include +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +} +#endif + + +#undef COMPAT53_INCLUDE_SOURCE +#if defined(COMPAT53_PREFIX) +/* - change the symbol names of functions to avoid linker conflicts + * - compat-5.3.c needs to be compiled (and linked) separately + */ +# if !defined(COMPAT53_API) +# define COMPAT53_API extern +# endif +#else /* COMPAT53_PREFIX */ +/* - make all functions static and include the source. + * - compat-5.3.c doesn't need to be compiled (and linked) separately + */ +# define COMPAT53_PREFIX compat53 +# undef COMPAT53_API +# if defined(__GNUC__) || defined(__clang__) +# define COMPAT53_API __attribute__((__unused__)) static +# else +# define COMPAT53_API static +# endif +# define COMPAT53_INCLUDE_SOURCE +#endif /* COMPAT53_PREFIX */ + +#define COMPAT53_CONCAT_HELPER(a, b) a##b +#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) + + + +/* declarations for Lua 5.1 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 + +/* XXX not implemented: + * lua_arith (new operators) + * lua_upvalueid + * lua_upvaluejoin + * lua_version + * lua_yieldk + */ + +#ifndef LUA_OK +# define LUA_OK 0 +#endif +#ifndef LUA_OPADD +# define LUA_OPADD 0 +#endif +#ifndef LUA_OPSUB +# define LUA_OPSUB 1 +#endif +#ifndef LUA_OPMUL +# define LUA_OPMUL 2 +#endif +#ifndef LUA_OPDIV +# define LUA_OPDIV 3 +#endif +#ifndef LUA_OPMOD +# define LUA_OPMOD 4 +#endif +#ifndef LUA_OPPOW +# define LUA_OPPOW 5 +#endif +#ifndef LUA_OPUNM +# define LUA_OPUNM 6 +#endif +#ifndef LUA_OPEQ +# define LUA_OPEQ 0 +#endif +#ifndef LUA_OPLT +# define LUA_OPLT 1 +#endif +#ifndef LUA_OPLE +# define LUA_OPLE 2 +#endif + +/* LuaJIT/Lua 5.1 does not have the updated + * error codes for thread status/function returns (but some patched versions do) + * define it only if it's not found + */ +#if !defined(LUA_ERRGCMM) +/* Use + 2 because in some versions of Lua (Lua 5.1) + * LUA_ERRFILE is defined as (LUA_ERRERR+1) + * so we need to avoid it (LuaJIT might have something at this + * integer value too) + */ +# define LUA_ERRGCMM (LUA_ERRERR + 2) +#endif /* LUA_ERRGCMM define */ + +typedef size_t lua_Unsigned; + +typedef struct luaL_Buffer_53 { + luaL_Buffer b; /* make incorrect code crash! */ + char *ptr; + size_t nelems; + size_t capacity; + lua_State *L2; +} luaL_Buffer_53; +#define luaL_Buffer luaL_Buffer_53 + +/* In PUC-Rio 5.1, userdata is a simple FILE* + * In LuaJIT, it's a struct where the first member is a FILE* + * We can't support the `closef` member + */ +typedef struct luaL_Stream { + FILE *f; +} luaL_Stream; + +#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) +COMPAT53_API int lua_absindex (lua_State *L, int i); + +#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) +COMPAT53_API void lua_arith (lua_State *L, int op); + +#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) +COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op); + +#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) +COMPAT53_API void lua_copy (lua_State *L, int from, int to); + +#define lua_getuservalue(L, i) \ + (lua_getfenv((L), (i)), lua_type((L), -1)) +#define lua_setuservalue(L, i) \ + (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i))) + +#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) +COMPAT53_API void lua_len (lua_State *L, int i); + +#define lua_pushstring(L, s) \ + (lua_pushstring((L), (s)), lua_tostring((L), -1)) + +#ifndef luaL_newlibtable +# define luaL_newlibtable(L, l) \ + (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1)) +#endif +#ifndef luaL_newlib +# define luaL_newlib(L, l) \ + (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l))) +#endif + +#define lua_pushglobaltable(L) \ + lua_pushvalue((L), LUA_GLOBALSINDEX) + +#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) +COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p); + +#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) +COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); + +#define lua_rawlen(L, i) lua_objlen((L), (i)) + +#define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL) + +#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) +COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); + +#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) +COMPAT53_API void luaL_checkversion (lua_State *L); + +#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) +COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); + +#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) +COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); + +#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) +COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); + +#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) +COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg); + +#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) +COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name); + +#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) +COMPAT53_API lua_Integer luaL_len (lua_State *L, int i); + +#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) +COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); + +#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) +COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname); + +#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) +COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname); + +#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) +COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); + +#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) +COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname); + +#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult) +COMPAT53_API int luaL_execresult (lua_State *L, int stat); + +#define lua_callk(L, na, nr, ctx, cont) \ + ((void)(ctx), (void)(cont), lua_call((L), (na), (nr))) +#define lua_pcallk(L, na, nr, err, ctx, cont) \ + ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err))) + +#define lua_resume(L, from, nargs) \ + ((void)(from), lua_resume((L), (nargs))) + +#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) +COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B); + +#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) +COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s); + +#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) +COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l); + +#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) +COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B); + +#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) +COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B); + +#undef luaL_buffinitsize +#define luaL_buffinitsize(L, B, s) \ + (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s))) + +#undef luaL_prepbuffer +#define luaL_prepbuffer(B) \ + luaL_prepbuffsize((B), LUAL_BUFFERSIZE) + +#undef luaL_addchar +#define luaL_addchar(B, c) \ + ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \ + ((B)->ptr[(B)->nelems++] = (c))) + +#undef luaL_addsize +#define luaL_addsize(B, s) \ + ((B)->nelems += (s)) + +#undef luaL_addstring +#define luaL_addstring(B, s) \ + luaL_addlstring((B), (s), strlen((s))) + +#undef luaL_pushresultsize +#define luaL_pushresultsize(B, s) \ + (luaL_addsize((B), (s)), luaL_pushresult((B))) + +#if defined(LUA_COMPAT_APIINTCASTS) +#define lua_pushunsigned(L, n) \ + lua_pushinteger((L), (lua_Integer)(n)) +#define lua_tounsignedx(L, i, is) \ + ((lua_Unsigned)lua_tointegerx((L), (i), (is))) +#define lua_tounsigned(L, i) \ + lua_tounsignedx((L), (i), NULL) +#define luaL_checkunsigned(L, a) \ + ((lua_Unsigned)luaL_checkinteger((L), (a))) +#define luaL_optunsigned(L, a, d) \ + ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d))) +#endif + +#endif /* Lua 5.1 only */ + + + +/* declarations for Lua 5.1 and 5.2 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 + +typedef int lua_KContext; + +typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); + +#define lua_dump(L, w, d, s) \ + ((void)(s), lua_dump((L), (w), (d))) + +#define lua_getfield(L, i, k) \ + (lua_getfield((L), (i), (k)), lua_type((L), -1)) + +#define lua_gettable(L, i) \ + (lua_gettable((L), (i)), lua_type((L), -1)) + +#define lua_pushlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _pushlstring_53) +COMPAT53_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len); + +#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) +COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i); + +#define lua_getextraspace COMPAT53_CONCAT(COMPAT53_PREFIX, _getextraspace) +COMPAT53_API void *lua_getextraspace (lua_State *L); + +#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) +COMPAT53_API int lua_isinteger (lua_State *L, int index); + +#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53) +COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum); + +#define lua_numbertointeger(n, p) \ + ((*(p) = (lua_Integer)(n)), 1) + +#define lua_rawget(L, i) \ + (lua_rawget((L), (i)), lua_type((L), -1)) + +#define lua_rawgeti(L, i, n) \ + (lua_rawgeti((L), (i), (n)), lua_type((L), -1)) + +#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) +COMPAT53_API void lua_rotate (lua_State *L, int idx, int n); + +#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) +COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i); + +#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) +COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s); + +#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) +COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len); + +#define luaL_getmetafield(L, o, e) \ + (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL) + +#define luaL_newmetatable(L, tn) \ + (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0) + +#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) +COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb ); + +#endif /* Lua 5.1 and Lua 5.2 */ + + + +/* declarations for Lua 5.2 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 + +/* XXX not implemented: + * lua_isyieldable + * lua_arith (new operators) + * lua_pushfstring (new formats) + */ + +#define lua_getglobal(L, n) \ + (lua_getglobal((L), (n)), lua_type((L), -1)) + +#define lua_getuservalue(L, i) \ + (lua_getuservalue((L), (i)), lua_type((L), -1)) + +#define lua_rawgetp(L, i, p) \ + (lua_rawgetp((L), (i), (p)), lua_type((L), -1)) + +#define LUA_KFUNCTION(_name) \ + static int (_name)(lua_State *L, int status, lua_KContext ctx); \ + static int (_name ## _52)(lua_State *L) { \ + lua_KContext ctx; \ + int status = lua_getctx(L, &ctx); \ + return (_name)(L, status, ctx); \ + } \ + static int (_name)(lua_State *L, int status, lua_KContext ctx) + +#define lua_pcallk(L, na, nr, err, ctx, cont) \ + lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52) + +#define lua_callk(L, na, nr, ctx, cont) \ + lua_callk((L), (na), (nr), (ctx), cont ## _52) + +#define lua_yieldk(L, nr, ctx, cont) \ + lua_yieldk((L), (nr), (ctx), cont ## _52) + +#ifdef lua_call +# undef lua_call +# define lua_call(L, na, nr) \ + (lua_callk)((L), (na), (nr), 0, NULL) +#endif + +#ifdef lua_pcall +# undef lua_pcall +# define lua_pcall(L, na, nr, err) \ + (lua_pcallk)((L), (na), (nr), (err), 0, NULL) +#endif + +#ifdef lua_yield +# undef lua_yield +# define lua_yield(L, nr) \ + (lua_yieldk)((L), (nr), 0, NULL) +#endif + +#endif /* Lua 5.2 only */ + + + +/* other Lua versions */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504 + +# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)" + +#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */ + + + +/* helper macro for defining continuation functions (for every version + * *except* Lua 5.2) */ +#ifndef LUA_KFUNCTION +#define LUA_KFUNCTION(_name) \ + static int (_name)(lua_State *L, int status, lua_KContext ctx) +#endif + + +#if defined(COMPAT53_INCLUDE_SOURCE) +# include "compat-5.3.c" +#endif + + +#endif /* COMPAT53_H_ */ + From 7687bf663f281e764b8c848701e11ed81e4f097e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Fri, 3 Nov 2023 22:13:22 +0300 Subject: [PATCH 180/357] fix(docker): Use LuaJIT not Lua5.1 for docker builds --- hooks/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/build b/hooks/build index 065a6024b..609df1bc8 100755 --- a/hooks/build +++ b/hooks/build @@ -7,7 +7,7 @@ REVISION=$(git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g') RUNTIME_DEPS='fontconfig freetype2 gentium-plus-font glibc harfbuzz icu libpng luajit zlib'\ ' libertinus-font luarocks noto-fonts-cjk ttf-hack' -BUILD_DEPS='cargo git jq lua51 poppler' +BUILD_DEPS='cargo git jq poppler' : "${DOCKER_BUILDKIT:=1}" export DOCKER_BUILDKIT From 0594f6398108bac1e0694bc8a0f9a9c3cc33c171 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 2 Nov 2023 22:57:06 +0300 Subject: [PATCH 181/357] chore(build): Setup to build using compat53 instead of home-brewed shims --- Cargo.toml | 2 +- Makefile.am | 11 +++++++- justenough/Makefile.am | 42 +++++++++++++++---------------- justenough/compat-5.2.c | 21 ---------------- justenough/compat-5.2.h | 7 ------ justenough/fontmetrics.c | 3 ++- justenough/justenoughfontconfig.c | 3 ++- justenough/justenoughharfbuzz.c | 3 ++- justenough/justenoughicu.c | 3 ++- justenough/justenoughlibtexpdf.c | 3 ++- justenough/macfonts.m | 3 ++- justenough/svg.c | 3 ++- 12 files changed, 46 insertions(+), 58 deletions(-) delete mode 100644 justenough/compat-5.2.c delete mode 100644 justenough/compat-5.2.h diff --git a/Cargo.toml b/Cargo.toml index 04ed08bdd..daba63adb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ lto = true [dependencies.rust-embed] version = "8.0" optional = true - features = [ "include-exclude", "debug-embed" ] + features = [ "include-exclude" ] [dependencies.harfbuzz-sys] version = "0.5" diff --git a/Makefile.am b/Makefile.am index b8d715efb..437bdee2b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -88,6 +88,13 @@ Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) if EMBEDED_RESOURCES sile_SOURCES += src/embed.rs src/embed-includes.rs BUILT_SOURCES += src/embed.rs src/embed-includes.rs +$(CARGO_BIN): justenough/.libs/fontmetrics.a +$(CARGO_BIN): justenough/.libs/justenoughfontconfig.a +$(CARGO_BIN): justenough/.libs/justenoughharfbuzz.a +$(CARGO_BIN): justenough/.libs/justenoughicu.a +$(CARGO_BIN): justenough/.libs/justenoughlibtexpdf.a +$(CARGO_BIN): justenough/.libs/svg.a +$(CARGO_BIN): libtexpdf/.libs/libtexpdf.a src/embed-includes.rs: Makefile-distfiles { @@ -184,10 +191,12 @@ _DOCS_DEPS = $(and $$(filter documentation/%,$@),$(addprefix .fonts/,$(DOCSFONTF # TODO: remove _BUILT_SUBDIRS hack and replace it with something sensible when # these subdirs don't do crazy things like copying files outside of their own trees! _BUILT_SUBDIRS = .built-subdirs -_SUBDIR_TELLS = justenough/.libs/justenoughfontconfig.so \ +_SUBDIR_TELLS = justenough/.libs/fontmetrics.so \ + justenough/.libs/justenoughfontconfig.so \ justenough/.libs/justenoughharfbuzz.so \ justenough/.libs/justenoughicu.so \ justenough/.libs/justenoughlibtexpdf.so \ + justenough/.libs/svg.so \ libtexpdf/.libs/libtexpdf.so.0.0.0 $(_BUILT_SUBDIRS): $(_SUBDIR_TELLS) touch $@ diff --git a/justenough/Makefile.am b/justenough/Makefile.am index 2137d5a5c..db862d281 100644 --- a/justenough/Makefile.am +++ b/justenough/Makefile.am @@ -1,64 +1,64 @@ ACLOCAL_AMFLAGS = -I ../build-aux if LINKLUA -MY_LUA_LIB=$(LUA_LIB) -UNDEFINED=-no-undefined +MY_LUA_LIB = $(LUA_LIB) +UNDEFINED = -no-undefined else -MY_LUA_LIB= -UNDEFINED= +MY_LUA_LIB = +UNDEFINED = endif if SYSTEM_LIBTEXPDF -LIBTEXPDF_LIB=-ltexpdf +LIBTEXPDF_LIB = -ltexpdf else -LIBTEXPDF_LIB=../libtexpdf/libtexpdf.la +LIBTEXPDF_LIB = ../libtexpdf/libtexpdf.la endif -AM_CFLAGS = $(WARNING_CFLAGS) -I../libtexpdf +AM_CFLAGS = $(WARNING_CFLAGS) -I../libtexpdf -I./justenough/ AM_LDFLAGS = -module -avoid-version $(UNDEFINED) pkglib_LTLIBRARIES = justenoughharfbuzz.la -justenoughharfbuzz_la_SOURCES = justenoughharfbuzz.c hb-utils.c hb-utils.h +justenoughharfbuzz_la_SOURCES = justenoughharfbuzz.c hb-utils.c hb-utils.h compat-5.3.h justenoughharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -justenoughharfbuzz_la_CFLAGS = $(AM_CFLAGS) $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) +justenoughharfbuzz_la_CFLAGS = $(AM_CFLAGS) $(HARFBUZZ_CFLAGS) $(HARFBUZZ_SUBSET_CFLAGS) $(LUA_INCLUDE) $(COMPAT53_CFLAGS) justenoughharfbuzz_la_LIBADD = $(HARFBUZZ_LIBS) $(HARFBUZZ_SUBSET_LIBS) $(MY_LUA_LIB) pkglib_LTLIBRARIES += justenoughfontconfig.la -justenoughfontconfig_la_SOURCES = justenoughfontconfig.c silewin32.h +justenoughfontconfig_la_SOURCES = justenoughfontconfig.c silewin32.h compat-5.3.h justenoughfontconfig_la_LDFLAGS = $(AM_LDFLAGS) -justenoughfontconfig_la_CFLAGS = $(AM_CFLAGS) $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) +justenoughfontconfig_la_CFLAGS = $(AM_CFLAGS) $(FONTCONFIG_CFLAGS) $(LUA_INCLUDE) $(COMPAT53_CFLAGS) justenoughfontconfig_la_LIBADD = $(FONTCONFIG_LIBS) $(MY_LUA_LIB) if APPKIT pkglib_LTLIBRARIES += macfonts.la -macfonts_la_SOURCES = macfonts.m +macfonts_la_SOURCES = macfonts.m compat-5.3.h macfonts_la_LDFLAGS = $(AM_LDFLAGS) -macfonts_la_OBJCFLAGS = -U VERSION $(HARFBUZZ_CFLAGS) $(LUA_INCLUDE) -fmodules +macfonts_la_OBJCFLAGS = -U VERSION $(HARFBUZZ_CFLAGS) $(LUA_INCLUDE) -fmodules $(COMPAT53_CFLAGS) macfonts_la_LIBADD = $(HARFBUZZ_LIBS) $(MY_LUA_LIB) endif pkglib_LTLIBRARIES += justenoughlibtexpdf.la -justenoughlibtexpdf_la_SOURCES = justenoughlibtexpdf.c imagebbox.c +justenoughlibtexpdf_la_SOURCES = justenoughlibtexpdf.c imagebbox.c compat-5.3.h justenoughlibtexpdf_la_LDFLAGS = $(AM_LDFLAGS) -justenoughlibtexpdf_la_CFLAGS = $(AM_CFLAGS) $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) +justenoughlibtexpdf_la_CFLAGS = $(AM_CFLAGS) $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) $(LIBPAPER_INCLUDES) $(LUA_INCLUDE) $(COMPAT53_CFLAGS) justenoughlibtexpdf_la_LIBADD = $(LIBTEXPDF_LIB) $(LIBPNG_LIBS) $(ZLIB_LIBS) $(LIBPAPER_LIBS) $(MY_LUA_LIB) pkglib_LTLIBRARIES += fontmetrics.la -fontmetrics_la_SOURCES = fontmetrics.c hb-utils.c hb-utils.h +fontmetrics_la_SOURCES = fontmetrics.c hb-utils.c hb-utils.h compat-5.3.h fontmetrics_la_LDFLAGS = $(AM_LDFLAGS) -fontmetrics_la_CFLAGS = $(AM_CFLAGS) $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) +fontmetrics_la_CFLAGS = $(AM_CFLAGS) $(LUA_INCLUDE) $(HARFBUZZ_CFLAGS) $(COMPAT53_CFLAGS) fontmetrics_la_LIBADD = $(MY_LUA_LIB) $(HARFBUZZ_LIBS) pkglib_LTLIBRARIES += svg.la -svg_la_SOURCES = svg.c nanosvg.h +svg_la_SOURCES = svg.c nanosvg.h compat-5.3.h svg_la_LDFLAGS = $(AM_LDFLAGS) -svg_la_CFLAGS = $(AM_CFLAGS) $(LUA_INCLUDE) +svg_la_CFLAGS = $(AM_CFLAGS) $(LUA_INCLUDE) $(COMPAT53_CFLAGS) svg_la_LIBADD = $(MY_LUA_LIB) if ICU pkglib_LTLIBRARIES += justenoughicu.la -justenoughicu_la_SOURCES = justenoughicu.c +justenoughicu_la_SOURCES = justenoughicu.c compat-5.3.h justenoughicu_la_LDFLAGS = $(AM_LDFLAGS) -justenoughicu_la_CFLAGS = $(AM_CFLAGS) $(ICU_CFLAGS) $(LUA_INCLUDE) +justenoughicu_la_CFLAGS = $(AM_CFLAGS) $(ICU_CFLAGS) $(LUA_INCLUDE) $(COMPAT53_CFLAGS) justenoughicu_la_LIBADD = $(ICU_LIBS) $(MY_LUA_LIB) endif diff --git a/justenough/compat-5.2.c b/justenough/compat-5.2.c deleted file mode 100644 index e2f63a3bd..000000000 --- a/justenough/compat-5.2.c +++ /dev/null @@ -1,21 +0,0 @@ -#if LUA_VERSION_NUM == 501 - -#include "compat-5.2.h" - -void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup + 1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup + 1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable( - L, - -(nup + - 3)); /* table must be below the upvalues, the name and the closure */ - } - lua_pop(L, nup); /* remove upvalues */ -} - -#endif diff --git a/justenough/compat-5.2.h b/justenough/compat-5.2.h deleted file mode 100644 index cb8231c94..000000000 --- a/justenough/compat-5.2.h +++ /dev/null @@ -1,7 +0,0 @@ -#if LUA_VERSION_NUM==501 - -#define lua_rawlen lua_objlen - -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); - -#endif diff --git a/justenough/fontmetrics.c b/justenough/fontmetrics.c index 064f5efae..6ff556075 100644 --- a/justenough/fontmetrics.c +++ b/justenough/fontmetrics.c @@ -6,7 +6,8 @@ #include "hb-utils.h" -#include "compat-5.2.c" +// #define COMPAT53_PREFIX compat53 +#include "compat-5.3.h" int fm_get_typographic_extents (lua_State *L) { diff --git a/justenough/justenoughfontconfig.c b/justenough/justenoughfontconfig.c index 50c520612..91d1b5225 100644 --- a/justenough/justenoughfontconfig.c +++ b/justenough/justenoughfontconfig.c @@ -9,7 +9,8 @@ #include "silewin32.h" -#include "compat-5.2.c" +// #define COMPAT53_PREFIX compat53 +#include "compat-5.3.h" int je_face_from_options(lua_State* L) { FcChar8 * font_path, * fullname, * familyname; diff --git a/justenough/justenoughharfbuzz.c b/justenough/justenoughharfbuzz.c index ca2ce7540..4b274979d 100644 --- a/justenough/justenoughharfbuzz.c +++ b/justenough/justenoughharfbuzz.c @@ -15,7 +15,8 @@ #include "hb-utils.h" #include "silewin32.h" -#include "compat-5.2.c" +/* #define COMPAT53_PREFIX compat53 */ +#include "compat-5.3.h" /* The following function stolen from XeTeX_ext.c */ static hb_tag_t diff --git a/justenough/justenoughicu.c b/justenough/justenoughicu.c index 249fb622e..1788e34cf 100644 --- a/justenough/justenoughicu.c +++ b/justenough/justenoughicu.c @@ -17,7 +17,8 @@ #include "silewin32.h" -#include "compat-5.2.c" +// #define COMPAT53_PREFIX compat53 +#include "compat-5.3.h" typedef int32_t (*conversion_function_t)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode); diff --git a/justenough/justenoughlibtexpdf.c b/justenough/justenoughlibtexpdf.c index e8c2a5b2c..46a3d7a60 100644 --- a/justenough/justenoughlibtexpdf.c +++ b/justenough/justenoughlibtexpdf.c @@ -8,7 +8,8 @@ #include -#include "compat-5.2.c" +/* #define COMPAT53_PREFIX compat53 */ +#include "compat-5.3.h" pdf_doc *p = NULL; double height = 0.0; diff --git a/justenough/macfonts.m b/justenough/macfonts.m index 2bca54aec..d63850d47 100644 --- a/justenough/macfonts.m +++ b/justenough/macfonts.m @@ -7,7 +7,8 @@ #include #include -#include "compat-5.2.c" +// #define COMPAT53_PREFIX compat53 +#include "compat-5.3.h" #define MAX_NAME_LEN 512 diff --git a/justenough/svg.c b/justenough/svg.c index a8f0e6ebb..03fb49a0d 100644 --- a/justenough/svg.c +++ b/justenough/svg.c @@ -9,7 +9,8 @@ #define NANOSVG_IMPLEMENTATION // Expands implementation #include "nanosvg.h" -#include "compat-5.2.c" +/* #define COMPAT53_PREFIX compat53 */ +#include "compat-5.3.h" static char* safe_append(char* output, int* output_l, int* max_output, char* s2) { int append_len = strlen(s2) + 1; // strlen doesn't count \0 From ba2b15dcab49bb6dc655be5c9da6fe5681178de9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 18 Nov 2023 22:02:05 +0300 Subject: [PATCH 182/357] ci(actions): Expand build matrix with new embedded options --- .github/workflows/build.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e3f9e3af7..b1dff4f29 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,14 @@ concurrency: jobs: build-ubuntu: + strategy: + matrix: + configuration: + - [ 'dynamic', '' ] + - [ 'embeded', '--enable-embeded-resources' ] + - [ 'system', '--with-system-lua-sources' ] runs-on: ubuntu-22.04 + name: Build Ubuntu ${{ matrix.configuration[0] }} steps: - name: Checkout uses: actions/checkout@v4 @@ -41,7 +48,8 @@ jobs: ./bootstrap.sh ./configure \ --disable-font-variations \ - --with-manual + --with-manual \ + ${{ matrix.configuration[1] }} echo "VERSION=$(./build-aux/git-version-gen .tarball-version)" >> $GITHUB_ENV echo "MAKEFLAGS=-j$(nproc) -Otarget" >> $GITHUB_ENV - name: Make @@ -68,6 +76,7 @@ jobs: build-nix: runs-on: ubuntu-22.04 + name: Build Nix steps: - name: Checkout uses: actions/checkout@v4 From a32168d5ae215186169ce267277b3968e8f18086 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 18 Nov 2023 22:22:56 +0300 Subject: [PATCH 183/357] chore(build): Don't try to static link subsetter if not present --- Cargo.toml | 1 + Makefile.am | 4 ++++ build-aux/build.rs | 1 + 3 files changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index daba63adb..fa0e6157d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ lua51 = [ "mlua/lua51" ] luajit = [ "mlua/luajit" ] vendored = [ "mlua/vendored" ] static = [ "rust-embed" ] +variations = [] completions = [ "cli", "clap_complete" ] cli = [ "clap" ] bash = [ "completions" ] diff --git a/Makefile.am b/Makefile.am index 437bdee2b..5631cd1cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,6 +128,10 @@ if EMBEDED_RESOURCES CARGO_FEATURE_ARGS += --features static endif +if FONT_VARIATIONS +CARGO_FEATURE_ARGS += --features variations +endif + DEPDIR := .deps LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf LOCALPATHS := SILE_PATH="$(PWD);libtexpdf/.libs;justenough/.libs" diff --git a/build-aux/build.rs b/build-aux/build.rs index ab9ab8fc7..fdb215eb8 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -56,6 +56,7 @@ fn main() { // These are automatically linked by Cargo, but sadly *previous* to our links above println!("cargo:rustc-link-arg=-lharfbuzz"); // needed by justenoughharfbuzz + #[cfg(feature = "variations")] println!("cargo:rustc-link-arg=-lharfbuzz-subset"); // needed by justenoughharfbuzz println!("cargo:rustc-link-arg=-lfontconfig"); // needed by justenoughfontconfig println!("cargo:rustc-link-arg=-licui18n"); // needed by justenoughicu From a29a0997b6ab365698e79a5af12da662c6aeb9b3 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 18 Nov 2023 23:23:13 +0300 Subject: [PATCH 184/357] chore(build): Make sure new sources are included in dist --- Makefile.am | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5631cd1cc..23a68cdac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,6 +75,7 @@ EXTRA_DIST += Dockerfile build-aux/docker-bootstrap.sh build-aux/docker-fontconf EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) +EXTRA_DIST += src/embed.rs.in BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles @@ -86,8 +87,10 @@ Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ if EMBEDED_RESOURCES -sile_SOURCES += src/embed.rs src/embed-includes.rs -BUILT_SOURCES += src/embed.rs src/embed-includes.rs +_EMBEDED_SOURCES = src/embed.rs src/embed-includes.rs +nodist_sile_SOURCES = $(_EMBEDED_SOURCES) +BUILT_SOURCES += $(_EMBEDED_SOURCES) +CLEANFILES += $(_EMBEDED_SOURCES) $(CARGO_BIN): justenough/.libs/fontmetrics.a $(CARGO_BIN): justenough/.libs/justenoughfontconfig.a $(CARGO_BIN): justenough/.libs/justenoughharfbuzz.a From 7a833b0fd3d8fd21e7f7bb29a0d780c404eba9c2 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sun, 19 Nov 2023 19:18:04 +0100 Subject: [PATCH 185/357] refactor(inputters): Ensure inputter options are always a table Annoyingly, options passed to an inputter constructor can be nil, depending on how the inputter is invoked. Let's be more tolerant and safe in that case, initializing to an empty table. --- inputters/base.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inputters/base.lua b/inputters/base.lua index a00c67673..d19c9f206 100644 --- a/inputters/base.lua +++ b/inputters/base.lua @@ -12,7 +12,7 @@ inputter._name = "base" inputter._docclass = nil function inputter:_init (options) - if options then self.options = options end + self.options = options or {} end function inputter:classInit (options) From 34e2e533503d4ef72bf605c9012d192a2591ed8f Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sun, 19 Nov 2023 19:46:53 +0100 Subject: [PATCH 186/357] feat(utilities): Add Greek alphabetical (non-arithmetic) numbering Useful in some context such as biblical annotations etc. where greek characters are used orderly for numbering. --- core/utilities-numbers.lua | 27 ++++++++++++++++++++++++--- packages/counters/init.lua | 3 ++- spec/utilities_spec.lua | 17 +++++++++++++---- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/core/utilities-numbers.lua b/core/utilities-numbers.lua index 4eef0ea43..6bb6dd024 100644 --- a/core/utilities-numbers.lua +++ b/core/utilities-numbers.lua @@ -20,8 +20,29 @@ local formatNumber = { num = (num - num % 26) / 26 until num < 1 return out + end, + -- Greek is another special case: + -- There are books where one wants to number items with Greek letters in + -- sequence, e.g. annotations in biblical material etc. + -- as in "α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ τ υ φ χ ψ ω". + -- We can't use ICU "grek" or "greklow" numbering systems because they are + -- non-arithmetical, e.g. 6 is a digamma (ϝ´), 11 is iota alpha (ια´), etc. + -- and they are also all followed by a numeric marker ("keraia"). + greek = function(num) + local out = "" + local a = SU.codepoint("α") -- alpha + if num < 18 then + -- alpha to rho + out = luautf8.char(num + a - 1) + elseif num < 25 then + -- sigma to omega (unicode has two sigmas here, we skip one) + out = luautf8.char(num + a) + else + -- Don't try to be too clever + SU.error("Greek numbering is only supported up to 24") + end + return out end - } } @@ -113,7 +134,7 @@ setmetatable (formatNumber, { New syntax is SU.formatNumber(num, options[, case]) with an options table, possibly containing: - system: a numbering system string, e.g. "latn" (= "arabic"), "roman", "arab", etc. - With the addition of "alpha". + With the addition of "alpha" and "greek". Casing is taken into account (e.g. roman, Roman, ROMAN) unless specified - style: a format style string, i.e. "default", "decimal", "ordinal", "string") E.g. in English and latin script: 1234 1,234 1,124th one thousand... @@ -176,7 +197,7 @@ setmetatable (formatNumber, { -- Global specific hooks exists: use them... result = self.und[system](num, options) elseif system and type(self["und"][system]) == "function" then - -- TRICK: Notably, special case for "alpha" + -- TRICK: Notably, special case for "alpha" and "greek" result = system and self.und[system](num, options) else --- Otherwise, rely on ICU... diff --git a/packages/counters/init.lua b/packages/counters/init.lua index 9f8b57c5f..be390896c 100644 --- a/packages/counters/init.lua +++ b/packages/counters/init.lua @@ -217,7 +217,8 @@ The available built-in display types are: \item{\code{alpha}, for lower-case alphabetic counting} \item{\code{Alpha}, for upper-case alphabetic counting} \item{\code{roman}, for lower-case Roman numerals} -\item{\code{ROMAN} for upper-case Roman numerals} +\item{\code{ROMAN}, for upper-case Roman numerals} +\item{\code{greek}, for Greek letters in alphabetical order (not Greek numerals)} \end{itemize} The ICU library also provides ways of formatting numbers in global (non-Latin) scripts. diff --git a/spec/utilities_spec.lua b/spec/utilities_spec.lua index 8c3747286..387222db6 100644 --- a/spec/utilities_spec.lua +++ b/spec/utilities_spec.lua @@ -149,25 +149,34 @@ describe("SILE.utilities", function() assert.is.equal("2", SU.formatNumber(2, { system = "arabic" })) end) - it("should format roman number", function () + it("should format roman numbers", function () assert.is.equal("mcmlxxxiv", SU.formatNumber(1984, { system = "roman" })) end) - it("should format ROMAN number", function () + it("should format ROMAN numbers", function () assert.is.equal("MCMLXXXIV", SU.formatNumber(1984, { system = "ROMAN" })) end) - it("should format alpha number", function () + it("should format alpha numbers", function () assert.is.equal("b", SU.formatNumber(2, { system = "alpha" })) end) - it("should format ALPHA number", function () + it("should format ALPHA numbers", function () assert.is.equal("B", SU.formatNumber(2, { system = "Alpha" })) end) it("should format 'arab' numbers", function () assert.is.equal("٢", SU.formatNumber(2, { system = "arab" })) end) + + it("should format greek numbers", function () + assert.is.equal("β", SU.formatNumber(2, { system = "greek" })) + end) + + it("should format GREEK numbers", function () + assert.is.equal("Β", SU.formatNumber(2, { system = "Greek" })) + end) + end) end) From 0c1c017c05a8c197dd5120afea2f769ffc5c89be Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sun, 19 Nov 2023 18:15:41 +0100 Subject: [PATCH 187/357] feat(classes)!: Support emphasis nesting BREAKING CHANGE: The former implementation of the "em" command did not support nesting and was just setting the font style to italic. The command now alternates italic and regular when nested. --- classes/plain.lua | 8 +++++--- documentation/c03-input.sil | 2 +- documentation/c04-useful.sil | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/classes/plain.lua b/classes/plain.lua index 12ef08f95..8a84904ef 100644 --- a/classes/plain.lua +++ b/classes/plain.lua @@ -236,12 +236,14 @@ function class:registerCommands () end) self:registerCommand("em", function (_, content) - SILE.call("font", { style = "Italic" }, content) - end) + local style = SILE.settings:get("font.style") + local toggle = (style and style:lower() == "italic") and "Regular" or "Italic" + SILE.call("font", { style = toggle }, content) + end, "Emphasizes its contents by switching the font style to italic (or back to regular if already italic)") self:registerCommand("strong", function (_, content) SILE.call("font", { weight = 700 }, content) - end) + end, "Sets the font weight to bold (700)") self:registerCommand("code", function (options, content) -- IMPLEMENTATION NOTE: diff --git a/documentation/c03-input.sil b/documentation/c03-input.sil index 3151e7f94..79f4eedb3 100644 --- a/documentation/c03-input.sil +++ b/documentation/c03-input.sil @@ -191,7 +191,7 @@ Here are a few more examples of SILE commands: \end{raw}% \section{Environments} -Commands like \autodoc:command{\chapter} (to start a chapter) and \autodoc:command{\em} (to emphasise text by making it italic) are normally used to enclose a relatively small piece of text—a few lines at most. +Commands like \autodoc:command{\chapter} (to start a chapter) and \autodoc:command{\em} (to emphasise text) are normally used to enclose a relatively small piece of text—a few lines at most. Where you want to enclose a larger piece of the document, you can use an \em{environment}. An environment begins with \code{\\begin\{\em{name}\}} and encloses all the text up until the corresponding \code{\\end\{\em{name}\}}. We’ve already seen an example: the \autodoc:environment[check=false]{document} environment, which must enclose the \em{entire} document. diff --git a/documentation/c04-useful.sil b/documentation/c04-useful.sil index c4ffacd3c..709f7b456 100644 --- a/documentation/c04-useful.sil +++ b/documentation/c04-useful.sil @@ -83,7 +83,7 @@ The full list of attributes to the \autodoc:command{\font} command are: It’s quite fiddly to be always changing font specifications manually; later we’ll see some ways to automate the process. -SILE’s \autodoc:class{plain} class notably provides the \autodoc:command{\em{…}} command as a shortcut for \autodoc:command{\font[style=italic]{…}}, and the \autodoc:command{\strong{…}} command as a a shortcut for \autodoc:command{\font[weight=700]{…}}. +SILE’s \autodoc:class{plain} class notably provides the \autodoc:command{\strong{…}} command as a a shortcut for \autodoc:command{\font[weight=700]{…}}, and the \autodoc:command{\em{…}} to emphasize text (switching between italic or regular style as needed). Note for parameters that accept multiple values, values may be separated with commas. Be sure to wrap the value in quotes so the commas don't get parsed as new parameters. From 624e3a8888c173497b39c13460604ce55d42ded0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Thu, 12 Oct 2023 00:02:26 +0300 Subject: [PATCH 188/357] feat(packages)!: Use OpenType +ruby feature for ruby, toggle with setting BREAKING CHANGE: The default rendering of Ruby readings has changed from just using a bold weight to using the OpenType +ruby feature. Fonts that support this should work with no change, but documents rendered in fonts that do not support it will neet to set the `ruby.opentype` feature to `false` to get the same rendering method as before. --- packages/ruby/init.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/ruby/init.lua b/packages/ruby/init.lua index 0da12ec66..98d64f0ca 100644 --- a/packages/ruby/init.lua +++ b/packages/ruby/init.lua @@ -51,12 +51,23 @@ function package.declareSettings (_) help = "Glue added between consecutive Latin ruby" }) + SILE.settings:declare({ + parameter = "ruby.opentype", + type = "boolean", + default = true, + help = "Use OpenType tate feature instead of of a bold weight" + }) + end function package:registerCommands () self:registerCommand("ruby:font", function (_, _) - SILE.call("font", { size = "0.6zw", weight = 800 }) + if SILE.settings:get("ruby.opentype") then + SILE.call("font", { size = "0.6zw", features = "+ruby" }) + else + SILE.call("font", { size = "0.6zw", weight = 700 }) + end end) self:registerCommand("ruby", function (options, content) From 433fcdc0f3fc5baed38f07f43c8f256de923454a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 21 Nov 2023 09:17:15 +0300 Subject: [PATCH 189/357] test(packages): Update tests to reflect lack of +ruby feature in font --- tests/bug-524.expected | 2 +- tests/bug-524.sil | 1 + tests/bug-525.expected | 12 ++++++------ tests/bug-525.sil | 1 + tests/bug-926.expected | 12 ++++++------ tests/bug-926.sil | 1 + 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/bug-524.expected b/tests/bug-524.expected index 73ff2a2cd..81d11b92f 100644 --- a/tests/bug-524.expected +++ b/tests/bug-524.expected @@ -1605,7 +1605,7 @@ Mx 59.5278 T 1506 w=10.0000 (は) Mx 51.7739 My 129.9592 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 56 w=5.2680 (W) Mx 49.4079 My 139.9592 diff --git a/tests/bug-524.sil b/tests/bug-524.sil index ed2381bc6..f851dca04 100644 --- a/tests/bug-524.sil +++ b/tests/bug-524.sil @@ -3,6 +3,7 @@ \neverindent \show-hanmen \use[module=packages.ruby] +\set[parameter=ruby.opentype,value=false] 私は {}私は diff --git a/tests/bug-525.expected b/tests/bug-525.expected index a0b19a1d6..edba4e9c8 100644 --- a/tests/bug-525.expected +++ b/tests/bug-525.expected @@ -2,7 +2,7 @@ Set paper size 297.6377985 419.5275636 Begin page Mx 24.7039 My 46.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 20220 w=6.0000 (日) Mx 30.8207 T 20758 w=6.0000 (本) @@ -15,7 +15,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 42.9375 My 46.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 45 w=3.2580 (L) Mx 46.3123 Mx 3.2940 @@ -33,7 +33,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 24.7039 My 63.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 45 w=3.2580 (L) Mx 28.0787 Mx 3.2940 @@ -51,7 +51,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 39.3011 My 63.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 20220 w=6.0000 (日) Mx 45.4179 T 20758 w=6.0000 (本) @@ -64,7 +64,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 24.7039 My 80.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 45 w=3.2580 (L) Mx 28.0790 Mx 3.2940 @@ -82,7 +82,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 41.8022 My 80.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 45 w=3.2580 (L) Mx 45.1773 Mx 3.2940 diff --git a/tests/bug-525.sil b/tests/bug-525.sil index 600f37cf1..3a0ee4c1c 100644 --- a/tests/bug-525.sil +++ b/tests/bug-525.sil @@ -2,6 +2,7 @@ \nofolios \neverindent \use[module=packages.ruby] +\set[parameter=ruby.opentype,value=false] \ruby[reading=日本語]{私}\ruby[reading=Latin]{私} \ruby[reading=Latin]{私}\ruby[reading=日本語]{私} diff --git a/tests/bug-926.expected b/tests/bug-926.expected index 9d7210dee..4c5125164 100644 --- a/tests/bug-926.expected +++ b/tests/bug-926.expected @@ -2,7 +2,7 @@ Set paper size 297.6377985 419.5275636 Begin page Mx 24.7039 My 46.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 20220 w=6.0000 (日) Mx 30.7039 T 20758 w=6.0000 (本) @@ -15,7 +15,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 42.7039 My 46.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR Mx 3.2580 Mx 3.2940 Mx 2.2620 @@ -29,7 +29,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 24.7039 My 63.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR Mx 3.2580 Mx 3.2940 Mx 2.2620 @@ -43,7 +43,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 38.8339 My 63.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR T 20220 w=6.0000 (日) Mx 44.8339 T 20758 w=6.0000 (本) @@ -56,7 +56,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 24.7039 My 80.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR Mx 3.2580 Mx 3.2940 Mx 2.2620 @@ -70,7 +70,7 @@ Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 29078 w=10.0000 (私) Mx 41.3339 My 80.9652 -Set font Noto Sans CJK JP;6;800;;normal;;;LTR +Set font Noto Sans CJK JP;6;700;;normal;;;LTR Mx 3.2580 Mx 3.2940 Mx 2.2620 diff --git a/tests/bug-926.sil b/tests/bug-926.sil index 15b355e3d..5d85584f9 100644 --- a/tests/bug-926.sil +++ b/tests/bug-926.sil @@ -3,6 +3,7 @@ \neverindent \language[main=en] \use[module=packages.ruby] +\set[parameter=ruby.opentype,value=false] \ruby[reading=日本語]{私}\ruby[reading=Latin]{私} \ruby[reading=Latin]{私}\ruby[reading=日本語]{私} From c6559b55146a9241cd250de69087e2ee73e376f0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 21 Nov 2023 11:26:04 +0300 Subject: [PATCH 190/357] test(packages): Add test covering OT +ruby feature --- Makefile-fonts | 5 +++++ tests/bug-1047.expected | 17 +++++++++++++++++ tests/bug-1047.sil | 10 ++++++++++ 3 files changed, 32 insertions(+) create mode 100644 tests/bug-1047.expected create mode 100644 tests/bug-1047.sil diff --git a/Makefile-fonts b/Makefile-fonts index 57cb88644..59b35676b 100644 --- a/Makefile-fonts +++ b/Makefile-fonts @@ -34,6 +34,7 @@ TESTFONTFILES = $(DOCSFONTFILES) TESTFONTFILES += Amiri-Regular.ttf TESTFONTFILES += AmiriQuran.ttf TESTFONTFILES += AwamiNastaliq-Regular.ttf +TESTFONTFILES += FRBTaiwaneseKana.otf TESTFONTFILES += LibertinusSans-Bold.otf TESTFONTFILES += NotoNaskhArabic-Regular.ttf TESTFONTFILES += NotoSansKannada-Regular.ttf @@ -73,6 +74,10 @@ notobase = $(shell echo $(notdir $1) | sed -e 's/-.*//') .fonts/TwemojiMozilla.ttf: | .fonts $(CURL) -fsSL https://github.com/mozilla/twemoji-colr/releases/download/v0.5.1/$(notdir $@) -o $@ +.fonts/FRBTaiwaneseKana.otf: | .fonts + : $(CURL) -fsSL https://github.com/ctrlcctrlv/FRBTaiwaneseKana/releases/download/v1.1/$(notdir $@) -o $@ + $(CURL) -fsSL https://raw.githubusercontent.com/ctrlcctrlv/FRBTaiwaneseKana/5c367e9ee5aefd54b5c9c9e996705f0561fe3d15/$(notdir $@) -o $@ + # Tell make how to download font file bundles (when not downloadable individually) .sources/AwamiNastaliq-2.200.zip: | .sources diff --git a/tests/bug-1047.expected b/tests/bug-1047.expected new file mode 100644 index 000000000..1328ef990 --- /dev/null +++ b/tests/bug-1047.expected @@ -0,0 +1,17 @@ +Set paper size 297.6377985 419.5275636 +Begin page +Mx 24.7039 +My 42.3452 +Set font FRB Taiwanese Kana;24;400;;normal;+ruby;;LTR +T 172 w=24.0000 (タ) +Mx 48.7039 +T 145 w=24.0000 (イ) +Mx 72.7039 +T 122 w=12.0000 (𚿳) +Mx 24.7039 +My 82.3452 +Mx 34.7039 +Set font Noto Serif CJK TC;40;400;;normal;;;LTR +T 34119 w=40.0000 (臺) +End page +Finish diff --git a/tests/bug-1047.sil b/tests/bug-1047.sil new file mode 100644 index 000000000..dd07fbbaa --- /dev/null +++ b/tests/bug-1047.sil @@ -0,0 +1,10 @@ +\begin[class=jplain,papersize=a6]{document} +\nofolios +\neverindent +\language[main=zh] +\use[module=packages.ruby] +\font:remove-fallback +\font:add-fallback[family=Noto Serif CJK TC] +\font[family=FRB Taiwanese Kana,size=40pt] +\ruby[reading=タイ𚿳]{臺} +\end{document} From 3e4e8c68c86d7e047c949e0081bcac3e62ad7262 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Wed, 6 Dec 2023 20:20:37 +0300 Subject: [PATCH 191/357] chore(build): Fix included Makefile to run even on BSD without .ONESHELL --- build-aux/rust_boilerplate.mk.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/rust_boilerplate.mk.in index fc61df56d..fd139b466 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/rust_boilerplate.mk.in @@ -57,7 +57,7 @@ $(_RUST_OUT) $(CARGO_BIN): $(@PACKAGE_VAR@_SOURCES) $(EXTRA_@PACKAGE_VAR@_SOURCE set -e export AUTOTOOLS_DEPENDENCIES="$^" $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) - $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | + $(CARGO_ENV) $(CARGO) build --quiet --message-format=json $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) | \ $(JQ) -sr 'map(select(.reason == "build-script-executed")) | last | .out_dir' > $(_RUST_OUT) RUST_DEVELOPER_TARGETS = cargo-test clippy rustfmt From fc7e7fbaad05b37aef573e10058209ca0eb8d123 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Tue, 21 Nov 2023 12:20:51 +0100 Subject: [PATCH 192/357] feat(utilities)!: Refactor and extend AST-handling utilities BREAKING CHANGE: For modules that rely on `SILE.utilities` (`SU`), and in particular raw content handling functions `subContent()`, `walkContent()`, `stripContentPos()`, `hasContent()`, and `contentToString()`, these and similar functions have been moved into `SILE.utilities.ast` (`SU.ast`). The `subContent()` implementation also no longer adds id="stuff" attributes to everything. --- classes/base.lua | 20 +-- classes/book.lua | 2 +- core/font.lua | 4 +- core/languages.lua | 2 +- core/utilities-ast.lua | 213 ++++++++++++++++++++++++++++++ core/utilities.lua | 93 ++++--------- documentation/c10-classdesign.sil | 2 +- documentation/c12-xmlproc.sil | 6 +- inputters/base.lua | 8 +- inputters/xml.lua | 21 +-- packages/autodoc/init.lua | 2 +- packages/bibtex/init.lua | 4 +- packages/inputfilter/init.lua | 10 +- packages/tableofcontents/init.lua | 4 +- typesetters/base.lua | 2 +- 15 files changed, 276 insertions(+), 117 deletions(-) create mode 100644 core/utilities-ast.lua diff --git a/classes/base.lua b/classes/base.lua index 7c7768bd3..90c42066a 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -334,7 +334,7 @@ function class:registerCommands () self:registerCommand("script", function (options, content) local packopts = packOptions(options) - if SU.hasContent(content) then + if SU.ast.hasContent(content) then return SILE.processString(content[1], options.format or "lua", nil, packopts) elseif options.src then return SILE.require(options.src) @@ -346,8 +346,8 @@ function class:registerCommands () self:registerCommand("include", function (options, content) local packopts = packOptions(options) - if SU.hasContent(content) then - local doc = SU.contentToString(content) + if SU.ast.hasContent(content) then + local doc = SU.ast.contentToString(content) return SILE.processString(doc, options.format, nil, packopts) elseif options.src then return SILE.processFile(options.src, options.format, packopts) @@ -358,8 +358,8 @@ function class:registerCommands () self:registerCommand("lua", function (options, content) local packopts = packOptions(options) - if SU.hasContent(content) then - local doc = SU.contentToString(content) + if SU.ast.hasContent(content) then + local doc = SU.ast.contentToString(content) return SILE.processString(doc, "lua", nil, packopts) elseif options.src then return SILE.processFile(options.src, "lua", packopts) @@ -373,8 +373,8 @@ function class:registerCommands () self:registerCommand("sil", function (options, content) local packopts = packOptions(options) - if SU.hasContent(content) then - local doc = SU.contentToString(content) + if SU.ast.hasContent(content) then + local doc = SU.ast.contentToString(content) return SILE.processString(doc, "sil") elseif options.src then return SILE.processFile(options.src, "sil", packopts) @@ -385,8 +385,8 @@ function class:registerCommands () self:registerCommand("xml", function (options, content) local packopts = packOptions(options) - if SU.hasContent(content) then - local doc = SU.contentToString(content) + if SU.ast.hasContent(content) then + local doc = SU.ast.contentToString(content) return SILE.processString(doc, "xml", nil, packopts) elseif options.src then return SILE.processFile(options.src, "xml", packopts) @@ -398,7 +398,7 @@ function class:registerCommands () self:registerCommand("use", function (options, content) local packopts = packOptions(options) if content[1] and string.len(content[1]) > 0 then - local doc = SU.contentToString(content) + local doc = SU.ast.contentToString(content) SILE.processString(doc, "lua", nil, packopts) else if options.src then diff --git a/classes/book.lua b/classes/book.lua index 20a0290d2..44fe28710 100644 --- a/classes/book.lua +++ b/classes/book.lua @@ -105,7 +105,7 @@ function class:registerCommands () number = self.packages.counters:formatMultilevelCounter(self:getMultilevelCounter("sectioning")) end if SU.boolean(options.toc, true) then - SILE.call("tocentry", { level = level, number = number }, SU.subContent(content)) + SILE.call("tocentry", { level = level, number = number }, SU.ast.subContent(content)) end if SU.boolean(options.numbering, true) then if options.msg then diff --git a/core/font.lua b/core/font.lua index eb822817a..10a059e41 100644 --- a/core/font.lua +++ b/core/font.lua @@ -3,7 +3,7 @@ local icu = require("justenoughicu") local lastshaper SILE.registerCommand("font", function (options, content) - if SU.hasContent(content) then SILE.settings:pushState() end + if SU.ast.hasContent(content) then SILE.settings:pushState() end if options.filename then SILE.settings:set("font.filename", options.filename) end if options.family then SILE.settings:set("font.family", options.family) @@ -49,7 +49,7 @@ SILE.registerCommand("font", function (options, content) -- that the post-load hook might want to do. SILE.font.cache(SILE.font.loadDefaults({}), SILE.shaper.getFace) - if SU.hasContent(content) then + if SU.ast.hasContent(content) then SILE.process(content) SILE.settings:popState() if SILE.shaper._name == "harfbuzzWithColor" and lastshaper then diff --git a/core/languages.lua b/core/languages.lua index fd084fdd1..180ff7104 100644 --- a/core/languages.lua +++ b/core/languages.lua @@ -81,7 +81,7 @@ SILE.registerCommand("ftl", function (options, content) fluent:set_locale(locale) if options.src then fluent:load_file(options.src, locale) - elseif SU.hasContent(content) then + elseif SU.ast.hasContent(content) then local input = content[1] fluent:add_messages(input, locale) end diff --git a/core/utilities-ast.lua b/core/utilities-ast.lua new file mode 100644 index 000000000..b1c4e6d25 --- /dev/null +++ b/core/utilities-ast.lua @@ -0,0 +1,213 @@ +--- SILE AST utilities +-- +local ast = {} + +--- Find a command node in a SILE AST tree, +--- looking only at the first level. +--- (We're not reimplementing XPath here.) +---@param tree table AST tree +---@param command string command name +---@return table|nil AST command node +function ast.findInTree (tree, command) + for i=1, #tree do + if type(tree[i]) == "table" and tree[i].command == command then + return tree[i] + end + end +end + +--- Find and extract (remove) a command node in a SILE AST tree, +--- looking only at the first level. +---@param tree table AST tree +---@param command string command name +---@return table|nil AST command node +function ast.removeFromTree (tree, command) + for i=1, #tree do + if type(tree[i]) == "table" and tree[i].command == command then + return table.remove(tree, i) + end + end +end + +--- Create a command from a simple content tree. +--- It encapsulates the content in a command node. +---@param command string command name +---@param options table command options +---@param content table child AST tree +---@param position table position in source (or parent AST command node) +---@return table AST command node +function ast.createCommand (command, options, content, position) + local result = { content } + result.options = options or {} + result.command = command + result.id = "command" + if position then + result.col = position.col or 0 + result.lno = position.lno or 0 + result.pos = position.pos or 0 + else + result.col = 0 + result.lno = 0 + result.pos = 0 + end + return result +end + +--- Create a command from a structured content tree. +--- The content is normally a table of an already prepared content list. +---@param command string command name +---@param options table command options +---@param content table child AST tree +---@param position table position in source (or parent AST command node) +---@return table AST command node +function ast.createStructuredCommand (command, options, content, position) + local result = type(content) == "table" and content or { content } + result.options = options or {} + result.command = command + result.id = "command" + if position then + result.col = position.col or 0 + result.lno = position.lno or 0 + result.pos = position.pos or 0 + else + result.col = 0 + result.lno = 0 + result.pos = 0 + end + return result +end + +--- Extract the sub-content tree from a (command) node, +--- that is the child nodes of the (command) node. +---@param content table AST tree +---@return table AST tree +function ast.subContent (content) + local out = {} + for _, val in ipairs(content) do + out[#out+1] = val + end + return out +end + +-- String trimming +local function trimLeft (str) + return str:gsub("^%s*", "") +end +local function trimRight (str) + return str:gsub("%s*$", "") +end + +--- Content tree trimming: remove leading and trailing spaces, but from +--- a content tree i.e. possibly containing several elements. +---@param content table AST tree +---@return table AST tree +function ast.trimSubContent (content) + if #content == 0 then + return + end + if type(content[1]) == "string" then + content[1] = trimLeft(content[1]) + if content[1] == "" then + table.remove(content, 1) + end + end + if type(content[#content]) == "string" then + content[#content] = trimRight(content[#content]) + if content[#content] == "" then + table.remove(content, #content) + end + end + return content +end + +--- Process the AST walking through content nodes as a "structure": +--- Text nodes are ignored (e.g. usually just spaces due to indentation) +--- Command options are enriched with their "true" node position, so we can later +--- refer to it (as with an XPath pos()). +---@param content table AST tree +function ast.processAsStructure (content) + local iElem = 0 + local nElem = 0 + for i = 1, #content do + if type(content[i]) == "table" then + nElem = nElem + 1 + end + end + for i = 1, #content do + if type(content[i]) == "table" then + iElem = iElem + 1 + content[i].options._pos_ = iElem + content[i].options._last_ = iElem == nElem + SILE.process({ content[i] }) + end + -- All text nodes in ignored in structure tags. + end +end + +--- Call `action` on each content AST node, recursively, including `content` itself. +--- Not called on leaves, i.e. strings. +---@param content table AST tree +---@param action function function to call on each node +function ast.walkContent (content, action) + if type(content) ~= "table" then + return + end + action(content) + for i = 1, #content do + ast.walkContent(content[i], action) + end +end + +--- Strip position, line and column recursively from a content tree. +--- This can be used to remove position details where we do not want them, +--- e.g. in table of contents entries (referring to the original content, +--- regardless where it was exactly, for the purpose of checking whether +--- the table of contents changed.) +---@param content table AST tree +---@return table AST tree +function ast.stripContentPos (content) + if type(content) ~= "table" then + return content + end + local stripped = {} + for k, v in pairs(content) do + if type(v) == "table" then + v = ast.stripContentPos(v) + end + stripped[k] = v + end + if content.id or content.command then + stripped.pos, stripped.col, stripped.lno = nil, nil, nil + end + return stripped +end + +--- Flatten content trees into just the string components (allows passing +--- objects with complex structures to functions that need plain strings) +--- @param content table AST tree +--- @return string string representation of content +function ast.contentToString (content) + local string = "" + for i = 1, #content do + if type(content[i]) == "table" and type(content[i][1]) == "string" then + string = string .. content[i][1] + elseif type(content[i]) == "string" then + -- Work around PEG parser returning env tags as content + -- TODO: refactor capture groups in PEG parser + if content.command == content[i] and content[i] == content[i+1] then + break + end + string = string .. content[i] + end + end + return string +end + +--- Check whether a content AST tree is empty. +---@param content table AST tree +---@return boolean true if content is not empty +function ast.hasContent (content) + return type(content) == "function" or type(content) == "table" and #content > 0 +end + +return ast diff --git a/core/utilities.lua b/core/utilities.lua index 05bef5ad3..031f961c8 100644 --- a/core/utilities.lua +++ b/core/utilities.lua @@ -343,76 +343,6 @@ utilities.cast = function (wantedType, value) end end -utilities.hasContent = function(content) - return type(content) == "function" or type(content) == "table" and #content > 0 -end - --- Flatten content trees into just the string components (allows passing --- objects with complex structures to functions that need plain strings) -utilities.contentToString = function (content) - local string = "" - for i = 1, #content do - if type(content[i]) == "table" and type(content[i][1]) == "string" then - string = string .. content[i][1] - elseif type(content[i]) == "string" then - -- Work around PEG parser returning env tags as content - -- TODO: refactor capture groups in PEG parser - if content.command == content[i] and content[i] == content[i+1] then - break - end - string = string .. content[i] - end - end - return string -end - --- Strip the top level command off a content object and keep only the child --- items — assuming that the current command is taking care of itself -utilities.subContent = function (content) - local out = { id="stuff" } - for key, val in utilities.sortedpairs(content) do - if type(key) == "number" then - out[#out+1] = val - end - end - return out -end - --- Call `action` on each content AST node, recursively, including `content` itself. --- Not called on leaves, i.e. strings. -utilities.walkContent = function (content, action) - if type(content) ~= "table" then - return - end - action(content) - for i = 1, #content do - utilities.walkContent(content[i], action) - end -end - ---- Strip position, line and column recursively from a content tree. --- This can be used to remove position details where we do not want them, --- e.g. in table of contents entries (referring to the original content, --- regardless where it was exactly, for the purpose of checking whether --- the table of contents changed.) --- -utilities.stripContentPos = function (content) - if type(content) ~= "table" then - return content - end - local stripped = {} - for k, v in pairs(content) do - if type(v) == "table" then - v = SU.stripContentPos(v) - end - stripped[k] = v - end - if content.id or content.command then - stripped.pos, stripped.col, stripped.lno = nil, nil, nil - end - return stripped -end - utilities.rateBadness = function(inf_bad, shortfall, spring) if spring == 0 then return inf_bad end local bad = math.floor(100 * math.abs(shortfall / spring) ^ 3) @@ -630,4 +560,27 @@ utilities.formatNumber = require("core.utilities-numbers") utilities.collatedSort = require("core.utilities-sorting") +utilities.ast = require("core.utilities-ast") +utilities.subContent = function (content) + SU.deprecated("SU.subContent", "SU.ast.subContent", "0.15.0", "0.17.0", [[ + Note that the new implementation no longer introduces an id="stuff" key.]]) + return utilities.ast.subContent(content) +end +utilities.hasContent = function(content) + SU.deprecated("SU.hasContent", "SU.ast.hasContent", "0.15.0", "0.17.0") + return SU.ast.hasContent(content) +end +utilities.contentToString = function (content) + SU.deprecated("SU.contentToString", "SU.ast.contentToString", "0.15.0", "0.17.0") + return SU.ast.contentToString(content) +end +utilities.walkContent = function (content, action) + SU.deprecated("SU.walkContent", "SU.ast.walkContent", "0.15.0", "0.17.0") + SU.ast.walkContent(content, action) +end +utilities.stripContentPos = function (content) + SU.deprecated("SU.stripContentPos", "SU.ast.stripContentPos", "0.15.0", "0.17.0") + return SU.ast.stripContentPos(content) +end + return utilities diff --git a/documentation/c10-classdesign.sil b/documentation/c10-classdesign.sil index 2a45581c0..e76514128 100644 --- a/documentation/c10-classdesign.sil +++ b/documentation/c10-classdesign.sil @@ -458,7 +458,7 @@ self:registerCommand("tocentry", function (options, content) SILE.call("info", { category = "toc", value = { - label = SU.stripContentPos(content), level = (options.level or 1) + label = SU.ast.stripContentPos(content), level = (options.level or 1) } }) end) diff --git a/documentation/c12-xmlproc.sil b/documentation/c12-xmlproc.sil index 4fc557dc3..409d58bea 100644 --- a/documentation/c12-xmlproc.sil +++ b/documentation/c12-xmlproc.sil @@ -69,10 +69,10 @@ self:registerCommand("example", function(options,content) \code{\\docbook-titling} is a command similarly defined in \code{docbook.sil} which sets the default font for titling and headers. Once again, if someone wants to customize the look of the output we make it easier for them by giving them simple, compartmentalized commands to override. So far so good, but how do we extract the \code{} tag from the \code{content} abstract syntax tree? -SILE does not provide XPath or CSS-style selectors to locate content form within the DOM tree;\footnote{Patches, as they say, are welcome.} instead there is a simple one-level function called \code{SILE.inputter:findInTree()} which looks for a particular tag or command name within the immediate children of the current tree: +SILE does not provide XPath or CSS-style selectors to locate content form within the DOM tree;\footnote{Patches, as they say, are welcome.} instead there is a simple one-level function called \code{SU.ast.findInTree()} which looks for a particular tag or command name within the immediate children of the current tree: \begin[type=autodoc:codeblock]{raw} - local t = SILE.inputter:findInTree(content, "title") + local t = SU.ast.findInTree(content, "title") if t then SILE.typesetter:typeset(": ") SILE.process(t) @@ -149,7 +149,7 @@ We also increment the count at the current level, while at the same time wiping Now we find the title, and prefix it by the concatenation of all the \code{seccount}s: \begin[type=autodoc:codeblock]{raw} - local title = SILE.inputter:findInTree(content, "title") + local title = SU.ast.findInTree(content, "title") local number = table.concat(SILE.scratch.docbook.seccount, '.') if title then SILE.call("docbook-section-"..SILE.scratch.docbook.seclevel.."-title",{},function() diff --git a/inputters/base.lua b/inputters/base.lua index d19c9f206..a72d86c38 100644 --- a/inputters/base.lua +++ b/inputters/base.lua @@ -49,13 +49,9 @@ function inputter:process (doc) return SILE.process(tree) end --- Just a simple one-level find. We're not reimplementing XPath here. function inputter.findInTree (_, tree, command) - for i=1, #tree do - if type(tree[i]) == "table" and tree[i].command == command then - return tree[i] - end - end + SU.deprecated("SILE.inputter:findInTree", "SU.ast.findInTree", "0.15.0", "0.17.0") + return SU.ast.findInTree(tree, command) end local function process_ambles (ambles) diff --git a/inputters/xml.lua b/inputters/xml.lua index 3c019b934..b448bf7da 100644 --- a/inputters/xml.lua +++ b/inputters/xml.lua @@ -8,8 +8,10 @@ inputter.order = 2 local function startcommand (parser, command, options) local stack = parser:getcallbacks().stack - local lno, col, _ = parser:pos() - local element = { command = command, options = options, lno = lno, col = col } + local lno, col, pos = parser:pos() + local position = { lno = lno, col = col, pos = pos } + -- create an empty command which content will be filled on closing tag + local element = SU.ast.createCommand(command, options, nil, position) table.insert(stack, element) end @@ -33,12 +35,13 @@ local function text (parser, msg) end local function parse (doc) - local content = { StartElement = startcommand, - EndElement = endcommand, - CharacterData = text, - _nonstrict = true, - stack = {{}} - } + local content = { + StartElement = startcommand, + EndElement = endcommand, + CharacterData = text, + _nonstrict = true, + stack = {{}} + } local parser = lxp.new(content) local status, err if type(doc) == "string" then @@ -80,7 +83,7 @@ function inputter.parse (_, doc) -- it doesn't look like a native SILE one already. local rootelement = tree.command if rootelement ~= "sile" and rootelement ~= "document" then - tree = { tree, command = "document" } + tree = SU.ast.createCommand("document", {}, tree) end return { tree } end diff --git a/packages/autodoc/init.lua b/packages/autodoc/init.lua index 167bba5f2..d93115953 100644 --- a/packages/autodoc/init.lua +++ b/packages/autodoc/init.lua @@ -126,7 +126,7 @@ end function package:registerRawHandlers () self:registerRawHandler("autodoc:codeblock", function(options, content) - SILE.call("autodoc:codeblock", options, { content[1] }) -- Still issues with SU.contentToString() witb raw content + SILE.call("autodoc:codeblock", options, { content[1] }) -- Still issues with SU.ast.contentToString() witb raw content end) end diff --git a/packages/bibtex/init.lua b/packages/bibtex/init.lua index d4b77a6b5..33829d330 100644 --- a/packages/bibtex/init.lua +++ b/packages/bibtex/init.lua @@ -84,7 +84,7 @@ function package:registerCommands () end) self:registerCommand("cite", function (options, content) - if not options.key then options.key = SU.contentToString(content) end + if not options.key then options.key = SU.ast.contentToString(content) end local style = SILE.settings:get("bibtex.style") local bibstyle = require("packages.bibtex.styles." .. style) local cite = Bibliography.produceCitation(options, SILE.scratch.bibtex.bib, bibstyle) @@ -96,7 +96,7 @@ function package:registerCommands () end) self:registerCommand("reference", function (options, content) - if not options.key then options.key = SU.contentToString(content) end + if not options.key then options.key = SU.ast.contentToString(content) end local style = SILE.settings:get("bibtex.style") local bibstyle = require("packages.bibtex.styles." .. style) local cite, err = Bibliography.produceReference(options, SILE.scratch.bibtex.bib, bibstyle) diff --git a/packages/inputfilter/init.lua b/packages/inputfilter/init.lua index 13fff8e07..448e5739d 100644 --- a/packages/inputfilter/init.lua +++ b/packages/inputfilter/init.lua @@ -25,14 +25,8 @@ function package:transformContent (content, transformFunction, extraArgs) end function package.createCommand (_, pos, col, lno, command, options, content) - local result = { content } - result.col = col - result.lno = lno - result.pos = pos - result.options = options - result.command = command - result.id = "command" - return result + local position = { lno = lno, col = col, pos = pos } + return SU.ast.createCommand(command, options, content, position) end function package:_init () diff --git a/packages/tableofcontents/init.lua b/packages/tableofcontents/init.lua index b4036660d..5d2f08129 100644 --- a/packages/tableofcontents/init.lua +++ b/packages/tableofcontents/init.lua @@ -57,7 +57,7 @@ local function _linkWrapper (dest, func) end -- Flatten a node list into just its string representation. --- (Similar to SU.contentToString(), but allows passing typeset +-- (Similar to SU.ast.contentToString(), but allows passing typeset -- objects to functions that need plain strings). local function _nodesToText (nodes) -- A real interword space width depends on several settings (depending on variable @@ -174,7 +174,7 @@ function package:registerCommands () SILE.call("info", { category = "toc", value = { - label = SU.stripContentPos(content), + label = SU.ast.stripContentPos(content), level = (options.level or 1), number = options.number, link = dest diff --git a/typesetters/base.lua b/typesetters/base.lua index 679334e07..58dacadb4 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -501,7 +501,7 @@ function typesetter:boxUpNodes () self:pushGlue(parfillskip) self:pushPenalty(-inf_bad) SU.debug("typesetter", function () - return "Boxed up "..(#nodelist > 500 and (#nodelist).." nodes" or SU.contentToString(nodelist)) + return "Boxed up "..(#nodelist > 500 and (#nodelist).." nodes" or SU.ast.contentToString(nodelist)) end) local breakWidth = SILE.settings:get("typesetter.breakwidth") or self.frame:getLineWidth() local lines = self:breakIntoLines(nodelist, breakWidth) From 06d9ea4178d0122b76f625dac912f3799c7c5fe5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 6 Dec 2023 15:16:19 +0300 Subject: [PATCH 193/357] refactor(utilities): Move utility libraries to directory for easier partial overrides --- core/{utilities-ast.lua => utilities/ast.lua} | 0 core/{utilities.lua => utilities/init.lua} | 11 ++++++++--- core/{utilities-numbers.lua => utilities/numbers.lua} | 0 core/{utilities-sorting.lua => utilities/sorting.lua} | 0 4 files changed, 8 insertions(+), 3 deletions(-) rename core/{utilities-ast.lua => utilities/ast.lua} (100%) rename core/{utilities.lua => utilities/init.lua} (99%) rename core/{utilities-numbers.lua => utilities/numbers.lua} (100%) rename core/{utilities-sorting.lua => utilities/sorting.lua} (100%) diff --git a/core/utilities-ast.lua b/core/utilities/ast.lua similarity index 100% rename from core/utilities-ast.lua rename to core/utilities/ast.lua diff --git a/core/utilities.lua b/core/utilities/init.lua similarity index 99% rename from core/utilities.lua rename to core/utilities/init.lua index 031f961c8..49e72adaf 100644 --- a/core/utilities.lua +++ b/core/utilities/init.lua @@ -556,28 +556,33 @@ utilities.breadcrumbs = function () return breadcrumbs end -utilities.formatNumber = require("core.utilities-numbers") +utilities.formatNumber = require("core.utilities.numbers") -utilities.collatedSort = require("core.utilities-sorting") +utilities.collatedSort = require("core.utilities.sorting") + +utilities.ast = require("core.utilities.ast") -utilities.ast = require("core.utilities-ast") utilities.subContent = function (content) SU.deprecated("SU.subContent", "SU.ast.subContent", "0.15.0", "0.17.0", [[ Note that the new implementation no longer introduces an id="stuff" key.]]) return utilities.ast.subContent(content) end + utilities.hasContent = function(content) SU.deprecated("SU.hasContent", "SU.ast.hasContent", "0.15.0", "0.17.0") return SU.ast.hasContent(content) end + utilities.contentToString = function (content) SU.deprecated("SU.contentToString", "SU.ast.contentToString", "0.15.0", "0.17.0") return SU.ast.contentToString(content) end + utilities.walkContent = function (content, action) SU.deprecated("SU.walkContent", "SU.ast.walkContent", "0.15.0", "0.17.0") SU.ast.walkContent(content, action) end + utilities.stripContentPos = function (content) SU.deprecated("SU.stripContentPos", "SU.ast.stripContentPos", "0.15.0", "0.17.0") return SU.ast.stripContentPos(content) diff --git a/core/utilities-numbers.lua b/core/utilities/numbers.lua similarity index 100% rename from core/utilities-numbers.lua rename to core/utilities/numbers.lua diff --git a/core/utilities-sorting.lua b/core/utilities/sorting.lua similarity index 100% rename from core/utilities-sorting.lua rename to core/utilities/sorting.lua From 70dfe8b2f7e5fa8d9481836679462bb8135a509f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 7 Dec 2023 12:04:53 +0300 Subject: [PATCH 194/357] refactor(build): Group feature-specific dependencies for easier reading --- build-aux/build.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/build-aux/build.rs b/build-aux/build.rs index fdb215eb8..b5efcb0f8 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -1,17 +1,16 @@ -#[cfg(feature = "completions")] -use clap::CommandFactory; -#[cfg(feature = "completions")] -use clap_complete::generator::generate_to; -#[cfg(feature = "completions")] -use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; #[cfg(feature = "manpage")] use clap_mangen::Man; -#[cfg(feature = "completions")] -use std::fs; -#[cfg(any(feature = "static", feature = "completions"))] +#[cfg(feature = "static")] use std::path::Path; use std::{collections, env}; use vergen::EmitBuilder; +#[cfg(feature = "completions")] +use { + clap::CommandFactory, + clap_complete::generator::generate_to, + clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}, + std::{fs, path::Path}, +}; #[cfg(feature = "completions")] include!("../src/cli.rs"); From 542c869cca59354a3f9319a844459467f92acf0d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 13 Dec 2023 15:31:33 +0300 Subject: [PATCH 195/357] chore(core)!: Change default paragraph indent to 1 baseline skip BREAKING CHANGE: The previous default paragraph indent was hard coded with a point size (20pt) that did not adapt will to different fonts or page layouts. The new default uses a relative unit that will adjust based on the leading (1bs). This will cause most documents to reflow. To keep them the same the setting may be reset to the old default either in the document: \set[parameter=document.parindent,value=20pt,makedefault=true] ...or even from the CLI when rendering a document: $ sile -e 'SILE.settings:set("document.parindent", "20pt", true)' --- core/settings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/settings.lua b/core/settings.lua index ac3b200cf..9de33a2db 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -21,7 +21,7 @@ function settings:_init() self:declare({ parameter = "document.parindent", type = "glue", - default = SILE.nodefactory.glue("20pt"), + default = SILE.nodefactory.glue("1bs"), help = "Glue at start of paragraph" }) From 66cdbad9b991df6664b2729da266f224afeeea55 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 13 Dec 2023 16:02:51 +0300 Subject: [PATCH 196/357] chore(core)!: Change default space width to 1 space BREAKING CHANGE: For ... reasons ... the default width of spaces in SILE has been a hightly opinionated and non-standard 1.2 spaces. While it can be argued that this makes some fonts and some documents look better, it is a very strange thing to have as a global default. Unfortunately setting it back to a more conventional 1 space is a major change and will cause many/most documents to reflow. The old default can be recovered either in documents with: \set[parameter=shaper.spaceenlargementfactor,value=1.2,makedefault=true] ...or even from the CLI when rendering a document: $ sile -e 'SILE.settings:set("shaper.spaceenlargementfactor", 1.2, true)' --- shapers/base.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shapers/base.lua b/shapers/base.lua index 330dea190..d0f347449 100644 --- a/shapers/base.lua +++ b/shapers/base.lua @@ -5,7 +5,7 @@ -- end SILE.settings:declare({ parameter = "shaper.variablespaces", type = "boolean", default = true }) -SILE.settings:declare({ parameter = "shaper.spaceenlargementfactor", type = "number or integer", default = 1.2 }) +SILE.settings:declare({ parameter = "shaper.spaceenlargementfactor", type = "number or integer", default = 1 }) SILE.settings:declare({ parameter = "shaper.spacestretchfactor", type = "number or integer", default = 1/2 }) SILE.settings:declare({ parameter = "shaper.spaceshrinkfactor", type = "number or integer", default = 1/3 }) From 8dfe3c3f070324ba0aced587fccbd063944fe4c0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 14 Dec 2023 15:28:52 +0300 Subject: [PATCH 197/357] fix(packages): Correct bogus mixup of variable names in package inits --- packages/balanced-frames/init.lua | 4 ++-- packages/boustrophedon/init.lua | 4 ++-- tests/inc/bug-337.lua | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/balanced-frames/init.lua b/packages/balanced-frames/init.lua index 644c1a175..1c3d10492 100644 --- a/packages/balanced-frames/init.lua +++ b/packages/balanced-frames/init.lua @@ -72,8 +72,8 @@ local function buildPage (typesetter, independent) return true end -function package:_init (class) - base._init(self, class) +function package:_init (options) + base._init(self, options) self.class:registerPostinit(function(_) if not unbalanced_buildPage then unbalanced_buildPage = SILE.typesetter.buildPage diff --git a/packages/boustrophedon/init.lua b/packages/boustrophedon/init.lua index ce81f8fd1..c77dfbfbd 100644 --- a/packages/boustrophedon/init.lua +++ b/packages/boustrophedon/init.lua @@ -3,8 +3,8 @@ local base = require("packages.base") local package = pl.class(base) package._name = "boustrophedon" -function package:_init (class) - base._init(self, class) +function package:_init (options) + base._init(self, options) SILE.hyphenator.languages.grc = { patterns={} } SILE.nodeMakers.grc = pl.class(SILE.nodeMakers.unicode) function SILE.nodeMakers.grc.iterator (node, items) diff --git a/tests/inc/bug-337.lua b/tests/inc/bug-337.lua index f6624cd7e..82e9dad7f 100644 --- a/tests/inc/bug-337.lua +++ b/tests/inc/bug-337.lua @@ -4,11 +4,11 @@ local package = pl.class(base) package._name = "bug-337" -function package:_init (class) +function package:_init (options) - base._init(self, class) + base._init(self, options) - class:defineMaster({ + self.class:defineMaster({ id = "right", firstContentFrame = "content", frames = { @@ -26,15 +26,15 @@ function package:_init (class) } } }) - class:defineMaster({ + self.class:defineMaster({ id = "left", firstContentFrame = "content", frames = {} }) - class:mirrorMaster("right", "left") - class:switchMasterOnePage("right") + self.class:mirrorMaster("right", "left") + self.class:switchMasterOnePage("right") - class:loadPackage("cropmarks") + self.class:loadPackage("cropmarks") end From 2fd6eaa13355e76ca51ac0fb630777d50e49a27b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 15 Dec 2023 14:36:48 +0300 Subject: [PATCH 198/357] chore(build): Avoid doubled Rust imports when combining features --- build-aux/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-aux/build.rs b/build-aux/build.rs index b5efcb0f8..2f90b107f 100644 --- a/build-aux/build.rs +++ b/build-aux/build.rs @@ -1,6 +1,6 @@ #[cfg(feature = "manpage")] use clap_mangen::Man; -#[cfg(feature = "static")] +#[cfg(any(feature = "static", feature = "completions"))] use std::path::Path; use std::{collections, env}; use vergen::EmitBuilder; @@ -9,7 +9,7 @@ use { clap::CommandFactory, clap_complete::generator::generate_to, clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}, - std::{fs, path::Path}, + std::fs, }; #[cfg(feature = "completions")] From fa8d40111736d1867d075b44da49d8dbb80af143 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 14 Dec 2023 15:04:33 +0300 Subject: [PATCH 199/357] feat(packages): Add package to reset some defaults similar to previous releases --- packages/retrograde/init.lua | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 packages/retrograde/init.lua diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua new file mode 100644 index 000000000..442d3958d --- /dev/null +++ b/packages/retrograde/init.lua @@ -0,0 +1,48 @@ +local base = require("packages.base") + +local package = pl.class(base) +package._name = "retrograde" + +local semver = require("semver") + +local semver_descending = function (a, b) + a, b = semver(a), semver(b) + return a > b +end + +-- Default settings that have gone out of fashion +package.default_settings = { +} + +function package:_init (options) + base._init(self, options) + self:defaults(options.target) +end + +function package:defaults (target) + target = semver(target and target or SILE.version) + local target_hit = false + for version, settings in pl.tablex.sort(self.default_settings, semver_descending) do + for parameter, value in pairs(settings) do + SILE.settings:set(parameter, value, true) + end + if target_hit then break end + if semver(version) <= target then target_hit = true end + end +end + +function package:registerCommands () + + self:registerCommand("defaults", function (options, content) + if content then + SILE.settings:temporarily(function () + self:defaults(options.target) + end) + else + self:defaults(options.target) + end + end) + +end + +return package From fc80d94d21ce6263f1d98eb12b57faff84eebabc Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 14 Dec 2023 15:04:33 +0300 Subject: [PATCH 200/357] docs(manual): Add documentation for now defaults package --- documentation/c05-packages.sil | 4 ++++ packages/retrograde/init.lua | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/documentation/c05-packages.sil b/documentation/c05-packages.sil index b3f6089a4..df4c4037c 100644 --- a/documentation/c05-packages.sil +++ b/documentation/c05-packages.sil @@ -274,6 +274,10 @@ This section introduces packages that could not fit in another category. \status:low \package-documentation{ifattop} +\subsection{retrograde} +\status:high +\package-documentation{retrograde} + \section{Frames and page layouts} As we mentioned in the first chapter, SILE uses frames as an indication of where to put text onto diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 442d3958d..c6c2bb201 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -45,4 +45,35 @@ function package:registerCommands () end +local doctarget = "v" .. tostring(semver(SILE.version)) +package.documentation = ([[ +\begin{document} + +From time to time, the default behavior of a function or value of a setting in SILE might change with a new release. +If these changes are expected to cause document reflows they will be noted in release notes as breaking changes. +That generally means old documents will have to be updated to keep rending the same way. +On a best-effort basis (not a guarantee) this package tries to restore earlier default behaviors and settings. + +For settings this is relatively simple. +You just set the old default value explicitly in your document or project. +But first, knowing what those are requires a careful reading of the release notes. +Then you have to chase down the incantations to set the old values. +This package tries to restore as many previous setting values as possible to make old documents render like they would have in previous releases without changing the documents themselves (beyond loading this package). + +For functions things are a little more complex, but for as many cases as possible we'll try to allow swapping old versions of code. + +None of this is a guarantee that your old document will be stable in new versions of SILE. +All of this is a danger zone. + +From inside a document, use \autodoc:command{\use[module=packages.retrograde,target=%s]} to load features from SILE %s. + +This can also be triggered from the command line with no changes to a document: + +\begin{autodoc:codeblock} +$ sile -u 'packages.retrograde[target=%s]' +\end{autodoc:codeblock} + +\end{document} +]]):format(doctarget, doctarget, doctarget) + return package From 90dfee0ac76189e242eaaa35de68c39a23c92177 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 14 Dec 2023 15:04:33 +0300 Subject: [PATCH 201/357] chore(packages): Add relevant debug output to defaults package --- packages/retrograde/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index c6c2bb201..1ff4fd023 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -23,11 +23,13 @@ function package:defaults (target) target = semver(target and target or SILE.version) local target_hit = false for version, settings in pl.tablex.sort(self.default_settings, semver_descending) do + version = semver(version) for parameter, value in pairs(settings) do + SU.debug("defaults", ("Resetting '%s' to '%s' as it was prior to v%s"):format(parameter, tostring(value), version)) SILE.settings:set(parameter, value, true) end if target_hit then break end - if semver(version) <= target then target_hit = true end + if version <= target then target_hit = true end end end From 766fecd0dc653a7d7f25a56542c9b46c5cdc4042 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 16 Dec 2023 23:11:21 +0300 Subject: [PATCH 202/357] chore(packages): Add changed default setting to retrograde package --- packages/retrograde/init.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 1ff4fd023..33e509ca0 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -12,6 +12,9 @@ end -- Default settings that have gone out of fashion package.default_settings = { + ["0.15.0"] = { + ["shaper.spaceenlargementfactor"] = 1.2, + }, } function package:_init (options) From e5b42aeba243b39c9692f04655a2c50f5dc18803 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 16 Dec 2023 23:34:24 +0300 Subject: [PATCH 203/357] test(packages): Use retrograde package to avoid test churn --- tests/alignment.sil | 1 + tests/amharic.sil | 1 + tests/arabic-scripts.sil | 1 + tests/bibtex.sil | 1 + tests/bidi.sil | 1 + tests/bug-1044.sil | 1 + tests/bug-1101.sil | 1 + tests/bug-117.sil | 1 + tests/bug-1259.sil | 1 + tests/bug-1280.sil | 1 + tests/bug-1297-hyph-fr-ca.sil | 1 + tests/bug-1317.sil | 1 + tests/bug-1320.sil | 1 + tests/bug-1343-dotfill-stretch.sil | 1 + tests/bug-1359.sil | 1 + tests/bug-1362.sil | 1 + tests/bug-1430.sil | 1 + tests/bug-1495-inline-math-layout.sil | 1 + tests/bug-1580.sil | 1 + tests/bug-162.sil | 1 + tests/bug-1647.sil | 1 + tests/bug-1674.sil | 1 + tests/bug-1708.sil | 3 ++- tests/bug-192.sil | 1 + tests/bug-200.sil | 1 + tests/bug-226.sil | 3 ++- tests/bug-241.sil | 1 + tests/bug-243.sil | 1 + tests/bug-244.sil | 1 + tests/bug-252.sil | 1 + tests/bug-252a.sil | 3 ++- tests/bug-254.sil | 3 ++- tests/bug-255.sil | 1 + tests/bug-255b.sil | 1 + tests/bug-262.sil | 1 + tests/bug-264.sil | 1 + tests/bug-264b.sil | 3 ++- tests/bug-266.sil | 1 + tests/bug-269.sil | 1 + tests/bug-283.sil | 1 + tests/bug-284.sil | 1 + tests/bug-301.sil | 1 + tests/bug-309.sil | 1 + tests/bug-317.sil | 1 + tests/bug-337.sil | 1 + tests/bug-344.sil | 1 + tests/bug-353.sil | 1 + tests/bug-355-tr-hyphenation.sil | 1 + tests/bug-39.sil | 1 + tests/bug-465-a.sil | 3 ++- tests/bug-526.sil | 1 + tests/bug-530.sil | 3 ++- tests/bug-54.sil | 1 + tests/bug-583.sil | 1 + tests/bug-61.sil | 1 + tests/bug-62.sil | 1 + tests/bug-621.sil | 1 + tests/bug-702.sil | 1 + tests/bug-704.sil | 5 +++-- tests/bug-76.sil | 1 + tests/bug-79.sil | 1 + tests/bug-80.sil | 1 + tests/bug-865.sil | 1 + tests/bug-990.sil | 1 + tests/centering.sil | 1 + tests/chapterverse.sil | 1 + tests/combining.sil | 1 + tests/counters.sil | 1 + tests/cursive-shaping.sil | 1 + tests/disappearing-skip.sil | 1 + tests/eject.sil | 1 + tests/feat-1092-raw.sil | 3 ++- tests/feat-1365-lists-alternate.sil | 1 + tests/feat-1365-lists-compact.sil | 1 + tests/feat-1365-lists-footnote.sil | 3 ++- tests/feat-875-dotfill-alignment.sil | 1 + tests/feat-875-leaders-alignment.sil | 1 + tests/feat-875-leaders-fixed-alignment.sil | 1 + tests/feat-fullrule-hfillrule.sil | 1 + tests/feat-italic-correction.sil | 3 ++- tests/fluent.sil | 1 + tests/font-features-cvXX.sil | 1 + tests/footnote-skip.sil | 1 + tests/footnote.sil | 1 + tests/grid.sil | 2 ++ tests/hangafter.sil | 1 + tests/image.sil | 1 + tests/inline-lua.sil | 1 + tests/kannada.sil | 1 + tests/letterspacing.sil | 1 + tests/linespacing.sil | 1 + tests/linespacing2.sil | 1 + tests/masters.sil | 1 + tests/math-bigops.xml | 1 + tests/math-fractions.xml | 1 + tests/math-ops.sil | 1 + tests/math-spaces.sil | 1 + tests/math-stretchy.xml | 1 + tests/math-subsup.xml | 1 + tests/math-tables-mathml.xml | 1 + tests/math-tables-tex.sil | 1 + tests/math-variants.xml | 1 + tests/mini-arabic.sil | 1 + tests/mlcounter.sil | 1 + tests/negative-spaces-in-line.sil | 1 + tests/nondeterminism.sil | 3 ++- tests/parshaping-simple.sil | 1 + tests/rskip.sil | 1 + tests/settings.sil | 1 + tests/split-footnote.sil | 1 + tests/sura-2.sil | 1 + tests/tracking.sil | 1 + tests/twoside.sil | 1 + tests/variations-axis.sil | 1 + tests/vertical.sil | 1 + 115 files changed, 129 insertions(+), 13 deletions(-) diff --git a/tests/alignment.sil b/tests/alignment.sil index f50f413a7..144257d62 100644 --- a/tests/alignment.sil +++ b/tests/alignment.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.lorem] \font[family=Libertinus Serif] diff --git a/tests/amharic.sil b/tests/amharic.sil index b22d154f8..247d2d62e 100644 --- a/tests/amharic.sil +++ b/tests/amharic.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \font[family=Noto Sans Ethiopic,language=am] የሰው፡ልጅ፡ሁሉ፡ሲወለድ፡ነጻና፡በክብርና፡በመብትም፡እኩልነት፡ያለው፡ነው።፡የተፈጥሮ፡ማስተዋልና፡ሕሊና፡ስላለው፡አንዱ፡ሌላውን፡በወንድማማችነት፡መንፈስ፡መመልከት፡ይገባዋል። diff --git a/tests/arabic-scripts.sil b/tests/arabic-scripts.sil index 10ec342c1..bf939b49d 100644 --- a/tests/arabic-scripts.sil +++ b/tests/arabic-scripts.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.bidi] \font[family=LateefGR,size=16pt,language=en] diff --git a/tests/bibtex.sil b/tests/bibtex.sil index d50221a8a..06adcc5c4 100644 --- a/tests/bibtex.sil +++ b/tests/bibtex.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \use[module=packages.bibtex] diff --git a/tests/bidi.sil b/tests/bidi.sil index 1e26ebff0..6f4a8a900 100644 --- a/tests/bidi.sil +++ b/tests/bidi.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \font[family=SBL Hebrew,language=he] \font[size=25pt] \set[parameter=document.baselineskip,value=29pt] diff --git a/tests/bug-1044.sil b/tests/bug-1044.sil index 26d156816..f9962bf15 100644 --- a/tests/bug-1044.sil +++ b/tests/bug-1044.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \font[family=Libertinus Serif]{Ta of} diff --git a/tests/bug-1101.sil b/tests/bug-1101.sil index ddc7e0a01..d2b2f6102 100644 --- a/tests/bug-1101.sil +++ b/tests/bug-1101.sil @@ -1,4 +1,5 @@ \begin[class=jplain,layout=tate,papersize=a4]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios diff --git a/tests/bug-117.sil b/tests/bug-117.sil index ed044f8f1..60250d6f3 100644 --- a/tests/bug-117.sil +++ b/tests/bug-117.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] %nice script from SILE book \begin{script} for i=1,10 do diff --git a/tests/bug-1259.sil b/tests/bug-1259.sil index 55f47dfa1..6f1a5dc47 100644 --- a/tests/bug-1259.sil +++ b/tests/bug-1259.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \use[module=packages.rules] diff --git a/tests/bug-1280.sil b/tests/bug-1280.sil index e70e280f5..b85dfcda8 100644 --- a/tests/bug-1280.sil +++ b/tests/bug-1280.sil @@ -1,4 +1,5 @@ \begin[papersize=15cm x 6cm]{document} +\use[module=packages.retrograde,target=v0.15.0] \font[filename=.fonts/NotoSerifCJK-Regular.ttc] \nofolios \neverindent diff --git a/tests/bug-1297-hyph-fr-ca.sil b/tests/bug-1297-hyph-fr-ca.sil index 77416554c..03fe2fac1 100644 --- a/tests/bug-1297-hyph-fr-ca.sil +++ b/tests/bug-1297-hyph-fr-ca.sil @@ -1,4 +1,5 @@ \begin[papersize=6in x 9in]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \language[main=fr] diff --git a/tests/bug-1317.sil b/tests/bug-1317.sil index 57413de07..bff19d3f4 100644 --- a/tests/bug-1317.sil +++ b/tests/bug-1317.sil @@ -1,4 +1,5 @@ \begin[direction=RTL,papersize=a7]{document} +\use[module=packages.retrograde,target=v0.15.0] \font[family=Amiri,size=30pt] \nofolios \neverindent diff --git a/tests/bug-1320.sil b/tests/bug-1320.sil index 285d12f93..169645c68 100644 --- a/tests/bug-1320.sil +++ b/tests/bug-1320.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \use[module=packages.rules] diff --git a/tests/bug-1343-dotfill-stretch.sil b/tests/bug-1343-dotfill-stretch.sil index 265b76f81..cb4d6d87e 100644 --- a/tests/bug-1343-dotfill-stretch.sil +++ b/tests/bug-1343-dotfill-stretch.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.leaders] \use[module=packages.lorem] diff --git a/tests/bug-1359.sil b/tests/bug-1359.sil index fc2205d0e..118a25641 100644 --- a/tests/bug-1359.sil +++ b/tests/bug-1359.sil @@ -1,4 +1,5 @@ \begin[papersize=6in x 9in]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \language[main=fr] diff --git a/tests/bug-1362.sil b/tests/bug-1362.sil index 5feb57409..8854f72bd 100644 --- a/tests/bug-1362.sil +++ b/tests/bug-1362.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \language[main=en] diff --git a/tests/bug-1430.sil b/tests/bug-1430.sil index 96788b9f4..3cd767d5c 100644 --- a/tests/bug-1430.sil +++ b/tests/bug-1430.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \use[module=packages.grid,spacing=50pt] diff --git a/tests/bug-1495-inline-math-layout.sil b/tests/bug-1495-inline-math-layout.sil index ca96b1272..56e2975d6 100644 --- a/tests/bug-1495-inline-math-layout.sil +++ b/tests/bug-1495-inline-math-layout.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \use[module=packages.math] diff --git a/tests/bug-1580.sil b/tests/bug-1580.sil index 3c0d6a3b4..753dd51f4 100644 --- a/tests/bug-1580.sil +++ b/tests/bug-1580.sil @@ -1,4 +1,5 @@ \begin[class=plain,papersize=a7]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \use[module=packages.masters] diff --git a/tests/bug-162.sil b/tests/bug-162.sil index acad9ffa6..87d6d6db1 100644 --- a/tests/bug-162.sil +++ b/tests/bug-162.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] Both lines below should end in a period. \font[language=cs] diff --git a/tests/bug-1647.sil b/tests/bug-1647.sil index 82e70794c..09789db28 100644 --- a/tests/bug-1647.sil +++ b/tests/bug-1647.sil @@ -1,4 +1,5 @@ \begin[papersize=a7]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \set[parameter=document.parskip, value=50pt] diff --git a/tests/bug-1674.sil b/tests/bug-1674.sil index 209af1e54..e8cb0a0d4 100644 --- a/tests/bug-1674.sil +++ b/tests/bug-1674.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \script{SILE.processString("Foo \\em{bar} \\em{baz}", "sil")} diff --git a/tests/bug-1708.sil b/tests/bug-1708.sil index cf6d14b1d..a1c498af0 100644 --- a/tests/bug-1708.sil +++ b/tests/bug-1708.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \set[parameter=document.letterspaceglue, value=5pt] @@ -9,4 +10,4 @@ Lorem ipsum\footnote{test} Lorem ipsum% Should still have letterspacing at 5pt -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-192.sil b/tests/bug-192.sil index f0a46b6a5..be773d121 100644 --- a/tests/bug-192.sil +++ b/tests/bug-192.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Noto Naskh Arabic,language=urd,size=18pt] \hbox\skip[height=95%fh] diff --git a/tests/bug-200.sil b/tests/bug-200.sil index ec9682e67..162b89f92 100644 --- a/tests/bug-200.sil +++ b/tests/bug-200.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Gentium Plus,size=16pt,language=en] \begin{raggedright} diff --git a/tests/bug-226.sil b/tests/bug-226.sil index 8a4876a90..35212e48c 100644 --- a/tests/bug-226.sil +++ b/tests/bug-226.sil @@ -1,4 +1,5 @@ \begin{document} +\use[module=packages.retrograde,target=v0.15.0] \hfill Filler content here: Par 1 (One) \hfill Par 2 (Two) @@ -8,4 +9,4 @@ \hfill Out, \hfill Caleb Maclennan -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-241.sil b/tests/bug-241.sil index 4d0d0a810..4ca7d2ccf 100644 --- a/tests/bug-241.sil +++ b/tests/bug-241.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Gentium Plus,size=9pt] \center{TITILE\break{}Then vfill to logo\vfill{}<logo>\par\break} diff --git a/tests/bug-243.sil b/tests/bug-243.sil index bf1377f40..9083807b8 100644 --- a/tests/bug-243.sil +++ b/tests/bug-243.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.leaders] \font[size=50pt] diff --git a/tests/bug-244.sil b/tests/bug-244.sil index 044c6462e..63bdb4412 100644 --- a/tests/bug-244.sil +++ b/tests/bug-244.sil @@ -1,3 +1,4 @@ \begin[papersize=a4,class=jplain,layout=tate]{document} +\use[module=packages.retrograde,target=v0.15.0] \latin-in-tate{Hello world.} \end{document} diff --git a/tests/bug-252.sil b/tests/bug-252.sil index 3c1f8e81f..6fed341b7 100644 --- a/tests/bug-252.sil +++ b/tests/bug-252.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.frametricks] \use[module=packages.lorem] This is a test\footnote{What happens to frames?}. diff --git a/tests/bug-252a.sil b/tests/bug-252a.sil index b9a4c8840..0e8bd4593 100644 --- a/tests/bug-252a.sil +++ b/tests/bug-252a.sil @@ -1,7 +1,8 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \use[module=packages.rebox] \footnote:separator{\skip[height=5pt]} \define[command=deepbox]{\rebox[depth=60pt,height=10pt]{x}} This is a test\footnote{\deepbox}. -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-254.sil b/tests/bug-254.sil index f9956afbf..6aa33e71a 100644 --- a/tests/bug-254.sil +++ b/tests/bug-254.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \raggedright{ \font[weight=600]{This} is a sample of bogus\break extra space. @@ -6,4 +7,4 @@ extra space. \font[weight=600]{This} does not have\break {}extra space. } -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-255.sil b/tests/bug-255.sil index bf9a2d019..3ea12f0d8 100644 --- a/tests/bug-255.sil +++ b/tests/bug-255.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.frametricks] \script{ SILE.registerCommand("donothing", function (options, content) diff --git a/tests/bug-255b.sil b/tests/bug-255b.sil index 6c0293fe1..707bedd3e 100644 --- a/tests/bug-255b.sil +++ b/tests/bug-255b.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.frametricks] \script{ SILE.registerCommand("donothing", function(o,c) diff --git a/tests/bug-262.sil b/tests/bug-262.sil index 091d21bbd..96881e880 100644 --- a/tests/bug-262.sil +++ b/tests/bug-262.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.lorem] \hbox diff --git a/tests/bug-264.sil b/tests/bug-264.sil index c29bd8d56..10072fe70 100644 --- a/tests/bug-264.sil +++ b/tests/bug-264.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios Footnote\skip[height=170pt plus 50pt] marker.\footnote{Same page\hfill\break as marker?} diff --git a/tests/bug-264b.sil b/tests/bug-264b.sil index ecaef722e..71afaea96 100644 --- a/tests/bug-264b.sil +++ b/tests/bug-264b.sil @@ -1,6 +1,7 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] % Note: The failure case for this involves an infinite loop when it -% erroniously matched penalty types that arent actually page breaks +% erroneously matched penalty types that aren't actually page breaks \use[module=packages.linespacing] \set[parameter=linespacing.method,value=fit-font] \set[parameter=linespacing.fit-font.extra-space,value=15pt plus 0.5pt minus 0.5pt] diff --git a/tests/bug-266.sil b/tests/bug-266.sil index 2294ba367..593cf29ad 100644 --- a/tests/bug-266.sil +++ b/tests/bug-266.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios Word\glue[width=1ex]to the wise diff --git a/tests/bug-269.sil b/tests/bug-269.sil index 091780cde..ec4a9a2fd 100644 --- a/tests/bug-269.sil +++ b/tests/bug-269.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Gentium Plus,size=10.1pt,language=tr] \use[module=packages.footnotes] diff --git a/tests/bug-283.sil b/tests/bug-283.sil index 7f0f3b724..d9a57cb1b 100644 --- a/tests/bug-283.sil +++ b/tests/bug-283.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Libertinus Serif,size=12.7pt,language=tr] \set[parameter=shaper.spacestretchfactor,value=1.2] diff --git a/tests/bug-284.sil b/tests/bug-284.sil index e87ced8c7..6c34b098c 100644 --- a/tests/bug-284.sil +++ b/tests/bug-284.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \set[parameter=document.lskip,value=15pt] \set[parameter=document.rskip,value=10pt] diff --git a/tests/bug-301.sil b/tests/bug-301.sil index 379286497..98dcb2f80 100644 --- a/tests/bug-301.sil +++ b/tests/bug-301.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.linespacing] \nofolios \font[family=Gentium Plus,size=9.5pt] diff --git a/tests/bug-309.sil b/tests/bug-309.sil index 6499873e8..7e7b3c38f 100644 --- a/tests/bug-309.sil +++ b/tests/bug-309.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \set[parameter=document.parskip,value=2em plus 1em] Test par diff --git a/tests/bug-317.sil b/tests/bug-317.sil index dc0a729c2..ca86f4cb5 100644 --- a/tests/bug-317.sil +++ b/tests/bug-317.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.verbatim] \define[command=verbatim:font]{\set[parameter=font.family,value=Hack]} diff --git a/tests/bug-337.sil b/tests/bug-337.sil index 66a746aa1..bab3d9f4c 100644 --- a/tests/bug-337.sil +++ b/tests/bug-337.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \script[src=inc.bug-337] \define[command=crop:header]{tests/bug-337.sil} \crop:setup[papersize=a6] diff --git a/tests/bug-344.sil b/tests/bug-344.sil index 22a5388ae..43485b9fe 100644 --- a/tests/bug-344.sil +++ b/tests/bug-344.sil @@ -1,4 +1,5 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \define[command=mwe]{One, two. Buckle my shoe.\smallskip} diff --git a/tests/bug-353.sil b/tests/bug-353.sil index 636cb60e5..73944caf8 100644 --- a/tests/bug-353.sil +++ b/tests/bug-353.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.background] \nofolios \background[color=#e9d8ba] diff --git a/tests/bug-355-tr-hyphenation.sil b/tests/bug-355-tr-hyphenation.sil index b0304a4f3..06ff668a3 100644 --- a/tests/bug-355-tr-hyphenation.sil +++ b/tests/bug-355-tr-hyphenation.sil @@ -1,4 +1,5 @@ \begin[papersize=a7]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \set[parameter=shaper.variablespaces, value=false] diff --git a/tests/bug-39.sil b/tests/bug-39.sil index 87f1c6697..9d6127c4b 100644 --- a/tests/bug-39.sil +++ b/tests/bug-39.sil @@ -1,4 +1,5 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.frametricks] \right-running-head{First Line of Header\skip[height=8mm] Second Line of Header} \showframe[id=all] diff --git a/tests/bug-465-a.sil b/tests/bug-465-a.sil index 34651f9c2..a57bb8fda 100644 --- a/tests/bug-465-a.sil +++ b/tests/bug-465-a.sil @@ -1,3 +1,4 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] Hello \include[src=bug-465-b.sil]. -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-526.sil b/tests/bug-526.sil index 63395abe4..52edb662e 100644 --- a/tests/bug-526.sil +++ b/tests/bug-526.sil @@ -1,4 +1,5 @@ \begin[class=plain,papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.frametricks] \use[module=packages.lorem] diff --git a/tests/bug-530.sil b/tests/bug-530.sil index 40ab0f816..d9fff3048 100644 --- a/tests/bug-530.sil +++ b/tests/bug-530.sil @@ -1,4 +1,5 @@ \begin[direction=RTL]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \lorem @@ -7,4 +8,4 @@ \lorem -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-54.sil b/tests/bug-54.sil index 5807b4dc5..160a951cb 100644 --- a/tests/bug-54.sil +++ b/tests/bug-54.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Gentium Plus,size=12pt] \set[parameter=document.parindent,value=10mm] diff --git a/tests/bug-583.sil b/tests/bug-583.sil index e843838d5..f8e33b50c 100644 --- a/tests/bug-583.sil +++ b/tests/bug-583.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \define[command=ah]{\discretionary[prebreak=-, replacement=’]} diff --git a/tests/bug-61.sil b/tests/bug-61.sil index 8a4efd80a..95218e40d 100644 --- a/tests/bug-61.sil +++ b/tests/bug-61.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.frametricks] \begin[first-content-frame=frame1]{pagetemplate} \frame[id=frame1,left=left(content),right=right(content),height=18pt,top=top(content),next=frame2] diff --git a/tests/bug-62.sil b/tests/bug-62.sil index 6d87df13d..f1b91a0f4 100644 --- a/tests/bug-62.sil +++ b/tests/bug-62.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] First paragraph %comment diff --git a/tests/bug-621.sil b/tests/bug-621.sil index 9fd878b1d..ba5b5056f 100644 --- a/tests/bug-621.sil +++ b/tests/bug-621.sil @@ -1,4 +1,5 @@ \begin{document} +\use[module=packages.retrograde,target=v0.15.0] \font[language=fr, size=15pt] La peine de mort est nécessaire, disent les partisans de l’antique et barbare routine ; sans elle il n’est point de frein assez puissant pour le crime. Qui vous l’a dit ? Avez-vous calculé tous les ressorts par lesquels les lois pénales peuvent agir sur la sensibilité humaine ? Hélas ! avant la mort, combien de douleurs physiques et morales l’homme ne peut-il pas endurer ! diff --git a/tests/bug-702.sil b/tests/bug-702.sil index 0c6b9b9c7..a101a6898 100644 --- a/tests/bug-702.sil +++ b/tests/bug-702.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \language[main=fr] Il était une fois, dans un pays très lointain (dont le nom périlleux ne doit pas être prononcé), vivait Bernadette, qui nous disait « Rien d’important! » As-tu entendu? \end{document} diff --git a/tests/bug-704.sil b/tests/bug-704.sil index 2205eba4f..18e4b9479 100644 --- a/tests/bug-704.sil +++ b/tests/bug-704.sil @@ -1,4 +1,5 @@ \begin[papersize=6in x 9in]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \language[main=fr] @@ -10,7 +11,7 @@ Cinq : « Six ‹ Sept › `Huit » ! Treize ; Quatorze… ! -Quinze (?), ?!, [!], …? etc. +Quinze (?), ?!, [!], …? etc. Un! Deux? Trois!? Quatre!!! @@ -21,6 +22,6 @@ Cinq: «Six ‹Sept› `Huit»! Treize; Quatorze…! -Quinze ( ?), ? !, [ !], … ? etc. +Quinze ( ?), ? !, [ !], … ? etc. \end{document} diff --git a/tests/bug-76.sil b/tests/bug-76.sil index dc7bdd0bc..6e06e48da 100644 --- a/tests/bug-76.sil +++ b/tests/bug-76.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.bidi] \thisframeRTL diff --git a/tests/bug-79.sil b/tests/bug-79.sil index 3178b8df4..28b72c312 100644 --- a/tests/bug-79.sil +++ b/tests/bug-79.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \begin[first-content-frame=frame]{pagetemplate} \frame[id=frame, left=2cm, width=5.8cm, top=2cm, bottom=10cm] diff --git a/tests/bug-80.sil b/tests/bug-80.sil index 90889a074..063a92cb8 100644 --- a/tests/bug-80.sil +++ b/tests/bug-80.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \define[command=item]{\quad – \process} diff --git a/tests/bug-865.sil b/tests/bug-865.sil index 8b2bb3012..b82a36eb5 100644 --- a/tests/bug-865.sil +++ b/tests/bug-865.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.pullquote] \use[module=packages.lorem] diff --git a/tests/bug-990.sil b/tests/bug-990.sil index 0ef9a521a..c12087fb2 100644 --- a/tests/bug-990.sil +++ b/tests/bug-990.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \define[command=open-spread]{} \nofolios diff --git a/tests/centering.sil b/tests/centering.sil index 702321fff..b0ae8b687 100644 --- a/tests/centering.sil +++ b/tests/centering.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \ragged[right=true,left=true]{\lorem[words=100]} diff --git a/tests/chapterverse.sil b/tests/chapterverse.sil index d309b318a..ded8997a1 100644 --- a/tests/chapterverse.sil +++ b/tests/chapterverse.sil @@ -1,4 +1,5 @@ \begin[papersize=a7,class=bible]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Gentium Plus] \begin{script} diff --git a/tests/combining.sil b/tests/combining.sil index 89c079f75..7ee1c4c6b 100644 --- a/tests/combining.sil +++ b/tests/combining.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Gentium Plus,size=24pt] Ầ Ầ diff --git a/tests/counters.sil b/tests/counters.sil index 6d581dc95..d6599a40e 100644 --- a/tests/counters.sil +++ b/tests/counters.sil @@ -1,5 +1,6 @@ \begin[papersize=a6]{document} \nofolios +\use[module=packages.retrograde,target=v0.15.0] \set[parameter=document.parindent,value=0pt] \font[family=Libertinus Serif] \use[module=packages.counters] diff --git a/tests/cursive-shaping.sil b/tests/cursive-shaping.sil index a70023414..57d3bd45d 100644 --- a/tests/cursive-shaping.sil +++ b/tests/cursive-shaping.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,direction=RTL]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \language[main=ar] diff --git a/tests/disappearing-skip.sil b/tests/disappearing-skip.sil index 5300b852e..34cf537f2 100644 --- a/tests/disappearing-skip.sil +++ b/tests/disappearing-skip.sil @@ -1,4 +1,5 @@ \begin[papersize=129mm x 198mm]{document} +\use[module=packages.retrograde,target=v0.15.0] Para 1. \skip[height=155mm] diff --git a/tests/eject.sil b/tests/eject.sil index 970473ed3..03b28a974 100644 --- a/tests/eject.sil +++ b/tests/eject.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \pagetemplate[first-content-frame=a]{ \frame[id=a,top=5%ph,bottom=95%ph,next=b,left=5%pw,right=28%pw] diff --git a/tests/feat-1092-raw.sil b/tests/feat-1092-raw.sil index cc36d2ef0..1e4cb6913 100644 --- a/tests/feat-1092-raw.sil +++ b/tests/feat-1092-raw.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \use[module=packages.svg] @@ -18,4 +19,4 @@ This is a plain text inline. A bit like a true verbatim. \lets[do]{weird things}% Yeah! } -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/feat-1365-lists-alternate.sil b/tests/feat-1365-lists-alternate.sil index 87709ad6c..07bb13c74 100644 --- a/tests/feat-1365-lists-alternate.sil +++ b/tests/feat-1365-lists-alternate.sil @@ -1,4 +1,5 @@ \begin[papersize=a6, class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lists] \font[family=Libertinus Serif]% Default Gentium lacks the white circle. \nofolios diff --git a/tests/feat-1365-lists-compact.sil b/tests/feat-1365-lists-compact.sil index 3040fae45..10fac5d94 100644 --- a/tests/feat-1365-lists-compact.sil +++ b/tests/feat-1365-lists-compact.sil @@ -1,4 +1,5 @@ \begin[papersize=a6, class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lists] \font[family=Libertinus Serif]% Default Gentium lacks the white circle. \nofolios diff --git a/tests/feat-1365-lists-footnote.sil b/tests/feat-1365-lists-footnote.sil index 5418482a7..1f44d4387 100644 --- a/tests/feat-1365-lists-footnote.sil +++ b/tests/feat-1365-lists-footnote.sil @@ -1,4 +1,5 @@ \begin[papersize=a6, class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lists] \font[family=Libertinus Serif]% Default Gentium lacks the white circle. \nofolios @@ -19,7 +20,7 @@ \item{Level 2 Ft} \end{itemize} \item{Level 1 Ft} -\end{itemize} +\end{itemize} }} \begin{itemize} \item{Level 3} diff --git a/tests/feat-875-dotfill-alignment.sil b/tests/feat-875-dotfill-alignment.sil index cb3c3d8a6..add5c385e 100644 --- a/tests/feat-875-dotfill-alignment.sil +++ b/tests/feat-875-dotfill-alignment.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.leaders] \nofolios \neverindent diff --git a/tests/feat-875-leaders-alignment.sil b/tests/feat-875-leaders-alignment.sil index fda2cdc09..10cd9ca15 100644 --- a/tests/feat-875-leaders-alignment.sil +++ b/tests/feat-875-leaders-alignment.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.leaders] \nofolios \neverindent diff --git a/tests/feat-875-leaders-fixed-alignment.sil b/tests/feat-875-leaders-fixed-alignment.sil index 6878f0acb..cf8fea785 100644 --- a/tests/feat-875-leaders-fixed-alignment.sil +++ b/tests/feat-875-leaders-fixed-alignment.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.leaders] \nofolios \neverindent diff --git a/tests/feat-fullrule-hfillrule.sil b/tests/feat-fullrule-hfillrule.sil index 2ba797163..3b58f7553 100644 --- a/tests/feat-fullrule-hfillrule.sil +++ b/tests/feat-fullrule-hfillrule.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \use[module=packages.rules] diff --git a/tests/feat-italic-correction.sil b/tests/feat-italic-correction.sil index 8820db833..7f2077549 100644 --- a/tests/feat-italic-correction.sil +++ b/tests/feat-italic-correction.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \font[size=15pt] @@ -43,7 +44,7 @@ % Enabled \set[parameter=typesetter.italicCorrection, value=true] -+ \em{fluff}! \em{fluff} fluff aaaaaaa aaaa aaaaaa \em{fluff} fluff ++ \em{fluff}! \em{fluff} fluff aaaaaaa aaaa aaaaaa \em{fluff} fluff % Repeated with another font \font[family=Cormorant Infant] diff --git a/tests/fluent.sil b/tests/fluent.sil index f78935f53..dbee08d7b 100644 --- a/tests/fluent.sil +++ b/tests/fluent.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios % Output a message with variable replacement diff --git a/tests/font-features-cvXX.sil b/tests/font-features-cvXX.sil index de0b9826d..e266d2038 100644 --- a/tests/font-features-cvXX.sil +++ b/tests/font-features-cvXX.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \use[module=packages.features] diff --git a/tests/footnote-skip.sil b/tests/footnote-skip.sil index 104cee520..4babbb28d 100644 --- a/tests/footnote-skip.sil +++ b/tests/footnote-skip.sil @@ -1,4 +1,5 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \use[module=packages.rules] \begin{script} diff --git a/tests/footnote.sil b/tests/footnote.sil index 53432aec3..f925d5e1c 100644 --- a/tests/footnote.sil +++ b/tests/footnote.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.lorem] \font[family=Gentium Plus,size=10pt] diff --git a/tests/grid.sil b/tests/grid.sil index b5bdbd28f..3d7f7c303 100644 --- a/tests/grid.sil +++ b/tests/grid.sil @@ -1,4 +1,6 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \use[module=packages.grid] \use[module=packages.frametricks] diff --git a/tests/hangafter.sil b/tests/hangafter.sil index 72e36f057..658afcc06 100644 --- a/tests/hangafter.sil +++ b/tests/hangafter.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.lorem] \set[parameter=document.parskip,value=1ex] diff --git a/tests/image.sil b/tests/image.sil index ea50fbd0f..ef03f44ab 100644 --- a/tests/image.sil +++ b/tests/image.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.image] One two \img[src=documentation/fig1.png,width=50] three diff --git a/tests/inline-lua.sil b/tests/inline-lua.sil index 174335f2c..9cecda9bf 100644 --- a/tests/inline-lua.sil +++ b/tests/inline-lua.sil @@ -1,4 +1,5 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] % A real comment \begin{script} answer = { output = tostring(3 * 3 % 5) } diff --git a/tests/kannada.sil b/tests/kannada.sil index 8d0e49d2e..8f9d232f9 100644 --- a/tests/kannada.sil +++ b/tests/kannada.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \noindent \font[family=Libertinus Serif,size=16pt] diff --git a/tests/letterspacing.sil b/tests/letterspacing.sil index 9d44e0852..9a319ab2c 100644 --- a/tests/letterspacing.sil +++ b/tests/letterspacing.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] No letterspacing. diff --git a/tests/linespacing.sil b/tests/linespacing.sil index e90724b75..90f2d22eb 100644 --- a/tests/linespacing.sil +++ b/tests/linespacing.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \nofolios \font[family=Libertinus Serif,size=12pt] diff --git a/tests/linespacing2.sil b/tests/linespacing2.sil index a56580c73..c753e17fb 100644 --- a/tests/linespacing2.sil +++ b/tests/linespacing2.sil @@ -1,4 +1,5 @@ \begin{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Libertinus Serif,size=11pt] \use[module=packages.linespacing] diff --git a/tests/masters.sil b/tests/masters.sil index f09a2ed95..a86b68e35 100644 --- a/tests/masters.sil +++ b/tests/masters.sil @@ -1,4 +1,5 @@ \begin{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.masters] \use[module=packages.lorem] \use[module=packages.frametricks] diff --git a/tests/math-bigops.xml b/tests/math-bigops.xml index b10e6805e..a4d714423 100644 --- a/tests/math-bigops.xml +++ b/tests/math-bigops.xml @@ -1,4 +1,5 @@ <sile> +<use module="packages.retrograde" target="v0.15.0" /> <use module="packages.math"/> Big operators, text, MathML: diff --git a/tests/math-fractions.xml b/tests/math-fractions.xml index 64e6e347d..46125a2e3 100644 --- a/tests/math-fractions.xml +++ b/tests/math-fractions.xml @@ -1,4 +1,5 @@ <sile> +<use module="packages.retrograde" target="v0.15.0" /> <use module="packages.math"/> Fractions, text, MathML: diff --git a/tests/math-ops.sil b/tests/math-ops.sil index 200c00ae1..229a3d61a 100644 --- a/tests/math-ops.sil +++ b/tests/math-ops.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \script[src=packages/math] diff --git a/tests/math-spaces.sil b/tests/math-spaces.sil index db1ca80fc..937d4bbed 100644 --- a/tests/math-spaces.sil +++ b/tests/math-spaces.sil @@ -1,4 +1,5 @@ \begin[class=plain]{document} +\use[module=packages.retrograde,target=v0.15.0] \script[src=packages/math] diff --git a/tests/math-stretchy.xml b/tests/math-stretchy.xml index 2dbb47547..a3c8ba33f 100644 --- a/tests/math-stretchy.xml +++ b/tests/math-stretchy.xml @@ -1,4 +1,5 @@ <sile> +<use module="packages.retrograde" target="v0.15.0" /> <use module="packages.math"/> Stretchy parentheses, text, MathML: diff --git a/tests/math-subsup.xml b/tests/math-subsup.xml index 0b5bb7663..dec315905 100644 --- a/tests/math-subsup.xml +++ b/tests/math-subsup.xml @@ -1,4 +1,5 @@ <sile> +<use module="packages.retrograde" target="v0.15.0" /> <use module="packages.math"/> Sub-superscripts, text, MathML: diff --git a/tests/math-tables-mathml.xml b/tests/math-tables-mathml.xml index 79ecabb10..7ebdfe5db 100644 --- a/tests/math-tables-mathml.xml +++ b/tests/math-tables-mathml.xml @@ -1,4 +1,5 @@ <sile> +<use module="packages.retrograde" target="v0.15.0" /> <use module="packages.math"/> Number matrix, text, MathML: diff --git a/tests/math-tables-tex.sil b/tests/math-tables-tex.sil index e22730bad..924bfb327 100644 --- a/tests/math-tables-tex.sil +++ b/tests/math-tables-tex.sil @@ -1,4 +1,5 @@ \begin[class=plain]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.math] diff --git a/tests/math-variants.xml b/tests/math-variants.xml index 0e08d9ad4..5850deabe 100644 --- a/tests/math-variants.xml +++ b/tests/math-variants.xml @@ -1,4 +1,5 @@ <sile> +<use module="packages.retrograde" target="v0.15.0" /> <use module="packages.math"/> Math variants, text, MathML: diff --git a/tests/mini-arabic.sil b/tests/mini-arabic.sil index 039b64745..206cf89aa 100644 --- a/tests/mini-arabic.sil +++ b/tests/mini-arabic.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.bidi] \thisframeRTL diff --git a/tests/mlcounter.sil b/tests/mlcounter.sil index f0c62a1ea..617c86dc7 100644 --- a/tests/mlcounter.sil +++ b/tests/mlcounter.sil @@ -1,4 +1,5 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.counters] \increment-multilevel-counter[id=test] diff --git a/tests/negative-spaces-in-line.sil b/tests/negative-spaces-in-line.sil index 4838acb3a..cd44cdcd4 100644 --- a/tests/negative-spaces-in-line.sil +++ b/tests/negative-spaces-in-line.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,direction=RTL-TTB]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \font[family=Awami Nastaliq,size=22] diff --git a/tests/nondeterminism.sil b/tests/nondeterminism.sil index 07412c8a1..c003469dd 100644 --- a/tests/nondeterminism.sil +++ b/tests/nondeterminism.sil @@ -1,6 +1,7 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[size=11pt,family=Gentium Plus] -\noindent{}Now that we understand some of what SILE is about and what it seeks to do, +\noindent{}Now that we understand some of what SILE is about and what it seeks to do, let’s dive into SILE itself. \end{document} diff --git a/tests/parshaping-simple.sil b/tests/parshaping-simple.sil index 1f7e8ebfc..d695f4b60 100644 --- a/tests/parshaping-simple.sil +++ b/tests/parshaping-simple.sil @@ -1,4 +1,5 @@ \begin[papersize=a7]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.lorem] \begin{script} diff --git a/tests/rskip.sil b/tests/rskip.sil index 1c2e1b393..97cba4ef4 100644 --- a/tests/rskip.sil +++ b/tests/rskip.sil @@ -1,4 +1,5 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \set[parameter=document.rskip,value=20mm] \lorem[words=50] diff --git a/tests/settings.sil b/tests/settings.sil index 03e13b2cb..e352a2fbf 100644 --- a/tests/settings.sil +++ b/tests/settings.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent foo diff --git a/tests/split-footnote.sil b/tests/split-footnote.sil index 9c5201416..5afe6e1ee 100644 --- a/tests/split-footnote.sil +++ b/tests/split-footnote.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \use[module=packages.lorem] \nofolios Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod diff --git a/tests/sura-2.sil b/tests/sura-2.sil index f077563a4..b845eef3d 100644 --- a/tests/sura-2.sil +++ b/tests/sura-2.sil @@ -1,4 +1,5 @@ \begin[papersize=a6,direction=RTL]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[family=Amiri Quran,size=20pt] \use[module=packages.linespacing] diff --git a/tests/tracking.sil b/tests/tracking.sil index 6b730039b..ce5c707f9 100644 --- a/tests/tracking.sil +++ b/tests/tracking.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[size=20pt] \set[parameter=document.parindent,value=0] diff --git a/tests/twoside.sil b/tests/twoside.sil index 45cac8390..837879def 100644 --- a/tests/twoside.sil +++ b/tests/twoside.sil @@ -1,4 +1,5 @@ \begin[papersize=a8,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent % Note folio suppression on some pages are part of test \begin[command=stuff]{define} diff --git a/tests/variations-axis.sil b/tests/variations-axis.sil index bc43280d5..4103ead91 100644 --- a/tests/variations-axis.sil +++ b/tests/variations-axis.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \font[family=Tourney,size=48pt] diff --git a/tests/vertical.sil b/tests/vertical.sil index 3c9fcf787..faaae3f17 100644 --- a/tests/vertical.sil +++ b/tests/vertical.sil @@ -1,4 +1,5 @@ \begin[class=jplain,layout=tate]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios % Note: differences between Noto font versions make adding more characters to % this test brittle. For example 日本は昔からruns into trouble when the height From c242ff7480cbbac180fc869d8d6534e0382f915f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 17 Dec 2023 00:16:25 +0300 Subject: [PATCH 204/357] chore(packages): Add changed default setting to retrograde package --- packages/retrograde/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 33e509ca0..3261b011c 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -14,6 +14,7 @@ end package.default_settings = { ["0.15.0"] = { ["shaper.spaceenlargementfactor"] = 1.2, + ["document.parindent"] = "20pt", }, } From 9fa3bd9fe1d82713e535faf6c06074325df9ade2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 17 Dec 2023 00:39:33 +0300 Subject: [PATCH 205/357] test(packages): Update test expectations to new defaults --- tests/absmin.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/absmin.expected b/tests/absmin.expected index 71163b2a5..59c4dc8ce 100644 --- a/tests/absmin.expected +++ b/tests/absmin.expected @@ -1,6 +1,6 @@ Set paper size 595.275597 841.8897729 Begin page -Mx 49.7638 +Mx 41.7638 My 48.3445 Set font Gentium Plus;10;400;;normal;;;LTR T 87 72 86 87 w=15.3662 (test) From fc4984225ae470d6efea6c312c8b9844238d2f99 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 17 Dec 2023 00:40:26 +0300 Subject: [PATCH 206/357] test(packages): Use retrograde package to avoid test expectation churn --- tests/bug-1699.sil | 1 + tests/bug-522.sil | 3 ++- tests/bug-892.sil | 1 + tests/crash.sil | 1 + tests/hyph-except.sil | 1 + tests/italic.sil | 1 + tests/parallel.sil | 1 + 7 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/bug-1699.sil b/tests/bug-1699.sil index 32f3f4474..6a59383a8 100644 --- a/tests/bug-1699.sil +++ b/tests/bug-1699.sil @@ -1,4 +1,5 @@ \begin[class=plain,papersize=a7]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios % Both "bar" entries should have parindent applied \noindent diff --git a/tests/bug-522.sil b/tests/bug-522.sil index e1c40bd7b..19139597a 100644 --- a/tests/bug-522.sil +++ b/tests/bug-522.sil @@ -1,4 +1,5 @@ \begin[papersize=a5,class=book]{document} +\use[module=packages.retrograde,target=v0.15.0] \show-multilevel-counter[id=foo] \increment-multilevel-counter[id=foo,level=3] @@ -10,4 +11,4 @@ \increment-multilevel-counter[id=foo,level=2] \show-multilevel-counter[id=foo] -\end{document} \ No newline at end of file +\end{document} diff --git a/tests/bug-892.sil b/tests/bug-892.sil index 2cf46ace5..078c03b3d 100644 --- a/tests/bug-892.sil +++ b/tests/bug-892.sil @@ -1,4 +1,5 @@ \begin{document} +\use[module=packages.retrograde,target=v0.15.0] \define[command=micro]{} \define[command=macro]{\process} \begin{script} diff --git a/tests/crash.sil b/tests/crash.sil index 74a7f0c95..249988786 100644 --- a/tests/crash.sil +++ b/tests/crash.sil @@ -1,3 +1,4 @@ \begin[papersize=a5]{document} +\use[module=packages.retrograde,target=v0.15.0] verylongwordverylongwordverylongwordverylongwordveryverylongwordveryverylongwordveryverylongwordveryverylongwordveryverylongwordveryverylongwordveryverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordvery \end{document} diff --git a/tests/hyph-except.sil b/tests/hyph-except.sil index e1b7766c9..3674a487d 100644 --- a/tests/hyph-except.sil +++ b/tests/hyph-except.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \language[main=tr] \script{SILE.typesetter:typeset(SILE.showHyphenationPoints("rab'bin", "tr"))} diff --git a/tests/italic.sil b/tests/italic.sil index 1e6520474..409f367d5 100644 --- a/tests/italic.sil +++ b/tests/italic.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \font[style=italic]{Italic?} \end{document} diff --git a/tests/parallel.sil b/tests/parallel.sil index 7476c5a0d..8c3fb1182 100644 --- a/tests/parallel.sil +++ b/tests/parallel.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \begin{script} local class = SILE.documentState.documentClass From e975ff9fe6715aa7df3acbe6b4983b87649a041c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 17 Dec 2023 00:48:42 +0300 Subject: [PATCH 207/357] chore(packages): Rename debug option to match package name --- packages/retrograde/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 3261b011c..56584b7bf 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -29,7 +29,7 @@ function package:defaults (target) for version, settings in pl.tablex.sort(self.default_settings, semver_descending) do version = semver(version) for parameter, value in pairs(settings) do - SU.debug("defaults", ("Resetting '%s' to '%s' as it was prior to v%s"):format(parameter, tostring(value), version)) + SU.debug("retrograde", ("Resetting '%s' to '%s' as it was prior to v%s"):format(parameter, tostring(value), version)) SILE.settings:set(parameter, value, true) end if target_hit then break end From ad2faa5a7f79d078decb26f592b2389ad1708a25 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 13 Dec 2023 15:25:38 +0300 Subject: [PATCH 208/357] refactor(packages): Re-organize sheet size logic so errors happen in a more related function --- classes/base.lua | 35 +++++++++++++++-------------------- documentation/c03-input.sil | 20 +++++++++++--------- outputters/libtexpdf.lua | 12 ++++++++---- packages/cropmarks/init.lua | 2 +- tests/bug-337.sil | 2 +- 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 090d5cdc8..aab8cb138 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -92,24 +92,6 @@ function class:setOptions (options) for option, value in pairs(options) do self.options[option] = value end - if not SILE.documentState.sheetSize then - SILE.documentState.sheetSize = { - SILE.documentState.paperSize[1], - SILE.documentState.paperSize[2] - } - end - if SILE.documentState.sheetSize[1] < SILE.documentState.paperSize[1] - or SILE.documentState.sheetSize[2] < SILE.documentState.paperSize[2] then - SU.error("Sheet size shall not be smaller than the paper size") - end - if SILE.documentState.sheetSize[1] < SILE.documentState.paperSize[1] + SILE.documentState.bleed then - SU.debug("frames", "Sheet size width augmented to take page bleed into account") - SILE.documentState.sheetSize[1] = SILE.documentState.paperSize[1] + SILE.documentState.bleed - end - if SILE.documentState.sheetSize[2] < SILE.documentState.paperSize[2] + SILE.documentState.bleed then - SU.debug("frames", "Sheet size height augmented to take page bleed into account") - SILE.documentState.sheetSize[2] = SILE.documentState.paperSize[2] + SILE.documentState.bleed - end end function class:declareOption (option, setter) @@ -153,9 +135,22 @@ function class:declareOptions () if size then self.sheetsize = size SILE.documentState.sheetSize = SILE.papersize(size, self.options.landscape) + if SILE.documentState.sheetSize[1] < SILE.documentState.paperSize[1] + or SILE.documentState.sheetSize[2] < SILE.documentState.paperSize[2] then + SU.error("Sheet size shall not be smaller than the paper size") + end + if SILE.documentState.sheetSize[1] < SILE.documentState.paperSize[1] + SILE.documentState.bleed then + SU.debug("frames", "Sheet size width augmented to take page bleed into account") + SILE.documentState.sheetSize[1] = SILE.documentState.paperSize[1] + SILE.documentState.bleed + end + if SILE.documentState.sheetSize[2] < SILE.documentState.paperSize[2] + SILE.documentState.bleed then + SU.debug("frames", "Sheet size height augmented to take page bleed into account") + SILE.documentState.sheetSize[2] = SILE.documentState.paperSize[2] + SILE.documentState.bleed + end + else + return self.sheetsize end - return self.sheetsize - end) + end) self:declareOption("bleed", function (_, dimen) if dimen then self.bleed = dimen diff --git a/documentation/c03-input.sil b/documentation/c03-input.sil index 16edf8e54..a8a42f390 100644 --- a/documentation/c03-input.sil +++ b/documentation/c03-input.sil @@ -8,7 +8,7 @@ It is even less true now that 3rd party plugins can add their own input formats. Hence this chanpter has been renamed. The original chapter title was "SILE’s Input Language", as if there was only one. -The truth is there \em{is} an input syntax we call "SIL", but even that is perhaps best thought of as a structured data systax rather than a unique language. +The truth is there \em{is} an input syntax we call "SIL", but even that is perhaps best thought of as a structured data syntax rather than a unique language. The input strings \code{\\em\{foo\}} in SIL input syntax is 100\% equivalent to \code{<em>foo</em>} in XML input syntax. The SIL input syntax is provided as an easier to type alternative than XML which can be a bit verbose and tedious to work with by hand. On the other hand if you're handling data written by some other program, XML might be a much better solution. @@ -61,6 +61,16 @@ Once some of the basic document properties have been set up using these fixed si For example, once the paper size is set, percentage of page width (\code{\%pw}) and height(\code{\%ph}) become valid units. In Chapter 4 we will meet more of these relative units, and in Chapter 7 we will meet some other ways of specifying lengths to make them stretchable or shrinkable. +\subsection{Setting orientation as landscape} + +The orientation of the page is defined as "portrait" by default, but if you want to set it as landscape there is an option for that: + +\begin[type=autodoc:codeblock]{raw} +\begin[landscape=true]{document} +\end{raw} + +\subsection{Full bleed printing} + When preparing a book for press printing, you may be asked by the professional printer to output the document on a larger sheet than your target paper, and to reserve a trim area around it. This trick is often called “full bleed printing”. Your document will be printed on an oversized sheet that will then be mechanically cut down to the target size. @@ -80,14 +90,6 @@ Finally, there is also the case when the actual paper sheets available to you ar For instance, \code{papersize=6in x 9in, sheetsize=a4} produces an A4-dimensioned document, but with you content formatted as a 6 per 9 inches US trade book. You may, obviously, combine these options and also specify a bleed area. -\subsection{Setting orientation as landscape} - -The orientation of the page is defined as "portrait" by default, but if you want to set it as landscape there is an option for that: - -\begin[type=autodoc:codeblock]{raw} -\begin[landscape=true]{document} -\end{raw} - \section{Ordinary text} On the whole, ordinary text isn’t particularly interesting—it’s just typeset. diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index 34d06f1d1..7750c135a 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -28,13 +28,15 @@ local deltaX local deltaY local function trueXCoord (x) if not deltaX then - deltaX = (SILE.documentState.sheetSize[1] - SILE.documentState.paperSize[1]) / 2 + local sheetSize = SILE.documentState.sheetSize or SILE.documentState.paperSize + deltaX = (sheetSize[1] - SILE.documentState.paperSize[1]) / 2 end return x + deltaX end local function trueYCoord (y) if not deltaY then - deltaY = (SILE.documentState.sheetSize[2] - SILE.documentState.paperSize[2]) / 2 + local sheetSize = SILE.documentState.sheetSize or SILE.documentState.paperSize + deltaY = (sheetSize[2] - SILE.documentState.paperSize[2]) / 2 end return y + deltaY end @@ -45,7 +47,8 @@ end function outputter:_ensureInit () if not started then - local w, h = SILE.documentState.sheetSize[1], SILE.documentState.sheetSize[2] + local sheetSize = SILE.documentState.sheetSize or SILE.documentState.paperSize + local w, h = sheetSize[1], sheetSize[2] local fname = self:getOutputFilename() -- Ideally we could want to set the PDF CropBox, BleedBox, TrimBox... -- Our wrapper only manages the MediaBox at this point. @@ -193,7 +196,8 @@ function outputter:drawSVG (figure, x, y, _, height, scalefactor) pdf.add_content("q") self:setCursor(x, y) x, y = self:getCursor() - local newy = y - SILE.documentState.paperSize[2] / 2 + height - SILE.documentState.sheetSize[2] / 2 + local sheetSize = SILE.documentState.sheetSize or SILE.documentState.paperSize + local newy = y - SILE.documentState.paperSize[2] / 2 + height - sheetSize[2] / 2 pdf.add_content(table.concat({ scalefactor, 0, 0, -scalefactor, trueXCoord(x), newy, "cm" }, " ")) pdf.add_content(figure) pdf.add_content("Q") diff --git a/packages/cropmarks/init.lua b/packages/cropmarks/init.lua index f889be605..2fd529f56 100644 --- a/packages/cropmarks/init.lua +++ b/packages/cropmarks/init.lua @@ -58,7 +58,7 @@ end function package:registerCommands () self:registerCommand("cropmarks:header", function (_, _) - local info = SILE.masterFilename + local info = SILE.input.filenames[1] .. " - " .. self.class.packages.date:date({ format = "%x %X" }) .. " - " .. outcounter diff --git a/tests/bug-337.sil b/tests/bug-337.sil index 54ca7a454..4cdfd922e 100644 --- a/tests/bug-337.sil +++ b/tests/bug-337.sil @@ -1,4 +1,4 @@ -\begin[papersize=a7,class=book, sheetsize=a6]{document} +\begin[papersize=a7,class=book,sheetsize=a6]{document} \use[module=packages.color] \script[src=inc.bug-337] \define[command=cropmarks:header]{tests/bug-337.sil} From c0571befc9187f74e9f8376ed238382fd87fac36 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 19 Dec 2023 15:17:41 +0300 Subject: [PATCH 209/357] fix(build): Adjust macfonts module to more robustly import AppKit --- build-aux/pkg.nix | 2 -- justenough/macfonts.m | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build-aux/pkg.nix b/build-aux/pkg.nix index 2b53be20d..9f6380360 100644 --- a/build-aux/pkg.nix +++ b/build-aux/pkg.nix @@ -118,8 +118,6 @@ in stdenv.mkDerivation (finalAttrs: { postPatch = '' patchShebangs build-aux/*.sh build-aux/git-version-gen - '' + lib.optionalString stdenv.isDarwin '' - sed -i -e 's|@import AppKit;|#import <AppKit/AppKit.h>|' src/macfonts.m ''; NIX_LDFLAGS = lib.optionalString stdenv.isDarwin "-framework AppKit"; diff --git a/justenough/macfonts.m b/justenough/macfonts.m index d63850d47..0596a144f 100644 --- a/justenough/macfonts.m +++ b/justenough/macfonts.m @@ -1,4 +1,5 @@ -@import AppKit; +#import <AppKit/AppKit.h> + #include <stdio.h> #include <lua.h> #include <lauxlib.h> From b6a79676f541a8ece79ec180e2c2a1860e9f4723 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 19 Dec 2023 15:23:57 +0300 Subject: [PATCH 210/357] chore(build): Drop obsolete Nix flake workaround --- build-aux/pkg.nix | 9 --------- 1 file changed, 9 deletions(-) diff --git a/build-aux/pkg.nix b/build-aux/pkg.nix index 9f6380360..0be09f536 100644 --- a/build-aux/pkg.nix +++ b/build-aux/pkg.nix @@ -138,15 +138,6 @@ in stdenv.mkDerivation (finalAttrs: { touch source/build-aux/rust_boilerplate.mk ''; - # remove forbidden references to $TMPDIR - preFixup = lib.optionalString stdenv.isLinux '' - for f in "$out"/bin/*; do - if isELF "$f"; then - patchelf --shrink-rpath --allowed-rpath-prefixes "$NIX_STORE" "$f" - fi - done - ''; - passthru = { # So it will be easier to inspect this environment, in comparison to others inherit luaEnv; From f5114d35312b293d8727a24d495789997f884764 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 19 Dec 2023 15:37:12 +0300 Subject: [PATCH 211/357] chore(build): Avoid baking Rust identifier into version string twice --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e77d704f5..6efc0b115 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,7 @@ pub fn inject_version(lua: &Lua) { let sile: LuaTable = lua.globals().get("SILE").unwrap(); let mut full_version: String = sile.get("full_version").unwrap(); full_version.push_str(" [Rust]"); + sile.set("full_version", full_version).unwrap(); } pub fn load_sile(lua: &Lua) { @@ -64,8 +65,7 @@ pub fn load_sile(lua: &Lua) { pub fn version() -> crate::Result<String> { let lua = start_luavm()?; let sile: LuaTable = lua.globals().get("SILE").unwrap(); - let mut full_version: String = sile.get("full_version").unwrap(); - full_version.push_str(" [Rust]"); + let full_version: String = sile.get("full_version").unwrap(); Ok(full_version) } From 694e000f6350ac3d054cec5595629b525193be4a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 19 Dec 2023 16:00:28 +0300 Subject: [PATCH 212/357] chore(cli): Avoid deprecation error if includes not actually used --- core/cli.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/cli.lua b/core/cli.lua index 2226f9896..0f81ab3e7 100644 --- a/core/cli.lua +++ b/core/cli.lua @@ -119,7 +119,7 @@ cli.parseArguments = function () for _, path in ipairs(opts.postamble) do table.insert(SILE.input.postambles, path) end - if opts.include then + if #opts.include > 0 then SU.deprecated("-I/--include", "-u/--use or -p/--preamble", "0.14.0", "0.15.0") end -- http://lua-users.org/wiki/VarargTheSecondClassCitizen From 6b5f52d37bae44c710eea17b297f038157eb1164 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 22 Dec 2023 15:21:46 +0300 Subject: [PATCH 213/357] feat(packages): Backport default font change from v0.9.5 to retrograde package --- packages/retrograde/init.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 33e509ca0..c6c602876 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -15,6 +15,9 @@ package.default_settings = { ["0.15.0"] = { ["shaper.spaceenlargementfactor"] = 1.2, }, + ["0.9.5"] = { + ["font.family"] = "Gentium Basic", + }, } function package:_init (options) From 6fc5bea38b524e88028677f4831eed25d37a92ef Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 22 Dec 2023 15:21:46 +0300 Subject: [PATCH 214/357] chore(packages): Fix retrograde package to stop at target, not target+1 --- packages/retrograde/init.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index c6c602876..2669cb900 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -27,14 +27,18 @@ end function package:defaults (target) target = semver(target and target or SILE.version) + SU.debug("retrograde", ("Targeting default changes back as far as the release of SILE v%s."):format(target)) local target_hit = false for version, settings in pl.tablex.sort(self.default_settings, semver_descending) do version = semver(version) + if target_hit then + SU.debug("retrograde", ("The next set of default changes is from the release of SILE v%s, stopping."):format(version)) + break + end for parameter, value in pairs(settings) do - SU.debug("defaults", ("Resetting '%s' to '%s' as it was prior to v%s"):format(parameter, tostring(value), version)) + SU.debug("retrograde", ("Resetting '%s' to '%s' as it was prior to v%s."):format(parameter, tostring(value), version)) SILE.settings:set(parameter, value, true) end - if target_hit then break end if version <= target then target_hit = true end end end From 75a07afe1b43426e73c48d971fb8603051a0a1f8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 22 Dec 2023 16:51:56 +0300 Subject: [PATCH 215/357] chore(tooling): Colorize regression test diff output (optional) To use a different diff highlighter, set at configure time. ./configure DELTA=diff-so-fancy To disable, use cat: ./configure DELTA=cat --- .cirrus.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/test.yml | 2 +- configure.ac | 1 + flake.nix | 2 ++ tests/regressions.pl.in | 5 ++++- 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index ab336409b..b85f5dd1a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -43,7 +43,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false PDFINFO=false NIX=false \ + --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false \ --disable-font-variations \ --with-system-lua-sources \ --with-system-luarocks \ diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 527cdff82..5af3ebd0d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -60,7 +60,7 @@ jobs: run: | ./bootstrap.sh ./configure \ - --enable-developer LUACHECK=false NIX=false \ + --enable-developer LUACHECK=false NIX=false DELTA=cat \ --disable-font-variations \ --without-manual - name: Make diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6393d6469..229faf68b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: ./bootstrap.sh ./configure \ ${{ matrix.luaVersion[1] }} \ - --enable-developer LUACHECK=false NIX=false \ + --enable-developer LUACHECK=false NIX=false DELTA=cat \ --disable-font-variations \ --with${{ !startsWith(matrix.luaVersion[0], 'luajit') && 'out' || '' }}-luajit \ --without-manual diff --git a/configure.ac b/configure.ac index 51446e1d8..0db7e0ad7 100644 --- a/configure.ac +++ b/configure.ac @@ -214,6 +214,7 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_PROGVAR([luarocks]) AX_PROGVAR([nix]) AX_PROGVAR([perl]) + AX_PROGVAR([delta]) ]) ]) diff --git a/flake.nix b/flake.nix index 756e3dbc4..fe1ceaf0c 100644 --- a/flake.nix +++ b/flake.nix @@ -80,6 +80,8 @@ configureFlags = sile.configureFlags ++ [ "--enable-developer" ]; nativeBuildInputs = sile.nativeBuildInputs ++ [ pkgs.luarocks + # For regression test diff highlighting + pkgs.delta # For commitlint git hook pkgs.yarn # For npx diff --git a/tests/regressions.pl.in b/tests/regressions.pl.in index 65198c357..bea5e7f64 100644 --- a/tests/regressions.pl.in +++ b/tests/regressions.pl.in @@ -10,6 +10,9 @@ my (@failed, @passed, @unsupported, @knownbad, @knownbadbutpassing, @missing); my @specifics = @ARGV; my @DISABLEDSRCS = split(/ +/, $DISABLEDSRCS); +my $highlighter = -t STDOUT ? "| @DELTA@" : ""; +my $diffcontext = -t STDOUT ? "2" : "0"; + my $exit = 0; for (@specifics ? @specifics : <tests/*.sil tests/*.xml tests/*.nil>) { my $expectation = $_; $expectation =~ s/\.(sil|xml)$/\.expected/; @@ -30,7 +33,7 @@ for (@specifics ? @specifics : <tests/*.sil tests/*.xml tests/*.nil>) { push @failed, $_; } elsif (!system("grep -qx 'UNSUPPORTED' $actual")) { $unsupported = 1; - } elsif (!system("diff -".($knownbad?"q":"")."U0 $expectation $actual")) { + } elsif (!system("diff -".($knownbad?"q":"")."U$diffcontext $expectation $actual $highlighter")) { if ($knownbad) { push @knownbadbutpassing, $_; } else { push @passed, $_; } } elsif ($knownbad) { From 5a3f6332ab4ae0ae6d9ab5090fd421a564ca9257 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 23 Dec 2023 23:03:35 +0300 Subject: [PATCH 216/357] test(packages): Update tests from master with development defaults --- tests/dropcaps-descenders.sil | 1 + tests/feat-unicode-nbsp.sil | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/dropcaps-descenders.sil b/tests/dropcaps-descenders.sil index cecf0d5e2..7c6789ac5 100644 --- a/tests/dropcaps-descenders.sil +++ b/tests/dropcaps-descenders.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent \script[src=packages/dropcaps] diff --git a/tests/feat-unicode-nbsp.sil b/tests/feat-unicode-nbsp.sil index f4ce0f5c2..b28a557db 100644 --- a/tests/feat-unicode-nbsp.sil +++ b/tests/feat-unicode-nbsp.sil @@ -1,4 +1,5 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] \neverindent \nofolios \language[main=und] From f581b54a0dcf23fc7e0d64dc4206cfea68c4a2e3 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 00:05:33 +0300 Subject: [PATCH 217/357] feat(tooling): Add DRAFT flag to allow rendering docs without regenerating TOC --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 23a68cdac..2e796171e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -139,6 +139,7 @@ DEPDIR := .deps LOCALFONTS := FONTCONFIG_FILE=$(PWD)/fontconfig.conf LOCALPATHS := SILE_PATH="$(PWD);libtexpdf/.libs;justenough/.libs" SILEFLAGS ?= -m $(DEPDIR)/$(basename $@).d -d versions -f fontconfig +DRAFT ?= false dist-hook: $(MANUAL) dist-hook-distfiles @@ -185,7 +186,7 @@ define runsile = mkdir -p $(DEPDIR)/$$(dirname $@) $(silepass) export -n SILE_COVERAGE - if $(hastoc); then + if $$($(hastoc)) && ! $(DRAFT); then $${hadtoc} || $(silepass) [ "$${pg}" = "$${pg0}" ] || $(silepass) fi From e05b9e0a7835a6f3542ef9e9ee2ef1846006c8fa Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 08:35:26 +0300 Subject: [PATCH 218/357] refactor(packages,outputters): Raname and adjust argument order of new functions --- outputters/base.lua | 6 +++--- outputters/libtexpdf.lua | 10 +++++----- packages/pdf/init.lua | 7 +++---- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/outputters/base.lua b/outputters/base.lua index 4888a0605..32b7df2fb 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -34,11 +34,11 @@ function outputter.debugFrame (_, _, _) end function outputter.debugHbox (_, _, _) end -function outputter.linkAnchor (_, _, _) end -- Unstable API +function outputter.setLinkAnchor (_, _, _) end -- Unstable API -function outputter.enterLinkTarget (_, _, _) end -- Unstable API +function outputter.beginLink (_, _, _) end -- Unstable API -function outputter.leaveLinkTarget (_, _, _, _, _, _, _) end -- Unstable API +function outputter.endLink (_, _, _, _, _, _, _) end -- Unstable API function outputter.setMetadata (_, _, _) end diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index 7750c135a..abef5d489 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -307,7 +307,7 @@ end -- Unstable link APIs -function outputter:linkAnchor (x, y, name) +function outputter:setLinkAnchor (name, x, y) x = SU.cast("number", x) y = SU.cast("number", y) self:_ensureInit() @@ -328,17 +328,18 @@ local function borderStyle (style, width) return "/Border[0 0 " .. width .. "]" end -function outputter:enterLinkTarget (_, _) -- destination, options as argument +function outputter:startLink (_, _) -- destination, options as argument + self:_ensureInit() -- HACK: -- Looking at the code, pdf.begin_annotation does nothing, and Simon wrote a comment -- about tracking boxes. Unsure what he implied with this obscure statement. -- Sure thing is that some backends may need the destination here, e.g. an HTML backend -- would generate a <a href="#destination">, as well as the options possibly for styling -- on the link opening? - self:_ensureInit() pdf.begin_annotation() end -function outputter.leaveLinkTarget (_, x0, y0, x1, y1, dest, opts) + +function outputter.endLink (_, dest, opts, x0, y0, x1, y1) local bordercolor = borderColor(opts.bordercolor) local borderwidth = SU.cast("integer", opts.borderwidth) local borderstyle = borderStyle(opts.borderstyle, borderwidth) @@ -375,7 +376,6 @@ function outputter:setMetadata (key, value) end function outputter:setBookmark (dest, title, level) - -- Added UTF8 to UTF16-BE conversion -- For annotations and bookmarks, text strings must be encoded using -- either PDFDocEncoding or UTF16-BE with a leading byte-order marker. -- As PDFDocEncoding supports only limited character repertoire for diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index 9a9e2f394..223578709 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -19,7 +19,7 @@ function package:registerCommands () local x, y = state.cursorX, state.cursorY typesetter.frame:advancePageDirection(line.height) local _y = SILE.documentState.paperSize[2] - y - SILE.outputter:linkAnchor(x, _y, name) + SILE.outputter:setLinkAnchor(name, x, _y) end }) end) @@ -74,7 +74,6 @@ function package:registerCommands () borderwidth = borderwidth, borderoffset = borderoffset } - local x0, y0 SILE.typesetter:pushHbox({ value = nil, @@ -84,7 +83,7 @@ function package:registerCommands () outputYourself = function (_, typesetter, _) x0 = typesetter.frame.state.cursorX:tonumber() y0 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber() - SILE.outputter:enterLinkTarget(dest, opts) + SILE.outputter:beginLink(dest, opts) end }) local hbox, hlist = SILE.typesetter:makeHbox(content) -- hack @@ -97,7 +96,7 @@ function package:registerCommands () outputYourself = function (_, typesetter, _) local x1 = typesetter.frame.state.cursorX:tonumber() local y1 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + hbox.height):tonumber() - SILE.outputter:leaveLinkTarget(x0, y0, x1, y1, dest, opts) -- Unstable API + SILE.outputter:endLink(dest, opts, x0, y0, x1, y1) -- Unstable API end }) SILE.typesetter:pushHlist(hlist) From 3d214c3786e96a7d8add7a3742591f6b2ae1caf7 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 00:18:58 +0300 Subject: [PATCH 219/357] docs(packages): Restyle PDF package documentation --- packages/pdf/init.lua | 13 ++++++++++--- packages/pdfstructure/init.lua | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index 223578709..8bb032400 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -119,15 +119,22 @@ package.documentation = [[ The \autodoc:package{pdf} package enables basic support for PDF links and table-of-contents entries. It provides the four commands \autodoc:command{\pdf:destination}, \autodoc:command{\pdf:link}, \autodoc:command{\pdf:bookmark}, and \autodoc:command{\pdf:metadata}. -The \autodoc:command{\pdf:destination} parameter creates a link target; it expects a parameter called \autodoc:parameter{name} to uniquely identify the target. +The \autodoc:command{\pdf:destination} parameter creates a link target; + it expects a parameter called \autodoc:parameter{name} to uniquely identify the target. To create a link to that location in the document, use \autodoc:command{\pdf:link[dest=<name>]{<content>}}. -The \autodoc:command{\pdf:link} command accepts several options defining its border style: a \autodoc:parameter{borderwidth} length setting the border width (defaults to \code{0}, meaning no border), a \autodoc:parameter{borderstyle} string (can be set to \code{underline} or \code{dashed}, otherwise a solid box), a \autodoc:parameter{bordercolor} color specification for this border (defaults to \code{blue}), and finally a \autodoc:parameter{borderoffset} length for adjusting the border with some vertical space above the content and below the baseline (defaults to \code{1pt}). +The \autodoc:command{\pdf:link} command accepts several options defining its border style: + a \autodoc:parameter{borderwidth} length setting the border width (defaults to \code{0}, meaning no border), + a \autodoc:parameter{borderstyle} string (can be set to \code{underline} or \code{dashed}, otherwise a solid box), + a \autodoc:parameter{bordercolor} color specification for this border (defaults to \code{blue}), + and finally a \autodoc:parameter{borderoffset} length for adjusting the border with some vertical space above the content and below the baseline (defaults to \code{1pt}). Note that PDF renderers may vary on how they honor these border styling features on link annotations. It also has an \autodoc:parameter{external} option for URL links, which is not intended to be used directly—refer to the \autodoc:package{url} package for more flexibility typesetting external links. -To set arbitrary key-value metadata, use something like \autodoc:command{\pdf:metadata[key=Author, value=J. Smith]}. The PDF metadata field names are case-sensitive. Common keys include \code{Title}, \code{Author}, \code{Subject}, \code{Keywords}, \code{CreationDate}, and \code{ModDate}. +To set arbitrary key-value metadata, use something like \autodoc:command{\pdf:metadata[key=Author, value=J. Smith]}. +The PDF metadata field names are case-sensitive. +Common keys include \code{Title}, \code{Author}, \code{Subject}, \code{Keywords}, \code{CreationDate}, and \code{ModDate}. \end{document} ]] diff --git a/packages/pdfstructure/init.lua b/packages/pdfstructure/init.lua index 4dbfbc7c4..b4e6b113b 100644 --- a/packages/pdfstructure/init.lua +++ b/packages/pdfstructure/init.lua @@ -127,7 +127,8 @@ package.documentation = [[ \pdf:structure[type=P]{% For PDF documents to be considered accessible, they must contain a description of the PDF’s document structure. This package allows structure trees to be created and saved to the PDF file. -Currently this provides a low-level interface to creating nodes in the tree; classes which require PDF accessibility should use the \autodoc:command{\pdf:structure} command in their sectioning implementation to declare the document structure. +Currently this provides a low-level interface to creating nodes in the tree; + classes which require PDF accessibility should use the \autodoc:command{\pdf:structure} command in their sectioning implementation to declare the document structure. } \pdf:structure[type=P]{% From a33e5c73d956f07ffb70830032aeb7fb79107e5f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 00:19:26 +0300 Subject: [PATCH 220/357] feat(outputters): Add support for pdf elements to debug outputter --- outputters/debug.lua | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/outputters/debug.lua b/outputters/debug.lua index 472de5ecc..16236e090 100644 --- a/outputters/debug.lua +++ b/outputters/debug.lua @@ -162,4 +162,24 @@ function outputter:drawRule (x, y, width, depth) self:_writeline("Draw line", _round(x), _round(y), _round(width), _round(depth)) end +function outputter:setLinkAnchor (name, x, y) + self:_writeline("Setting link anchor", name, x, y) +end + +function outputter:beginLink (dest, opts) + self:_writeline("Begining a link", dest, opts) +end + +function outputter:endLink(dest, opts, x0, y0, x1, y1) + self:_writeline("Ending a link", dest, opts, x0, y0, x1, y1) +end + +function outputter:setBookmark (dest, title, level) + self:_writeline("Setting bookmark", dest, title, level) +end + +function outputter:setMetadata (key, value) + self:_writeline("Set metadata", key, value) +end + return outputter From b5422a83dd7727c671359a8a926ab5bbc450b1b2 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 12:40:02 +0300 Subject: [PATCH 221/357] feat(outputters): Add hook system to outputters --- outputters/base.lua | 22 ++++++++++++++++++++-- outputters/cairo.lua | 1 + outputters/debug.lua | 1 + outputters/libtexpdf.lua | 2 +- outputters/podofo.lua | 4 +++- outputters/text.lua | 1 + packages/pdfstructure/init.lua | 4 ++-- 7 files changed, 29 insertions(+), 6 deletions(-) diff --git a/outputters/base.lua b/outputters/base.lua index 32b7df2fb..ab0cd79b9 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -2,11 +2,29 @@ local outputter = pl.class() outputter.type = "outputter" outputter._name = "base" -function outputter._init () end +function outputter:_init () + self.hooks = {} + return self +end + +function outputter:registerHook (category, func) + if not self.hooks[category] then self.hooks[category] = {} end + table.insert(self.hooks[category], func) +end + +function outputter:runHooks (category, data) + if not self.hooks[category] then return nil end + for _, func in ipairs(self.hooks[category]) do + data = func(self, data) + end + return data +end function outputter.newPage () end -function outputter.finish () end +function outputter:finish () + self:runHooks("prefinish") +end function outputter.getCursor () end diff --git a/outputters/cairo.lua b/outputters/cairo.lua index a394b9b98..fdde05712 100644 --- a/outputters/cairo.lua +++ b/outputters/cairo.lua @@ -22,6 +22,7 @@ outputter._name = "cairo" outputter.extension = "pdf" function outputter:_init () + base._init(self) local fname = self:getOutputFilename() local surface = cairolgi.PdfSurface.create(fname == "-" and "/dev/stdout" or fname, SILE.documentState.paperSize[1], SILE.documentState.paperSize[2]) cr = cairolgi.Context.create(surface) diff --git a/outputters/debug.lua b/outputters/debug.lua index 16236e090..f3e4b2cfd 100644 --- a/outputters/debug.lua +++ b/outputters/debug.lua @@ -59,6 +59,7 @@ end function outputter:finish () if SILE.status.unsupported then self:_writeline("UNSUPPORTED") end self:_writeline("End page") + self:runHooks("prefinish") self:_writeline("Finish") outfile:close() end diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index abef5d489..f9b4915eb 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -71,7 +71,7 @@ end function outputter:finish () self:_ensureInit() pdf.endpage() - self:_endHook() + self:runHooks("prefinish") pdf.finish() started = false lastkey = nil diff --git a/outputters/podofo.lua b/outputters/podofo.lua index 61a47f451..bb3e2004c 100644 --- a/outputters/podofo.lua +++ b/outputters/podofo.lua @@ -21,7 +21,8 @@ local outputter = pl.class(base) outputter._name = "podofo" outputter.extension = "pdf" -function outputter._init (_) +function outputter:_init (_) + base._init(self) document = pdf.PdfMemDocument() pagesize = pdf.PdfRect() pagesize:SetWidth(SILE.documentState.paperSize[1]) @@ -39,6 +40,7 @@ end function outputter:finish () painter:FinishPage() + self:runHooks("prefinish") local fname = self:getOutputFilename() document:Write(fname == "-" and "/dev/stdout" or fname) end diff --git a/outputters/text.lua b/outputters/text.lua index 38fff3ed0..b9580c81a 100644 --- a/outputters/text.lua +++ b/outputters/text.lua @@ -36,6 +36,7 @@ end function outputter:finish () self:_ensureInit() + self:runHooks("prefinish") outfile:close() end diff --git a/packages/pdfstructure/init.lua b/packages/pdfstructure/init.lua index b4e6b113b..74d546e60 100644 --- a/packages/pdfstructure/init.lua +++ b/packages/pdfstructure/init.lua @@ -79,7 +79,7 @@ function package:_init () local stRoot = stNode("Document") stPointer = stRoot self:loadPackage("pdf") - function SILE.outputters.libtexpdf._endHook (_) + SILE.outputter:registerHook("prefinish", function() local catalog = pdf.get_dictionary("Catalog") local structureTree = pdf.parse("<< /Type /StructTreeRoot >>") pdf.add_dict(catalog, pdf.parse("/StructTreeRoot"), pdf.reference(structureTree)) @@ -88,7 +88,7 @@ function package:_init () pdf.add_dict(structureTree, pdf.parse("/K"), dumpTree(stRoot)) if structureNumberTree then pdf.release(structureNumberTree) end if structureTree then pdf.release(structureTree) end - end + end) end function package:registerCommands () From c0f32a5503ededeb0fb1eb8a9fc8746d8953ff1c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 09:26:30 +0300 Subject: [PATCH 222/357] refactor(packages): Mode \pdf:literal to pdfstructure package --- packages/pdf/init.lua | 24 ++---------------------- packages/pdfstructure/init.lua | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index 8bb032400..1f6b3a349 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -39,28 +39,8 @@ function package:registerCommands () }) end) - self:registerCommand("pdf:literal", function (_, content) - -- NOTE: This method is used by the pdfstructure package and should - -- probably be moved elsewhere, so there's no attempt here to delegate - -- the low-level libtexpdf call to te outputter. - if SILE.outputter._name ~= "libtexpdf" then - SU.error("pdf package requires libtexpdf backend") - end - local pdf = require("justenoughlibtexpdf") - if type(SILE.outputter._ensureInit) == "function" then - SILE.outputter:_ensureInit() - end - SILE.typesetter:pushHbox({ - value = nil, - height = SILE.measurement(0), - width = SILE.measurement(0), - depth = SILE.measurement(0), - outputYourself = function (_, _, _) - pdf.add_content(content[1]) - end - }) - end) - + -- TODO: Shim to pdfannotations package + -- self:registerCommand("pdf:literal", function (_, content) self:registerCommand("pdf:link", function (options, content) local dest = SU.required(options, "dest", "pdf:link") local external = SU.boolean(options.external, false) diff --git a/packages/pdfstructure/init.lua b/packages/pdfstructure/init.lua index 74d546e60..9deeba3d0 100644 --- a/packages/pdfstructure/init.lua +++ b/packages/pdfstructure/init.lua @@ -119,6 +119,27 @@ function package:registerCommands () stPointer = oldstPointer end) + self:registerCommand("pdf:literal", function (_, content) + -- NOTE: This method is used by the pdfstructure package and should + -- probably be moved elsewhere, so there's no attempt here to delegate + -- the low-level libtexpdf call to te outputter. + if SILE.outputter._name ~= "libtexpdf" then + SU.error("pdf package requires libtexpdf backend") + end + if type(SILE.outputter._ensureInit) == "function" then + SILE.outputter:_ensureInit() + end + SILE.typesetter:pushHbox({ + value = nil, + height = SILE.measurement(0), + width = SILE.measurement(0), + depth = SILE.measurement(0), + outputYourself = function (_, _, _) + pdf.add_content(content[1]) + end + }) + end) + end package.documentation = [[ From 23ef07eef4d0d34a2f482a4b86bd7a6e088e9b93 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 5 Jan 2024 22:34:08 +0300 Subject: [PATCH 223/357] refactor(outputters): Move backend specific functions to outputter --- outputters/base.lua | 2 ++ outputters/cairo.lua | 5 +++++ outputters/debug.lua | 4 ++++ outputters/libtexpdf.lua | 6 ++++++ outputters/podofo.lua | 6 ++++++ outputters/text.lua | 5 +++++ packages/pdfstructure/init.lua | 5 +---- 7 files changed, 29 insertions(+), 4 deletions(-) diff --git a/outputters/base.lua b/outputters/base.lua index ab0cd79b9..2d5042d8d 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -62,6 +62,8 @@ function outputter.setMetadata (_, _, _) end function outputter.setBookmark (_, _, _) end +function outputter.drawRaw (_) end + function outputter:getOutputFilename () local fname if SILE.outputFilename then diff --git a/outputters/cairo.lua b/outputters/cairo.lua index fdde05712..f5d8a5efc 100644 --- a/outputters/cairo.lua +++ b/outputters/cairo.lua @@ -120,4 +120,9 @@ function outputter:debugHbox (hbox, scaledWidth) cr:move_to(x, y) end +-- untested +function outputter.drawRaw (_, literal) + cr:show_text(literal) +end + return outputter diff --git a/outputters/debug.lua b/outputters/debug.lua index f3e4b2cfd..fa08e7152 100644 --- a/outputters/debug.lua +++ b/outputters/debug.lua @@ -183,4 +183,8 @@ function outputter:setMetadata (key, value) self:_writeline("Set metadata", key, value) end +function outputter:drawRaw (literal) + self:_writeline("Draw raw", literal) +end + return outputter diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index f9b4915eb..b18949744 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -386,4 +386,10 @@ function outputter:setBookmark (dest, title, level) pdf.bookmark(d, level) end +-- Assumes the caller known what they want to stuff in raw PDF format +function outputter:drawRaw (literal) + self:_ensureInit() + pdf.add_content(literal) +end + return outputter diff --git a/outputters/podofo.lua b/outputters/podofo.lua index bb3e2004c..70d12114d 100644 --- a/outputters/podofo.lua +++ b/outputters/podofo.lua @@ -106,4 +106,10 @@ function outputter:debugHbox (hbox, scaledWidth) --cr:move_to(x, y) end +-- untested +function outputter:drawRaw (literal) + local x, y = self:getCursor() + painter:DrawText(x, y, literal, string.len(literal)) +end + return outputter diff --git a/outputters/text.lua b/outputters/text.lua index b9580c81a..6bf74f7d8 100644 --- a/outputters/text.lua +++ b/outputters/text.lua @@ -82,4 +82,9 @@ function outputter:drawHbox (value, width) end end +function outputter:drawRaw (literal) + self:_ensureInit() + outfile:write(literal) +end + return outputter diff --git a/packages/pdfstructure/init.lua b/packages/pdfstructure/init.lua index 9deeba3d0..4749993b5 100644 --- a/packages/pdfstructure/init.lua +++ b/packages/pdfstructure/init.lua @@ -126,16 +126,13 @@ function package:registerCommands () if SILE.outputter._name ~= "libtexpdf" then SU.error("pdf package requires libtexpdf backend") end - if type(SILE.outputter._ensureInit) == "function" then - SILE.outputter:_ensureInit() - end SILE.typesetter:pushHbox({ value = nil, height = SILE.measurement(0), width = SILE.measurement(0), depth = SILE.measurement(0), outputYourself = function (_, _, _) - pdf.add_content(content[1]) + SILE.outputter:drawRaw (content[1]) end }) end) From b73850745f283fa600ce9aa85a3a22b17641369c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 6 Dec 2023 12:17:58 +0300 Subject: [PATCH 224/357] chore(classes)!: Deprecate \script in favor of more explicit options BREAKING CHANGE: The \script function was heavily overloaded to have many different functions at once and more targeted tools were introduced in SILE v0.14.0 To load 3rd party modules designed for use with SILE, use \use[module=...] instead of \script[src=...]. To run arbitrary Lua code inline use \lua{}; Lua code may be provided inline or externally via either a require= option to load a regular (non-SILE) Lua module using the Lua module path or src= option to load a file by file path. --- classes/base.lua | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 7c7768bd3..2356bb9ac 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -334,10 +334,36 @@ function class:registerCommands () self:registerCommand("script", function (options, content) local packopts = packOptions(options) + local function _deprecated (original, suggested) + SU.deprecated("\\script", "\\lua or \\use", "0.15.0", "0.16.0", ([[ + The \script function has been deprecated. It was overloaded to mean + too many different things and more targeted tools were introduced in + SILE v0.14.0. To load 3rd party modules designed for use with SILE, + replace \script[src=...] with \use[module=...]. To run arbitrary Lua + code inline use \lua{}, optionally with a require= parameter to load + a (non-SILE) Lua module using the Lua module path or src= to load a + file by file path. + + For this use case consider replacing: + + %s + + with: + + %s + ]]):format(original, suggested)) + end if SU.hasContent(content) then - return SILE.processString(content[1], options.format or "lua", nil, packopts) + local result = SILE.processString(content[1], options.format or "lua", nil, packopts) + _deprecated("\\script{...}", "\\lua{...}") + return result elseif options.src then - return SILE.require(options.src) + local module = options.src:gsub("%/", ".") + local original = (("\\script[src=%s]"):format(options.src)) + local result = SILE.require(options.src) + local suggested = (result._name and "\\use[module=%s]" or "\\lua[require=%s]"):format(module) + _deprecated(original, suggested) + return result else SU.error("\\script function requires inline content or a src file path") return SILE.processString(content[1], options.format or "lua", nil, packopts) From e2292c51dac0cae04ec13c6907dd9d0d9ba0ec94 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 6 Dec 2023 12:40:04 +0300 Subject: [PATCH 225/357] chore(tests): Update tests to use \use function --- tests/bug-1442-fallback-font-options.sil | 2 +- tests/bug-337.sil | 2 +- tests/dropcaps.sil | 2 +- tests/inc/bug-337.lua | 14 +++++++------- tests/math-ops.sil | 2 +- tests/math-spaces.sil | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/bug-1442-fallback-font-options.sil b/tests/bug-1442-fallback-font-options.sil index cbaa8f4d8..3286f03e0 100644 --- a/tests/bug-1442-fallback-font-options.sil +++ b/tests/bug-1442-fallback-font-options.sil @@ -1,7 +1,7 @@ \begin[papersize=a6]{document} \nofolios \neverindent -\script[src=packages.font-fallback] +\use[module=packages.font-fallback] \font[family=Libertinus Serif,size=50pt] \font:add-fallback[family=Libertinus Sans,size=6pt] \font:add-fallback[family=Symbola,size=.2en] diff --git a/tests/bug-337.sil b/tests/bug-337.sil index 66a746aa1..abe69f27b 100644 --- a/tests/bug-337.sil +++ b/tests/bug-337.sil @@ -1,5 +1,5 @@ \begin[papersize=a7,class=book]{document} -\script[src=inc.bug-337] +\use[module=inc.bug-337] \define[command=crop:header]{tests/bug-337.sil} \crop:setup[papersize=a6] \nofolios diff --git a/tests/dropcaps.sil b/tests/dropcaps.sil index 0515ff92e..7b72c2086 100644 --- a/tests/dropcaps.sil +++ b/tests/dropcaps.sil @@ -1,6 +1,6 @@ \begin[papersize=a6]{document} \nofolios -\script[src=packages/dropcaps] +\use[module=packages.dropcaps] \font[size=25pt] \dropcap[lines=2]{T}esting one two three, don't collide with me. Four five six, no crossing sticks. diff --git a/tests/inc/bug-337.lua b/tests/inc/bug-337.lua index f6624cd7e..1c60bc951 100644 --- a/tests/inc/bug-337.lua +++ b/tests/inc/bug-337.lua @@ -4,11 +4,11 @@ local package = pl.class(base) package._name = "bug-337" -function package:_init (class) +function package:_init () - base._init(self, class) + base._init(self) - class:defineMaster({ + self.class:defineMaster({ id = "right", firstContentFrame = "content", frames = { @@ -26,15 +26,15 @@ function package:_init (class) } } }) - class:defineMaster({ + self.class:defineMaster({ id = "left", firstContentFrame = "content", frames = {} }) - class:mirrorMaster("right", "left") - class:switchMasterOnePage("right") + self.class:mirrorMaster("right", "left") + self.class:switchMasterOnePage("right") - class:loadPackage("cropmarks") + self.class:loadPackage("cropmarks") end diff --git a/tests/math-ops.sil b/tests/math-ops.sil index 200c00ae1..0ac686dff 100644 --- a/tests/math-ops.sil +++ b/tests/math-ops.sil @@ -1,6 +1,6 @@ \begin[papersize=a5]{document} -\script[src=packages/math] +\use[module=packages.math] Custom atom types: diff --git a/tests/math-spaces.sil b/tests/math-spaces.sil index db1ca80fc..7a1122cfd 100644 --- a/tests/math-spaces.sil +++ b/tests/math-spaces.sil @@ -1,6 +1,6 @@ \begin[class=plain]{document} -\script[src=packages/math] +\use[module=packages.math] Positive space commands: From 6c0ec4d2ddc117644b860b9e0d106c41ff74c87e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 6 Dec 2023 13:27:21 +0300 Subject: [PATCH 226/357] docs(manual): Relpace suggested use of \script with \lua --- documentation/c04-useful.sil | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/documentation/c04-useful.sil b/documentation/c04-useful.sil index c4ffacd3c..6797946c0 100644 --- a/documentation/c04-useful.sil +++ b/documentation/c04-useful.sil @@ -268,41 +268,53 @@ To Sherlock Holmes she is always \em{the woman}. This is because every file is required to contain a valid XML tree, which wouldn’t be the case without a common root. SILE is written in the Lua programming language, and the Lua interpreter is available at runtime. -Just as one can run Javascript code from within a HTML document using a \code{<script>} tag, one can run Lua code from within a SILE document using a \code{\\script} command. -(It looks better in XML-flavor.) -This command has two forms: - \code{\\script[src=\em{<filename>}]} which includes a Lua file, and \code{\\script\{…\}} which runs Lua code inline. +Just as one can run Javascript code from within a HTML document using a \code{<script>} tag, one can run Lua code from within a SILE document using a \code{\\lua} command. +(A \code{\\script} command exists, but is being deprecated beginning in SILE v0.15.0.) + +This command has three modes: +\begin{itemize} +\item{A Lua library may be loaded using the Lua package path, as in \code{\\lua[require=module.spec]}.} +\item{A Lua script may run by giving a filesystem path, as in \code{\\lua[src=path/to/file.lua]}.} +\item{Lua code can be provided as inline content, as in \code{\\lua\{SILE.typesetter:typeset("foo")\}}.} +\end{itemize} + +\begin{autodoc:note} + Another former use case or \code{\\script[src=…]} was to load SILE packages. + This use case has been deprecated in favor of the more robust loader \code{\\use[module=…]}. + Be sure to use a module spec with period delimiters not a path with slashes (e.g. \code{packages.math} not \code{packages/math}). + This will ensure cross-platform compatibility as well as make sure packages don't get loaded multiple times. +\end{autodoc:note} Doing anything interesting inline requires knowledge of the internals of SILE, (thankfully the code is not that hard to read) but to get you started, the Lua function \code{SILE.typesetter:typeset(…)} will add text to a page, \code{SILE.call("…")} will call a SILE command, and \code{SILE.typesetter:leaveHmode()} ends the current paragraph and outputs the text. For example: \begin[type=autodoc:codeblock]{raw} -\begin{script} +\begin{lua} for i=1,10 do SILE.typesetter:typeset(i .. " x " .. i .. " = " .. i*i .. ". ") SILE.typesetter:leaveHmode() SILE.call("smallskip") end -\end{script} +\end{lua} \end{raw} produces the following output: \begin{autodoc:example} -\begin{script} +\begin{lua} SILE.call("indent");SILE.typesetter:leaveHmode() for i=1,10 do SILE.typesetter:typeset(i .. " x " .. i .. " = " .. i*i .. ". ") SILE.typesetter:leaveHmode() SILE.call("smallskip") end -\end{script} +\end{lua} \end{autodoc:example} There is one notable caveat when embedding Lua code documents written with the TeX-flavor markup. -Since SILE has to first parse the TeX markup to find the start and end of such script commands \em{without} understanding what’s in between, it is strictly necessary that no end tags appear inside the Lua code. -This means that for the environment block version (\code{\\begin\{script\}}) there must be no instances of \code{\\end\{script\}} inside the Lua code block, even inside a string that would otherwise be valid Lua code (e.g., if it was inside a quoted string or Lua comment). +Since SILE has to first parse the TeX markup to find the start and end of such lua commands \em{without} understanding what’s in between, it is strictly necessary that no end tags appear inside the Lua code. +This means that for the environment block version (\code{\\begin\{lua\}}) there must be no instances of \code{\\end\{lua\}} inside the Lua code block, even inside a string that would otherwise be valid Lua code (e.g., if it was inside a quoted string or Lua comment). The first instance of such an end tag terminates the block, and there is currently no way to escape it. -For the inline command form (\code{\\script}) an exact matching number of open and closing braces may appear in the Lua code—the next closing brace at the same level as the opening brace will close the tag, even if it happens to be inside some quoted string in the Lua code. +For the inline command form (\code{\\lua}) an exact matching number of open and closing braces may appear in the Lua code—the next closing brace at the same level as the opening brace will close the tag, even if it happens to be inside some quoted string in the Lua code. Including any number of nested opening and closing braces is possible as long as they are balanced. \end{document} From cd11c569f07c9b288ffb7dfdb3f7cb519cdc5f48 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 6 Jan 2024 13:08:24 +0300 Subject: [PATCH 227/357] chore(utilities): Cleanup whitespace in error messages --- core/utilities.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utilities.lua b/core/utilities.lua index 05bef5ad3..d6fa645e9 100644 --- a/core/utilities.lua +++ b/core/utilities.lua @@ -104,7 +104,7 @@ utilities.deprecated = function (old, new, warnat, errorat, extra) -- Hence we fake it ‘till we make it, all deprecations internally are warnings. local brackets = old:sub(1,1) == '\\' and "" or "()" local _new = new and "Please use " .. (new .. brackets) .. " instead." or "Plase don't use it." - local msg = (old .. brackets) .. " was deprecated in SILE v" .. tostring(warnat) .. ". " .. _new .. (extra and "\n" .. extra .. "\n\n" or "") + local msg = (old .. brackets) .. " was deprecated in SILE v" .. tostring(warnat) .. ". " .. _new .. (extra and ("\n\n" .. extra .. "\n") or "") if errorat and current >= errorat then SU.error(msg) elseif warnat and current >= warnat then From 87888565a9956d0434ea89861ba7214f016c3062 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 6 Jan 2024 14:51:17 +0300 Subject: [PATCH 228/357] ci(actions): Post embeded build artifacts --- .github/workflows/build.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1a5d6e52..27d8ef36b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,27 +52,39 @@ jobs: ${{ matrix.configuration[1] }} echo "VERSION=$(./build-aux/git-version-gen .tarball-version)" >> $GITHUB_ENV echo "MAKEFLAGS=-j$(nproc) -Otarget" >> $GITHUB_ENV + echo "CARCH=$(uname -m)" >> $GITHUB_ENV - name: Make run: | make - name: Package run: | make dist - - name: Upload artifacts - if: ${{ !contains(github.ref, 'refs/tags/v') }} + - name: Upload source dist artifact + if: ${{ matrix.configuration[0] == 'dynamic' && !contains(github.ref, 'refs/tags/v') }} uses: actions/upload-artifact@v4 with: name: sile-${{ env.VERSION }} path: sile-${{ env.VERSION }}.zip + - name: Append architecture to embeded binary + if: ${{ matrix.configuration[0] == 'embeded' }} + run: | + cp sile sile-${{ env.CARCH }} + - name: Upload embeded binary artifact + if: ${{ matrix.configuration[0] == 'embeded' && !contains(github.ref, 'refs/tags/v') }} + uses: actions/upload-artifact@v4 + with: + name: sile-${{ env.CARCH }} + path: sile-${{ env.CARCH }} - name: Release uses: softprops/action-gh-release@v1 - if: github.repository == 'sile-typesetter/sile' && startsWith(github.ref, 'refs/tags/v') + if: matrix.configuration[0] == 'embeded' && github.repository == 'sile-typesetter/sile' && startsWith(github.ref, 'refs/tags/v') with: body_path: sile-${{ env.VERSION }}.md files: | sile-${{ env.VERSION }}.pdf sile-${{ env.VERSION }}.zip sile-${{ env.VERSION }}.tar.xz + sile-${{ env.CARCH }} build-nix: runs-on: ubuntu-22.04 From 931f27d4f3d215dd75a61e85a8afc8d4a9ae6d07 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 6 Jan 2024 15:59:09 +0300 Subject: [PATCH 229/357] ci(actions): Expand build matrix with new embedded options --- .github/workflows/build.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27d8ef36b..98c9321c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,8 +13,9 @@ jobs: matrix: configuration: - [ 'dynamic', '' ] - - [ 'embeded', '--enable-embeded-resources' ] - [ 'system', '--with-system-lua-sources' ] + - [ 'embeded', '--enable-embeded-resources' ] + - [ 'static', '--enable-embeded-resources --disable-shared --enable-static' ] runs-on: ubuntu-22.04 name: Build Ubuntu ${{ matrix.configuration[0] }} steps: @@ -65,19 +66,19 @@ jobs: with: name: sile-${{ env.VERSION }} path: sile-${{ env.VERSION }}.zip - - name: Append architecture to embeded binary - if: ${{ matrix.configuration[0] == 'embeded' }} + - name: Append architecture to static binary + if: ${{ matrix.configuration[0] == 'static' }} run: | cp sile sile-${{ env.CARCH }} - - name: Upload embeded binary artifact - if: ${{ matrix.configuration[0] == 'embeded' && !contains(github.ref, 'refs/tags/v') }} + - name: Upload static binary artifact + if: ${{ matrix.configuration[0] == 'static' && !contains(github.ref, 'refs/tags/v') }} uses: actions/upload-artifact@v4 with: name: sile-${{ env.CARCH }} path: sile-${{ env.CARCH }} - name: Release uses: softprops/action-gh-release@v1 - if: matrix.configuration[0] == 'embeded' && github.repository == 'sile-typesetter/sile' && startsWith(github.ref, 'refs/tags/v') + if: matrix.configuration[0] == 'static' && github.repository == 'sile-typesetter/sile' && startsWith(github.ref, 'refs/tags/v') with: body_path: sile-${{ env.VERSION }}.md files: | From 2a0e13bf1271fb838a45e9d983ae3bb3ebfcf2d3 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 9 Jan 2024 17:24:31 +0300 Subject: [PATCH 230/357] chore(build): Tweak build to avoid race condition building manual with static config --- Makefile.am | 46 +++++++++++++++++++++++++++++++++++----------- configure.ac | 3 +++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2e796171e..e8f99c459 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,7 +79,7 @@ EXTRA_DIST += src/embed.rs.in BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles -CLEANFILES = $(DEPFILES) $(ACTUALS) $(TESTPDFS) $(MANUAL) $(_BUILT_SUBDIRS) +CLEANFILES = $(MANUAL) include $(top_srcdir)/build-aux/rust_boilerplate.mk @@ -172,7 +172,10 @@ selfcheck: | $(bin_PROGRAMS) $(_BUILT_SUBDIRS) $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" .PHONY: docs -docs: $(MANUAL) +docs: $(_MANUAL) + +.PHONY: docs-figures +docs-figures: $(FIGURES) # This is a monkey patch to figure out how many passes we have to to to # garantee the TOC is up to date, simplify when #230 is fixed. @@ -199,16 +202,33 @@ _DOCS_DEPS = $(and $$(filter documentation/%,$@),$(addprefix .fonts/,$(DOCSFONTF # TODO: remove _BUILT_SUBDIRS hack and replace it with something sensible when # these subdirs don't do crazy things like copying files outside of their own trees! _BUILT_SUBDIRS = .built-subdirs -_SUBDIR_TELLS = justenough/.libs/fontmetrics.so \ - justenough/.libs/justenoughfontconfig.so \ - justenough/.libs/justenoughharfbuzz.so \ - justenough/.libs/justenoughicu.so \ - justenough/.libs/justenoughlibtexpdf.so \ - justenough/.libs/svg.so \ - libtexpdf/.libs/libtexpdf.so.0.0.0 +_SUBDIR_TELLS = + +if SHARED +_SUBDIR_TELLS += justenough/.libs/fontmetrics.$(SHARED_LIB_EXT) \ + justenough/.libs/justenoughfontconfig.$(SHARED_LIB_EXT) \ + justenough/.libs/justenoughharfbuzz.$(SHARED_LIB_EXT) \ + justenough/.libs/justenoughicu.$(SHARED_LIB_EXT) \ + justenough/.libs/justenoughlibtexpdf.$(SHARED_LIB_EXT) \ + justenough/.libs/svg.$(SHARED_LIB_EXT) \ + libtexpdf/.libs/libtexpdf.$(SHARED_LIB_EXT).0.0.0 +endif + +if STATIC +_SUBDIR_TELLS += justenough/.libs/fontmetrics.a \ + justenough/.libs/justenoughfontconfig.a \ + justenough/.libs/justenoughharfbuzz.a \ + justenough/.libs/justenoughicu.a \ + justenough/.libs/justenoughlibtexpdf.a \ + justenough/.libs/svg.a \ + libtexpdf/.libs/libtexpdf.a +endif + $(_BUILT_SUBDIRS): $(_SUBDIR_TELLS) touch $@ +CLEANFILES += $(_BUILT_SUBDIRS) + $(_SUBDIR_TELLS): $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -263,6 +283,7 @@ update_libtexpdf: TESTPDFS = $(addsuffix .pdf,$(basename $(TESTSRCS))) EXPECTEDS ?= $(filter $(addsuffix .expected,$(basename $(TESTSRCS))),$(TESTEXPECTS)) ACTUALS = $(addsuffix .actual,$(basename $(EXPECTEDS))) +CLEANFILES += $(TESTPDFS) $(ACTUALS) REGRESSIONSCRIPT := ./tests/regressions.pl BUSTEDFLAGS ?= @@ -341,6 +362,7 @@ tests/%.actual: tests/%.nil $$(patterndeps) DEPFILES = $(addsuffix .d,$(addprefix $(DEPDIR)/,$(basename $(TESTSRCS) $(MANUAL)))) DEPDIRS = $(sort $(dir $(DEPFILES))) +CLEANFILES += $(DEPFILES) $(DEPDIRS): | Makefile-distfiles mkdir -p $@ @@ -362,19 +384,21 @@ docker: Dockerfile hooks/build .version docker-dep-check: .docker_deps .aur_deps diff -u $^ -CLEANFILES += .docker_deps .docker_deps: hooks/build $(SHELL) -c 'source <($(SED) -nE "/^(RUN|'"'"')/{s/.*=/echo /;p}" $<)' | \ tr ' ' '\n' | \ sort > $@ -CLEANFILES += .aur_deps +CLEANFILES += .docker_deps + .aur_deps: curl -Ls 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h=sile-git' | \ $(SED) -nE '/\bdepends =/{s/.*= //;p}' | \ $(GREP) -vxE '(lua-.*|.*\.so|git|glibc)' | \ sort > $@ +CLEANFILES += .aur_deps + define docker_push = test -z "$(DOCKER_PAT)" || \ docker login https://$(DOCKER_REGISTRY) -u $(DOCKER_USERNAME) -p $(DOCKER_PAT) diff --git a/configure.ac b/configure.ac index 0db7e0ad7..f8678bb48 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,9 @@ AC_ARG_ENABLE([developer], [Check for and enable tooling required only for developers])) AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) +AM_CONDITIONAL([SHARED], [test "x$enable_shared" = "xyes"]) +AM_CONDITIONAL([STATIC], [test "x$enable_static" = "xyes"]) + AC_ARG_ENABLE([embeded], AS_HELP_STRING([--enable-embeded-resources], [Compile resources such as Lua module files directly into the Rust CLI binary])) From 62cea1af3fed76c9d264165b04919b2866a6aede Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 9 Jan 2024 21:48:17 +0300 Subject: [PATCH 231/357] chore(docker): Drop self-check that requires developer mode --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 335d543d3..c17bad642 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,6 @@ RUN build-aux/docker-bootstrap.sh RUN ./bootstrap.sh RUN ./configure --with-system-lua-sources --without-manual RUN make -RUN make check RUN make install DESTDIR=/pkgdir # Work around BuiltKit / buildx bug, they can’t copy to symlinks only dirs From d03f8bd97f7c43b7403fdc14a1640d2cd544e197 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 9 Jan 2024 22:23:40 +0300 Subject: [PATCH 232/357] chore(docker): Enable installation of LuaRocks in Docker w/ LuaJIT --- hooks/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/build b/hooks/build index 609df1bc8..065a6024b 100755 --- a/hooks/build +++ b/hooks/build @@ -7,7 +7,7 @@ REVISION=$(git describe --long --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g') RUNTIME_DEPS='fontconfig freetype2 gentium-plus-font glibc harfbuzz icu libpng luajit zlib'\ ' libertinus-font luarocks noto-fonts-cjk ttf-hack' -BUILD_DEPS='cargo git jq poppler' +BUILD_DEPS='cargo git jq lua51 poppler' : "${DOCKER_BUILDKIT:=1}" export DOCKER_BUILDKIT From 293a9c306061cbae191bb53567d1200da806e849 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 9 Jan 2024 23:25:45 +0300 Subject: [PATCH 233/357] test(core): Disable test with different output on older ICU --- .github/workflows/build.yml | 4 ++-- tests/feat-unicode-softhyphen.sil | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 98c9321c8..bd5d72f04 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -111,6 +111,6 @@ jobs: nix develop --command ./bootstrap.sh nix develop --configure nix develop --command make - - name: Run HB6+ only regressions + - name: Run regression tests for which Ubuntu can't provide deps run: | - nix develop --command make regressions TESTSRCS=tests/variations-axis.sil + nix develop --command make regressions TESTSRCS='tests/variations-axis.sil tests/feat-unicode-softhyphen.sil' diff --git a/tests/feat-unicode-softhyphen.sil b/tests/feat-unicode-softhyphen.sil index 1a34c76f6..8eb691855 100644 --- a/tests/feat-unicode-softhyphen.sil +++ b/tests/feat-unicode-softhyphen.sil @@ -1,4 +1,12 @@ \begin[papersize=a6]{document} +\use[module=packages.retrograde,target=v0.15.0] +\begin{lua} + -- Recent versions of ICU report different information about chunking around + -- soft hyphens. Our test expectations are wired for 74, but our IC has 70. + local icu = require("justenoughicu") + local icu70minus = tostring(icu.version()) <= "70.0" + if icu70minus then SILE.status.unsupported = true end +\end{lua} \nofolios \neverindent % Language without hyphenation patterns From 8ff0dbecd8412677a90b79ac1141152dae65a48d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 00:01:12 +0300 Subject: [PATCH 234/357] chore(build): Bump Cargo release to current previous release --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9159408f5..914d4371b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1413,7 +1413,7 @@ dependencies = [ [[package]] name = "sile" -version = "0.14.8" +version = "0.14.14" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index fa0e6157d..2bb64ac56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sile" -version = "0.14.8" +version = "0.14.14" edition = "2021" rust-version = "1.71.0" description = "Simon’s Improved Layout Engine" From a1d74faf9d0883045c2912a691da821348e15e52 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 00:11:03 +0300 Subject: [PATCH 235/357] chore(deps): Bump pinned versions of patch level crate updates --- Cargo.lock | 591 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 335 insertions(+), 256 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 914d4371b..fbd96faf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,18 +10,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -39,37 +39,37 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arc-swap" @@ -91,9 +91,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "regex-automata", @@ -141,9 +141,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.6" +version = "4.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" dependencies = [ "clap_builder", "clap_derive", @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" dependencies = [ "anstream", "anstyle", @@ -164,36 +164,36 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.3" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clap_mangen" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b44f35c514163027542f7147797ff930523eea288e03642727348ef1a9666f6b" +checksum = "10b5db60b3310cdb376fbeb8826e875a38080d0c61bdec0a91a3da8338948736" dependencies = [ "clap", "roff", @@ -222,9 +222,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -232,9 +232,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" @@ -251,9 +251,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -302,9 +302,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] [[package]] name = "digest" @@ -330,30 +333,19 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "errno" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "faster-hex" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239f7bfb930f820ab16a9cd95afc26f88264cf6905c960b340a615384aa3338a" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" dependencies = [ "serde", ] @@ -366,32 +358,26 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foreign-types" version = "0.3.2" @@ -409,9 +395,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -449,9 +435,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.53.1" +version = "0.55.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06a8c9f9452078f474fecd2880de84819b8c77224ab62273275b646bf785f906" +checksum = "002667cd1ebb789313d0d0afe3d23b2821cf3b0e91605095f0e6d8751f0ceeea" dependencies = [ "gix-actor", "gix-commitgraph", @@ -492,9 +478,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.26.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8c6778cc03bca978b2575a03e04e5ba6f430a9dd9b0f1259f0a8a9a5e5cc66" +checksum = "2eadca029ef716b4378f7afb19f7ee101fde9e58ba1f1445971315ac866db417" dependencies = [ "bstr", "btoi", @@ -506,41 +492,41 @@ dependencies = [ [[package]] name = "gix-bitmap" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ccab4bc576844ddb51b78d81b4a42d73e6229660fa614dfc3d3999c874d1959" +checksum = "78b6cd0f246180034ddafac9b00a112f19178135b21eb031b3f79355891f7325" dependencies = [ "thiserror", ] [[package]] name = "gix-chunk" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b42ea64420f7994000130328f3c7a2038f639120518870436d31b8bde704493" +checksum = "003ec6deacf68076a0c157271a127e0bb2c031c1a41f7168cbe5d248d9b85c78" dependencies = [ "thiserror", ] [[package]] name = "gix-commitgraph" -version = "0.20.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4676ede3a7d37e7028e2889830349a6aca22efc1d2f2dd9fa3351c1a8ddb0c6a" +checksum = "85a7007ba021f059803afaf6f8a48872422abc20550ac12ede6ddea2936cec36" dependencies = [ "bstr", "gix-chunk", "gix-features", "gix-hash", - "memmap2", + "memmap2 0.9.3", "thiserror", ] [[package]] name = "gix-config" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1108c4ac88248dd25cc8ab0d0dae796e619fb72d92f88e30e00b29d61bb93cc4" +checksum = "5cae98c6b4c66c09379bc35274b172587d6b0ac369a416c39128ad8c6454f9bb" dependencies = [ "bstr", "gix-config-value", @@ -559,11 +545,11 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea7505b97f4d8e7933e29735a568ba2f86d8de466669d9f0e8321384f9972f47" +checksum = "52e0be46f4cf1f8f9e88d0e3eb7b29718aff23889563249f379119bd1ab6910e" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "bstr", "gix-path", "libc", @@ -572,9 +558,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7df669639582dc7c02737642f76890b03b5544e141caba68a7d6b4eb551e0d" +checksum = "fb7f3dfb72bebe3449b5e642be64e3c6ccbe9821c8b8f19f487cf5bfbbf4067e" dependencies = [ "bstr", "itoa", @@ -584,9 +570,9 @@ dependencies = [ [[package]] name = "gix-diff" -version = "0.35.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45e342d148373bd9070d557e6fb1280aeae29a3e05e32506682d027278501eb" +checksum = "931394f69fb8c9ed6afc0aae3487bd869e936339bcc13ed8884472af072e0554" dependencies = [ "gix-hash", "gix-object", @@ -595,9 +581,9 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4cacda5ee9dd1b38b0e2506834e40e66c08cf050ef55c344334c76745f277b" +checksum = "a45d5cf0321178883e38705ab2b098f625d609a7d4c391b33ac952eff2c490f2" dependencies = [ "bstr", "dunce", @@ -610,9 +596,9 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.34.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f414c99e1a7abc69b21f3225a6539d203b0513f1d1d448607c4ea81cdcf9ee59" +checksum = "4d46a4a5c6bb5bebec9c0d18b65ada20e6517dbd7cf855b87dd4bbdce3a771b2" dependencies = [ "crc32fast", "flate2", @@ -628,20 +614,20 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.6.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404795da3d4c660c9ab6c3b2ad76d459636d1e1e4b37b0c7ff68eee898c298d4" +checksum = "20e86eb040f5776a5ade092282e51cdcad398adb77d948b88d17583c2ae4e107" dependencies = [ "gix-features", ] [[package]] name = "gix-glob" -version = "0.12.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ac79c444193b0660fe0c0925d338bd338bd643e32138784dccfb12c628b892" +checksum = "5db19298c5eeea2961e5b3bf190767a2d1f09b8802aeb5f258e42276350aff19" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "bstr", "gix-features", "gix-path", @@ -649,9 +635,9 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.13.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ccf425543779cddaa4a7c62aba3fa9d90ea135b160be0a72dd93c063121ad4a" +checksum = "1f8cf8c2266f63e582b7eb206799b63aa5fa68ee510ad349f637dfe2d0653de0" dependencies = [ "faster-hex", "thiserror", @@ -659,9 +645,9 @@ dependencies = [ [[package]] name = "gix-hashtable" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409268480841ad008e81c17ca5a293393fbf9f2b6c2f85b8ab9de1f0c5176a16" +checksum = "feb61880816d7ec4f0b20606b498147d480860ddd9133ba542628df2f548d3ca" dependencies = [ "gix-hash", "hashbrown", @@ -670,11 +656,11 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e9599fc30b3d6aad231687a403f85dfa36ae37ccf1b68ee1f621ad5b7fc7a0d" +checksum = "c83a4fcc121b2f2e109088f677f89f85e7a8ebf39e8e6659c0ae54d4283b1650" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "bstr", "btoi", "filetime", @@ -686,16 +672,16 @@ dependencies = [ "gix-object", "gix-traverse", "itoa", - "memmap2", + "memmap2 0.7.1", "smallvec", "thiserror", ] [[package]] name = "gix-lock" -version = "9.0.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1568c3d90594c60d52670f325f5db88c2d572e85c8dd45fabc23d91cadb0fd52" +checksum = "7e5c65e6a29830a435664891ced3f3c1af010f14900226019590ee0971a22f37" dependencies = [ "gix-tempfile", "gix-utils", @@ -704,20 +690,20 @@ dependencies = [ [[package]] name = "gix-macros" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d8acb5ee668d55f0f2d19a320a3f9ef67a6999ad483e11135abcc2464ed18b6" +checksum = "d75e7ab728059f595f6ddc1ad8771b8d6a231971ae493d9d5948ecad366ee8bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "gix-object" -version = "0.36.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5528d5b2c984044d547e696e44a8c45fa122e83cd8c2ac1da69bd474336be8" +checksum = "740f2a44267f58770a1cb3a3d01d14e67b089c7136c48d4bddbb3cfd2bf86a51" dependencies = [ "bstr", "btoi", @@ -734,9 +720,9 @@ dependencies = [ [[package]] name = "gix-odb" -version = "0.52.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0446eca295459deb3d6dd6ed7d44a631479f1b7381d8087166605c7a9f717c6" +checksum = "8630b56cb80d8fa684d383dad006a66401ee8314e12fbf0e566ddad8c115143b" dependencies = [ "arc-swap", "gix-date", @@ -753,9 +739,9 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.42.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be19ee650300d7cbac5829b637685ec44a8d921a7c2eaff8a245d8f2f008870c" +checksum = "1431ba2e30deff1405920693d54ab231c88d7c240dd6ccc936ee223d8f8697c3" dependencies = [ "clru", "gix-chunk", @@ -765,7 +751,7 @@ dependencies = [ "gix-object", "gix-path", "gix-tempfile", - "memmap2", + "memmap2 0.7.1", "parking_lot", "smallvec", "thiserror", @@ -773,9 +759,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1d370115171e3ae03c5c6d4f7d096f2981a40ddccb98dfd704c773530ba73b" +checksum = "b8dd0998ab245f33d40ca2267e58d542fe54185ebd1dc41923346cf28d179fb6" dependencies = [ "bstr", "gix-trace", @@ -786,9 +772,9 @@ dependencies = [ [[package]] name = "gix-quote" -version = "0.4.7" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "475c86a97dd0127ba4465fbb239abac9ea10e68301470c9791a6dd5351cdc905" +checksum = "9f7dc10303d73a960d10fb82f81188b036ac3e6b11b5795b20b1a60b51d1321f" dependencies = [ "bstr", "btoi", @@ -797,9 +783,9 @@ dependencies = [ [[package]] name = "gix-ref" -version = "0.36.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cccbfa8d5cd9b86465f27a521e0c017de54b92d9fd37c143e49c658a2f04f3a" +checksum = "0ec2f6d07ac88d2fb8007ee3fa3e801856fb9d82e7366ec0ca332eb2c9d74a52" dependencies = [ "gix-actor", "gix-date", @@ -811,16 +797,16 @@ dependencies = [ "gix-path", "gix-tempfile", "gix-validate", - "memmap2", + "memmap2 0.7.1", "thiserror", "winnow", ] [[package]] name = "gix-refspec" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678ba30d95baa5462df9875628ed40655d5f5b8aba7028de86ed57f36e762c6c" +checksum = "ccb0974cc41dbdb43a180c7f67aa481e1c1e160fcfa8f4a55291fd1126c1a6e7" dependencies = [ "bstr", "gix-hash", @@ -832,9 +818,9 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e80a5992ae446fe1745dd26523b86084e3f1b6b3e35377fe09b4f35ac8f151" +checksum = "2ca97ac73459a7f3766aa4a5638a6e37d56d4c7962bc1986fbaf4883d0772588" dependencies = [ "bstr", "gix-date", @@ -848,9 +834,9 @@ dependencies = [ [[package]] name = "gix-revwalk" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b806349bc1f668e09035800e07ac8045da4e39a8925a245d93142c4802224ec1" +checksum = "a16d8c892e4cd676d86f0265bf9d40cefd73d8d94f86b213b8b77d50e77efae0" dependencies = [ "gix-commitgraph", "gix-date", @@ -863,11 +849,11 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b9542ac025a8c02ed5d17b3fc031a111a384e859d0be3532ec4d58c40a0f28" +checksum = "78f6dce0c6683e2219e8169aac4b1c29e89540a8262fef7056b31d80d969408c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "gix-path", "libc", "windows", @@ -875,9 +861,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "9.0.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2762b91ff95e27ff3ea95758c0d4efacd7435a1be3629622928b8276de0f72a8" +checksum = "388dd29114a86ec69b28d1e26d6d63a662300ecf61ab3f4cc578f7d7dc9e7e23" dependencies = [ "gix-fs", "libc", @@ -890,15 +876,15 @@ dependencies = [ [[package]] name = "gix-trace" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b6d623a1152c3facb79067d6e2ecdae48130030cf27d6eb21109f13bd7b836" +checksum = "e8e1127ede0475b58f4fe9c0aaa0d9bb0bad2af90bbd93ccd307c8632b863d89" [[package]] name = "gix-traverse" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec6358f8373fb018af8fc96c9d2ec6a5b66999e2377dc40b7801351fec409ed" +checksum = "14d050ec7d4e1bb76abf0636cf4104fb915b70e54e3ced9a4427c999100ff38a" dependencies = [ "gix-commitgraph", "gix-date", @@ -912,9 +898,9 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.23.0" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c79d595b99a6c7ab274f3c991735a0c0f5a816a3da460f513c48edf1c7bf2cc" +checksum = "0c427a1a11ccfa53a4a2da47d9442c2241deee63a154bc15cc14b8312fbc4005" dependencies = [ "bstr", "gix-features", @@ -926,18 +912,18 @@ dependencies = [ [[package]] name = "gix-utils" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b85d89dc728613e26e0ed952a19583744e7f5240fcd4aa30d6c824ffd8b52f0f" +checksum = "de6225e2de30b6e9bca2d9f1cc4731640fcef0fb3cabddceee366e7e85d3e94f" dependencies = [ "fastrand", ] [[package]] name = "gix-validate" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05cab2b03a45b866156e052aa38619f4ece4adcb2f79978bfc249bc3b21b8c5" +checksum = "ac7cc36f496bd5d96cdca0f9289bb684480725d40db60f48194aa7723b883854" dependencies = [ "bstr", "thiserror", @@ -945,15 +931,15 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata", + "regex-syntax", ] [[package]] @@ -972,9 +958,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" @@ -984,18 +970,18 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1012,27 +998,27 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1046,18 +1032,18 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lua-src" -version = "546.0.1" +version = "546.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c26d4af78361e025a3d03a2b964cd1592aff7495f4d4f7947218c084c6fdca8" +checksum = "2da0daa7eee611a4c30c8f5ee31af55266e26e573971ba9336d2993e2da129b2" dependencies = [ "cc", ] [[package]] name = "luajit-src" -version = "210.4.8+resty107baaf" +version = "210.5.4+c525bcb" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05167e8b2a2185758d83ed23541e5bd8bce37072e4204e0ef2c9b322bc87c4e" +checksum = "2a10ab4ed12d22cb50ef43ece4f6c5ca594b2d2480019e87facfd422225a9908" dependencies = [ "cc", "which", @@ -1065,9 +1051,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -1078,6 +1064,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92" +dependencies = [ + "libc", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1089,9 +1084,9 @@ dependencies = [ [[package]] name = "mlua" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c3a7a7ff4481ec91b951a733390211a8ace1caba57266ccb5f4d4966704e560" +checksum = "1aba10897af47c8e85283db95529b0c6a2d8f3c7b9733c0d2f206d9ee8fc51a3" dependencies = [ "bstr", "mlua-sys", @@ -1103,9 +1098,9 @@ dependencies = [ [[package]] name = "mlua-sys" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec8b54eddb76093069cce9eeffb4c7b3a1a0fe66962d7bd44c4867928149ca3" +checksum = "4655631a02e3739d014951291ecfa08db49c4da3f7f8c6f3931ed236af5dd78e" dependencies = [ "cc", "cfg-if", @@ -1126,14 +1121,14 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -1149,9 +1144,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" @@ -1165,28 +1160,34 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro-error" @@ -1214,9 +1215,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -1229,27 +1230,27 @@ checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.9.6" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -1259,9 +1260,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -1270,9 +1271,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "roff" @@ -1282,9 +1283,9 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rust-embed" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" +checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1293,22 +1294,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" +checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.38", + "syn 2.0.48", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" +checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" dependencies = [ "globset", "sha2", @@ -1323,15 +1324,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.17" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1357,22 +1358,22 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -1427,9 +1428,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "strsim" @@ -1449,9 +1450,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -1460,15 +1461,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1478,39 +1479,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "time" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", "libc", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -1524,9 +1526,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -1554,15 +1556,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-bom" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" +checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" @@ -1581,9 +1583,9 @@ dependencies = [ [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1598,9 +1600,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "vergen" -version = "8.2.5" +version = "8.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e7dc29b3c54a2ea67ef4f953d5ec0c4085035c0ae2d325be1c0d2144bd9f16" +checksum = "1290fd64cc4e7d3c9b07d7f333ce0ce0007253e32870e632624835cc80b83939" dependencies = [ "anyhow", "gix", @@ -1626,14 +1628,15 @@ dependencies = [ [[package]] name = "which" -version = "4.4.2" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" dependencies = [ "either", "home", "once_cell", "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -1669,11 +1672,21 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-targets", + "windows-core", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1682,7 +1695,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1691,13 +1713,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1706,47 +1743,89 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" -version = "0.5.15" +version = "0.5.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa" dependencies = [ "memchr", ] From 013744b805efe3577f89fbe4cc91e0d741600b40 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 00:54:23 +0300 Subject: [PATCH 236/357] chore(cli): Add easier to read spacing to full errors --- shapers/harfbuzz.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shapers/harfbuzz.lua b/shapers/harfbuzz.lua index b932ef867..b65116b42 100644 --- a/shapers/harfbuzz.lua +++ b/shapers/harfbuzz.lua @@ -98,12 +98,15 @@ function shaper.getFace (opts) SU.debug("fonts", "Instanciated", _pretty_varitions(face), "as", face.tempfilename) elseif (face.variations ~= "") or (bitshim.rshift(face.index, 16) ~= 0) then if not SILE.features.font_variations then - SU.warn([[This build of SILE was compiled with font variations support disabled, + SU.warn([[ + This build of SILE was compiled with font variations support disabled, likely due to not having the subsetter library included in HarfBuzz >= 6. This document specifies font variations which cannot be correctly rendered. Please rebuild SILE with the necessary library support. Alternatively to procede anyway *incorrectly* render this document run: + sile -e 'SILE.features.font_variations = true' .... + Or modify the document to remove variations options from font commands.]]) end SU.error("Failed to instanciate: " .. _pretty_varitions(face)) From ebec8a2970a46a5010ee1eccc4020ac0d0f136f5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 11:44:22 +0300 Subject: [PATCH 237/357] ci(cirrus): Drop testing on EOL FreeBSD 12, add 14 --- .cirrus.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index b85f5dd1a..02bb4da3e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,8 +2,8 @@ task: name: Cirrus CI (FreeBSD) freebsd_instance: matrix: + - image_family: freebsd-14-0 - image_family: freebsd-13-2 - - image_family: freebsd-12-4 env: MAKEFLAGS: -j$(nproc) -Otarget CFLAGS: -I/usr/local/include -fPIC @@ -24,14 +24,13 @@ task: fingerprint_script: cat sile.rockspec.in dependencies_script: - pkg install -y autoconf automake fontconfig GentiumPlus git gmake harfbuzz jq libtool pkgconf png rust - - pkg install -y luajit lua51-luaexpat lua51-lpeg lua51-luafilesystem lua51-luarocks lua51-luasec lua51-luasocket + - pkg install -y luajit lua51-luaexpat lua51-lpeg lua51-luafilesystem lua51-luarocks lua51-luasec lua51-luasocket lua51-lzlib - luarocks51 install cassowary - luarocks51 install cldr - luarocks51 install compat53 - luarocks51 install fluent - luarocks51 install linenoise - luarocks51 install loadkit - - luarocks51 install lua-zlib - luarocks51 install lua_cliargs - luarocks51 install luaepnf - luarocks51 install luarepl From 83f8c39df003d45389cf6c7cfebe9da09cbb001a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 13:07:26 +0300 Subject: [PATCH 238/357] chore(tooling): Fix regression tests to show failures in interactive terminals --- tests/regressions.pl.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/regressions.pl.in b/tests/regressions.pl.in index bea5e7f64..7f48d1531 100644 --- a/tests/regressions.pl.in +++ b/tests/regressions.pl.in @@ -33,7 +33,7 @@ for (@specifics ? @specifics : <tests/*.sil tests/*.xml tests/*.nil>) { push @failed, $_; } elsif (!system("grep -qx 'UNSUPPORTED' $actual")) { $unsupported = 1; - } elsif (!system("diff -".($knownbad?"q":"")."U$diffcontext $expectation $actual $highlighter")) { + } elsif (!system("cmp -s $expectation $actual")) { if ($knownbad) { push @knownbadbutpassing, $_; } else { push @passed, $_; } } elsif ($knownbad) { @@ -41,6 +41,7 @@ for (@specifics ? @specifics : <tests/*.sil tests/*.xml tests/*.nil>) { } elsif ($unsupported) { push @unsupported, $_; } else { + system("diff -".($knownbad?"q":"")."U$diffcontext $expectation $actual $highlighter"); push @failed, $_; } } else { From 320920c1cfa0b211c4f1a5fcda988583c326d872 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 13:16:36 +0300 Subject: [PATCH 239/357] chore(tooling): Allow more developer tools to be configured --- .github/workflows/deploy.yml | 2 +- Makefile.am | 60 ++++++++++++++++++------------------ configure.ac | 13 ++++++-- tests/regressions.pl.in | 8 ++--- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cdaa8290b..ddd17a16e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,7 +25,7 @@ jobs: run: | echo "REF=${GITHUB_REF##refs/*/}" >> $GITHUB_ENV ./bootstrap.sh - ./configure --disable-dependency-checks --enable-developer + ./configure --disable-dependency-checks --enable-developer DOCKER=docker - name: Publish Docker Image to GH Container Registry run: | make docker-build-push diff --git a/Makefile.am b/Makefile.am index e8f99c459..9acecba5e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -156,7 +156,7 @@ CLEAN ?= dist: sile-$(VERSION).pdf sile-$(VERSION).md sile-$(VERSION).pdf: $(MANUAL) - cp $(MANUAL) $@ + $(CP) $(MANUAL) $@ sile-%.md: CHANGELOG.md $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ @@ -167,7 +167,7 @@ check: selfcheck .PHONY: selfcheck selfcheck: | $(bin_PROGRAMS) $(_BUILT_SUBDIRS) output=$$(mktemp -t selfcheck-XXXXXX.pdf) - trap 'rm -f $$output' EXIT HUP TERM + trap '$(RM) $$output' EXIT HUP TERM echo "<sile>foo</sile>" | $(LOCALPATHS) ./$(bin_PROGRAMS) -o $$output - $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" @@ -186,7 +186,7 @@ silepass = $(localsile) $< -o $@ && pg0=$${pg} pg=$$($(pages)) || false define runsile = set -e pg=$$($(pages)) hadtoc=$$($(hastoc)) - mkdir -p $(DEPDIR)/$$(dirname $@) + $(MKDIR_P) $(DEPDIR)/$$(dirname $@) $(silepass) export -n SILE_COVERAGE if $$($(hastoc)) && ! $(DRAFT); then @@ -264,12 +264,12 @@ tagrelease: test -z $$($(GIT) tag --points-at HEAD) || exit 0 # end if we are already on a release tag $(GIT) diff-index --quiet --cached HEAD || exit 1 # die if anything staged but not committed $(GIT) diff-files --quiet || exit 1 # die if any tracked files have unstagged changes - npm run release -- $(and $(RELTYPE),--release-as $(RELTYPE)) + $(NPM) run release -- $(and $(RELTYPE),--release-as $(RELTYPE)) prerelease: test docs update_libtexpdf release-preview: - npm run release -- --dry-run $(and $(RELTYPE),--release-as $(RELTYPE)) + $(NPM) run release -- --dry-run $(and $(RELTYPE),--release-as $(RELTYPE)) release: tagrelease @@ -324,16 +324,16 @@ _BASESHA ?= $(shell test -e .git && $(GIT) rev-parse --short=7 $(BASESHA)) clean-recursive: clean-tests clean-tests: - rm -rf tests/*.actual - rm -rf $(DEPDIR)/tests/* + $(RM) -r tests/*.actual + $(RM) -r $(DEPDIR)/tests/* clean-recursive: clean-deps clean-deps: - rm -rf $(DEPDIR) + $(RM) -r $(DEPDIR) time-%.json: benchmark-%/time.json - cp $< $@ + $(CP) $< $@ update_expecteds: $(EXPECTEDS) @@ -349,15 +349,15 @@ tests/%.expected: tests/%.nil $$(patterndeps) regression_previews: $(TESTPREVIEWS) tests/%.actual: tests/%.sil $$(patterndeps) - -$(if $(CLEAN),rm -f $@,:) + -$(if $(CLEAN),$(RM) $@,:) $(localsile) -b debug $< -o $@ tests/%.actual: tests/%.xml $$(patterndeps) - -$(if $(CLEAN),rm -f $@,:) + -$(if $(CLEAN),$(RM) $@,:) $(localsile) -b debug $< -o $@ tests/%.actual: tests/%.nil $$(patterndeps) - -$(if $(CLEAN),rm -f $@,:) + -$(if $(CLEAN),$(RM) $@,:) $(localsile) -b debug $< -o $@ DEPFILES = $(addsuffix .d,$(addprefix $(DEPDIR)/,$(basename $(TESTSRCS) $(MANUAL)))) @@ -365,7 +365,7 @@ DEPDIRS = $(sort $(dir $(DEPFILES))) CLEANFILES += $(DEPFILES) $(DEPDIRS): | Makefile-distfiles - mkdir -p $@ + $(MKDIR_P) $@ $(DEPFILES): | $(DEPDIRS) @@ -382,53 +382,53 @@ docker: Dockerfile hooks/build .version ./hooks/build $(VERSION) docker-dep-check: .docker_deps .aur_deps - diff -u $^ + $(DIFF) -u $^ .docker_deps: hooks/build $(SHELL) -c 'source <($(SED) -nE "/^(RUN|'"'"')/{s/.*=/echo /;p}" $<)' | \ - tr ' ' '\n' | \ - sort > $@ + $(TR) ' ' '\n' | \ + $(SORT) > $@ CLEANFILES += .docker_deps .aur_deps: - curl -Ls 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h=sile-git' | \ + $(CURL) -Ls 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h=sile-git' | \ $(SED) -nE '/\bdepends =/{s/.*= //;p}' | \ $(GREP) -vxE '(lua-.*|.*\.so|git|glibc)' | \ - sort > $@ + $(SORT) > $@ CLEANFILES += .aur_deps define docker_push = test -z "$(DOCKER_PAT)" || \ - docker login https://$(DOCKER_REGISTRY) -u $(DOCKER_USERNAME) -p $(DOCKER_PAT) - docker push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) + $(DOCKER) login https://$(DOCKER_REGISTRY) -u $(DOCKER_USERNAME) -p $(DOCKER_PAT) + $(DOCKER) push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) if [[ "$(DOCKER_TAG)" == v*.*.* ]]; then \ tag=$(DOCKER_TAG) ; \ - docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ - docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ - docker push $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ - docker push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ + $(DOCKER) tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ + $(DOCKER) tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ + $(DOCKER) push $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ + $(DOCKER) push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ fi endef docker-ghcr-to-hub: - docker pull $(GHCR_REGISTRY)/$(GHCR_REPO):$(DOCKER_TAG) - docker tag $(GHCR_REGISTRY)/$(GHCR_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) + $(DOCKER) pull $(GHCR_REGISTRY)/$(GHCR_REPO):$(DOCKER_TAG) + $(DOCKER) tag $(GHCR_REGISTRY)/$(GHCR_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) $(docker_push) docker-build-push: docker - docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) + $(DOCKER) tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) $(docker_push) gource.webm: - mkdir -p /tmp/gravatars + $(MKDIR_P) /tmp/gravatars magick documentation/sile-logo.pdf[0] -density 300 -colorspace RGB -negate -resize 50% /tmp/sile-logo.jpg $(GIT) log --pretty=format:"%an—%ae" | \ - sort -u | \ + $(SORT) -u | \ while IFS=— read name email; do \ test -f "/tmp/gravatars/$$name.jpg" || \ - curl -S "https://www.gravatar.com/avatar/$$(echo -n $$email | md5sum | cut -d\ -f1)?d=identicon&s=256" -o "/tmp/gravatars/$$name.jpg" ; \ + $(CURL) -S "https://www.gravatar.com/avatar/$$(echo -n $$email | md5sum | cut -d\ -f1)?d=identicon&s=256" -o "/tmp/gravatars/$$name.jpg" ; \ done ;\ gource -a 0.2 -s 0.2 -i 0 --logo /tmp/sile-logo.jpg -b 000000 --max-file-lag 5 --hide filenames --date-format '%Y-%m-%d' --user-image-dir /tmp/gravatars --user-filter simoncozens --key -1920x1080 -o - | \ ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i - -vcodec libvpx -b 10000K $@ diff --git a/configure.ac b/configure.ac index f8678bb48..5d221d056 100644 --- a/configure.ac +++ b/configure.ac @@ -211,13 +211,22 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ ]) AM_COND_IF([DEVELOPER], [ - AX_PROGVAR([git]) AX_PROGVAR([busted]) + AX_PROGVAR([cmp]) + AX_PROGVAR([curl]) + AX_PROGVAR([delta]) + AX_PROGVAR([diff]) + AX_PROGVAR([docker]) + AX_PROGVAR([git]) + AX_PROGVAR([grep]) + AX_PROGVAR([head]) AX_PROGVAR([luacheck]) AX_PROGVAR([luarocks]) AX_PROGVAR([nix]) + AX_PROGVAR([npm]) AX_PROGVAR([perl]) - AX_PROGVAR([delta]) + AX_PROGVAR([sort]) + AX_PROGVAR([tr]) ]) ]) diff --git a/tests/regressions.pl.in b/tests/regressions.pl.in index 7f48d1531..0c6a7e58b 100644 --- a/tests/regressions.pl.in +++ b/tests/regressions.pl.in @@ -26,14 +26,14 @@ for (@specifics ? @specifics : <tests/*.sil tests/*.xml tests/*.nil>) { next; } # Run but don't fail on tests that exist but are known to fail - if (!system("head -n1 $_ | grep -q KNOWNBAD")) { + if (!system("@HEAD@ -n1 $_ | @GREP@ -q KNOWNBAD")) { $knownbad = 1; } if (! -f $actual and ! $knownbad) { push @failed, $_; - } elsif (!system("grep -qx 'UNSUPPORTED' $actual")) { + } elsif (!system("@GREP@ -qx 'UNSUPPORTED' $actual")) { $unsupported = 1; - } elsif (!system("cmp -s $expectation $actual")) { + } elsif (!system("@CMP@ -s $expectation $actual")) { if ($knownbad) { push @knownbadbutpassing, $_; } else { push @passed, $_; } } elsif ($knownbad) { @@ -41,7 +41,7 @@ for (@specifics ? @specifics : <tests/*.sil tests/*.xml tests/*.nil>) { } elsif ($unsupported) { push @unsupported, $_; } else { - system("diff -".($knownbad?"q":"")."U$diffcontext $expectation $actual $highlighter"); + system("@DIFF@ -".($knownbad?"q":"")."U$diffcontext $expectation $actual $highlighter"); push @failed, $_; } } else { From f418f3532cb2927a9a2a3273e946e3662041589c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 13:43:08 +0300 Subject: [PATCH 240/357] chore(tooling): Remove vestiges of subtree based benchmarking (use flake) --- Makefile.am | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9acecba5e..2453851a0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -250,7 +250,7 @@ patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(bin_PROGRAMS) $(DEPDIRS .PHONY: force force: ; -PHONY_DEVELOPER_TARGETS = benchmark busted compare coverage docker docker-build-push \ +PHONY_DEVELOPER_TARGETS = busted compare coverage docker docker-build-push \ docker-dep-check docker-ghcr-to-hub gource.webm lint luacheck luarocks-lint \ prerelease regression_previews regressions release release-preview tagrelease \ test update_expecteds update_libtexpdf @@ -332,9 +332,6 @@ clean-recursive: clean-deps clean-deps: $(RM) -r $(DEPDIR) -time-%.json: benchmark-%/time.json - $(CP) $< $@ - update_expecteds: $(EXPECTEDS) tests/%.expected: tests/%.sil $$(patterndeps) From 0164b8dd1c05001dc02e5050b75948f77f902261 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 14:10:25 +0300 Subject: [PATCH 241/357] test(core): Reset tate expectations with new default parindent Tests affected by parindent default change because the class makes changes to it as well but only after using it once. The real solution is an overhaul to the tplain package and how it initiates, which is out of scope for the current PR. --- tests/bug-244.expected | 6 +++--- tests/bug-244.sil | 1 - tests/vertical.expected | 2 +- tests/vertical.sil | 1 - 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/bug-244.expected b/tests/bug-244.expected index 987b52a0e..364c72c24 100644 --- a/tests/bug-244.expected +++ b/tests/bug-244.expected @@ -1,12 +1,12 @@ Set paper size 595.275597 841.8897729 Begin page Mx 541.9479 -My 117.7637 +My 117.7638 Set font Noto Sans CJK JP;10;400;;normal;;;LTR T 41 70 77 77 80 w=24.5800 (Hello) -My 145.0785 +My 144.6306 T 88 80 83 77 69 w=26.9700 (world) -My 172.0485 +My 171.6006 T 15 w=2.7800 (.) Mx 298.1329 My 781.8786 diff --git a/tests/bug-244.sil b/tests/bug-244.sil index 63bdb4412..044c6462e 100644 --- a/tests/bug-244.sil +++ b/tests/bug-244.sil @@ -1,4 +1,3 @@ \begin[papersize=a4,class=jplain,layout=tate]{document} -\use[module=packages.retrograde,target=v0.15.0] \latin-in-tate{Hello world.} \end{document} diff --git a/tests/vertical.expected b/tests/vertical.expected index 47aa08f8c..55b5609f2 100644 --- a/tests/vertical.expected +++ b/tests/vertical.expected @@ -4,7 +4,7 @@ Mx 528.4079 My 107.6592 Set font Noto Sans CJK JP;24;400;;normal;;;TTB T 20220 w=24.0000 (日) -My 131.9203 +My 131.9210 T 20758 w=24.0000 (本) End page Finish diff --git a/tests/vertical.sil b/tests/vertical.sil index faaae3f17..3c9fcf787 100644 --- a/tests/vertical.sil +++ b/tests/vertical.sil @@ -1,5 +1,4 @@ \begin[class=jplain,layout=tate]{document} -\use[module=packages.retrograde,target=v0.15.0] \nofolios % Note: differences between Noto font versions make adding more characters to % this test brittle. For example 日本は昔からruns into trouble when the height From 28738feedf012654a0046a53d3e0d350e940d5c5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 14:23:09 +0300 Subject: [PATCH 242/357] chore(tooling): Fix variables used in dist packaging --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 2453851a0..d9f677be3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -156,7 +156,7 @@ CLEAN ?= dist: sile-$(VERSION).pdf sile-$(VERSION).md sile-$(VERSION).pdf: $(MANUAL) - $(CP) $(MANUAL) $@ + $(INSTALL) $(MANUAL) $@ sile-%.md: CHANGELOG.md $(SED) -e '/\.\.\.v$*/,/\.\.\.v/!d' CHANGELOG.md | \ From 7cde8a31ff65913e8aed8784183cc939116c18d2 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Sun, 19 Nov 2023 18:58:24 +0100 Subject: [PATCH 243/357] feat(classes)!: Make text alignment commands honor nesting and margins BREAKING CHANGE: The "center", "raggedleft" and "raggedright" environments formerly reset the margins (left or right skips), meaning they'd take the full frame width. They all cancelled the paragraph indent. The new behaviour honors the fixed part of the parent context's margins, meaning that if you have an environment playing with margins such as an epigraph or an indented quote, those margins are not lost. The raggedleft and raggedright environment also now no longer cancel the pararagraph indent. --- classes/plain.lua | 121 ++++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 43 deletions(-) diff --git a/classes/plain.lua b/classes/plain.lua index 8a84904ef..5a1b0d510 100644 --- a/classes/plain.lua +++ b/classes/plain.lua @@ -221,20 +221,6 @@ function class:registerCommands () SILE.call("penalty", { penalty = -20000 }) end, "Fills the page with stretchable vglue and then requests a non-negotiable page break") - self:registerCommand("justified", function (_, content) - SILE.settings:set("document.rskip", nil) - SILE.settings:set("document.spaceskip", nil) - SILE.process(content) - SILE.call("par") - end) - - self:registerCommand("rightalign", function (_, content) - SILE.call("raggedleft", {}, function () - SILE.process(content) - SILE.call("par") - end) - end) - self:registerCommand("em", function (_, content) local style = SILE.settings:get("font.style") local toggle = (style and style:lower() == "italic") and "Regular" or "Italic" @@ -262,20 +248,92 @@ function class:registerCommands () SILE.call("font", { language = "und" }, content) end) + self:registerCommand("center", function (_, content) + if #SILE.typesetter.state.nodes ~= 0 then + SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected") + end + SILE.settings:temporarily(function () + local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue(rskip.width.length)) + SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + SILE.process(content) + SILE.call("par") + end) + end, "Typeset its contents in a centered block (keeping margins).") + self:registerCommand("raggedright", function (_, content) - SILE.call("ragged", { right = true }, content) - end) + SILE.settings:temporarily(function () + local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue(rskip.width.length)) + SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + SILE.process(content) + SILE.call("par") + end) + end, "Typeset its contents in a left aligned block (keeping margins).") self:registerCommand("raggedleft", function (_, content) - SILE.call("ragged", { left = true }, content) + SILE.settings:temporarily(function () + local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width.length)) + SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + SILE.process(content) + SILE.call("par") + end) + end, "Typeset its contents in a right aligned block (keeping margins).") + + self:registerCommand("justified", function (_, content) + SILE.settings:temporarily(function () + local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width.length)) + SILE.settings:set("document.spaceskip", nil) + -- HACK. This knows too much about parfillskip defaults... + -- (Which must be big, but smaller than infinity. Doh!) + SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue("0pt plus 10000pt")) + SILE.process(content) + SILE.call("par") + end) + end, "Typeset its contents in a justified block (keeping margins).") + + self:registerCommand("ragged", function (options, content) + -- Fairly dubious command for compatibility + local l = SU.boolean(options.left, false) + local r = SU.boolean(options.right, false) + if l and r then + SILE.call("center", {}, content) + elseif r then + SILE.call("raggedleft", {}, content) + elseif l then + SILE.call("raggedright", {}, content) + else + SILE.call("justified", {}, content) + end + end) + + self:registerCommand("rightalign", function (_, content) + SU.deprecated("\\rightalign", "\\raggedleft", "0.15.0", "0.17.0") + SILE.call("raggedleft", {}, content) end) self:registerCommand("quote", function (_, content) SU.deprecated("\\quote", "\\pullquote", "0.14.5", "0.16.0", [[ The \quote command has *such* bad output it is being completely - deprecated as unsuitable for general purpose use. The pullquote - package (\use[module=packages.pullquote]) provides one alternative, - but you can also copy and adapt the original source from the plain + deprecated as unsuitable for general purpose use. + The pullquote package (\use[module=packages.pullquote]) provides one + alternative, and the blockquote environment provides another. + But you can also copy and adapt the original source from the plain class if you need to maintain exact output past SILE v0.16.0.]]) SILE.call("smallskip") SILE.call("par") @@ -312,29 +370,6 @@ function class:registerCommands () SILE.settings:set("linebreak.tolerance", 10000) end) - self:registerCommand("center", function (_, content) - if #SILE.typesetter.state.nodes ~= 0 then - SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected") - end - SILE.settings:temporarily(function() - SILE.settings:set("current.parindent", 0) - SILE.settings:set("document.parindent", 0) - SILE.call("ragged", { left = true, right = true }, content) - end) - end) - - self:registerCommand("ragged", function (options, content) - SILE.settings:temporarily(function () - if SU.boolean(options.left, false) then SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) end - if SU.boolean(options.right, false) then SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) end - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) - SILE.process(content) - SILE.call("par") - end) - end) - self:registerCommand("hbox", function (_, content) local hbox, hlist = SILE.typesetter:makeHbox(content) SILE.typesetter:pushHbox(hbox) From 75a8bdf35a9ad470d45559ce9c373d8983ba75e3 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Sun, 19 Nov 2023 18:58:24 +0100 Subject: [PATCH 244/357] feat(classes): Provide a "blockquote" environment in the plain class The plain class now provides a "blockquote" environment for indented (and possibly nested) quotations. --- classes/plain.lua | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/classes/plain.lua b/classes/plain.lua index 5a1b0d510..f88c764f8 100644 --- a/classes/plain.lua +++ b/classes/plain.lua @@ -327,8 +327,26 @@ function class:registerCommands () SILE.call("raggedleft", {}, content) end) + self:registerCommand("blockquote", function (_, content) + SILE.call("smallskip") + SILE.typesetter:leaveHmode() + SILE.settings:temporarily(function () + local indent = SILE.measurement("2em"):absolute() + local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + -- We keep the stretcheability of the lskip and rskip: honoring text alignment + -- from the parent context. + SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width + indent)) + SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width + indent)) + SILE.settings:set("font.size", SILE.settings:get("font.size") * 0.95) + SILE.process(content) + SILE.typesetter:leaveHmode() + end) + SILE.call("smallskip") + end, "A blockquote environment") + self:registerCommand("quote", function (_, content) - SU.deprecated("\\quote", "\\pullquote", "0.14.5", "0.16.0", [[ + SU.deprecated("\\quote", "\\pullquote or \\blockquote", "0.14.5", "0.16.0", [[ The \quote command has *such* bad output it is being completely deprecated as unsuitable for general purpose use. The pullquote package (\use[module=packages.pullquote]) provides one From be81261cdc65e23667fdac65c1c87821540b02f3 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Sun, 19 Nov 2023 19:48:32 +0100 Subject: [PATCH 245/357] docs(manual): Fix the blockquote example in command design example The command being now proposed in the plain class, align the example code with it (i.e. keep the stretchability of the nesting context) --- documentation/c10-classdesign.sil | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/c10-classdesign.sil b/documentation/c10-classdesign.sil index 2a45581c0..e94ed107f 100644 --- a/documentation/c10-classdesign.sil +++ b/documentation/c10-classdesign.sil @@ -116,7 +116,7 @@ We use the \code{SILE.typesetter:typeset} and \code{SILE.call} functions to outp end) \end{raw} -Now, let’s design a (naive) \autodoc:environment[check=false]{blockquote} environment implementing indented (and possibly nested) quotations. +Now, let’s (re-)design a \autodoc:environment[check=false]{blockquote} environment implementing indented (and possibly nested) quotations. You do remember, right, that an environment in SILE is not much different from a command? So a command be it, without any option this time, but playing with vertical skip, measurements, glue, (temporary) left and right margin settings. (If these concepts elude you, consider re-reading the previous chapters where they are introduced.) @@ -129,14 +129,14 @@ So a command be it, without any option this time, but playing with vertical skip local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() SILE.settings:set("document.lskip", - SILE.nodefactory.glue(lskip.width.length + indent)) + SILE.nodefactory.glue(lskip.width + indent)) SILE.settings:set("document.rskip", - SILE.nodefactory.glue(rskip.width.length + indent)) + SILE.nodefactory.glue(rskip.width + indent)) SILE.process(content) SILE.typesetter:leaveHmode() -- gather paragraphs now. end) SILE.call("smallskip") - end, "A naive blockquote environment") + end, "A blockquote environment") \end{raw} \subsection{Defining settings} From cd6efff53e536b288999e71df7ea08b4fb84e406 Mon Sep 17 00:00:00 2001 From: Didier Willis <didier.willis@delair.aero> Date: Sun, 26 Nov 2023 11:44:31 +0100 Subject: [PATCH 246/357] refactor(classes): Reset parfillskip rather than hard-code it in justified environment --- classes/plain.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/classes/plain.lua b/classes/plain.lua index f88c764f8..6300124be 100644 --- a/classes/plain.lua +++ b/classes/plain.lua @@ -296,12 +296,13 @@ function class:registerCommands () SILE.settings:temporarily(function () local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + -- Keep the fixed part of the margins for nesting but remove the stretchability. SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width.length)) SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width.length)) + -- Reset parfillskip to its default value, in case the surrounding context + -- is ragged and cancelled it. + SILE.settings:set("typesetter.parfillskip", nil, false, true) SILE.settings:set("document.spaceskip", nil) - -- HACK. This knows too much about parfillskip defaults... - -- (Which must be big, but smaller than infinity. Doh!) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue("0pt plus 10000pt")) SILE.process(content) SILE.call("par") end) From ad5dadef5fef751a722e9c8bbf8662966bd6c572 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 15:46:22 +0300 Subject: [PATCH 247/357] test(classes): Update test expectations with breaking alignment changes --- tests/alignment.expected | 370 ++++++++++++++++++++------------------- tests/alignment.sil | 1 - tests/bug-182.expected | 2 +- tests/bug-301.expected | 2 +- 4 files changed, 188 insertions(+), 187 deletions(-) diff --git a/tests/alignment.expected b/tests/alignment.expected index e8edf7e08..be4fe4129 100644 --- a/tests/alignment.expected +++ b/tests/alignment.expected @@ -1,6 +1,6 @@ Set paper size 297.6377985 419.5275636 Begin page -Mx 29.9059 +Mx 33.9059 My 27.9564 Set font Libertinus Serif;10;400;Italic;normal;;;LTR Mx 5.8700 @@ -10,9 +10,9 @@ Mx 5.0000 Mx 4.5400 Mx 5.0600 T 51 a=5.8700 66 a=4.5700 72 a=5.0000 72 a=5.0000 70 a=4.4700 69 a=5.0600 (Ragged) -Mx 62.9459 +Mx 66.4459 T 77 70 2385 w=13.0700 (left) -Mx 79.0159 +Mx 82.0159 Set font Libertinus Serif;10;400;;normal;;;LTR Mx 2.6400 Mx 5.0400 @@ -20,31 +20,31 @@ Mx 3.6400 Mx 4.4700 Mx 7.9000 T 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 78 a=7.9000 (lorem) -Mx 105.7059 +Mx 108.2059 T 74 81 84 86 78 w=25.0100 (ipsum) -Mx 133.7159 +Mx 135.7159 T 69 80 77 80 83 w=21.5000 (dolor) -Mx 158.2159 +Mx 159.7159 T 84 74 85 w=9.7700 (sit) -Mx 170.9859 +Mx 171.9859 T 66 78 70 85 w=20.1000 (amet) -Mx 194.0859 +Mx 194.5859 T 68 80 79 84 70 85 70 85 86 83 w=42.9300 (consetetur) Mx 240.0159 T 84 66 69 74 81 84 68 74 79 72 w=42.7400 (sadipscing) -Mx 36.3059 +Mx 14.8819 My 39.9564 T 70 77 74 85 83 w=16.7000 (elitr) -Mx 56.0059 +Mx 33.8353 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 72.5059 +Mx 49.5887 T 69 74 66 78 w=20.2400 (diam) -Mx 95.7459 +Mx 72.0821 T 79 80 79 86 78 90 w=34.2400 (nonumy) -Mx 132.9859 +Mx 108.5755 Mx 4.4700 Mx 2.7100 Mx 3.7200 @@ -52,7 +52,7 @@ Mx 7.9000 Mx 5.1100 Mx 5.0600 T 70 a=4.4700 74 a=2.7100 83 a=3.7200 78 a=7.9000 80 a=5.0400 69 a=5.0600 (eirmod) -Mx 164.9559 +Mx 139.7989 Mx 3.1600 Mx 4.4700 Mx 7.9000 @@ -60,11 +60,11 @@ Mx 5.2600 Mx 5.0400 Mx 3.7200 T 85 a=3.1600 70 a=4.4700 78 a=7.9000 81 a=5.1900 80 a=5.0400 83 a=3.7200 (tempor) -Mx 197.5059 +Mx 171.6023 T 74 79 87 74 69 86 79 85 w=34.7600 (invidunt) -Mx 235.2659 +Mx 208.6157 T 86 85 w=8.4700 (ut) -Mx 246.7359 +Mx 219.3391 Mx 2.6400 Mx 4.5700 Mx 5.0300 @@ -72,10 +72,9 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 77 a=2.6400 66 a=4.5700 67 a=4.9300 80 a=5.0400 83 a=3.7200 70 a=4.4700 (labore) -Mx 275.1259 +Mx 246.9825 T 70 85 w=7.6300 (et) -Mx 28.8759 -My 51.9564 +Mx 256.8659 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -83,20 +82,21 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 (dolore) -Mx 57.7659 +Mx 14.8819 +My 51.9564 T 78 66 72 79 66 w=27.4600 (magna) -Mx 88.2259 +Mx 44.8368 T 66 77 74 82 86 90 66 78 w=37.8800 (aliquyam) -Mx 129.1059 +Mx 85.2117 T 70 83 66 85 w=15.9200 (erat) -Mx 148.0259 +Mx 103.6266 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 164.5259 +Mx 119.6215 T 69 74 66 78 w=20.2400 (diam) -Mx 187.7659 +Mx 142.3564 Mx 4.8900 Mx 5.0400 Mx 2.6400 @@ -106,31 +106,31 @@ Mx 3.1600 Mx 5.3100 Mx 4.5700 T 87 a=4.9700 80 a=5.0400 77 a=2.6400 86 a=5.3100 81 a=5.1900 85 a=3.1600 86 a=5.3100 66 a=4.5700 (voluptua) -Mx 226.8759 +Mx 180.9614 T 66 85 w=7.7300 (at) -Mx 237.6059 +Mx 191.1863 Mx 4.8900 Mx 4.4700 Mx 3.6400 Mx 5.0400 T 87 a=4.9700 70 a=4.4700 83 a=3.7200 80 a=5.0400 (vero) -Mx 258.6459 +Mx 211.7212 Mx 4.5400 Mx 5.0400 Mx 3.9000 T 70 a=4.4700 80 a=5.0400 84 a=3.9000 (eos) -Mx 275.1259 +Mx 227.6961 T 70 85 w=7.6300 (et) -Mx 51.3659 -My 63.9564 +Mx 237.8210 T 66 68 68 86 84 66 78 w=34.8100 (accusam) -Mx 89.1759 +Mx 275.1259 T 70 85 w=7.6300 (et) -Mx 99.8059 +Mx 59.2459 +My 63.9564 T 75 86 84 85 80 w=20.1300 (justo) -Mx 122.9359 +Mx 81.8759 T 69 86 80 w=15.4100 (duo) -Mx 141.3459 +Mx 99.7859 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -139,25 +139,24 @@ Mx 3.6400 Mx 4.4700 Mx 3.9000 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 84 a=3.9000 (dolores) -Mx 174.1359 +Mx 132.0759 T 70 85 w=7.6300 (et) -Mx 184.7659 +Mx 142.2059 T 70 66 w=9.0400 (ea) -Mx 196.8059 +Mx 153.7459 Mx 3.6400 Mx 4.4700 Mx 4.9300 Mx 5.3100 Mx 7.9000 T 83 a=3.7200 70 a=4.4700 67 a=4.9300 86 a=5.3100 78 a=7.9000 (rebum) -Mx 226.0559 +Mx 182.4959 T 84 85 70 85 w=14.6900 (stet) -Mx 243.7459 +Mx 199.6859 T 68 77 74 85 66 w=17.3600 (clita) -Mx 264.1059 +Mx 219.5459 T 76 66 84 69 w=18.6500 (kasd) Mx 240.6959 -My 75.9564 Mx 5.0000 Mx 5.3100 Mx 5.0300 @@ -168,8 +167,8 @@ Mx 3.6400 Mx 4.4700 Mx 5.4200 T 72 a=5.0000 86 a=5.3100 67 a=4.9300 70 a=4.4700 83 a=3.7200 72 a=5.0000 83 a=3.7200 70 a=4.4700 79 a=5.4200 (gubergren) -Mx 14.8819 -My 107.9564 +Mx 26.8819 +My 95.9564 Set font Libertinus Serif;10;400;Italic;normal;;;LTR Mx 5.8700 Mx 4.5700 @@ -178,9 +177,9 @@ Mx 5.0000 Mx 4.5400 Mx 5.0600 T 51 a=5.8700 66 a=4.5700 72 a=5.0000 72 a=5.0000 70 a=4.4700 69 a=5.0600 (Ragged) -Mx 47.9219 +Mx 59.4219 T 83 74 72 73 85 w=19.9700 (right) -Mx 70.8919 +Mx 81.8919 Set font Libertinus Serif;10;400;;normal;;;LTR Mx 2.6400 Mx 5.0400 @@ -188,31 +187,31 @@ Mx 3.6400 Mx 4.4700 Mx 7.9000 T 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 78 a=7.9000 (lorem) -Mx 97.5819 +Mx 108.0819 T 74 81 84 86 78 w=25.0100 (ipsum) -Mx 125.5919 +Mx 135.5919 T 69 80 77 80 83 w=21.5000 (dolor) -Mx 150.0919 +Mx 159.5919 T 84 74 85 w=9.7700 (sit) -Mx 162.8619 +Mx 171.8619 T 66 78 70 85 w=20.1000 (amet) -Mx 185.9619 +Mx 194.4619 T 68 80 79 84 70 85 70 85 86 83 w=42.9300 (consetetur) -Mx 231.8919 +Mx 239.8919 T 84 66 69 74 81 84 68 74 79 72 w=42.7400 (sadipscing) Mx 14.8819 -My 119.9564 +My 107.9564 T 70 77 74 85 83 w=16.7000 (elitr) -Mx 34.5819 +Mx 33.8353 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 51.0819 +Mx 49.5887 T 69 74 66 78 w=20.2400 (diam) -Mx 74.3219 +Mx 72.0821 T 79 80 79 86 78 90 w=34.2400 (nonumy) -Mx 111.5619 +Mx 108.5755 Mx 4.4700 Mx 2.7100 Mx 3.7200 @@ -220,7 +219,7 @@ Mx 7.9000 Mx 5.1100 Mx 5.0600 T 70 a=4.4700 74 a=2.7100 83 a=3.7200 78 a=7.9000 80 a=5.0400 69 a=5.0600 (eirmod) -Mx 143.5319 +Mx 139.7989 Mx 3.1600 Mx 4.4700 Mx 7.9000 @@ -228,11 +227,11 @@ Mx 5.2600 Mx 5.0400 Mx 3.7200 T 85 a=3.1600 70 a=4.4700 78 a=7.9000 81 a=5.1900 80 a=5.0400 83 a=3.7200 (tempor) -Mx 176.0819 +Mx 171.6023 T 74 79 87 74 69 86 79 85 w=34.7600 (invidunt) -Mx 213.8419 +Mx 208.6157 T 86 85 w=8.4700 (ut) -Mx 225.3119 +Mx 219.3391 Mx 2.6400 Mx 4.5700 Mx 5.0300 @@ -240,10 +239,9 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 77 a=2.6400 66 a=4.5700 67 a=4.9300 80 a=5.0400 83 a=3.7200 70 a=4.4700 (labore) -Mx 253.7019 +Mx 246.9825 T 70 85 w=7.6300 (et) -Mx 14.8819 -My 131.9564 +Mx 256.8659 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -251,20 +249,21 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 (dolore) -Mx 43.7719 +Mx 14.8819 +My 119.9564 T 78 66 72 79 66 w=27.4600 (magna) -Mx 74.2319 +Mx 44.8368 T 66 77 74 82 86 90 66 78 w=37.8800 (aliquyam) -Mx 115.1119 +Mx 85.2117 T 70 83 66 85 w=15.9200 (erat) -Mx 134.0319 +Mx 103.6266 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 150.5319 +Mx 119.6215 T 69 74 66 78 w=20.2400 (diam) -Mx 173.7719 +Mx 142.3564 Mx 4.8900 Mx 5.0400 Mx 2.6400 @@ -274,31 +273,31 @@ Mx 3.1600 Mx 5.3100 Mx 4.5700 T 87 a=4.9700 80 a=5.0400 77 a=2.6400 86 a=5.3100 81 a=5.1900 85 a=3.1600 86 a=5.3100 66 a=4.5700 (voluptua) -Mx 212.8819 +Mx 180.9614 T 66 85 w=7.7300 (at) -Mx 223.6119 +Mx 191.1863 Mx 4.8900 Mx 4.4700 Mx 3.6400 Mx 5.0400 T 87 a=4.9700 70 a=4.4700 83 a=3.7200 80 a=5.0400 (vero) -Mx 244.6519 +Mx 211.7212 Mx 4.5400 Mx 5.0400 Mx 3.9000 T 70 a=4.4700 80 a=5.0400 84 a=3.9000 (eos) -Mx 261.1319 +Mx 227.6961 T 70 85 w=7.6300 (et) -Mx 14.8819 -My 143.9564 +Mx 237.8210 T 66 68 68 86 84 66 78 w=34.8100 (accusam) -Mx 52.6919 +Mx 275.1259 T 70 85 w=7.6300 (et) -Mx 63.3219 +Mx 14.8819 +My 131.9564 T 75 86 84 85 80 w=20.1300 (justo) -Mx 86.4519 +Mx 37.5119 T 69 86 80 w=15.4100 (duo) -Mx 104.8619 +Mx 55.4219 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -307,25 +306,24 @@ Mx 3.6400 Mx 4.4700 Mx 3.9000 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 84 a=3.9000 (dolores) -Mx 137.6519 +Mx 87.7119 T 70 85 w=7.6300 (et) -Mx 148.2819 +Mx 97.8419 T 70 66 w=9.0400 (ea) -Mx 160.3219 +Mx 109.3819 Mx 3.6400 Mx 4.4700 Mx 4.9300 Mx 5.3100 Mx 7.9000 T 83 a=3.7200 70 a=4.4700 67 a=4.9300 86 a=5.3100 78 a=7.9000 (rebum) -Mx 189.5719 +Mx 138.1319 T 84 85 70 85 w=14.6900 (stet) -Mx 207.2619 +Mx 155.3219 T 68 77 74 85 66 w=17.3600 (clita) -Mx 227.6219 +Mx 175.1819 T 76 66 84 69 w=18.6500 (kasd) -Mx 14.8819 -My 155.9564 +Mx 196.3319 Mx 5.0000 Mx 5.3100 Mx 5.0300 @@ -336,8 +334,8 @@ Mx 3.6400 Mx 4.4700 Mx 5.4200 T 72 a=5.0000 86 a=5.3100 67 a=4.9300 70 a=4.4700 83 a=3.7200 72 a=5.0000 83 a=3.7200 70 a=4.4700 79 a=5.4200 (gubergren) -Mx 16.9889 -My 187.9564 +Mx 18.9889 +My 163.9564 Set font Libertinus Serif;10;400;Italic;normal;;;LTR Mx 6.4600 Mx 4.4700 @@ -348,7 +346,7 @@ Mx 3.6400 Mx 4.5400 Mx 5.0600 T 36 a=6.4600 70 a=4.4700 79 a=5.4200 85 a=3.1600 70 a=4.4700 83 a=3.7200 70 a=4.4700 69 a=5.0600 (Centered) -Mx 57.2089 +Mx 58.7089 Set font Libertinus Serif;10;400;;normal;;;LTR Mx 2.6400 Mx 5.0400 @@ -356,31 +354,31 @@ Mx 3.6400 Mx 4.4700 Mx 7.9000 T 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 78 a=7.9000 (lorem) -Mx 83.8989 +Mx 84.8989 T 74 81 84 86 78 w=25.0100 (ipsum) -Mx 111.9089 +Mx 112.4089 T 69 80 77 80 83 w=21.5000 (dolor) Mx 136.4089 T 84 74 85 w=9.7700 (sit) -Mx 149.1789 +Mx 148.6789 T 66 78 70 85 w=20.1000 (amet) -Mx 172.2789 +Mx 171.2789 T 68 80 79 84 70 85 70 85 86 83 w=42.9300 (consetetur) -Mx 218.2089 +Mx 216.7089 T 84 66 69 74 81 84 68 74 79 72 w=42.7400 (sadipscing) -Mx 263.9489 +Mx 261.9489 T 70 77 74 85 83 w=16.7000 (elitr) -Mx 20.9989 -My 199.9564 +Mx 23.2489 +My 175.9564 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 37.4989 +Mx 39.2489 T 69 74 66 78 w=20.2400 (diam) -Mx 60.7389 +Mx 61.9889 T 79 80 79 86 78 90 w=34.2400 (nonumy) -Mx 97.9789 +Mx 98.7289 Mx 4.4700 Mx 2.7100 Mx 3.7200 @@ -388,7 +386,7 @@ Mx 7.9000 Mx 5.1100 Mx 5.0600 T 70 a=4.4700 74 a=2.7100 83 a=3.7200 78 a=7.9000 80 a=5.0400 69 a=5.0600 (eirmod) -Mx 129.9489 +Mx 130.1989 Mx 3.1600 Mx 4.4700 Mx 7.9000 @@ -396,11 +394,11 @@ Mx 5.2600 Mx 5.0400 Mx 3.7200 T 85 a=3.1600 70 a=4.4700 78 a=7.9000 81 a=5.1900 80 a=5.0400 83 a=3.7200 (tempor) -Mx 162.4989 +Mx 162.2489 T 74 79 87 74 69 86 79 85 w=34.7600 (invidunt) -Mx 200.2589 +Mx 199.5089 T 86 85 w=8.4700 (ut) -Mx 211.7289 +Mx 210.4789 Mx 2.6400 Mx 4.5700 Mx 5.0300 @@ -408,9 +406,9 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 77 a=2.6400 66 a=4.5700 67 a=4.9300 80 a=5.0400 83 a=3.7200 70 a=4.4700 (labore) -Mx 240.1189 +Mx 238.3689 T 70 85 w=7.6300 (et) -Mx 250.7489 +Mx 248.4989 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -418,21 +416,21 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 (dolore) -Mx 17.4189 -My 211.9564 +Mx 14.8819 +My 187.9564 T 78 66 72 79 66 w=27.4600 (magna) -Mx 47.8789 +Mx 44.8368 T 66 77 74 82 86 90 66 78 w=37.8800 (aliquyam) -Mx 88.7589 +Mx 85.2117 T 70 83 66 85 w=15.9200 (erat) -Mx 107.6789 +Mx 103.6266 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 124.1789 +Mx 119.6215 T 69 74 66 78 w=20.2400 (diam) -Mx 147.4189 +Mx 142.3564 Mx 4.8900 Mx 5.0400 Mx 2.6400 @@ -442,31 +440,31 @@ Mx 3.1600 Mx 5.3100 Mx 4.5700 T 87 a=4.9700 80 a=5.0400 77 a=2.6400 86 a=5.3100 81 a=5.1900 85 a=3.1600 86 a=5.3100 66 a=4.5700 (voluptua) -Mx 186.5289 +Mx 180.9614 T 66 85 w=7.7300 (at) -Mx 197.2589 +Mx 191.1863 Mx 4.8900 Mx 4.4700 Mx 3.6400 Mx 5.0400 T 87 a=4.9700 70 a=4.4700 83 a=3.7200 80 a=5.0400 (vero) -Mx 218.2989 +Mx 211.7212 Mx 4.5400 Mx 5.0400 Mx 3.9000 T 70 a=4.4700 80 a=5.0400 84 a=3.9000 (eos) -Mx 234.7789 +Mx 227.6961 T 70 85 w=7.6300 (et) -Mx 245.4089 +Mx 237.8210 T 66 68 68 86 84 66 78 w=34.8100 (accusam) -Mx 29.4989 -My 223.9564 +Mx 275.1259 T 70 85 w=7.6300 (et) -Mx 40.1289 +Mx 37.0639 +My 199.9564 T 75 86 84 85 80 w=20.1300 (justo) -Mx 63.2589 +Mx 59.6939 T 69 86 80 w=15.4100 (duo) -Mx 81.6689 +Mx 77.6039 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -475,24 +473,24 @@ Mx 3.6400 Mx 4.4700 Mx 3.9000 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 84 a=3.9000 (dolores) -Mx 114.4589 +Mx 109.8939 T 70 85 w=7.6300 (et) -Mx 125.0889 +Mx 120.0239 T 70 66 w=9.0400 (ea) -Mx 137.1289 +Mx 131.5639 Mx 3.6400 Mx 4.4700 Mx 4.9300 Mx 5.3100 Mx 7.9000 T 83 a=3.7200 70 a=4.4700 67 a=4.9300 86 a=5.3100 78 a=7.9000 (rebum) -Mx 166.3789 +Mx 160.3139 T 84 85 70 85 w=14.6900 (stet) -Mx 184.0689 +Mx 177.5039 T 68 77 74 85 66 w=17.3600 (clita) -Mx 204.4289 +Mx 197.3639 T 76 66 84 69 w=18.6500 (kasd) -Mx 226.0789 +Mx 218.5139 Mx 5.0000 Mx 5.3100 Mx 5.0300 @@ -503,8 +501,8 @@ Mx 3.6400 Mx 4.4700 Mx 5.4200 T 72 a=5.0000 86 a=5.3100 67 a=4.9300 70 a=4.4700 83 a=3.7200 72 a=5.0000 83 a=3.7200 70 a=4.4700 79 a=5.4200 (gubergren) -Mx 34.8819 -My 255.9564 +Mx 26.8819 +My 231.9564 Set font Libertinus Serif;10;400;Italic;normal;;;LTR Mx 3.2200 Mx 5.3100 @@ -515,7 +513,7 @@ Mx 5.6000 Mx 4.5400 Mx 5.0600 T 43 a=3.2200 86 a=5.3100 84 a=3.9000 85 a=3.1600 74 a=2.7100 2361 a=5.6000 70 a=4.4700 69 a=5.0600 (Justified) -Mx 72.4725 +Mx 62.8736 Set font Libertinus Serif;10;400;;normal;;;LTR Mx 2.6400 Mx 5.0400 @@ -523,31 +521,31 @@ Mx 3.6400 Mx 4.4700 Mx 7.9000 T 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 78 a=7.9000 (lorem) -Mx 100.2530 +Mx 89.0554 T 74 81 84 86 78 w=25.0100 (ipsum) -Mx 129.3536 +Mx 116.5571 T 69 80 77 80 83 w=21.5000 (dolor) -Mx 154.9442 +Mx 140.5489 T 84 74 85 w=9.7700 (sit) -Mx 168.8048 +Mx 152.8107 T 66 78 70 85 w=20.1000 (amet) -Mx 192.9953 +Mx 175.4024 T 68 80 79 84 70 85 70 85 86 83 w=42.9300 (consetetur) -Mx 240.0159 +Mx 220.8242 T 84 66 69 74 81 84 68 74 79 72 w=42.7400 (sadipscing) -Mx 14.8819 -My 267.9564 +Mx 266.0559 T 70 77 74 85 83 w=16.7000 (elitr) -Mx 33.8353 +Mx 14.8819 +My 243.9564 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 49.5887 +Mx 30.7203 T 69 74 66 78 w=20.2400 (diam) -Mx 72.0821 +Mx 53.2987 T 79 80 79 86 78 90 w=34.2400 (nonumy) -Mx 108.5755 +Mx 89.8771 Mx 4.4700 Mx 2.7100 Mx 3.7200 @@ -555,7 +553,7 @@ Mx 7.9000 Mx 5.1100 Mx 5.0600 T 70 a=4.4700 74 a=2.7100 83 a=3.7200 78 a=7.9000 80 a=5.0400 69 a=5.0600 (eirmod) -Mx 139.7989 +Mx 121.1855 Mx 3.1600 Mx 4.4700 Mx 7.9000 @@ -563,11 +561,11 @@ Mx 5.2600 Mx 5.0400 Mx 3.7200 T 85 a=3.1600 70 a=4.4700 78 a=7.9000 81 a=5.1900 80 a=5.0400 83 a=3.7200 (tempor) -Mx 171.6023 +Mx 153.0739 T 74 79 87 74 69 86 79 85 w=34.7600 (invidunt) -Mx 208.6157 +Mx 190.1723 T 86 85 w=8.4700 (ut) -Mx 219.3391 +Mx 200.9807 Mx 2.6400 Mx 4.5700 Mx 5.0300 @@ -575,9 +573,9 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 77 a=2.6400 66 a=4.5700 67 a=4.9300 80 a=5.0400 83 a=3.7200 70 a=4.4700 (labore) -Mx 246.9825 +Mx 228.7091 T 70 85 w=7.6300 (et) -Mx 256.8659 +Mx 238.6775 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -585,21 +583,25 @@ Mx 5.0400 Mx 3.6400 Mx 4.4700 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 (dolore) +Mx 266.9059 +T 78 66 w=12.4700 (ma) +Mx 279.3759 +T 14 w=3.3800 (-) Mx 14.8819 -My 279.9564 -T 78 66 72 79 66 w=27.4600 (magna) -Mx 45.8493 +My 255.9564 +T 72 79 66 w=14.9900 (gna) +Mx 33.5004 T 66 77 74 82 86 90 66 78 w=37.8800 (aliquyam) -Mx 87.2367 +Mx 75.0090 T 70 83 66 85 w=15.9200 (erat) -Mx 106.6641 +Mx 94.5575 Mx 3.9000 Mx 4.5400 Mx 5.0600 T 84 a=3.9000 70 a=4.4700 69 a=5.0600 (sed) -Mx 123.6715 +Mx 111.6861 T 69 74 66 78 w=20.2400 (diam) -Mx 147.4189 +Mx 135.5546 Mx 4.8900 Mx 5.0400 Mx 2.6400 @@ -609,31 +611,31 @@ Mx 3.1600 Mx 5.3100 Mx 4.5700 T 87 a=4.9700 80 a=5.0400 77 a=2.6400 86 a=5.3100 81 a=5.1900 85 a=3.1600 86 a=5.3100 66 a=4.5700 (voluptua) -Mx 187.0363 +Mx 175.2932 T 66 85 w=7.7300 (at) -Mx 198.2737 +Mx 186.6517 Mx 4.8900 Mx 4.4700 Mx 3.6400 Mx 5.0400 T 87 a=4.9700 70 a=4.4700 83 a=3.7200 80 a=5.0400 (vero) -Mx 219.8211 +Mx 208.3203 Mx 4.5400 Mx 5.0400 Mx 3.9000 T 70 a=4.4700 80 a=5.0400 84 a=3.9000 (eos) -Mx 236.8085 +Mx 225.4288 T 70 85 w=7.6300 (et) -Mx 247.9459 +Mx 236.6874 T 66 68 68 86 84 66 78 w=34.8100 (accusam) -Mx 14.8819 -My 291.9564 +Mx 275.1259 T 70 85 w=7.6300 (et) -Mx 25.5155 +Mx 14.8819 +My 267.9564 T 75 86 84 85 80 w=20.1300 (justo) -Mx 48.6492 +Mx 37.5174 T 69 86 80 w=15.4100 (duo) -Mx 67.0628 +Mx 55.4330 Mx 5.0600 Mx 5.0400 Mx 2.6400 @@ -642,24 +644,24 @@ Mx 3.6400 Mx 4.4700 Mx 3.9000 T 69 a=5.0600 80 a=5.0400 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 84 a=3.9000 (dolores) -Mx 99.8565 +Mx 87.7285 T 70 85 w=7.6300 (et) -Mx 110.4901 +Mx 97.8640 T 70 66 w=9.0400 (ea) -Mx 122.5338 +Mx 109.4096 Mx 3.6400 Mx 4.4700 Mx 4.9300 Mx 5.3100 Mx 7.9000 T 83 a=3.7200 70 a=4.4700 67 a=4.9300 86 a=5.3100 78 a=7.9000 (rebum) -Mx 151.7874 +Mx 138.1651 T 84 85 70 85 w=14.6900 (stet) -Mx 169.4811 +Mx 155.3607 T 68 77 74 85 66 w=17.3600 (clita) -Mx 189.8447 +Mx 175.2262 T 76 66 84 69 w=18.6500 (kasd) -Mx 211.4984 +Mx 196.3817 Mx 5.0000 Mx 5.3100 Mx 5.0300 @@ -670,11 +672,11 @@ Mx 3.6400 Mx 4.4700 Mx 5.4200 T 72 a=5.0000 86 a=5.3100 67 a=4.9300 70 a=4.4700 83 a=3.7200 72 a=5.0000 83 a=3.7200 70 a=4.4700 79 a=5.4200 (gubergren) -Mx 135.7259 -My 323.9564 +Mx 138.2259 +My 299.9564 Set font Libertinus Serif;10;400;Italic;normal;;;LTR T 51 74 72 73 85 w=22.1200 (Right) -Mx 160.8459 +Mx 162.8459 Mx 4.5700 Mx 2.6400 Mx 2.7100 @@ -683,7 +685,7 @@ Mx 5.4200 Mx 4.5400 Mx 5.0600 T 66 a=4.5700 77 a=2.6400 74 a=2.7100 72 a=5.0000 79 a=5.4200 70 a=4.4700 69 a=5.0600 (aligned) -Mx 193.7859 +Mx 195.2859 Set font Libertinus Serif;10;400;;normal;;;LTR Mx 2.6400 Mx 5.0400 @@ -691,9 +693,9 @@ Mx 3.6400 Mx 4.4700 Mx 7.9000 T 77 a=2.6400 80 a=5.0400 83 a=3.7200 70 a=4.4700 78 a=7.9000 (lorem) -Mx 220.4759 +Mx 221.4759 T 74 81 84 86 78 w=25.0100 (ipsum) -Mx 248.4859 +Mx 248.9859 T 69 80 77 80 83 w=21.5000 (dolor) Mx 272.9859 T 84 74 85 w=9.7700 (sit) diff --git a/tests/alignment.sil b/tests/alignment.sil index 144257d62..f50f413a7 100644 --- a/tests/alignment.sil +++ b/tests/alignment.sil @@ -1,5 +1,4 @@ \begin[papersize=a6]{document} -\use[module=packages.retrograde,target=v0.15.0] \nofolios \use[module=packages.lorem] \font[family=Libertinus Serif] diff --git a/tests/bug-182.expected b/tests/bug-182.expected index 468f70b61..60c444d89 100644 --- a/tests/bug-182.expected +++ b/tests/bug-182.expected @@ -1,6 +1,6 @@ Set paper size 595.275597 841.8897729 Begin page -Mx 256.5354 +Mx 268.5354 My 48.5252 Set font Gentium Plus;10;400;;normal;;;LTR T 36 37 38 w=16.8115 (ABC) diff --git a/tests/bug-301.expected b/tests/bug-301.expected index 677ced152..e9c59861e 100644 --- a/tests/bug-301.expected +++ b/tests/bug-301.expected @@ -108,7 +108,7 @@ T 88 81 71 72 85 86 76 74 81 72 71 w=48.8127 (undersigned) Mx 190.1779 T 15 w=2.1755 (,) Mx 138.1542 -My 79.7247 +My 78.7247 T 45 82 75 81 w=18.1604 (John) Mx 158.8251 T 43 68 81 70 82 70 78 w=33.5283 (Hancock) From 82101776c93a1c25091b76bebb887dcad94358fc Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 16:00:55 +0300 Subject: [PATCH 248/357] refactor(packages): Cleanup retrograde package to make room for behavior shims --- packages/retrograde/init.lua | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 925b3fc1a..69c7bdba2 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -23,36 +23,52 @@ package.default_settings = { function package:_init (options) base._init(self, options) - self:defaults(options.target) + self:recede(options.target) end -function package:defaults (target) +function package:recede (target) + self:recede_defaults(target) +end + +function package._prep (_, target, type) target = semver(target and target or SILE.version) - SU.debug("retrograde", ("Targeting default changes back as far as the release of SILE v%s."):format(target)) + SU.debug("retrograde", ("Targeting %s changes back as far as the release of SILE v%s."):format(type, target)) + local terminal = function (version) + SU.debug("retrograde", ("The next set of %s changes is from the release of SILE v%s, stopping."):format(type, version)) + end + return target, terminal +end + +function package:recede_defaults (target) + local semvertarget, terminal = self:_prep(target, "default") local target_hit = false for version, settings in pl.tablex.sort(self.default_settings, semver_descending) do version = semver(version) if target_hit then - SU.debug("retrograde", ("The next set of default changes is from the release of SILE v%s, stopping."):format(version)) + terminal() break end for parameter, value in pairs(settings) do SU.debug("retrograde", ("Resetting '%s' to '%s' as it was prior to v%s."):format(parameter, tostring(value), version)) SILE.settings:set(parameter, value, true) end - if version <= target then target_hit = true end + if version <= semvertarget then target_hit = true end end end function package:registerCommands () - self:registerCommand("defaults", function (options, content) + self:registerCommand("recede", function (options, content) + SILE.call("recede-defaults", options, content) + end) + + self:registerCommand("recede-defaults", function (options, content) if content then SILE.settings:temporarily(function () - self:defaults(options.target) + self:recede_defaults(options.target) end) else - self:defaults(options.target) + self:recede_defaults(options.target) end end) From 2ae82e00ad2abeef8f4be082430f40f5d4904789 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 16:59:58 +0300 Subject: [PATCH 249/357] chore(packages): Fix retrograde defaults function to process content --- packages/retrograde/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 69c7bdba2..aa8a35bc9 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -66,6 +66,7 @@ function package:registerCommands () if content then SILE.settings:temporarily(function () self:recede_defaults(options.target) + SILE.process(content) end) else self:recede_defaults(options.target) From a549b445700641fcaad7ea91ef3f879cdbfd0945 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 16:59:58 +0300 Subject: [PATCH 250/357] feat(packages): Expand retrograde package to handle behavior shims --- packages/retrograde/init.lua | 42 +++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index aa8a35bc9..93f5fbfb9 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -21,13 +21,17 @@ package.default_settings = { }, } +package.shim_commands = { +} + function package:_init (options) base._init(self, options) self:recede(options.target) end function package:recede (target) - self:recede_defaults(target) + self:recede_defaults(target) + self:recede_commands(target) end function package._prep (_, target, type) @@ -56,6 +60,32 @@ function package:recede_defaults (target) end end +function package:recede_commands (target) + local semvertarget, terminal = self:_prep(target, "command") + local currents = {} + local target_hit = false + for version, commands in pl.tablex.sort(self.shim_commands, semver_descending) do + version = semver(version) + if target_hit then + terminal() + break + end + for command, get_function in pairs(commands) do + SU.debug("retrograde", ("Shimming command '%s' to behavior similar to prior to v%s."):format(command, version)) + local current = SILE.Commands[command] + currents[command] = current + SILE.Commands[command] = get_function(current) + end + if version <= semvertarget then target_hit = true end + end + local function reverter () + for command, current in pairs(currents) do + SILE.Commands[command] = current + end + end + return reverter +end + function package:registerCommands () self:registerCommand("recede", function (options, content) @@ -73,6 +103,16 @@ function package:registerCommands () end end) + self:registerCommand("recede-commands", function (options, content) + if content then + local reverter = self:recede_commands(options.target) + SILE.process(content) + reverter() + else + self:recede_commands(options.target) + end + end) + end local doctarget = "v" .. tostring(semver(SILE.version)) From bd5df747d952746fe796b9d790bdf8d40d0526ae Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 17:01:15 +0300 Subject: [PATCH 251/357] chore(classes): Add retrograde shims for old class alignment behavior --- packages/retrograde/init.lua | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index 93f5fbfb9..e3bb81ef4 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -21,7 +21,45 @@ package.default_settings = { }, } +local function _v14_aligns (content) + SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + SILE.process(content) + SILE.call("par") +end + package.shim_commands = { + ["0.15.0"] = { + ["center"] = function (_) + return function (_, content) + if #SILE.typesetter.state.nodes ~= 0 then + SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected") + end + SILE.settings:temporarily(function () + SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) + SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) + _v14_aligns(content) + end) + end + end, + ["raggedright"] = function (_) + return function (_, content) + SILE.settings:temporarily(function () + SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) + _v14_aligns(content) + end) + end + end, + ["raggedleft"] = function (_) + return function (_, content) + SILE.settings:temporarily(function () + SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) + _v14_aligns(content) + end) + end + end, + } } function package:_init (options) From 139e47d3edb702ea1bc2822dac7751c2d7d501f3 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 22:23:24 +0300 Subject: [PATCH 252/357] test(classes): Update test expectations with alignment bug fixes --- tests/bug-1003.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bug-1003.expected b/tests/bug-1003.expected index ad865893c..586dcfbf3 100644 --- a/tests/bug-1003.expected +++ b/tests/bug-1003.expected @@ -1,6 +1,6 @@ Set paper size 297.6377985 419.5275636 Begin page -Mx 142.2344 +Mx 14.8819 My 28.5447 Set font Gentium Plus;10;400;;normal;;;LTR T 73 82 82 w=13.1689 (foo) From a596000f737ca6dd6ddba13388f96502d3cec534 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 10 Jan 2024 23:03:11 +0300 Subject: [PATCH 253/357] ci(cirrus): Ignore Docker tooling in FreeBSD build tests --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 02bb4da3e..0059298b7 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -42,7 +42,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false \ + --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false DOCKER=false \ --disable-font-variations \ --with-system-lua-sources \ --with-system-luarocks \ From 4486a194efd9ae89491d43f67028a54e57db073c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 13 Dec 2023 01:37:19 +0300 Subject: [PATCH 254/357] chore(core)!: Deprecate SILE.paperSizeParser() BREAKING CHANGE: Use SILE.papersize() instead of SILE.paperSizeParser() --- core/sile.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sile.lua b/core/sile.lua index 211c53e78..a0b1c8145 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -478,7 +478,7 @@ function SILE.registerUnit (unit, spec) end function SILE.paperSizeParser (size) - -- SU.deprecated("SILE.paperSizeParser", "SILE.papersize", "0.10.0", nil) + SU.deprecated("SILE.paperSizeParser", "SILE.papersize", "0.15.0", "0.16.0") return SILE.papersize(size) end From fd03f4719dd58841387df1f6160dc86f3636fa91 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 00:24:14 +0300 Subject: [PATCH 255/357] test(packages): Drop workarounds for PDF specific actions in non-pdf backends --- tests/bug-1280.expected | 5 +++++ tests/bug-1280.sil | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/bug-1280.expected b/tests/bug-1280.expected index fe9692491..2c0992b8a 100644 --- a/tests/bug-1280.expected +++ b/tests/bug-1280.expected @@ -1,5 +1,10 @@ Set paper size 425.196855 170.078742 Begin page +Set metadata Author Erwin Schrödinger +Set metadata Title Erwin Schrödinger’s 猫🐈 +Set metadata CreationDate D:19990209153925 - 08 ' 00 ' +Set metadata ModDate should fail +Set metadata Trapped should be skipped Mx 21.2598 My 16.5739 Set font ;10;400;;normal;;;LTR;.fonts/NotoSerifCJK-Regular.ttc diff --git a/tests/bug-1280.sil b/tests/bug-1280.sil index b85dfcda8..00c3dd58f 100644 --- a/tests/bug-1280.sil +++ b/tests/bug-1280.sil @@ -1,5 +1,6 @@ \begin[papersize=15cm x 6cm]{document} \use[module=packages.retrograde,target=v0.15.0] +\use[module=packages.pdf] \font[filename=.fonts/NotoSerifCJK-Regular.ttc] \nofolios \neverindent @@ -44,11 +45,6 @@ for i = 1, fchecks do check() end - if SILE.backend ~= "debug" then - SILE.use("packages.pdf") - else - SILE.registerCommand("pdf:metadata", function (_, _) end) - end \end{script} \pdf:metadata[key=Author, value=Erwin Schrödinger] \pdf:metadata[key=Title, value=Erwin Schrödinger’s 猫🐈] From d3449f330a16a9d878a2b65f664438dc6cf06490 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 00:40:15 +0300 Subject: [PATCH 256/357] ci(cirrus): Ignore NPM tooling in FreeBSD build tests --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 0059298b7..c50746cdc 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -42,7 +42,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false DOCKER=false \ + --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false NPM=false DOCKER=false \ --disable-font-variations \ --with-system-lua-sources \ --with-system-luarocks \ From 5f78af34580d1d9afab6f343d5da2455689008ef Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 14 Feb 2023 14:49:59 +0300 Subject: [PATCH 257/357] feat(inputters): Add formal grammar specification for SIL files --- sil.abnf | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 sil.abnf diff --git a/sil.abnf b/sil.abnf new file mode 100644 index 000000000..7421fa9d3 --- /dev/null +++ b/sil.abnf @@ -0,0 +1,71 @@ +; Formal grammar definition for SIL (SILE Input Language) files +; +; Based on RFC 5234 (Augmented BNF for Syntax Specifications: ABNF) +; Uses RFC 7405 (Case-Sensitive String Support in ABNF) + +; A master document can only have one top level content item, but we allow +; loading of fragments as well which can have any number of top level content +; items, hence valid grammar can be any number of content items. +document = *content + +; Top level content can be any sequence of these things +content = environment +content =/ comment +content =/ text +content =/ braced_content +content =/ command + +; Environments come in two flavors, raw passthrough and regular. The difference +; is what is allowed to terminate them and what escapes are needed for the +; content in the middle. +environment = %s"\begin" [ options ] "{" command-id "}" content %s"\end{" command-id "}" +environment =/ %s"\begin" [ options ] "{" passthrough-command-id "}" passthrough-content %s"\end{" passthrough-command-id "}" + +; Nothing to see here. +comment = "%" utf8-octets CRLF + +; Input strings that are not wrapped in some SILE command. +text = *text-char + +; Input content wrapped in braces can be attatched to a command or just used to +; create a settings wrapper. +braced_content = "{" content "}" + +; As with environments, can be raw passthrough or regular content depending on the command. With raw variants we require contents. +command = "\" command-id [ options ] [ braced_content ] +command =/ "\" passthrough-command-id [ options ] braced-passthrough-content + +; Building blocks +options = "[" parameter *( "," parameter ) "]" +parameter = *1( sil-identifier "=" value) +value = +quoted-value = DQUOTE *( *SP / value / "," ) DQUOTE +s = *WS +any = %x20-7F / valid-non-ascii / tab + +escaped-char = "\\" / "\%" / "\{" / "\}" + +; non-ascii-char = %x80-D7FF / %xE000-10FFFF +text-char = %x0-24 ; omit % +text-char = %x26-5B ; omit \ +text-char =/ %x5D-7A ; omit { +text-char =/ %x7C ; omit } +text-char =/ %x7E-7F ; end of utf8-1 +text-char =/ utf8-2 +text-char =/ utf8-3 +text-char =/ utf8-4 + +letters = ALPHA / "_" +identifier = letters *( letters / DIGIT ) +sil-identifier = 1*( identifier / ":" / "-" ) +command-id = sil-identifier - %s"begin" - %s"end" - passthrough-command-id +passthrough-command-id = %s"ftl" / %s"lua" / %s"math" / %s"raw" / %s"script" / %s"sil" / %s"use" / %s"xml" + +; ASCII isn't good enough for us. +utf8-octets = *utf8-char +utf8-char = utf8-1 / utf8-2 / utf8-3 / utf8-4 +utf8-1 = %x00-7F +utf8-2 = %xC2-DF utf8-tail +utf8-3 = %xE0 %xA0-BF utf8-tail / %xE1-EC 2utf8-tail / %xED %x80-9F utf8-tail / %xEE-EF 2utf8-tail +utf8-4 = %xF0 %x90-BF 2utf8-tail / %xF1-F3 3utf8-tail / %xF4 %x80-8F 2utf8-tail +utf8-tail = %x80-BF From cac1bc00401841c6cf45602f65122fc4ff868d56 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 01:12:38 +0300 Subject: [PATCH 258/357] docs(manual): Un-document unsupported systax for multiple parameters --- documentation/c03-input.sil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/c03-input.sil b/documentation/c03-input.sil index 2e455b420..acbae619d 100644 --- a/documentation/c03-input.sil +++ b/documentation/c03-input.sil @@ -186,7 +186,7 @@ The \code{\\begin} command at the start of the document is an example of this.% \end{raw} The parameters to a command are enclosed in square brackets and take the form \code{\em{key}=\em{value}}; - multiple parameters are separated by commas or semicolons, as in \code{[key1=value1,key2=value2,…]}. + multiple parameters are separated by commas, as in \code{[key1=value1,key2=value2,…]}. Spaces around the keys are not significant; we could equally write that as \code{[key1 = value1; key2 = value2; …]}. If you need to include a comma or semicolon within the value to a parameter, you can enclose the value in quotes: From 296a4e5b6ef5d668dafa3abd6e493bfce531c99d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 01:22:43 +0300 Subject: [PATCH 259/357] test(inputters): Add test for AST settings wrapper --- tests/bug-1715.sil | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/bug-1715.sil diff --git a/tests/bug-1715.sil b/tests/bug-1715.sil new file mode 100644 index 000000000..b32cd3e5b --- /dev/null +++ b/tests/bug-1715.sil @@ -0,0 +1,4 @@ +\begin[papersize=a7]{document} +\nofolios +Before {\set[parameter=font.style,value=Italic]inside} after. +\end{document} From 59755c98fa640ae3274c0bb3c21ab8c5b9c942a6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 14:15:42 +0300 Subject: [PATCH 260/357] feat(settings): Allow \set with no parameter as a temporary wrapper --- core/settings.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/settings.lua b/core/settings.lua index 9de33a2db..c63d5f411 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -75,7 +75,6 @@ function settings:_init() }) SILE.registerCommand("set", function(options, content) - local parameter = SU.required(options, "parameter", "\\set command") local makedefault = SU.boolean(options.makedefault, false) local reset = SU.boolean(options.reset, false) local value = options.value @@ -84,10 +83,14 @@ function settings:_init() SU.warn("Are you sure meant to set default settings *and* pass content to ostensibly apply them to temporarily?") end self:temporarily(function() - self:set(parameter, value, makedefault, reset) + if options.parameter then + local parameter = SU.required(options, "parameter", "\\set command") + self:set(parameter, value, makedefault, reset) + end SILE.process(content) end) else + local parameter = SU.required(options, "parameter", "\\set command") self:set(parameter, value, makedefault, reset) end end, "Set a SILE parameter <parameter> to value <value> (restoring the value afterwards if <content> is provided)", nil, true) From f519db7e0d93575be76b0f14d755228ee660668d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 14:15:42 +0300 Subject: [PATCH 261/357] test(settings): Add test for empty \set as settings wrapper --- tests/bug-1715.expected | 16 ++++++++++++++++ tests/bug-1715.sil | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/bug-1715.expected diff --git a/tests/bug-1715.expected b/tests/bug-1715.expected new file mode 100644 index 000000000..b54b230a4 --- /dev/null +++ b/tests/bug-1715.expected @@ -0,0 +1,16 @@ +Set paper size 209.7637818 297.6377985 +Begin page +Mx 22.4882 +My 22.4502 +Set font Gentium Plus;10;400;;normal;;;LTR +T 37 72 73 82 85 72 w=26.8359 (Before) +Mx 51.5371 +Set font Gentium Plus;10;400;Italic;normal;;;LTR +T 71 88 85 76 81 74 w=25.1221 (during) +Mx 78.8722 +Set font Gentium Plus;10;400;;normal;;;LTR +T 68 73 87 72 85 w=19.7217 (after) +Mx 98.5938 +T 17 w=2.2900 (.) +End page +Finish diff --git a/tests/bug-1715.sil b/tests/bug-1715.sil index b32cd3e5b..757fd6f41 100644 --- a/tests/bug-1715.sil +++ b/tests/bug-1715.sil @@ -1,4 +1,4 @@ \begin[papersize=a7]{document} \nofolios -Before {\set[parameter=font.style,value=Italic]inside} after. +Before \set{\set[parameter=font.style,value=Italic]during} after. \end{document} From 70fc8635124f89cd1ae4e45ccf83bc8b078f14c0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 13:43:14 +0300 Subject: [PATCH 262/357] chore(tooling): Work on correctness of ABNF --- inputters/sil.lua | 2 +- sil.abnf | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/inputters/sil.lua b/inputters/sil.lua index 9e4e66902..1c5a69c82 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -71,7 +71,7 @@ function inputter._grammar (_ENV) eol^-1 ) / "" - START "document" + START"document" document = V"content" * EOF"Unexpected character at end of input" content = Cg( V"environment" + diff --git a/sil.abnf b/sil.abnf index 7421fa9d3..3635e990f 100644 --- a/sil.abnf +++ b/sil.abnf @@ -12,7 +12,7 @@ document = *content content = environment content =/ comment content =/ text -content =/ braced_content +content =/ braced-content content =/ command ; Environments come in two flavors, raw passthrough and regular. The difference @@ -27,12 +27,12 @@ comment = "%" utf8-octets CRLF ; Input strings that are not wrapped in some SILE command. text = *text-char -; Input content wrapped in braces can be attatched to a command or just used to -; create a settings wrapper. -braced_content = "{" content "}" +; Input content wrapped in braces can be attatched to a command or used to +; manually isolate chunks of content (e.g. to hinder ligatures). +braced-content = "{" content "}" ; As with environments, can be raw passthrough or regular content depending on the command. With raw variants we require contents. -command = "\" command-id [ options ] [ braced_content ] +command = "\" command-id [ options ] [ braced-content ] command =/ "\" passthrough-command-id [ options ] braced-passthrough-content ; Building blocks @@ -47,7 +47,7 @@ escaped-char = "\\" / "\%" / "\{" / "\}" ; non-ascii-char = %x80-D7FF / %xE000-10FFFF text-char = %x0-24 ; omit % -text-char = %x26-5B ; omit \ +text-char =/ %x26-5B ; omit \ text-char =/ %x5D-7A ; omit { text-char =/ %x7C ; omit } text-char =/ %x7E-7F ; end of utf8-1 From 450944a6781d2bd72c611bb0d173be34cf523af1 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 17:06:52 +0300 Subject: [PATCH 263/357] refactor(inputters): Move PEG grammar to a separate file --- inputters/sil-epnf.lua | 97 +++++++++++++++++++++++++++++++++++++++++ inputters/sil.lua | 98 +----------------------------------------- 2 files changed, 99 insertions(+), 96 deletions(-) create mode 100644 inputters/sil-epnf.lua diff --git a/inputters/sil-epnf.lua b/inputters/sil-epnf.lua new file mode 100644 index 000000000..d68d437c9 --- /dev/null +++ b/inputters/sil-epnf.lua @@ -0,0 +1,97 @@ +local bits = SILE.parserBits + +local passthroughCommands = { + ftl = true, + lua = true, + math = true, + raw = true, + script = true, + sil = true, + use = true, + xml = true +} + +local isPassthrough = function (_, _, command) + return passthroughCommands[command] or false +end + +local isNotPassthrough = function (...) + return not isPassthrough(...) +end + +local isMatchingEndEnv = function (_, _, thisCommand, lastCommand) + return thisCommand == lastCommand +end + +-- luacheck: push ignore +---@diagnostic disable: undefined-global, unused-local, lowercase-global +local function grammar (_ENV) + local _ = WS^0 + local eol = S"\r\n" + local specials = S"{}%\\" + local escaped_specials = P"\\" * specials + local unescapeSpecials = function (str) + return str:gsub('\\([{}%%\\])', '%1') + end + local myID = C(bits.silidentifier) / 1 + local cmdID = myID - P"begin" - P"end" + local wrapper = function (a) return type(a)=="table" and a or {} end + local parameters = (P"[" * bits.parameters * P"]")^-1 / wrapper + local comment = ( + P"%" * + P(1-eol)^0 * + eol^-1 + ) / "" + + START"document" + document = V"content" * EOF"Unexpected character at end of input" + content = Cg( + V"environment" + + comment + + V"text" + + V"braced_content" + + V"command" + )^0 + passthrough_content = C(Cg( + V"passthrough_text" + + V"debraced_passthrough_text" + )^0) + env_passthrough_content = Cg( + V"env_passthrough_text" + )^0 + text = C((1 - specials + escaped_specials)^1) / unescapeSpecials + passthrough_text = C((1-S("{}"))^1) + env_passthrough_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1) + braced_content = P"{" * V"content" * ( P"}" + E("} expected") ) + braced_passthrough_content = P"{" * V"passthrough_content" * ( P"}" + E("} expected") ) + debraced_passthrough_text = C(V"braced_passthrough_content") + command = ( + P"\\" * + Cg(cmdID, "command") * + Cg(parameters, "options") * + ( + (Cmt(Cb"command", isPassthrough) * V"braced_passthrough_content") + + (Cmt(Cb"command", isNotPassthrough) * V"braced_content") + )^0 + ) + local notpass_end = + P"\\end{" * + ( Cmt(cmdID * Cb"command", isMatchingEndEnv) + E"Environment mismatch") * + ( P"}" * _ ) + E"Environment begun but never ended" + local pass_end = + P"\\end{" * + ( cmdID * Cb"command" ) * + ( P"}" * _ ) + E"Environment begun but never ended" + environment = + P"\\begin" * + Cg(parameters, "options") * + P"{" * + Cg(cmdID, "command") * + P"}" * + ( + (Cmt(Cb"command", isPassthrough) * V"env_passthrough_content" * pass_end) + + (Cmt(Cb"command", isNotPassthrough) * V"content" * notpass_end) + ) +end + +return grammar diff --git a/inputters/sil.lua b/inputters/sil.lua index 1c5a69c82..145f68d1b 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -7,6 +7,8 @@ inputter._name = "sil" inputter.order = 50 +inputter._grammar = require("inputters.sil-epnf") + inputter.appropriate = function (round, filename, doc) if round == 1 then return filename:match(".sil$") @@ -21,20 +23,6 @@ inputter.appropriate = function (round, filename, doc) end end -local bits = SILE.parserBits - - -inputter.passthroughCommands = { - ftl = true, - lua = true, - math = true, - raw = true, - script = true, - sil = true, - use = true, - xml = true -} - function inputter:_init () -- Save time when parsing strings by only setting up the grammar once per -- instantiation then re-using it on every use. @@ -42,88 +30,6 @@ function inputter:_init () base._init(self) end --- luacheck: push ignore ----@diagnostic disable: undefined-global, unused-local, lowercase-global -function inputter._grammar (_ENV) - local isPassthrough = function (_, _, command) - return inputter.passthroughCommands[command] or false - end - local isNotPassthrough = function (...) - return not isPassthrough(...) - end - local isMatchingEndEnv = function (a, b, thisCommand, lastCommand) - return thisCommand == lastCommand - end - local _ = WS^0 - local eol = S"\r\n" - local specials = S"{}%\\" - local escaped_specials = P"\\" * specials - local unescapeSpecials = function (str) - return str:gsub('\\([{}%%\\])', '%1') - end - local myID = C(bits.silidentifier) / 1 - local cmdID = myID - P"begin" - P"end" - local wrapper = function (a) return type(a)=="table" and a or {} end - local parameters = (P"[" * bits.parameters * P"]")^-1 / wrapper - local comment = ( - P"%" * - P(1-eol)^0 * - eol^-1 - ) / "" - - START"document" - document = V"content" * EOF"Unexpected character at end of input" - content = Cg( - V"environment" + - comment + - V"text" + - V"braced_content" + - V"command" - )^0 - passthrough_content = C(Cg( - V"passthrough_text" + - V"debraced_passthrough_text" - )^0) - env_passthrough_content = Cg( - V"env_passthrough_text" - )^0 - text = C((1 - specials + escaped_specials)^1) / unescapeSpecials - passthrough_text = C((1-S("{}"))^1) - env_passthrough_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1) - braced_content = P"{" * V"content" * ( P"}" + E("} expected") ) - braced_passthrough_content = P"{" * V"passthrough_content" * ( P"}" + E("} expected") ) - debraced_passthrough_text = C(V"braced_passthrough_content") - command = ( - P"\\" * - Cg(cmdID, "command") * - Cg(parameters, "options") * - ( - (Cmt(Cb"command", isPassthrough) * V"braced_passthrough_content") + - (Cmt(Cb"command", isNotPassthrough) * V"braced_content") - )^0 - ) - local notpass_end = - P"\\end{" * - ( Cmt(cmdID * Cb"command", isMatchingEndEnv) + E"Environment mismatch") * - ( P"}" * _ ) + E"Environment begun but never ended" - local pass_end = - P"\\end{" * - ( cmdID * Cb"command" ) * - ( P"}" * _ ) + E"Environment begun but never ended" - environment = - P"\\begin" * - Cg(parameters, "options") * - P"{" * - Cg(cmdID, "command") * - P"}" * - ( - (Cmt(Cb"command", isPassthrough) * V"env_passthrough_content" * pass_end) + - (Cmt(Cb"command", isNotPassthrough) * V"content" * notpass_end) - ) -end --- luacheck: pop ----@diagnostic enable: undefined-global, unused-local, lowercase-global - local linecache = {} local lno, col, lastpos local function resetCache () From 0e311fe375b1576cc64c1fbee63c77372672137d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Jan 2024 11:20:26 +0300 Subject: [PATCH 264/357] chore(inputters): Add informative message to input parsing errors --- inputters/sil.lua | 10 ++++++---- inputters/sil_spec.lua | 22 ++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/inputters/sil.lua b/inputters/sil.lua index 145f68d1b..0fb725b5e 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -102,12 +102,14 @@ function inputter:rebuildParser () end function inputter:parse (doc) - local parsed = epnf.parsestring(self._parser, doc)[1] - if not parsed then - return SU.error("Unable to parse input document to an AST tree") + local status, result = pcall(epnf.parsestring, self._parser, doc) + if not status then + return SU.error(([[Unable to parse input document to an AST tree. Parser error: + +%s thrown from document beginning]]):format(pl.stringx.indent(result, 6))) end resetCache() - local top = massage_ast(parsed, doc) + local top = massage_ast(result[1], doc) local tree -- Content not part of a tagged command could either be part of a document -- fragment or junk (e.g. comments, whitespace) outside of a document tag. We diff --git a/inputters/sil_spec.lua b/inputters/sil_spec.lua index 242dc5cb2..2797f1920 100644 --- a/inputters/sil_spec.lua +++ b/inputters/sil_spec.lua @@ -72,27 +72,25 @@ describe("#SIL #inputter", function () describe("should reject", function () it("commands with bad characters", function() - assert.has_error(function() inputter:parse([[\"]]) end, - "parse error, Unexpected character at end of input\n\\\"\n^") - assert.has_error(function() inputter:parse([[\']]) end, - "parse error, Unexpected character at end of input\n\\'\n^") - assert.has_error(function() inputter:parse([[\"o]]) end, - "parse error, Unexpected character at end of input\n\\\"o\n^") + local pattern = "parse error, Unexpected character at end of input" + assert.has_error.match(function() inputter:parse([[\"]]) end, pattern) + assert.has_error.match(function() inputter:parse([[\']]) end, pattern) + assert.has_error.match(function() inputter:parse([[\"o]]) end, pattern) end) - it("commands with unclosed content", function() - assert.has_error(function() inputter:parse([[\foo{bar]]) end, - "parse error at <eof>, } expected") + it("unclosed commands", function() + assert.has_error.matches(function() inputter:parse([[\foo{bar]]) end, + "parse error at <eof>, %} expected") end) it("unclosed environments", function() - assert.has_error(function() inputter:parse([[\begin{foo}bar]]) end, + assert.has_error.matches(function() inputter:parse([[\begin{foo}bar]]) end, "parse error at <eof>, Environment begun but never ended") end) it("mismatched environments", function() - assert.has_error(function() inputter:parse([[\begin{foo}\begin{bar}baz\end{foo}\end{bar}]]) end, - "parse error, Environment mismatch\n\\begin{foo}\\begin{bar}baz\\end{foo}\\end{bar}\n ^") + assert.has_error.matches(function() inputter:parse([[\begin{foo}\begin{bar}baz\end{foo}\end{bar}]]) end, + "parse error, Environment mismatch") end) end) From 65bcbf4870934ab8e1d1b55b6c92f88059da413a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Jan 2024 11:35:12 +0300 Subject: [PATCH 265/357] refactor(packages): Normalize variable name used for package options --- packages/masters/init.lua | 18 ++++++++-------- packages/pandoc/init.lua | 43 +++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/packages/masters/init.lua b/packages/masters/init.lua index e00806776..90419bfa5 100644 --- a/packages/masters/init.lua +++ b/packages/masters/init.lua @@ -5,20 +5,20 @@ package._name = "masters" local _currentMaster -local function defineMaster (_, args) - SU.required(args, "id", "defining master") - SU.required(args, "frames", "defining master") - SU.required(args, "firstContentFrame", "defining master") - SILE.scratch.masters[args.id] = { frames = {}, firstContentFrame = nil } - for frame, spec in pairs(args.frames) do +local function defineMaster (_, options) + SU.required(options, "id", "defining master") + SU.required(options, "frames", "defining master") + SU.required(options, "firstContentFrame", "defining master") + SILE.scratch.masters[options.id] = { frames = {}, firstContentFrame = nil } + for frame, spec in pairs(options.frames) do spec.id = frame if spec.solve then - SILE.scratch.masters[args.id].frames[frame] = spec + SILE.scratch.masters[options.id].frames[frame] = spec else - SILE.scratch.masters[args.id].frames[frame] = SILE.newFrame(spec) + SILE.scratch.masters[options.id].frames[frame] = SILE.newFrame(spec) end end - SILE.scratch.masters[args.id].firstContentFrame = SILE.scratch.masters[args.id].frames[args.firstContentFrame] + SILE.scratch.masters[options.id].firstContentFrame = SILE.scratch.masters[options.id].frames[options.firstContentFrame] end local function defineMasters (class, list) diff --git a/packages/pandoc/init.lua b/packages/pandoc/init.lua index 24356f1bc..f157a1db4 100644 --- a/packages/pandoc/init.lua +++ b/packages/pandoc/init.lua @@ -3,10 +3,9 @@ local base = require("packages.base") local package = pl.class(base) package._name = "pandoc" --- Process arguments that might not actually have that much to do with their --- immediate function but affect the document in other ways, such as setting --- bookmarks on anything tagged with an ID attribute. -local handlePandocArgs = function (options) +-- Process command options that are not actually intended to be options for a specific function but affect the document +-- in other ways, such as setting bookmarks on anything tagged with an ID attribute. +local handlePandocOptions = function (options) local wrapper = SILE.process if options.id then SU.debug("pandoc", "Set ID on tag") @@ -69,16 +68,16 @@ function package:registerCommands () end) self:registerCommand("BulletList", function (options, content) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("itemize", args, content) + SILE.call("itemize", options_, content) end) end) self:registerCommand("CodeBlock", function (options, content) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("verbatim", args, content) + SILE.call("verbatim", options_, content) end) SILE.typesetter:leaveHmode() end) @@ -89,17 +88,17 @@ function package:registerCommands () end) self:registerCommand("Div", function (options, content) - handlePandocArgs(options)(content) + handlePandocOptions(options)(content) SILE.typesetter:leaveHmode() end, "Generic block wrapper") self:registerCommand("Header", function (options, content) local analog = options.type options.level, options.type = nil, nil - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () if analog and SILE.Commands[analog] then - SILE.call(analog, args, content) + SILE.call(analog, options_, content) else SILE.process(content) end @@ -126,9 +125,9 @@ function package:registerCommands () end) self:registerCommand("OrderedList", function (options, content) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("enumerate", args, content) + SILE.call("enumerate", options_, content) end) end) @@ -169,9 +168,9 @@ function package:registerCommands () end, "Creates a Cite inline element") self:registerCommand("Code", function (options, content) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("code", args, content) + SILE.call("code", options_, content) end) end, "Creates a Code inline element") @@ -180,9 +179,9 @@ function package:registerCommands () end, "Creates an inline element representing emphasised text.") self:registerCommand("Image", function (options, _) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("img", args) + SILE.call("img", options_) end) end, "Creates a Image inline element") @@ -191,9 +190,9 @@ function package:registerCommands () end, "Create a LineBreak inline element") self:registerCommand("Link", function (options, content) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("url", args, content) + SILE.call("url", options_, content) end) end, "Creates a link inline element, usually a hyperlink.") @@ -229,7 +228,7 @@ function package:registerCommands () end, "Creates text rendered in small caps") self:registerCommand("Span", function (options, content) - handlePandocArgs(options)(content) + handlePandocOptions(options)(content) end, "Creates a Span inline element") self:registerCommand("Strikeout", function (_, content) @@ -272,9 +271,9 @@ function package:registerCommands () -- Non native types self:registerCommand("ListItem", function (options, content) - local wrapper, args = handlePandocArgs(options) + local wrapper, options_ = handlePandocOptions(options) wrapper(function () - SILE.call("item", args, content) + SILE.call("item", options_, content) end) end) From 7ed691a5861031bc1a10597675373b2118120e2b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Jan 2024 11:41:11 +0300 Subject: [PATCH 266/357] chore(inputters): Fix passing of options from input document to script --- inputters/lua.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inputters/lua.lua b/inputters/lua.lua index 0c5d49dd2..4391d915a 100644 --- a/inputters/lua.lua +++ b/inputters/lua.lua @@ -27,7 +27,7 @@ end function inputter:process (doc) local tree = self:parse(doc)() if type(tree) == "string" then - return SILE.processString(tree, nil, nil, self.args) + return SILE.processString(tree, nil, nil, self.options) elseif type(tree) == "function" then SILE.process(tree) elseif type(tree) == "table" then @@ -36,7 +36,7 @@ function inputter:process (doc) self:requireClass(tree) return SILE.process(tree) else - SILE.use(tree, self.args) + SILE.use(tree, self.options) end end end From 1a23bc46d31e7bc68585e6d050e36771c4f275ff Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Jan 2024 23:59:04 +0300 Subject: [PATCH 267/357] chore(tooling): Add sil.abnf to distribution tarball --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index d9f677be3..44377e867 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,6 +76,7 @@ EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker EXTRA_DIST += $(MANUAL) $(FIGURES) EXTRA_DIST += src/embed.rs.in +EXTRA_DIST += sil.abnf BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles From 1f8a724102e9814301e60a7f668d1823e308cd4f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Jan 2024 23:58:46 +0300 Subject: [PATCH 268/357] docs(manual): Mention SIL grammar spec in manual --- documentation/c03-input.sil | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/documentation/c03-input.sil b/documentation/c03-input.sil index acbae619d..525a74c2c 100644 --- a/documentation/c03-input.sil +++ b/documentation/c03-input.sil @@ -230,6 +230,16 @@ Hi there! However, in some cases the environment form of the command will be easier to read and will help you to be clearer on where the command begins and ends. +\section{SIL flavor grammar specifications} + +The official grammar for the SIL flavor is the LPEG reference implementation. +That being said the reference implementation has some idiosyncrasies and is not the easiest to read. +For convenience an ABNF grammar is also provided in the source tree, see \code{sil.abnf}. +This grammar does not completely express the language as it cannot express the way SIL can embed other syntaxes, but it is a decent approximation. + +The intent behind many of the syntax choices is to make it easy to have parity with XML flavors. +This means limiting commands to valid XML identifiers (e.g. starting with an ASCII letter, not a digit or special character), requiring a single top level command as the document, and so forth. + \section{The XML flavor} As mentioned at the start of the chapter, SILE can actually process its input in a completely different file format. From 92834dd9ca30f69169781a568f2f8770411b99cf Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 11 Jan 2024 18:07:09 +0300 Subject: [PATCH 269/357] chore(tooling): Flesh out ABNF grammar --- inputters/sil-epnf.lua | 70 ++++++++++++++++++++---------------------- inputters/sil.lua | 46 +++++++++++++++++---------- sil.abnf | 45 +++++++++++++++++---------- 3 files changed, 92 insertions(+), 69 deletions(-) diff --git a/inputters/sil-epnf.lua b/inputters/sil-epnf.lua index d68d437c9..36b61ce08 100644 --- a/inputters/sil-epnf.lua +++ b/inputters/sil-epnf.lua @@ -28,7 +28,7 @@ end local function grammar (_ENV) local _ = WS^0 local eol = S"\r\n" - local specials = S"{}%\\" + local specials = S"\\{}%" local escaped_specials = P"\\" * specials local unescapeSpecials = function (str) return str:gsub('\\([{}%%\\])', '%1') @@ -37,11 +37,28 @@ local function grammar (_ENV) local cmdID = myID - P"begin" - P"end" local wrapper = function (a) return type(a)=="table" and a or {} end local parameters = (P"[" * bits.parameters * P"]")^-1 / wrapper - local comment = ( - P"%" * - P(1-eol)^0 * - eol^-1 - ) / "" + + local pass_end = + P"\\end{" * + ( cmdID * Cb"command" ) * + ( P"}" * _ ) + E"Environment begun but never ended" + local notpass_end = + P"\\end{" * + ( Cmt(cmdID * Cb"command", isMatchingEndEnv) + E"Environment mismatch") * + ( P"}" * _ ) + E"Environment begun but never ended" + + env_passthrough_content = Cg( + V"env_passthrough_text" + )^0 + env_passthrough_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1) + passthrough_content = C(Cg( + V"passthrough_text" + + V"debraced_passthrough_text" + )^0) + passthrough_text = C((1-S("{}"))^1) + debraced_passthrough_text = C(V"braced_passthrough_text") + braced_passthrough_text = P"{" * V"passthrough_content" * ( P"}" + E("} expected") ) + local comment = P"%" * P(1-eol)^0 * eol^-1 / "" START"document" document = V"content" * EOF"Unexpected character at end of input" @@ -52,36 +69,6 @@ local function grammar (_ENV) V"braced_content" + V"command" )^0 - passthrough_content = C(Cg( - V"passthrough_text" + - V"debraced_passthrough_text" - )^0) - env_passthrough_content = Cg( - V"env_passthrough_text" - )^0 - text = C((1 - specials + escaped_specials)^1) / unescapeSpecials - passthrough_text = C((1-S("{}"))^1) - env_passthrough_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1) - braced_content = P"{" * V"content" * ( P"}" + E("} expected") ) - braced_passthrough_content = P"{" * V"passthrough_content" * ( P"}" + E("} expected") ) - debraced_passthrough_text = C(V"braced_passthrough_content") - command = ( - P"\\" * - Cg(cmdID, "command") * - Cg(parameters, "options") * - ( - (Cmt(Cb"command", isPassthrough) * V"braced_passthrough_content") + - (Cmt(Cb"command", isNotPassthrough) * V"braced_content") - )^0 - ) - local notpass_end = - P"\\end{" * - ( Cmt(cmdID * Cb"command", isMatchingEndEnv) + E"Environment mismatch") * - ( P"}" * _ ) + E"Environment begun but never ended" - local pass_end = - P"\\end{" * - ( cmdID * Cb"command" ) * - ( P"}" * _ ) + E"Environment begun but never ended" environment = P"\\begin" * Cg(parameters, "options") * @@ -92,6 +79,17 @@ local function grammar (_ENV) (Cmt(Cb"command", isPassthrough) * V"env_passthrough_content" * pass_end) + (Cmt(Cb"command", isNotPassthrough) * V"content" * notpass_end) ) + text = C((1 - specials + escaped_specials)^1) / unescapeSpecials + braced_content = P"{" * V"content" * ( P"}" + E("} expected") ) + command = ( + P"\\" * + Cg(cmdID, "command") * + Cg(parameters, "options") * + ( + (Cmt(Cb"command", isPassthrough) * V"braced_passthrough_text") + + (Cmt(Cb"command", isNotPassthrough) * V"braced_content") + )^0 + ) end return grammar diff --git a/inputters/sil.lua b/inputters/sil.lua index 0fb725b5e..02329a482 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -68,33 +68,44 @@ local function getline (str, pos) end local function massage_ast (tree, doc) - -- Sort out pos if type(tree) == "string" then return tree end if tree.pos then tree.lno, tree.col = getline(doc, tree.pos) + tree.pos = nil end - if tree.id == "document" - or tree.id == "braced_content" - or tree.id == "passthrough_content" - or tree.id == "braced_passthrough_content" - or tree.id == "env_passthrough_content" + SU.debug("inputter", "Processing ID:", tree.id) + if false + or tree.id == "document" + or tree.id == "braced_content" + or tree.id == "passthrough_content" + or tree.id == "braced_passthrough_content" + or tree.id == "env_passthrough_content" then - return massage_ast(tree[1], doc) - end - if tree.id == "text" + SU.debug("inputter", "Re-massage subtree", tree.id) + return massage_ast(tree[1], doc) + elseif false + or tree.id == "text" or tree.id == "passthrough_text" + or tree.id == "braced_passthrough_text" or tree.id == "env_passthrough_text" then - return tree[1] - end - for key, val in ipairs(tree) do - if val.id == "content" then - SU.splice(tree, key, key, massage_ast(val, doc)) - else - tree[key] = massage_ast(val, doc) + SU.debug("inputter", " - Collapse subtree") + return tree[1] + elseif false + or tree.id == "content" + or tree.id == "environment" + or tree.id == "command" then + SU.debug("inputter", " - Massage in place", tree.id) + for key, val in ipairs(tree) do + SU.debug("inputter", " -", val.id) + if val.id == "content" then + SU.splice(tree, key, key, massage_ast(val, doc)) + else + tree[key] = massage_ast(val, doc) + end end + return tree end - return tree end function inputter:rebuildParser () @@ -126,6 +137,7 @@ function inputter:parse (doc) if not tree then tree = { top, command = "document" } end + -- SU.dump(tree) return { tree } end diff --git a/sil.abnf b/sil.abnf index 3635e990f..8ccd594f1 100644 --- a/sil.abnf +++ b/sil.abnf @@ -3,6 +3,11 @@ ; Based on RFC 5234 (Augmented BNF for Syntax Specifications: ABNF) ; Uses RFC 7405 (Case-Sensitive String Support in ABNF) +; NOTE: ABNF does not seem to have a way to express matching / balancing of +; tags. The grammar below does not express SILE's ability to skip over +; passthrough content until it hits the correct matching closing tag for +; environments or the first unballanced brace for braced content. + ; A master document can only have one top level content item, but we allow ; loading of fragments as well which can have any number of top level content ; items, hence valid grammar can be any number of content items. @@ -15,35 +20,43 @@ content =/ text content =/ braced-content content =/ command -; Environments come in two flavors, raw passthrough and regular. The difference -; is what is allowed to terminate them and what escapes are needed for the -; content in the middle. -environment = %s"\begin" [ options ] "{" command-id "}" content %s"\end{" command-id "}" -environment =/ %s"\begin" [ options ] "{" passthrough-command-id "}" passthrough-content %s"\end{" passthrough-command-id "}" +; Environments come in two flavors, passthrough (raw) and regular. The +; difference is what is allowed to terminate them and what escapes are needed +; for the content in the middle. +environment = %s"\\begin" [ options ] "{" command-id "}" content s"\\end{" command-id "}" +environment =/ %s"\\begin" [ options ] "{" passthrough-command-id "}" env-passthrough-text s"\\end{" passthrough-command-id "}" + +; Passthrough (raw) environments can have any valid UTF-8 except the closing +; delimiter matching the opening. +env-passthrough-text = utf8-octets - ( %s"\\end{" passthrough-command-id "}" ) ; Nothing to see here. +; But potentially important because it eats newlines! comment = "%" utf8-octets CRLF -; Input strings that are not wrapped in some SILE command. -text = *text-char +; Input strings that are not special +text = *text-char / escaped-specials ; Input content wrapped in braces can be attatched to a command or used to ; manually isolate chunks of content (e.g. to hinder ligatures). braced-content = "{" content "}" -; As with environments, can be raw passthrough or regular content depending on the command. With raw variants we require contents. -command = "\" command-id [ options ] [ braced-content ] -command =/ "\" passthrough-command-id [ options ] braced-passthrough-content +; As with environments, the content format may be passthrough (raw) or more sil +; content depending on the command. +command = "\\" command-id [ options ] [ braced-content ] +command =/ "\\" passthrough-command-id [ options ] [ braced-passthrough-text ] + +; Passthrough (raw) command text can have any valid UTF-8 except an unbalanced closing delimiter +braced-passthrough-text = utf8-octets - "}" ; Building blocks options = "[" parameter *( "," parameter ) "]" -parameter = *1( sil-identifier "=" value) -value = -quoted-value = DQUOTE *( *SP / value / "," ) DQUOTE -s = *WS -any = %x20-7F / valid-non-ascii / tab +parameter = *( sil-identifier "=" ( value / quoted-value ) ) +value = utf8-octets - "," - "]" +quoted-value = DQUOTE *( utf8-octets ) DQUOTE -escaped-char = "\\" / "\%" / "\{" / "\}" +specials = "\\" / "%" / "{" / "}" +escaped-specials = "\\" specials ; non-ascii-char = %x80-D7FF / %xE000-10FFFF text-char = %x0-24 ; omit % From 672226f7b5d2d96eb9df32b368f2c6cfaf485e8d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Jan 2024 15:32:51 +0300 Subject: [PATCH 270/357] feat(inputters): Output source comments in SIL debug info --- inputters/sil-epnf.lua | 4 ++-- inputters/sil.lua | 7 ++++++- packages/lists/init.lua | 6 +++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/inputters/sil-epnf.lua b/inputters/sil-epnf.lua index 36b61ce08..8be206a44 100644 --- a/inputters/sil-epnf.lua +++ b/inputters/sil-epnf.lua @@ -58,13 +58,12 @@ local function grammar (_ENV) passthrough_text = C((1-S("{}"))^1) debraced_passthrough_text = C(V"braced_passthrough_text") braced_passthrough_text = P"{" * V"passthrough_content" * ( P"}" + E("} expected") ) - local comment = P"%" * P(1-eol)^0 * eol^-1 / "" START"document" document = V"content" * EOF"Unexpected character at end of input" content = Cg( V"environment" + - comment + + V"comment" + V"text" + V"braced_content" + V"command" @@ -79,6 +78,7 @@ local function grammar (_ENV) (Cmt(Cb"command", isPassthrough) * V"env_passthrough_content" * pass_end) + (Cmt(Cb"command", isNotPassthrough) * V"content" * notpass_end) ) + comment = C( P"%" * P(1-eol)^0 * eol^-1 / "" ) text = C((1 - specials + escaped_specials)^1) / unescapeSpecials braced_content = P"{" * V"content" * ( P"}" + E("} expected") ) command = ( diff --git a/inputters/sil.lua b/inputters/sil.lua index 02329a482..f37fa4e22 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -75,6 +75,11 @@ local function massage_ast (tree, doc) end SU.debug("inputter", "Processing ID:", tree.id) if false + or tree.id == "comment" + then + SU.debug("inputter", ("Discarding comment:"), pl.stringx.strip(tree[1])) + return {} + elseif false or tree.id == "document" or tree.id == "braced_content" or tree.id == "passthrough_content" @@ -100,7 +105,7 @@ local function massage_ast (tree, doc) SU.debug("inputter", " -", val.id) if val.id == "content" then SU.splice(tree, key, key, massage_ast(val, doc)) - else + elseif val.id then -- requiring an id discards nodes with no content such as comments tree[key] = massage_ast(val, doc) end end diff --git a/packages/lists/init.lua b/packages/lists/init.lua index 29db687a2..e7b943ffe 100644 --- a/packages/lists/init.lua +++ b/packages/lists/init.lua @@ -164,7 +164,7 @@ function package.doNestedList (_, listType, options, content) local counter = options.start and (SU.cast("integer", options.start) - 1) or 0 for i = 1, #content do - if type(content[i]) == "table" then + if type(content[i]) == "table" and #content[i] > 0 then if content[i].command == "item" or content[i].command == "ListItem" then counter = counter + 1 -- Enrich the node with internal properties @@ -182,6 +182,10 @@ function package.doNestedList (_, listType, options, content) else SILE.typesetter:leaveHmode() end + -- Whitespace left around comment nodes is fine too + elseif type(content[i]) == "table" and #content[i] == 0 then + -- ignore whitespace leaking in from in front of indented comments + assert(true) elseif type(content[i]) == "string" then -- All text nodes are ignored in structure tags, but just warn -- if there do not just consist in spaces. From 760e261583bea9c9d8100f7937a1e689936d0a06 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 14 Jan 2024 00:55:04 +0300 Subject: [PATCH 271/357] chore(tooling): Fixup ABNF grammar enough to validate and convert to EBNF --- sil.abnf | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sil.abnf b/sil.abnf index 8ccd594f1..ad0cf789f 100644 --- a/sil.abnf +++ b/sil.abnf @@ -23,12 +23,16 @@ content =/ command ; Environments come in two flavors, passthrough (raw) and regular. The ; difference is what is allowed to terminate them and what escapes are needed ; for the content in the middle. -environment = %s"\\begin" [ options ] "{" command-id "}" content s"\\end{" command-id "}" -environment =/ %s"\\begin" [ options ] "{" passthrough-command-id "}" env-passthrough-text s"\\end{" passthrough-command-id "}" +environment = %s"\\begin" [ options ] "{" passthrough-command-id "}" + env-passthrough-text + s"\\end{" passthrough-command-id "}" +environment =/ %s"\\begin" [ options ] "{" command-id "}" + content + s"\\end{" command-id "}" ; Passthrough (raw) environments can have any valid UTF-8 except the closing -; delimiter matching the opening. -env-passthrough-text = utf8-octets - ( %s"\\end{" passthrough-command-id "}" ) +; delimiter matching the opening, per the environment rule. +env-passthrough-text = utf8-octets ; Nothing to see here. ; But potentially important because it eats newlines! @@ -43,17 +47,17 @@ braced-content = "{" content "}" ; As with environments, the content format may be passthrough (raw) or more sil ; content depending on the command. -command = "\\" command-id [ options ] [ braced-content ] -command =/ "\\" passthrough-command-id [ options ] [ braced-passthrough-text ] +command = "\\" passthrough-command-id [ options ] [ braced-passthrough-text ] +command =/ "\\" command-id [ options ] [ braced-content ] ; Passthrough (raw) command text can have any valid UTF-8 except an unbalanced closing delimiter -braced-passthrough-text = utf8-octets - "}" +braced-passthrough-text = utf8-octets ; Building blocks -options = "[" parameter *( "," parameter ) "]" +options = "[" parameter *( "," parameter ) [ "," ] "]" parameter = *( sil-identifier "=" ( value / quoted-value ) ) -value = utf8-octets - "," - "]" -quoted-value = DQUOTE *( utf8-octets ) DQUOTE +value = utf8-octets +quoted-value = DQUOTE utf8-octets DQUOTE specials = "\\" / "%" / "{" / "}" escaped-specials = "\\" specials @@ -68,10 +72,9 @@ text-char =/ utf8-2 text-char =/ utf8-3 text-char =/ utf8-4 -letters = ALPHA / "_" -identifier = letters *( letters / DIGIT ) -sil-identifier = 1*( identifier / ":" / "-" ) -command-id = sil-identifier - %s"begin" - %s"end" - passthrough-command-id +letter = ALPHA / "_" / ":" +identifier = letter *( letter / DIGIT / "-" / "." ) +command-id = identifier ; - ( %s"begin" / %s"end" / passthrough-command-id ) passthrough-command-id = %s"ftl" / %s"lua" / %s"math" / %s"raw" / %s"script" / %s"sil" / %s"use" / %s"xml" ; ASCII isn't good enough for us. From 1ed539faf3265e2035074d76315d4b9f107a833f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 27 Jan 2024 18:14:36 +0300 Subject: [PATCH 272/357] chore(core): Drop code supporting deprecated prelude system --- sile.in | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sile.in b/sile.in index 945766662..57511a5a5 100755 --- a/sile.in +++ b/sile.in @@ -32,19 +32,6 @@ SILE.init() if SILE.input.filenames and #SILE.input.filenames >= 1 then - -- Deprecated, notice given in core.cli when argument used - for _, path in ipairs(SILE.input.includes) do - if not SILE.quiet then - io.stderr:write("Loading "..path.."\n") - end - local c = SILE.resolveFile(path, "classes") - if c then - SILE.processFile(c) - else - SILE.require(path, "classes") - end - end - for _, spec in ipairs(SILE.input.uses) do SILE.use(spec.module, spec.options) end From 8e9cf2b4a9fb40d76b723e00d18bed28785dc882 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 14 Jan 2024 00:55:04 +0300 Subject: [PATCH 273/357] chore(tooling): Proofread and correct ABNF grammar --- sil.abnf | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/sil.abnf b/sil.abnf index ad0cf789f..e47a319e0 100644 --- a/sil.abnf +++ b/sil.abnf @@ -23,23 +23,23 @@ content =/ command ; Environments come in two flavors, passthrough (raw) and regular. The ; difference is what is allowed to terminate them and what escapes are needed ; for the content in the middle. -environment = %s"\\begin" [ options ] "{" passthrough-command-id "}" +environment = %s"\begin" [ options ] "{" passthrough-command-id "}" env-passthrough-text - s"\\end{" passthrough-command-id "}" -environment =/ %s"\\begin" [ options ] "{" command-id "}" + %s"\end{" passthrough-command-id "}" +environment =/ %s"\begin" [ options ] "{" command-id "}" content - s"\\end{" command-id "}" + %s"\end{" command-id "}" ; Passthrough (raw) environments can have any valid UTF-8 except the closing ; delimiter matching the opening, per the environment rule. -env-passthrough-text = utf8-octets +env-passthrough-text = utf8-text ; Nothing to see here. ; But potentially important because it eats newlines! -comment = "%" utf8-octets CRLF +comment = "%" utf8-text CRLF ; Input strings that are not special -text = *text-char / escaped-specials +text = *( text-char / escaped-specials ) ; Input content wrapped in braces can be attatched to a command or used to ; manually isolate chunks of content (e.g. to hinder ligatures). @@ -47,20 +47,20 @@ braced-content = "{" content "}" ; As with environments, the content format may be passthrough (raw) or more sil ; content depending on the command. -command = "\\" passthrough-command-id [ options ] [ braced-passthrough-text ] -command =/ "\\" command-id [ options ] [ braced-content ] +command = "\" passthrough-command-id [ options ] [ braced-passthrough-text ] +command =/ "\" command-id [ options ] [ braced-content ] ; Passthrough (raw) command text can have any valid UTF-8 except an unbalanced closing delimiter -braced-passthrough-text = utf8-octets +braced-passthrough-text = utf8-text ; Building blocks -options = "[" parameter *( "," parameter ) [ "," ] "]" -parameter = *( sil-identifier "=" ( value / quoted-value ) ) -value = utf8-octets -quoted-value = DQUOTE utf8-octets DQUOTE +options = "[" parameter *( "," parameter ) "]" +parameter = sil-identifier "=" ( value / quoted-value ) +value = utf8-text +quoted-value = DQUOTE utf8-text DQUOTE -specials = "\\" / "%" / "{" / "}" -escaped-specials = "\\" specials +specials = "\" / "%" / "{" / "}" +escaped-specials = "\" specials ; non-ascii-char = %x80-D7FF / %xE000-10FFFF text-char = %x0-24 ; omit % @@ -78,7 +78,7 @@ command-id = identifier ; - ( %s"begin" / %s"end" / passthrough-command-id ) passthrough-command-id = %s"ftl" / %s"lua" / %s"math" / %s"raw" / %s"script" / %s"sil" / %s"use" / %s"xml" ; ASCII isn't good enough for us. -utf8-octets = *utf8-char +utf8-text = *utf8-char utf8-char = utf8-1 / utf8-2 / utf8-3 / utf8-4 utf8-1 = %x00-7F utf8-2 = %xC2-DF utf8-tail From ea2e36fb8b9a8f7947bb4579ca392e6b7ca66554 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 29 Jan 2024 15:46:48 +0300 Subject: [PATCH 274/357] chore(core): Avoid error when suggesting LuaRocks and no input document present e.g. When using process substitution or pipes for input... --- core/sile.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sile.lua b/core/sile.lua index 4ec807731..06710d7c4 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -170,7 +170,7 @@ local function suggest_luarocks (module) SILE.lua_version, guessed_module_name, SILE.lua_version, - pl.stringx.join(" ", _G.arg) + pl.stringx.join(" ", _G.arg or {}) ) end From 1043764d5cb901a839d9f7e64d2ffeeebb043c67 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 29 Jan 2024 15:48:32 +0300 Subject: [PATCH 275/357] chore(tooling): Make whitespace handling more lenient in ABNF grammar --- sil.abnf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sil.abnf b/sil.abnf index e47a319e0..9081d0b45 100644 --- a/sil.abnf +++ b/sil.abnf @@ -55,7 +55,7 @@ braced-passthrough-text = utf8-text ; Building blocks options = "[" parameter *( "," parameter ) "]" -parameter = sil-identifier "=" ( value / quoted-value ) +parameter = *WSP sil-identifier *WSP "=" *WSP ( value / quoted-value ) *WSP value = utf8-text quoted-value = DQUOTE utf8-text DQUOTE From 2feba59398e2d120c5b3ad170f8514c23928ecba Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 20 Jan 2024 15:27:49 +0300 Subject: [PATCH 276/357] refactor(inputters): Rehash SIL inputter to move EPNF to entirely optional module --- inputters/sil-epnf.lua | 13 ++++++++++--- inputters/sil.lua | 29 +++++++++++++++++------------ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/inputters/sil-epnf.lua b/inputters/sil-epnf.lua index 8be206a44..4cc90196e 100644 --- a/inputters/sil-epnf.lua +++ b/inputters/sil-epnf.lua @@ -1,4 +1,5 @@ -local bits = SILE.parserBits +local epnf = require("epnf") +local bits = require("core.parserbits") local passthroughCommands = { ftl = true, @@ -25,7 +26,7 @@ end -- luacheck: push ignore ---@diagnostic disable: undefined-global, unused-local, lowercase-global -local function grammar (_ENV) +local function builder (_ENV) local _ = WS^0 local eol = S"\r\n" local specials = S"\\{}%" @@ -92,4 +93,10 @@ local function grammar (_ENV) ) end -return grammar +local grammar = epnf.define(builder) + +local function parser (string) + return epnf.parsestring(grammar, string) +end + +return parser diff --git a/inputters/sil.lua b/inputters/sil.lua index f37fa4e22..3c11aa5f5 100644 --- a/inputters/sil.lua +++ b/inputters/sil.lua @@ -1,15 +1,18 @@ local base = require("inputters.base") -local epnf = require("epnf") +local _variant = "epnf" +local parser +local function load_parser () + parser = require("inputters.sil-" .. _variant) +end local inputter = pl.class(base) inputter._name = "sil" inputter.order = 50 -inputter._grammar = require("inputters.sil-epnf") - inputter.appropriate = function (round, filename, doc) + if not parser then load_parser() end if round == 1 then return filename:match(".sil$") elseif round == 2 then @@ -17,16 +20,22 @@ inputter.appropriate = function (round, filename, doc) local promising = sniff:match("\\begin") or sniff:match("\\document") or sniff:match("\\sile") return promising and inputter.appropriate(3, filename, doc) or false elseif round == 3 then - local _parser = epnf.define(inputter._grammar) - local status, _ = pcall(epnf.parsestring, _parser, doc) + local status, _ = pcall(parser, doc) return status end end -function inputter:_init () +function inputter:_init (options) + options = options or {} + if options.variant then + _variant = options.variant + load_parser() + else if not parser + then load_parser() end + end -- Save time when parsing strings by only setting up the grammar once per -- instantiation then re-using it on every use. - self._parser = self:rebuildParser() + self._parser = parser base._init(self) end @@ -113,12 +122,8 @@ local function massage_ast (tree, doc) end end -function inputter:rebuildParser () - return epnf.define(self._grammar) -end - function inputter:parse (doc) - local status, result = pcall(epnf.parsestring, self._parser, doc) + local status, result = pcall(self._parser, doc) if not status then return SU.error(([[Unable to parse input document to an AST tree. Parser error: From 160501cc8e424a0fffac8a4a9641f760ec7861a0 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 29 Jan 2024 17:49:16 +0300 Subject: [PATCH 277/357] fix(inputters): Allow empty string as option value in SIL parser --- core/parserbits.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/parserbits.lua b/core/parserbits.lua index f77a0ebe0..13d42b251 100644 --- a/core/parserbits.lua +++ b/core/parserbits.lua @@ -61,15 +61,16 @@ local shrink = bits.ws * P"minus" * bits.ws * Cg(amount, "shrink") bits.length = Ct(length * stretch^-1 * shrink^-1) bits.utf8char = utf8char -local pairsep = S",;" * bits.ws +local pairsep = S",;" local quote = P'"' local escaped_quote = B(P"\\") * quote local unescapeQuote = function (str) local a = str:gsub('\\"', '"'); return a end -local quotedString = quote * C((1 - quote + escaped_quote)^1 / unescapeQuote) * quote -local value = quotedString + (1-S",;]")^1 +local quotedValueString = quote * C((1 - quote + escaped_quote)^0 / unescapeQuote) * quote +local valueString = (1-pairsep-quote-S"]")^0 / pl.stringx.strip +local value = quotedValueString + valueString + P"" local ID = C(bits.letter * (bits.letter + bits.digit)^0) bits.silidentifier = (ID + S":-")^1 -local pair = Cg(C(bits.silidentifier) * bits.ws * "=" * bits.ws * C(value)) * pairsep^-1 / unwrapper +local pair = Cg(bits.ws * C(bits.silidentifier) * bits.ws * "=" * bits.ws * C(value) * bits.ws) * pairsep^-1 / unwrapper bits.parameters = Cf(Ct"" * pair^0, rawset) local wrapper = function (a) return type(a)=="table" and a or {} end From 3cfbf5f6f8729673f864ccfd0430760e7b4a8bcc Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 29 Jan 2024 22:29:37 +0300 Subject: [PATCH 278/357] chore(tooling): Fixup ABNF grammar with proper quoted value handling --- inputters/sil_spec.lua | 6 ++++++ sil.abnf | 29 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/inputters/sil_spec.lua b/inputters/sil_spec.lua index 2797f1920..20dd8fa87 100644 --- a/inputters/sil_spec.lua +++ b/inputters/sil_spec.lua @@ -44,6 +44,12 @@ describe("#SIL #inputter", function () assert.is.equal("bar", t[1][1]) end) + it("commands with space around args and values", function() + local t = inputter:parse([[\foo[ baz = qiz qiz ]{bar}]])[1][1][1] + assert.is.equal("foo", t.command) + assert.is.equal("qiz qiz", t.options.baz) + end) + it("commands with multiple quoted args", function() local t = inputter:parse([[\foo[baz="qiz, qiz",qiz="baz, baz"]{bar}]])[1][1][1] assert.is.equal("foo", t.command) diff --git a/sil.abnf b/sil.abnf index 9081d0b45..072d5ff11 100644 --- a/sil.abnf +++ b/sil.abnf @@ -39,7 +39,7 @@ env-passthrough-text = utf8-text comment = "%" utf8-text CRLF ; Input strings that are not special -text = *( text-char / escaped-specials ) +text = *text-char ; Input content wrapped in braces can be attatched to a command or used to ; manually isolate chunks of content (e.g. to hinder ligatures). @@ -55,15 +55,28 @@ braced-passthrough-text = utf8-text ; Building blocks options = "[" parameter *( "," parameter ) "]" -parameter = *WSP sil-identifier *WSP "=" *WSP ( value / quoted-value ) *WSP -value = utf8-text -quoted-value = DQUOTE utf8-text DQUOTE +parameter = *WSP sil-identifier *WSP "=" *WSP ( quoted-value / value ) *WSP +quoted-value = DQUOTE *quoted-value-char DQUOTE +value = *value-char -specials = "\" / "%" / "{" / "}" -escaped-specials = "\" specials +value-char =/ %x00-21 ; omit " +value-char =/ %x23-2B ; omit , +value-char =/ %x2D-3A ; omit ; +value-char =/ %x3C-5C ; omit ] +value-char =/ %x3E-7F ; end of utf8-1 +value-char =/ utf8-2 +value-char =/ utf8-3 +value-char =/ utf8-4 -; non-ascii-char = %x80-D7FF / %xE000-10FFFF -text-char = %x0-24 ; omit % +quoted-value-char = "\" %x22 +quoted-value-char =/ %x00-21 ; omit " +quoted-value-char =/ %x23-7F ; end of utf8-1 +quoted-value-char =/ utf8-2 +quoted-value-char =/ utf8-3 +quoted-value-char =/ utf8-4 + +text-char = "\" ( %x5C / %x25 / %x7B / %x7D ) +text-char =/ %x00-24 ; omit % text-char =/ %x26-5B ; omit \ text-char =/ %x5D-7A ; omit { text-char =/ %x7C ; omit } From f2f147a22e6d63c8b32d25fb97f4d5d5c99553e6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 29 Jan 2024 23:24:01 +0300 Subject: [PATCH 279/357] chore(tooling): Fixup ABNF grammar to allow braces in raw content --- sil.abnf | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/sil.abnf b/sil.abnf index 072d5ff11..beba09e23 100644 --- a/sil.abnf +++ b/sil.abnf @@ -32,11 +32,11 @@ environment =/ %s"\begin" [ options ] "{" command-id "}" ; Passthrough (raw) environments can have any valid UTF-8 except the closing ; delimiter matching the opening, per the environment rule. -env-passthrough-text = utf8-text +env-passthrough-text = *utf8-char ; Nothing to see here. ; But potentially important because it eats newlines! -comment = "%" utf8-text CRLF +comment = "%" *utf8-char CRLF ; Input strings that are not special text = *text-char @@ -51,14 +51,27 @@ command = "\" passthrough-command-id [ options ] [ braced-passthrough-text ] command =/ "\" command-id [ options ] [ braced-content ] ; Passthrough (raw) command text can have any valid UTF-8 except an unbalanced closing delimiter -braced-passthrough-text = utf8-text +braced-passthrough-text = "{" *( *braced-passthrough-char / braced-passthrough-text ) "}" + +braced-passthrough-char = %x00-7A ; omit { +braced-passthrough-char =/ %x7C ; omit } +braced-passthrough-char =/ %x7E-7F ; end of utf8-1 +braced-passthrough-char =/ utf8-2 +braced-passthrough-char =/ utf8-3 +braced-passthrough-char =/ utf8-4 -; Building blocks options = "[" parameter *( "," parameter ) "]" -parameter = *WSP sil-identifier *WSP "=" *WSP ( quoted-value / value ) *WSP +parameter = *WSP identifier *WSP "=" *WSP ( quoted-value / value ) *WSP + quoted-value = DQUOTE *quoted-value-char DQUOTE -value = *value-char +quoted-value-char = "\" %x22 +quoted-value-char =/ %x00-21 ; omit " +quoted-value-char =/ %x23-7F ; end of utf8-1 +quoted-value-char =/ utf8-2 +quoted-value-char =/ utf8-3 +quoted-value-char =/ utf8-4 +value = *value-char value-char =/ %x00-21 ; omit " value-char =/ %x23-2B ; omit , value-char =/ %x2D-3A ; omit ; @@ -68,13 +81,6 @@ value-char =/ utf8-2 value-char =/ utf8-3 value-char =/ utf8-4 -quoted-value-char = "\" %x22 -quoted-value-char =/ %x00-21 ; omit " -quoted-value-char =/ %x23-7F ; end of utf8-1 -quoted-value-char =/ utf8-2 -quoted-value-char =/ utf8-3 -quoted-value-char =/ utf8-4 - text-char = "\" ( %x5C / %x25 / %x7B / %x7D ) text-char =/ %x00-24 ; omit % text-char =/ %x26-5B ; omit \ @@ -87,14 +93,13 @@ text-char =/ utf8-4 letter = ALPHA / "_" / ":" identifier = letter *( letter / DIGIT / "-" / "." ) -command-id = identifier ; - ( %s"begin" / %s"end" / passthrough-command-id ) passthrough-command-id = %s"ftl" / %s"lua" / %s"math" / %s"raw" / %s"script" / %s"sil" / %s"use" / %s"xml" +command-id = identifier ; ASCII isn't good enough for us. -utf8-text = *utf8-char -utf8-char = utf8-1 / utf8-2 / utf8-3 / utf8-4 -utf8-1 = %x00-7F -utf8-2 = %xC2-DF utf8-tail -utf8-3 = %xE0 %xA0-BF utf8-tail / %xE1-EC 2utf8-tail / %xED %x80-9F utf8-tail / %xEE-EF 2utf8-tail -utf8-4 = %xF0 %x90-BF 2utf8-tail / %xF1-F3 3utf8-tail / %xF4 %x80-8F 2utf8-tail -utf8-tail = %x80-BF +utf8-char = utf8-1 / utf8-2 / utf8-3 / utf8-4 +utf8-1 = %x00-7F +utf8-2 = %xC2-DF utf8-tail +utf8-3 = %xE0 %xA0-BF utf8-tail / %xE1-EC 2utf8-tail / %xED %x80-9F utf8-tail / %xEE-EF 2utf8-tail +utf8-4 = %xF0 %x90-BF 2utf8-tail / %xF1-F3 3utf8-tail / %xF4 %x80-8F 2utf8-tail +utf8-tail = %x80-BF From 0faf4fc2a09c36c49fb305c6068ab56464f4b17e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 30 Jan 2024 14:08:01 +0300 Subject: [PATCH 280/357] chore(tooling): Fix ABNF definition of values --- sil.abnf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sil.abnf b/sil.abnf index beba09e23..f51039e51 100644 --- a/sil.abnf +++ b/sil.abnf @@ -72,9 +72,8 @@ quoted-value-char =/ utf8-3 quoted-value-char =/ utf8-4 value = *value-char -value-char =/ %x00-21 ; omit " +value-char = %x00-21 ; omit " value-char =/ %x23-2B ; omit , -value-char =/ %x2D-3A ; omit ; value-char =/ %x3C-5C ; omit ] value-char =/ %x3E-7F ; end of utf8-1 value-char =/ utf8-2 From f29c6e8cab1a53a6620aaf6bc8ef1def09ddd513 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 31 Jan 2024 00:25:09 +0300 Subject: [PATCH 281/357] chore(tooling): Cleanup comments in ABNF --- sil.abnf | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/sil.abnf b/sil.abnf index f51039e51..8d02f400c 100644 --- a/sil.abnf +++ b/sil.abnf @@ -1,12 +1,13 @@ -; Formal grammar definition for SIL (SILE Input Language) files +; Formal grammar specification for SIL (SILE Input Language) files ; -; Based on RFC 5234 (Augmented BNF for Syntax Specifications: ABNF) +; Uses RFC 5234 (Augmented BNF for Syntax Specifications: ABNF) ; Uses RFC 7405 (Case-Sensitive String Support in ABNF) -; NOTE: ABNF does not seem to have a way to express matching / balancing of -; tags. The grammar below does not express SILE's ability to skip over -; passthrough content until it hits the correct matching closing tag for -; environments or the first unballanced brace for braced content. +; IMPORTANT CAVEAT: +; Backus-Naur Form grammars (like ABNF and EBNF) do not have a way to +; express matching opening and closing tags. The grammar below does +; not express SILE's ability to skip over passthrough content until +; it hits the matching closing tag for environments. ; A master document can only have one top level content item, but we allow ; loading of fragments as well which can have any number of top level content @@ -26,9 +27,13 @@ content =/ command environment = %s"\begin" [ options ] "{" passthrough-command-id "}" env-passthrough-text %s"\end{" passthrough-command-id "}" + ; ^^^^^^^^^^^^^^^^^^^^^^ + ; End command must match id used in begin, see caveat at top environment =/ %s"\begin" [ options ] "{" command-id "}" content %s"\end{" command-id "}" + ; ^^^^^^^^^^ + ; End command must match id used in begin, see caveat at top ; Passthrough (raw) environments can have any valid UTF-8 except the closing ; delimiter matching the opening, per the environment rule. @@ -41,17 +46,20 @@ comment = "%" *utf8-char CRLF ; Input strings that are not special text = *text-char -; Input content wrapped in braces can be attatched to a command or used to +; Input content wrapped in braces can be attached to a command or used to ; manually isolate chunks of content (e.g. to hinder ligatures). braced-content = "{" content "}" -; As with environments, the content format may be passthrough (raw) or more sil +; As with environments, the content format may be passthrough (raw) or more SIL ; content depending on the command. command = "\" passthrough-command-id [ options ] [ braced-passthrough-text ] command =/ "\" command-id [ options ] [ braced-content ] -; Passthrough (raw) command text can have any valid UTF-8 except an unbalanced closing delimiter -braced-passthrough-text = "{" *( *braced-passthrough-char / braced-passthrough-text ) "}" +; Passthrough (raw) command text can have any valid UTF-8 except an unbalanced +; closing delimiter +braced-passthrough-text = "{" + *( braced-passthrough-text / braced-passthrough-char ) + "}" braced-passthrough-char = %x00-7A ; omit { braced-passthrough-char =/ %x7C ; omit } @@ -92,13 +100,25 @@ text-char =/ utf8-4 letter = ALPHA / "_" / ":" identifier = letter *( letter / DIGIT / "-" / "." ) -passthrough-command-id = %s"ftl" / %s"lua" / %s"math" / %s"raw" / %s"script" / %s"sil" / %s"use" / %s"xml" +passthrough-command-id = %s"ftl" + / %s"lua" + / %s"math" + / %s"raw" + / %s"script" + / %s"sil" + / %s"use" + / %s"xml" command-id = identifier ; ASCII isn't good enough for us. utf8-char = utf8-1 / utf8-2 / utf8-3 / utf8-4 utf8-1 = %x00-7F utf8-2 = %xC2-DF utf8-tail -utf8-3 = %xE0 %xA0-BF utf8-tail / %xE1-EC 2utf8-tail / %xED %x80-9F utf8-tail / %xEE-EF 2utf8-tail -utf8-4 = %xF0 %x90-BF 2utf8-tail / %xF1-F3 3utf8-tail / %xF4 %x80-8F 2utf8-tail +utf8-3 = %xE0 %xA0-BF utf8-tail + / %xE1-EC 2utf8-tail + / %xED %x80-9F utf8-tail + / %xEE-EF 2utf8-tail +utf8-4 = %xF0 %x90-BF 2utf8-tail + / %xF1-F3 3utf8-tail + / %xF4 %x80-8F 2utf8-tail utf8-tail = %x80-BF From ec6ed657b40ec55a109652abb1d3af7366b3bde4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 31 Jan 2024 01:59:39 +0300 Subject: [PATCH 282/357] chore(core): Wire SILE.use() to class:loadPackage() when module is a package --- classes/base.lua | 10 ++++++++-- core/sile.lua | 5 ++--- inputters/base.lua | 3 ++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 405ab3a52..856628825 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -182,9 +182,15 @@ function class.declareSettings (_) end function class:loadPackage (packname, options, reload) - local pack = require(("packages.%s"):format(packname)) + local pack + if type(packname) == "table" then + pack = packname + else + pack = require(("packages.%s"):format(packname)) + end if type(pack) == "table" and pack.type == "package" then -- new package - self.packages[pack._name] = pack(options, reload) + local name = pack._name + self.packages[name] = pack(options, reload) else -- legacy package self:initPackage(pack, options) end diff --git a/core/sile.lua b/core/sile.lua index 06710d7c4..83f0ce40f 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -174,7 +174,7 @@ local function suggest_luarocks (module) ) end -SILE.use = function (module, options) +SILE.use = function (module, options, reload) local status, pack if type(module) == "string" then status, pack = pcall(require, module) @@ -211,9 +211,8 @@ SILE.use = function (module, options) SILE.pagebuilders[name] = pack SILE.pagebuilder = pack(options) elseif pack.type == "package" then - SILE.packages[name] = pack if class then - pack(options) + class:loadPackage(pack, options, reload) else table.insert(SILE.input.preambles, { pack = pack, options = options }) end diff --git a/inputters/base.lua b/inputters/base.lua index a72d86c38..4674bdfde 100644 --- a/inputters/base.lua +++ b/inputters/base.lua @@ -65,7 +65,8 @@ local function process_ambles (ambles) local options = {} if amble.pack then amble, options = amble.pack, amble.options end if amble.type == "package" then - amble(options) + local class = SILE.documentState.documentClass + class:loadPackage(amble.pack, options) else SILE.documentState.documentClass:initPackage(amble, options) end From 3c3fada13021ca774c3b1c435ed0e1ac4c9e8c2d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 31 Jan 2024 11:17:05 +0300 Subject: [PATCH 283/357] chore(packages): Protect existing instances of packages This re-runs the _init() function to potentially force a reload or change options, but it avoids re-instantiating a new instance from the package class. --- classes/base.lua | 27 ++++++++++++++++++++++----- core/sile.lua | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 856628825..b83a68ff3 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -183,14 +183,31 @@ end function class:loadPackage (packname, options, reload) local pack + -- Allow loading by injecting whole packages as-is, otherwise try to load it with the usual packages path. if type(packname) == "table" then - pack = packname + pack, packname = packname, packname._name else - pack = require(("packages.%s"):format(packname)) + pack = require(("packages.%s"):format(packname)) + if pack._name ~= packname then + SU.error(("Loaded module name '%s' does not match requested name '%s'"):format(pack._name, packname)) + end end - if type(pack) == "table" and pack.type == "package" then -- new package - local name = pack._name - self.packages[name] = pack(options, reload) + SILE.packages[packname] = pack + if type(pack) == "table" and pack.type == "package" then -- current package api + if self.packages[packname] then + -- If the same package name has been loaded before, we might be loading a modified version of the same package or + -- we might be re-loading the same package, or we might just be doubling up work because somebody called us twice. + -- The package itself should take care of the difference between load and reload based on the reload flag here, + -- but in addition to that we also want to avoid creating a new instance. We want to run the intitializer from the + -- (possibly different) new module, but not create a new instance ID and loose any connections it made. + -- To do this we add a create function that returns the current instance. This brings along the _initialized flag + -- and of course anything else already setup and running. + local current_instance = self.packages[packname] + pack._create = function () return current_instance end + pack(options, true) + else + self.packages[packname] = pack(options, reload) + end else -- legacy package self:initPackage(pack, options) end diff --git a/core/sile.lua b/core/sile.lua index 83f0ce40f..698a43340 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -211,6 +211,7 @@ SILE.use = function (module, options, reload) SILE.pagebuilders[name] = pack SILE.pagebuilder = pack(options) elseif pack.type == "package" then + SILE.packages[pack._name] = pack if class then class:loadPackage(pack, options, reload) else From a493c26c635517f2440fd61f509a7ddec91da12d Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Thu, 1 Feb 2024 17:47:43 +0100 Subject: [PATCH 284/357] refactor(typesetters): Simplify discretionary logic and line ratio computation (#1980) --- core/nodefactory.lua | 39 ++++++++++++------- typesetters/base.lua | 89 ++++++++++++++++++-------------------------- 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/core/nodefactory.lua b/core/nodefactory.lua index 9d986e007..fbb17a21e 100644 --- a/core/nodefactory.lua +++ b/core/nodefactory.lua @@ -287,6 +287,28 @@ function nodefactory.discretionary:toText () return self.used and "-" or "_" end +function nodefactory.discretionary:markAsPrebreak () + self.used = true + if self.parent then + self.parent.hyphenated = true + end + self.is_prebreak = true +end + +function nodefactory.discretionary:cloneAsPostbreak () + if not self.used then + SU.error("Cannot clone a non-used discretionary (previously marked as prebreak)") + end + return SILE.nodefactory.discretionary({ + prebreak = self.prebreak, + postbreak = self.postbreak, + replacement = self.replacement, + parent = self.parent, + used = true, + is_prebreak = false, + }) +end + function nodefactory.discretionary:outputYourself (typesetter, line) -- See typesetter:computeLineRatio() which implements the currently rather -- messy hyphenated checks. @@ -300,22 +322,13 @@ function nodefactory.discretionary:outputYourself (typesetter, line) -- It's possible not to have a parent (e.g. on a discretionary directly -- added in the queue and not coming from the hyphenator logic). - -- Eiher that, or we have a hyphenate parent. + -- Eiher that, or we have a hyphenated parent. if self.used then -- This is the actual hyphenation point. - -- Skip margin glue and zero boxes. - -- If we then reach our discretionary, it means its the first in the line, - -- i.e. a postbreak. Otherwise, its a prebreak (near the end of the line, - -- notwithstanding glues etc.) - local i = 1 - while (line.nodes[i].is_glue and line.nodes[i].value == "margin") - or line.nodes[i].type == "zerohbox" do - i = i + 1 - end - if (line.nodes[i] == self) then - for _, node in ipairs(self.postbreak) do node:outputYourself(typesetter, line) end - else + if self.is_prebreak then for _, node in ipairs(self.prebreak) do node:outputYourself(typesetter, line) end + else + for _, node in ipairs(self.postbreak) do node:outputYourself(typesetter, line) end end else -- This is not the hyphenation point (but another discretionary in the queue) diff --git a/typesetters/base.lua b/typesetters/base.lua index 3cc524ba0..c92cb3116 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -945,6 +945,11 @@ function typesetter:breakpointsToLines (breakpoints) local slice = {} local seenNonDiscardable = false for j = linestart, point.position do + if nodes[j].is_discretionary and nodes[j].used then + -- This is the used (prebreak) discretionary from a previous line, + -- repeated. Replace it with a clone, changed to a postbreak. + nodes[j] = nodes[j]:cloneAsPostbreak() + end slice[#slice+1] = nodes[j] if nodes[j] then if not nodes[j].discardable then @@ -957,10 +962,12 @@ function typesetter:breakpointsToLines (breakpoints) SU.debug("typesetter", "Skipping a line containing only discardable nodes") linestart = point.position + 1 else - -- If the line ends with a discretionary, repeat it on the next line, - -- so as to account for a potential postbreak. if slice[#slice].is_discretionary then + -- The line ends, with a discretionary: + -- repeat it on the next line, so as to account for a potential postbreak. linestart = point.position + -- And mark it as used as prebreak for now. + slice[#slice]:markAsPrebreak() else linestart = point.position + 1 end @@ -985,49 +992,31 @@ function typesetter:breakpointsToLines (breakpoints) end function typesetter.computeLineRatio (_, breakwidth, slice) - -- This somewhat wrong, see #1362 and #1528 - -- This is a somewhat partial workaround, at least made consistent with - -- the nnode and discretionary outputYourself routines - -- (which are somewhat wrong too, or to put it otherwise, the whole - -- logic here, marking nodes without removing/replacing them, likely makes - -- things more complex than they should). - -- TODO Possibly consider a full rewrite/refactor. local naturalTotals = SILE.length() - -- From the line end, check if the line is hyphenated (to account for a prebreak) - -- or contains extraneous glues (e.g. to account for spaces to ignore). - local n = #slice - while n > 1 do - if slice[n].is_glue or slice[n].is_zero then - -- Skip margin glues (they'll be accounted for in the loop below) and - -- zero boxes, so as to reach actual content... - if slice[n].value ~= "margin" then - -- ... but any other glue than a margin, at the end of a line, is actually - -- extraneous. It will however also be accounted for below, so subtract - -- them to cancel their width. Typically, if a line break occurred at - -- a space, the latter is then at the end of the line now, and must be - -- ignored. - naturalTotals:___sub(slice[n].width) - end - elseif slice[n].is_discretionary then - -- Stop as we reached an hyphenation, and account for the prebreak. - slice[n].used = true - if slice[n].parent then - slice[n].parent.hyphenated = true + -- From the line end, account for the margin but skip any trailing + -- glues (spaces to ignore) and zero boxes until we reach actual content. + local npos = #slice + while npos > 1 do + if slice[npos].is_glue or slice[npos].is_zero then + if slice[npos].value == "margin" then + naturalTotals:___add(slice[npos].width) end - naturalTotals:___add(slice[n]:prebreakWidth()) - slice[n].height = slice[n]:prebreakHeight() - break else - -- Stop as we reached actual content. break end - n = n - 1 + npos = npos - 1 end + -- Due to discretionaries, keep track of seen parent nodes local seenNodes = {} + -- CODE SMELL: Not sure which node types were supposed to be skipped + -- at initial positions in the line! local skipping = true - for i, node in ipairs(slice) do + + -- Until end of actual content + for i = 1, npos do + local node = slice[i] if node.is_box then skipping = false if node.parent and not node.parent.hyphenated then @@ -1043,29 +1032,25 @@ function typesetter.computeLineRatio (_, breakwidth, slice) elseif node.is_discretionary then skipping = false local seen = node.parent and seenNodes[node.parent] - if not seen and not node.used then - naturalTotals:___add(node:replacementWidth():absolute()) - slice[i].height = slice[i]:replacementHeight():absolute() + if not seen then + if node.used then + if node.is_prebreak then + naturalTotals:___add(node:prebreakWidth()) + node.height = node:prebreakHeight() + else + naturalTotals:___add(node:postbreakWidth()) + node.height = node:postbreakHeight() + end + else + naturalTotals:___add(node:replacementWidth():absolute()) + node.height = node:replacementHeight():absolute() + end end elseif not skipping then naturalTotals:___add(node.width) end end - -- From the line start, skip glues and margins, and check if it then starts - -- with a used discretionary. If so, account for a postbreak. - n = 1 - while n < #slice do - if slice[n].is_discretionary and slice[n].used then - naturalTotals:___add(slice[n]:postbreakWidth()) - slice[n].height = slice[n]:postbreakHeight() - break - elseif not (slice[n].is_glue or slice[n].is_zero) then - break - end - n = n + 1 - end - local _left = breakwidth:tonumber() - naturalTotals:tonumber() local ratio = _left / naturalTotals[_left < 0 and "shrink" or "stretch"]:tonumber() ratio = math.max(ratio, -1) From e645dbd300fcc6541e8e62445eb1d405a04503b3 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 30 Jan 2024 19:56:28 +0100 Subject: [PATCH 285/357] feat(typesetters): Add base typesetter (multi-)liner support A construct for content spanning multiple lines and needing to be wrapped for some effect on each line. --- typesetters/base.lua | 244 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 239 insertions(+), 5 deletions(-) diff --git a/typesetters/base.lua b/typesetters/base.lua index c92cb3116..65d7ba64d 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -166,6 +166,7 @@ function typesetter:initState () nodes = {}, outputQueue = {}, lastBadness = awful_bad, + liners = {}, } end @@ -912,6 +913,177 @@ function typesetter.leadingFor (_, vbox, previous) end end +-- Beggining of liner logic (contructs spanning over several lines) + +-- These two special nodes are used to track the current liner entry and exit. +-- As Sith Lords, they are always two: they are local here, so no one can +-- use one alone and break the balance of the Force. +local linerEnterNode = pl.class(SILE.nodefactory.hbox) +function linerEnterNode:_init(name, outputMethod) + SILE.nodefactory.hbox._init(self) + self.outputMethod = outputMethod + self.name = name + self.is_enter = true +end +function linerEnterNode:clone() + return linerEnterNode(self.name, self.outputMethod) +end +function linerEnterNode:outputYourself () + SU.error("A liner enter node " .. tostring(self) .. "'' made it to output", true) +end +function linerEnterNode:__tostring () + return "+L[" .. self.name .. "]" +end +local linerLeaveNode = pl.class(SILE.nodefactory.hbox) +function linerLeaveNode:_init(name) + SILE.nodefactory.hbox._init(self) + self.name = name + self.is_leave = true +end +function linerLeaveNode:clone() + return linerLeaveNode(self.name) +end +function linerLeaveNode:outputYourself () + SU.error("A liner leave node " .. tostring(self) .. "'' made it to output", true) +end +function linerLeaveNode:__tostring () + return "-L[" .. self.name .. "]" +end + +local linerBox = pl.class(SILE.nodefactory.hbox) +function linerBox:_init (name, outputMethod) + SILE.nodefactory.hbox._init(self) + self.width = SILE.length() + self.height = SILE.length() + self.depth = SILE.length() + self.name = name + self.inner = {} + self.outputYourself = outputMethod +end +function linerBox:append (node) + self.inner[#self.inner+1] = node + self.width = self.width + node.width + self.height = SU.max(self.height, node.height) + self.depth = SU.max(self.depth, node.depth) +end +function linerBox:count () + return #self.inner +end +function linerBox:outputContent (tsetter, line) + for _, node in ipairs(self.inner) do + node.outputYourself(node, tsetter, line) + end +end +function linerBox:__tostring () + return "*L[" .. self.name .. "]H<" .. tostring(self.width) .. ">^" .. tostring(self.height) .. "-" .. tostring(self.depth) .. "v" +end + +--- Any unclosed liner is reopened on the current line, so we clone and repeat +-- it. +-- An assumption is that the inserts are done after the current slice content, +-- supposed to be just before meaningful (visible) content. +---@param slice table Current line nodes +---@return boolean Whether a liner was reopened +function typesetter:_repeatEnterLiners (slice) + local m = self.state.liners + if #m > 0 then + for i = 1, #m do + local n = m[i]:clone() + slice[#slice+1] = n + SU.debug("typesetter.liner", "Reopening liner", n) + end + return true + end + return false +end + +--- All pairs of liners are rebuilt as hboxes wrapping their content. +-- Migrating content, however, must be kept outside the hboxes at top slice level. +---@param slice table Flat nodes from current line +---@return table New reboxed slice +function typesetter._reboxLiners (_, slice) + local outSlice = {} + local migratingList = {} + local lboxStack = {} + for i = 1, #slice do + local node = slice[i] + if node.is_enter then + SU.debug("typesetter.liner", "Start reboxing", node) + local n = linerBox(node.name, node.outputMethod) + lboxStack[#lboxStack+1] = n + elseif node.is_leave then + if #lboxStack == 0 then + SU.error("Multiliner box stacking mismatch" .. node) + elseif #lboxStack == 1 then + SU.debug("typesetter.liner", "End reboxing", node, + "(toplevel) =", lboxStack[1]:count(), "nodes") + if lboxStack[1]:count() > 0 then + outSlice[#outSlice+1] = lboxStack[1] + end + else + SU.debug("typesetter.liner", "End reboxing", node, + "(sublevel) =", lboxStack[#lboxStack]:count(), "nodes") + if lboxStack[#lboxStack]:count() > 0 then + local hbox = lboxStack[#lboxStack - 1] + hbox:append(lboxStack[#lboxStack]) + end + end + lboxStack[#lboxStack] = nil + pl.tablex.insertvalues(outSlice, migratingList) + migratingList = {} + else + if #lboxStack > 0 then + if not node.is_migrating then + local lbox = lboxStack[#lboxStack] + lbox:append(node) + else + migratingList[#migratingList+1] = node + end + else + outSlice[#outSlice+1] = node + end + end + end + return outSlice -- new reboxed slice +end + +--- Check if a node is a liner, and process it if so, in a stack. +---@param node any Current node +---@return boolean Whether a liner was opened +function typesetter:_processIfLiner(node) + local entered = false + if node.is_enter then + SU.debug("typesetter.liner", "Enter liner", node) + self.state.liners[#self.state.liners+1] = node + entered = true + elseif node.is_leave then + SU.debug("typesetter.liner", "Leave liner", node) + if #self.state.liners == 0 then + SU.error("Multiliner stack mismatch" .. node) + elseif self.state.liners[#self.state.liners].name == node.name then + self.state.liners[#self.state.liners].link = node -- for consistency check + self.state.liners[#self.state.liners] = nil + else + SU.error("Multiliner stack inconsistency" + .. self.state.liners[#self.state.liners] .. "vs. " .. node) + end + end + return entered +end + +function typesetter:_repeatLeaveLiners(slice, insertIndex) + for _, v in ipairs(self.state.liners) do + if not v.link then + local n = linerLeaveNode(v.name) + SU.debug("typesetter.liner", "Closing liner", n) + table.insert(slice, insertIndex, n) + else + SU.error("Multiliner stack inconsistency" .. v) + end + end +end +-- End of liner logic + function typesetter:addrlskip (slice, margins, hangLeft, hangRight) local LTR = self.frame:writingDirection() == "LTR" local rskip = margins[LTR and "rskip" or "lskip"] @@ -944,17 +1116,34 @@ function typesetter:breakpointsToLines (breakpoints) if point.position ~= 0 then local slice = {} local seenNonDiscardable = false + local seenLiner = false + local lastContentNodeIndex + for j = linestart, point.position do - if nodes[j].is_discretionary and nodes[j].used then + local currentNode = nodes[j] + if not currentNode.discardable + and not (currentNode.is_glue and not currentNode.explicit) + and not currentNode.is_zero then + -- actual visible content starts here + lastContentNodeIndex = #slice + 1 + end + if not seenLiner and lastContentNodeIndex then + -- Any stacked liner (unclosed from a previous line) is reopened on + -- the current line. + seenLiner = self:_repeatEnterLiners(slice) + lastContentNodeIndex = #slice + 1 + end + if currentNode.is_discretionary and currentNode.used then -- This is the used (prebreak) discretionary from a previous line, -- repeated. Replace it with a clone, changed to a postbreak. - nodes[j] = nodes[j]:cloneAsPostbreak() + currentNode = currentNode:cloneAsPostbreak() end - slice[#slice+1] = nodes[j] - if nodes[j] then - if not nodes[j].discardable then + slice[#slice+1] = currentNode + if currentNode then + if not currentNode.discardable then seenNonDiscardable = true end + seenLiner = self:_processIfLiner(currentNode) or seenLiner end end if not seenNonDiscardable then @@ -972,12 +1161,23 @@ function typesetter:breakpointsToLines (breakpoints) linestart = point.position + 1 end + -- Any unclosed liner is closed on the next line in reverse order. + if lastContentNodeIndex then + self:_repeatLeaveLiners(slice, lastContentNodeIndex + 1) + end + -- Then only we can add some extra margin glue... local mrg = self:getMargins() self:addrlskip(slice, mrg, point.left, point.right) -- And compute the line... local ratio = self:computeLineRatio(point.width, slice) + + -- Re-shuffle liners, if any, into their own boxes. + if seenLiner then + slice = self:_reboxLiners(slice) + end + local thisLine = { ratio = ratio, nodes = slice } lines[#lines+1] = thisLine end @@ -1160,4 +1360,38 @@ function typesetter:pushHlist (hlist) end end +--- A liner is a construct that may span multiple lines. +-- This is the user-facing method for creating such liners in packages. +-- The content may be line-broken, and each bit on each line will be wrapped +-- into a box. +-- These boxes will be formatted according to some output logic. +-- The output method has the same signature as the outputYourself method +-- of a box, and is responsible for outputting the liner inner content with the +-- outputContent(typesetter, line) method, possibly surrounded by some additional +-- effects. +-- If we are already in horizontal-restricted mode, the liner is processed +-- immediately, since line breaking won't occur then. +---@param name string Name of the liner (usefull for debugging) +---@param content table SILE AST to process +---@param outputYourself function Output method for wrapped boxes +function typesetter:liner (name, content, outputYourself) + if self.state.hmodeOnly then + SU.debug("typesetter.liner", "Applying liner in horizontal-restricted mode") + local hbox, hlist = self:makeHbox(content) + local lbox = linerBox(name, outputYourself) + lbox:append(hbox) + self:pushHorizontal(lbox) + self:pushHlist(hlist) + else + self.state.linerCount = (self.state.linerCount or 0) + 1 + local uname = name .. "_" .. self.state.linerCount + SU.debug("typesetter.liner", "Applying liner in standard mode") + local enter = linerEnterNode(uname, outputYourself) + local leave = linerLeaveNode(uname) + self:pushHorizontal(enter) + SILE.process(content) + self:pushHorizontal(leave) + end +end + return typesetter From 3eb1a1f944594283bb68e5876eeaf692dd92678a Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 30 Jan 2024 20:26:51 +0100 Subject: [PATCH 286/357] feat(packages): Strikethrough and underline can span multiple lines --- packages/rules/init.lua | 42 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/packages/rules/init.lua b/packages/rules/init.lua index b6efbc3a7..3366f6021 100644 --- a/packages/rules/init.lua +++ b/packages/rules/init.lua @@ -126,22 +126,14 @@ function package:registerCommands () self:registerCommand("underline", function (_, content) local underlinePosition, underlineThickness = getUnderlineParameters() - local hbox, hlist = SILE.typesetter:makeHbox(content) - -- Re-wrap the hbox in another hbox responsible for boxing it at output - -- time, when we will know the line contribution and can compute the scaled width - -- of the box, taking into account possible stretching and shrinking. - SILE.typesetter:pushHbox({ - inner = hbox, - width = hbox.width, - height = hbox.height, - depth = hbox.depth, - outputYourself = function (node, typesetter, line) + SILE.typesetter:liner("underline", content, + function (box, typesetter, line) local oldX = typesetter.frame.state.cursorX local Y = typesetter.frame.state.cursorY - -- Build the original hbox. + -- Build the content. -- Cursor will be moved by the actual definitive size. - node.inner:outputYourself(SILE.typesetter, line) + box:outputContent(typesetter, line) local newX = typesetter.frame.state.cursorX -- Output a line. @@ -150,36 +142,28 @@ function package:registerCommands () -- should expand downwards SILE.outputter:drawRule(oldX, Y - underlinePosition, newX - oldX, underlineThickness) end - }) - SILE.typesetter:pushHlist(hlist) + ) end, "Underlines some content") self:registerCommand("strikethrough", function (_, content) local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters() - local hbox, hlist = SILE.typesetter:makeHbox(content) - -- Re-wrap the hbox in another hbox responsible for boxing it at output - -- time, when we will know the line contribution and can compute the scaled width - -- of the box, taking into account possible stretching and shrinking. - SILE.typesetter:pushHbox({ - inner = hbox, - width = hbox.width, - height = hbox.height, - depth = hbox.depth, - outputYourself = function (node, typesetter, line) + SILE.typesetter:liner("strikethrough", content, + function (box, typesetter, line) local oldX = typesetter.frame.state.cursorX local Y = typesetter.frame.state.cursorY - -- Build the original hbox. + + -- Build the content. -- Cursor will be moved by the actual definitive size. - node.inner:outputYourself(SILE.typesetter, line) + box:outputContent(typesetter, line) local newX = typesetter.frame.state.cursorX + -- Output a line. -- NOTE: The OpenType spec is not explicit regarding how the size -- (thickness) affects the position. We opt to distribute evenly SILE.outputter:drawRule(oldX, Y - yStrikeoutPosition - yStrikeoutSize / 2, newX - oldX, yStrikeoutSize) end - }) - SILE.typesetter:pushHlist(hlist) + ) end, "Strikes out some content") self:registerCommand("boxaround", function (_, content) @@ -237,6 +221,8 @@ The \autodoc:command{\underline} command \underline{underlines} its content. The \autodoc:command{\strikethrough} command \strikethrough{strikes} its content. +Both commands support paragraph content spanning multiple lines. + \autodoc:note{The position and thickness of the underlines and strikethroughs are based on the metrics of the current font, honoring the values defined by the type designer.} The \autodoc:command{\hrulefill} inserts an infinite horizontal rubber, similar to an \autodoc:command{\hfill}, but—as its name implies—filled with a rule (that is, a solid line). From f500be3f781574a24c724f2c0a7591766a4d69bb Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 2 Feb 2024 13:23:15 +0300 Subject: [PATCH 287/357] chore(deps): Bump version on GH Actions --- .github/workflows/build.yml | 2 +- .github/workflows/nix.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ac3b7830..334be762b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -105,7 +105,7 @@ jobs: - name: Install Nix uses: DeterminateSystems/nix-installer-action@v9 - name: Cache Nix dependencies - uses: DeterminateSystems/magic-nix-cache-action@v2 + uses: DeterminateSystems/magic-nix-cache-action@v3 - name: Setup developer environment run: | nix develop --command ./bootstrap.sh diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 247fe6033..857149f45 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -18,7 +18,7 @@ jobs: - name: Install Nix uses: DeterminateSystems/nix-installer-action@v9 - name: Cache Nix dependencies - uses: DeterminateSystems/magic-nix-cache-action@v2 + uses: DeterminateSystems/magic-nix-cache-action@v3 # Upstream package sometimes has flags set that disable flake checking - name: Setup test env run: | From 9d6d409a5cb2f593f5c2dee349aad67c8bdacf83 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 30 Jan 2024 20:35:36 +0100 Subject: [PATCH 288/357] fix(packages): Color changes shall not affect other content at page breaks --- packages/color/init.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/color/init.lua b/packages/color/init.lua index 2ee86b494..4c1dfd279 100644 --- a/packages/color/init.lua +++ b/packages/color/init.lua @@ -7,13 +7,16 @@ function package:registerCommands () self:registerCommand("color", function (options, content) local color = SILE.color(options.color or "black") - SILE.typesetter:pushHbox({ - outputYourself = function () SILE.outputter:pushColor(color) end - }) - SILE.process(content) - SILE.typesetter:pushHbox({ - outputYourself = function () SILE.outputter:popColor() end - }) + -- This is a bit of a hack to use a liner. + -- (Due to how the color stack is currently handled) + -- If the content spans multiple lines, and a page break occurs in between, + -- this avoids the color being propagated to other page content. + -- (folio, footnotes, etc.) + SILE.typesetter:liner("color", content, function (box, typesetter, line) + SILE.outputter:pushColor(color) + box:outputContent(typesetter, line) + SILE.outputter:popColor() + end) end, "Changes the active ink color to the color <color>.") end From c4fcc5b363cd765175bbe4b81bc0d34c458e748e Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 30 Jan 2024 20:48:23 +0100 Subject: [PATCH 289/357] test(packages): Add test showing strikethrough and underline spanning multiple lines --- tests/feat-liner-spanning.expected | 29 +++++++++++++++++++++++++++++ tests/feat-liner-spanning.sil | 13 +++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/feat-liner-spanning.expected create mode 100644 tests/feat-liner-spanning.sil diff --git a/tests/feat-liner-spanning.expected b/tests/feat-liner-spanning.expected new file mode 100644 index 000000000..6bab893f5 --- /dev/null +++ b/tests/feat-liner-spanning.expected @@ -0,0 +1,29 @@ +Set paper size 297.6377985 419.5275636 +Begin page +Mx 14.8819 +My 31.5721 +Set font Gentium Plus;14;400;;normal;;;LTR +T 86 87 85 76 78 72 w=32.8604 (strike) +Mx 52.5440 +T 86 87 85 76 78 72 w=32.8604 (strike) +Mx 90.2061 +T 86 87 85 76 78 72 w=32.8604 (strike) +Mx 127.8682 +T 86 87 85 76 78 72 w=32.8604 (strike) +Mx 165.5303 +T 88 81 71 72 85 79 76 81 72 w=56.2119 (underline) +Mx 226.5440 +T 88 81 71 72 85 79 76 81 72 w=56.2119 (underline) +Draw line 165.5303 33.2811 117.2256 0.6836 +Draw line 14.8819 27.8123 267.8740 0.6836 +Mx 14.8819 +My 48.3721 +T 88 81 71 72 85 79 76 81 72 w=56.2119 (underline) +Draw line 14.8819 50.0811 56.2119 0.6836 +Mx 74.2034 +T 86 87 85 76 78 72 w=32.8604 (strike) +Mx 107.0638 +T 17 w=3.2061 (.) +Draw line 14.8819 44.6123 95.3879 0.6836 +End page +Finish diff --git a/tests/feat-liner-spanning.sil b/tests/feat-liner-spanning.sil new file mode 100644 index 000000000..e0f19d133 --- /dev/null +++ b/tests/feat-liner-spanning.sil @@ -0,0 +1,13 @@ +\begin[papersize=a6]{document} +\neverindent +\nofolios +\set[parameter=shaper.spaceenlargementfactor, value=1] +\script[src=packages/rules] +\font[size=14pt] +% strikethrough and underline can span multiple lines +% Here line-breaking (paragraphing) occurs in the underlined sequence. +\strikethrough{strike strike strike strike +\underline{underline underline underline} strike.} + +\end{document} + From 842cb5640ff61e297fbd3299eaafe55e07ef30db Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 30 Jan 2024 21:26:42 +0100 Subject: [PATCH 290/357] feat(packages): PDF links can now span multiple lines --- packages/pdf/init.lua | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index 1f6b3a349..fbe58658b 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -54,32 +54,23 @@ function package:registerCommands () borderwidth = borderwidth, borderoffset = borderoffset } - local x0, y0 - SILE.typesetter:pushHbox({ - value = nil, - height = 0, - width = 0, - depth = 0, - outputYourself = function (_, typesetter, _) - x0 = typesetter.frame.state.cursorX:tonumber() - y0 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber() + + SILE.typesetter:liner("pdf:link", content, + function (box, typesetter, line) + local x0 = typesetter.frame.state.cursorX:tonumber() + local y0 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber() SILE.outputter:beginLink(dest, opts) - end - }) - local hbox, hlist = SILE.typesetter:makeHbox(content) -- hack - SILE.typesetter:pushHbox(hbox) - SILE.typesetter:pushHbox({ - value = nil, - height = 0, - width = 0, - depth = 0, - outputYourself = function (_, typesetter, _) + + -- Build the content. + -- Cursor will be moved by the actual definitive size. + box:outputContent(typesetter, line) local x1 = typesetter.frame.state.cursorX:tonumber() - local y1 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + hbox.height):tonumber() + local y1 = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + box.height):tonumber() + SILE.outputter:endLink(dest, opts, x0, y0, x1, y1) -- Unstable API end - }) - SILE.typesetter:pushHlist(hlist) + ) + end) self:registerCommand("pdf:metadata", function (options, _) From b0027f8cdfc085ac13873770b67469997d72bf16 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 2 Feb 2024 14:25:27 +0300 Subject: [PATCH 291/357] chore(languages): Make Japanese node maker play nice with new liners feature --- languages/ja.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/ja.lua b/languages/ja.lua index 4e670e653..8a8b6ebfb 100644 --- a/languages/ja.lua +++ b/languages/ja.lua @@ -149,7 +149,7 @@ function SILE.nodeMakers.ja:iterator (items) intercharacterspace(lastcp, thiscp), stretchability(lastcp, thiscp), shrinkability(lastcp, thiscp) - ) + ):absolute() if breakAllowed(lastcp, thiscp) then db = db .." G ".. tostring(length) coroutine.yield(SILE.nodefactory.glue(length)) From 2fb363d560544819ba5ea2eaf2183a7be6fa1602 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 2 Feb 2024 14:47:53 +0300 Subject: [PATCH 292/357] test(languages): Tweak expectations to reflect ZW absolutization This notably affects Latin (non CJK) text in JA language because the spacer width node is computed at a different time and hence possible using a different font. This result isn't necessarily *correct* but it is not what this regression test is even testing. --- tests/bug-990.expected | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/bug-990.expected b/tests/bug-990.expected index cdf325b11..d00c5114d 100644 --- a/tests/bug-990.expected +++ b/tests/bug-990.expected @@ -15,42 +15,42 @@ Mx 24.7039 My 124.9953 Set font Noto Sans CJK JP;22;800;;normal;;;LTR T 29804 w=22.0000 (第) -Mx 46.7338 +Mx 46.7477 T 19 w=12.2100 (2) -Mx 58.9737 +Mx 59.0014 T 29653 w=22.0000 (章) Mx 24.7039 My 151.1793 Mx 14.0360 T 44 a=14.2120 (K) -Mx 38.7475 +Mx 38.7510 T 80 w=13.3320 (o) -Mx 52.0871 +Mx 52.0941 T 79 w=13.4420 (n) -Mx 65.5366 +Mx 65.5471 T 79 w=13.4420 (n) -Mx 78.9862 +Mx 79.0002 T 74 w=6.0500 (i) -Mx 85.0437 +Mx 85.0613 T 68 w=11.1980 (c) -Mx 96.2493 +Mx 96.2703 T 73 w=13.3540 (h) -Mx 109.6109 +Mx 109.6354 T 74 w=6.0500 (i) -Mx 121.5929 +Mx 121.6209 T 41 w=16.0160 (H) -Mx 137.6165 +Mx 137.6480 T 66 w=12.4080 (a) -Mx 155.9566 +Mx 155.9916 T 52 w=13.1340 (S) -Mx 169.0981 +Mx 169.1366 T 70 w=12.1880 (e) -Mx 181.2937 +Mx 181.3357 Mx 11.9020 T 76 a=12.1440 (k) -Mx 193.2033 +Mx 193.2488 T 66 w=12.4080 (a) -Mx 205.6188 +Mx 205.6678 T 74 w=6.0500 (i) Mx 24.7039 My 181.1157 From efade7614f02b59991560bb61beb94ae745bf554 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 13:42:39 +0300 Subject: [PATCH 293/357] feat(settings): Add hook callback system for settings --- core/settings.lua | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/settings.lua b/core/settings.lua index c63d5f411..454c6622f 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -10,6 +10,7 @@ function settings:_init() self.declarations = {} self.stateQueue = {} self.defaults = {} + self.hooks = {} self:declare({ parameter = "document.language", @@ -105,7 +106,16 @@ end function settings:popState () if not self then return deprecator() end + local previous = self.state self.state = table.remove(self.stateQueue) + for parameter, oldvalue in pairs(previous) do + if self.hooks[parameter] then + local newvalue = self.state[parameter] + if oldvalue ~= newvalue then + self:runHooks(parameter, newvalue) + end + end + end end function settings:declare (spec) @@ -118,6 +128,10 @@ function settings:declare (spec) return end self.declarations[spec.parameter] = spec + self.hooks[spec.parameter] = {} + if spec.hook then + self:registerHook(spec.parameter, spec.hook) + end self:set(spec.parameter, spec.default, true) end @@ -202,6 +216,20 @@ function settings:set (parameter, value, makedefault, reset) if makedefault then self.defaults[parameter] = value end + self:runHooks(parameter, value) +end + +function settings:registerHook (parameter, func) + table.insert(self.hooks[parameter], func) +end + +function settings:runHooks (parameter, value) + if self.hooks[parameter] then + for _, func in ipairs(self.hooks[parameter]) do + SU.debug("classhooks", "Running seting hook for", parameter) + func(value) + end + end end function settings:temporarily (func) From a1c49526ca8903c81ab6c28b613d298ff7c67cb8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 13:54:27 +0300 Subject: [PATCH 294/357] test(settings): Add unit test for setting hooks --- core/settings_spec.lua | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 core/settings_spec.lua diff --git a/core/settings_spec.lua b/core/settings_spec.lua new file mode 100644 index 000000000..0b5bd5df9 --- /dev/null +++ b/core/settings_spec.lua @@ -0,0 +1,42 @@ +SILE = require("core.sile") + +describe("The settings handler", function() + + it("should trigger callbacks on set", function() + local private = "foo" + local function callback (value) + private = value .. " hooked" + end + SILE.settings:declare({ + parameter = "test.callback", + type = "string", + default = "bar", + hook = callback + }) + SILE.settings:set("test.callback", "baz") + assert.is.equal("baz hooked", private) + end) + + it("should trigger callbacks on push/pop events", function() + local mystate = "foo" + local function callback2 (value) + mystate = value .. " stack" + end + SILE.settings:declare({ + parameter = "test.callback2", + type = "string", + default = "bar", + hook = callback2 + }) + SILE.settings:pushState() + SILE.settings:set("test.callback2", "baz1") + SILE.settings:pushState() + SILE.settings:set("test.callback2", "baz2") + assert.is.equal("baz2 stack", mystate) + SILE.settings:popState() + assert.is.equal("baz1 stack", mystate) + SILE.settings:popState() + assert.is.equal("bar stack", mystate) + end) + +end) From 0646bb234296a14755331d49550fdc9e9871e089 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Sat, 3 Feb 2024 16:07:52 +0100 Subject: [PATCH 295/357] chore(typesetters): Correct discretionary width in liners --- typesetters/base.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/typesetters/base.lua b/typesetters/base.lua index 65d7ba64d..176136d65 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -962,7 +962,20 @@ function linerBox:_init (name, outputMethod) end function linerBox:append (node) self.inner[#self.inner+1] = node - self.width = self.width + node.width + if node.is_discretionary then + -- Discretionary nodes don't have a width of their own. + if node.used then + if node.is_prebreak then + self.width:___add(node:prebreakWidth()) + else + self.width:___add(node:postbreakWidth()) + end + else + self.width:___add(node:replacementWidth()) + end + else + self.width:___add(node.width:absolute()) + end self.height = SU.max(self.height, node.height) self.depth = SU.max(self.depth, node.depth) end From 761b97358a8e497819d58603cfc2efe4ae8a588e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 18:53:24 +0300 Subject: [PATCH 296/357] chore(core): Reorder some core initialization with an eye to refactoring --- core/sile.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 698a43340..d9e75f5fc 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -81,8 +81,7 @@ SILE.packages = core_loader("packages") SILE.typesetters = core_loader("typesetters") SILE.pagebuilders = core_loader("pagebuilders") --- Internal libraries that don't make assumptions on load, only use -SILE.traceStack = require("core.tracestack")() +-- Internal libraries that don't make assumptions on load, only provide something SILE.parserBits = require("core.parserbits") SILE.frameParser = require("core.frameparser") SILE.color = require("core.color") @@ -501,8 +500,11 @@ function SILE.finish () end end --- Internal libraries that run core SILE functions on load +-- Internal libraries that return classes, but we only ever use one instantiation +SILE.traceStack = require("core.tracestack")() SILE.settings = require("core.settings")() + +-- Internal libraries that run core SILE functions on load require("core.hyphenator-liang") require("core.languages") SILE.linebreak = require("core.break") From 8fafd571aa32121caf9e48a1f19da4405e4052dd Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 18:53:24 +0300 Subject: [PATCH 297/357] refactor(core): Move CLI and REPL loading to wrappers ...and only load as needed. --- core/sile.lua | 2 -- sile.in | 6 ++++-- src/lib.rs | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index d9e75f5fc..408772a26 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -509,8 +509,6 @@ require("core.hyphenator-liang") require("core.languages") SILE.linebreak = require("core.break") require("core.frame") -SILE.cli = require("core.cli") -SILE.repl = require("core.repl") SILE.font = require("core.font") -- For warnings and shims scheduled for removal that are easier to keep track diff --git a/sile.in b/sile.in index 57511a5a5..940bb076d 100755 --- a/sile.in +++ b/sile.in @@ -22,7 +22,8 @@ end SILE = require("core.sile") SILE.full_version = SILE.full_version .. " [Lua]" -SILE.cli:parseArguments() +local cli = require("core.cli") +cli:parseArguments() if not os.getenv 'LUA_REPL_RLWRAP' and not SILE.quiet then io.stderr:write(SILE.full_version .. '\n') @@ -52,7 +53,8 @@ if SILE.input.filenames and #SILE.input.filenames >= 1 then SILE.finish() else - SILE.repl:enter() + local repl = require("core.repl") + repl:enter() end -- vim: ft=lua diff --git a/src/lib.rs b/src/lib.rs index 6efc0b115..28ae63b11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,7 +184,9 @@ pub fn run( let finish: LuaFunction = sile.get("finish")?; finish.call::<_, _>(())?; } else { - let repl: LuaTable = sile.get("repl")?; + let repl_module: LuaString = lua.create_string("core.repl")?; + let r#require: LuaFunction = lua.globals().get("require")?; + let repl: LuaTable = r#require.call::<LuaString, LuaTable>(repl_module)?; repl.call_method::<_, _>("enter", ())?; } Ok(()) From 580e22ff18b76360e46c857c7532fd8ec8ecfda1 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 18:53:24 +0300 Subject: [PATCH 298/357] chore(core): Reorder some core initialization with an eye to refactoring --- core/sile.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 408772a26..c5c7ea19a 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -33,6 +33,11 @@ local lfs = require("lfs") -- Developer tooling profiler local ProFi +-- For warnings and shims scheduled for removal that are easier to keep track +-- of when they are not spread across so many locations... +-- Loaded early to make it easier to manage migrations in core code. +require("core/deprecations") + SILE.utilities = require("core.utilities") SU = SILE.utilities -- regrettable global alias @@ -511,8 +516,4 @@ SILE.linebreak = require("core.break") require("core.frame") SILE.font = require("core.font") --- For warnings and shims scheduled for removal that are easier to keep track --- of when they are not spread across so many locations... -require("core/deprecations") - return SILE From a0ecbcf8b3bc334c891bd443894d0e354bfff737 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 4 Feb 2024 14:18:30 +0300 Subject: [PATCH 299/357] test(typesetters): Add test for liner width computation regression Co-authored-by: Omikhleia <didier.willis@gmail.com> --- tests/bug-liner-width.expected | 35 ++++++++++++++++++++++++++++++++++ tests/bug-liner-width.sil | 31 ++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 tests/bug-liner-width.expected create mode 100644 tests/bug-liner-width.sil diff --git a/tests/bug-liner-width.expected b/tests/bug-liner-width.expected new file mode 100644 index 000000000..9df478fab --- /dev/null +++ b/tests/bug-liner-width.expected @@ -0,0 +1,35 @@ +Set paper size 209.7637818 297.6377985 +Begin page +Push color 0.5020 0.5020 0.5020 +Draw line 10.4882 14.8819 188.7874 34.5868 +Pop color +Push color 0.5020 0.5020 0.5020 +Draw line 10.4882 53.2819 188.7874 34.5868 +Pop color +Push color 0.5020 0.5020 0.5020 +Draw line 10.4882 91.6819 116.2969 34.5868 +Pop color +Mx 10.4882 +My 154.3006 +Set font Gentium Plus;32;400;;normal;;;LTR +T 79 82 74 76 16 w=59.8281 (logi-) +Mx 70.3163 +T 93 82 87 92 w=56.4688 (zoty) +Mx 139.4475 +T 79 82 74 76 16 w=59.8281 (logi-) +Mx 10.4882 +My 192.7006 +T 16 w=10.7813 (-) +Mx 21.2694 +T 93 82 87 92 w=56.4688 (zoty) +Mx 82.9787 +T 79 82 74 76 16 w=59.8281 (logi-) +Mx 142.8068 +T 93 82 87 92 w=56.4688 (zoty) +Mx 10.4882 +My 231.1006 +T 79 82 74 76 16 w=59.8281 (logi-) +Mx 70.3163 +T 93 82 87 92 w=56.4688 (zoty) +End page +Finish diff --git a/tests/bug-liner-width.sil b/tests/bug-liner-width.sil new file mode 100644 index 000000000..2dc8cb458 --- /dev/null +++ b/tests/bug-liner-width.sil @@ -0,0 +1,31 @@ +\begin[papersize=a7]{document} +\nofolios +\neverindent +\font[size=32pt,language=pl] +\begin{lua} +-- MVE: Use the box width to advance position, rather than rely on internal content to move it. +SILE.documentState.documentClass:registerCommand("advance-box-width", function (options, content) + local bs = SILE.measurement("0.9bs"):tonumber() + local bsratio = 0.3 + SILE.typesetter:liner("advance-box-width", content, + function (box, typesetter, line) + local outputWidth = SU.rationWidth(box.width, box.width, line.ratio) + local height = SU.max(box.height:tonumber(), (1 - bsratio) * bs) + local depth = SU.max(box.depth:tonumber(), bsratio * bs) + local cx, cy = typesetter.frame.state.cursorX, typesetter.frame.state.cursorY + SILE.outputter:pushColor(SILE.color("gray")) + SILE.outputter:drawRule(cx, cy - height, outputWidth, height + depth) + SILE.outputter:popColor() + typesetter.frame:advanceWritingDirection(outputWidth) + end + ) +end) +\end{lua} + +% In liner +\advance-box-width{logi-zoty logi-zoty logi-zoty logi-zoty} + +% Vs. normal +logi-zoty logi-zoty logi-zoty logi-zoty + +\end{document} From f4918cac7fab06eca3e46b337cce4c0f0d3d6bed Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 4 Feb 2024 14:27:00 +0300 Subject: [PATCH 300/357] test(core): Update tests to use non-deprecated syntax --- tests/dropcaps-descenders.sil | 2 +- tests/feat-liner-spanning.sil | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dropcaps-descenders.sil b/tests/dropcaps-descenders.sil index 7c6789ac5..347d848e1 100644 --- a/tests/dropcaps-descenders.sil +++ b/tests/dropcaps-descenders.sil @@ -2,7 +2,7 @@ \use[module=packages.retrograde,target=v0.15.0] \nofolios \neverindent -\script[src=packages/dropcaps] +\use[module=packages.dropcaps] \set[parameter=document.baselineskip, value=1.2em] \font[family=Cormorant Infant, size=11pt] % Normal I diff --git a/tests/feat-liner-spanning.sil b/tests/feat-liner-spanning.sil index e0f19d133..7a2cf008f 100644 --- a/tests/feat-liner-spanning.sil +++ b/tests/feat-liner-spanning.sil @@ -2,7 +2,7 @@ \neverindent \nofolios \set[parameter=shaper.spaceenlargementfactor, value=1] -\script[src=packages/rules] +\use[module=packages.rules] \font[size=14pt] % strikethrough and underline can span multiple lines % Here line-breaking (paragraphing) occurs in the underlined sequence. From 8287a0f316cc876231eeea643e7338db318932c4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 22:04:38 +0300 Subject: [PATCH 301/357] refactor(core)!: Move assorted classes from oddball names in core to types BREAKING CHANGE: Several top level instance creaters of various names have been re-organized under SILE.types. Specifically SILE.color, SILE.measurement, and SILE.length have the same names, just under SILE.types.<name>. Additionally SILE.nodefactory is now SILE.types.node and SILE.units is not SILE.types.unit. This brings a little bit of sanity to the naming schemes so that you can guess how to use something from the name, but it also makes room for 3rd party add ons to more easily extend or replace these functions. It also makes it easier to start substituting Rust bits where desired. reorg --- build-aux/list-dist-files.sh.in | 2 +- core/deprecations.lua | 47 +++ core/parserbits.lua | 5 +- core/sile.lua | 10 +- packages/math/base-elements.lua | 2 +- {core => types}/color.lua | 0 {core => types}/color_spec.lua | 0 {core => types}/length.lua | 0 {core => types}/measurement.lua | 0 core/nodefactory.lua => types/node.lua | 344 +++++++++--------- .../node_spec.lua | 24 +- core/units.lua => types/unit.lua | 58 +-- 12 files changed, 268 insertions(+), 224 deletions(-) rename {core => types}/color.lua (100%) rename {core => types}/color_spec.lua (100%) rename {core => types}/length.lua (100%) rename {core => types}/measurement.lua (100%) rename core/nodefactory.lua => types/node.lua (68%) rename spec/nodefactory_spec.lua => types/node_spec.lua (75%) rename core/units.lua => types/unit.lua (88%) diff --git a/build-aux/list-dist-files.sh.in b/build-aux/list-dist-files.sh.in index c007dcb00..4c7af2f6c 100755 --- a/build-aux/list-dist-files.sh.in +++ b/build-aux/list-dist-files.sh.in @@ -8,7 +8,7 @@ finder () { printf '%s' "SILEDATA =" finder core -name '*.lua' -not -name '*_spec.lua' -not -name 'version.lua' -not -name 'features.lua' -not -name 'pathsetup.lua' -finder classes inputters languages outputters packages shapers typesetters pagebuilders -name '*.lua' -not -name '*_spec.lua' +finder classes inputters languages outputters packages shapers types typesetters pagebuilders -name '*.lua' -not -name '*_spec.lua' finder classes i18n packages -name '*.ftl' finder packages -name '*.svg' diff --git a/core/deprecations.lua b/core/deprecations.lua index 8540753d8..d3c20bc28 100644 --- a/core/deprecations.lua +++ b/core/deprecations.lua @@ -70,6 +70,53 @@ SILE.readFile = function (filename) return SILE.processFile(filename) end +local usetypes = function (type) + SU.deprecated(("SILE.%s"):format(type), ("SILE.types.%s"):format(type), "0.15.0", "0.16.0", ([[ + In order to keep things tidy internally, more easily allow 3rd party + packages to override core functions, and substitute some slow bits + with Rust modules, internal types have been moved from the top level + SILE global to a types namespace. + + Please substitute 'SILE.%s()' with 'SILE.types.%s()'. + ]]):format(type, type)) + return SILE.types[type] +end + +SILE.color = setmetatable({}, { + __call = function (_, ...) return usetypes("color")(...) end, + __index = function () return usetypes("color") end, + }) + +SILE.measurement = setmetatable({}, { + __call = function (_, ...) return usetypes("measurement")(...) end, + __index = function () return usetypes("measurement") end, + }) + +SILE.length = setmetatable({}, { + __call = function (_, ...) return usetypes("length")(...) end, + __index = function () return usetypes("length") end, + }) + +local usetypes2 = function (old, new, type) + SU.deprecated(("SILE.%s.%s"):format(old, type), ("SILE.types.%s.%s"):format(new, type), "0.15.0", "0.16.0", ([[ + In order to keep things tidy internally, more easily allow 3rd party + packages to override core functions, and substitute some slow bits + with Rust modules, internal types have been moved from the top level + SILE global to a types namespace. + + Please substitute 'SILE.%s.%s()' with 'SILE.types.%s.%s()'. + ]]):format(old, type, new, type)) + return SILE.types[new][type] +end + +SILE.nodefactory = setmetatable({}, { + __index = function (_, type) return usetypes2("nodefactory", "node", type) end, + }) + +SILE.units = setmetatable({}, { + __index = function (_, type) return usetypes2("units", "unit", type) end, + }) + SILE.colorparser = function (input) SU.deprecated("SILE.colorparser", "SILE.color", "0.14.0", "0.16.0", [[Color results are now color objects, not just tables with relevant values.]]) diff --git a/core/parserbits.lua b/core/parserbits.lua index 13d42b251..f41e7373f 100644 --- a/core/parserbits.lua +++ b/core/parserbits.lua @@ -5,8 +5,9 @@ local C, Cf, Cg, Ct, Cmt = lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.Cmt local function isaunit (_, _, unit) -- TODO: fix race condition so we can validate units - if not SILE or not SILE.units then return true end - return SILE.units[unit] and true or false + local factory = rawget(SILE.types, "unit") + if not SILE or not factory then return true end + return factory[unit] and true or false end local function inferpoints (number) diff --git a/core/sile.lua b/core/sile.lua index c5c7ea19a..7a94c6412 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -85,19 +85,13 @@ SILE.classes = core_loader("classes") SILE.packages = core_loader("packages") SILE.typesetters = core_loader("typesetters") SILE.pagebuilders = core_loader("pagebuilders") +SILE.types = core_loader("types") --- Internal libraries that don't make assumptions on load, only provide something +-- Internal libraries that don't try to use anything on load, only provide something SILE.parserBits = require("core.parserbits") SILE.frameParser = require("core.frameparser") -SILE.color = require("core.color") -SILE.units = require("core.units") SILE.fontManager = require("core.fontmanager") - --- Internal libraries that assume globals, may be picky about load order -SILE.measurement = require("core.measurement") -SILE.length = require("core.length") SILE.papersize = require("core.papersize") -SILE.nodefactory = require("core.nodefactory") -- NOTE: -- See remainaing internal libraries loaded at the end of this file because diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 2a57d3367..bfc7b1640 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -1,4 +1,4 @@ -local nodefactory = require("core.nodefactory") +local nodefactory = require("types.node") local hb = require("justenoughharfbuzz") local ot = require("core.opentype-parser") local syms = require("packages.math.unicode-symbols") diff --git a/core/color.lua b/types/color.lua similarity index 100% rename from core/color.lua rename to types/color.lua diff --git a/core/color_spec.lua b/types/color_spec.lua similarity index 100% rename from core/color_spec.lua rename to types/color_spec.lua diff --git a/core/length.lua b/types/length.lua similarity index 100% rename from core/length.lua rename to types/length.lua diff --git a/core/measurement.lua b/types/measurement.lua similarity index 100% rename from core/measurement.lua rename to types/measurement.lua diff --git a/core/nodefactory.lua b/types/node.lua similarity index 68% rename from core/nodefactory.lua rename to types/node.lua index fbb17a21e..50f5cb4fe 100644 --- a/core/nodefactory.lua +++ b/types/node.lua @@ -1,4 +1,4 @@ -local nodefactory = {} +local nodetypes = {} -- This infinity needs to be smaller than an actual infinity but bigger than the infinite stretch -- added by the typesetter. See https://github.com/sile-typesetter/sile/issues/227 @@ -16,19 +16,19 @@ end local _dims = pl.Set { "width", "height", "depth" } -nodefactory.box = pl.class() -nodefactory.box.type = "special" +nodetypes.box = pl.class() +nodetypes.box.type = "special" -nodefactory.box.height = nil -nodefactory.box.depth = nil -nodefactory.box.width = nil -nodefactory.box.misfit = false -nodefactory.box.explicit = false -nodefactory.box.discardable = false -nodefactory.box.value = nil -nodefactory.box._default_length = "width" +nodetypes.box.height = nil +nodetypes.box.depth = nil +nodetypes.box.width = nil +nodetypes.box.misfit = false +nodetypes.box.explicit = false +nodetypes.box.discardable = false +nodetypes.box.value = nil +nodetypes.box._default_length = "width" -function nodefactory.box:_init (spec) +function nodetypes.box:_init (spec) if type(spec) == "string" or type(spec) == "number" or SU.type(spec) == "measurement" @@ -52,24 +52,24 @@ function nodefactory.box:_init (spec) end -- De-init instances by shallow copying properties and removing meta table -function nodefactory.box:_tospec () +function nodetypes.box:_tospec () return pl.tablex.copy(self) end -function nodefactory.box:tostring () +function nodetypes.box:tostring () return self:__tostring() end -function nodefactory.box:__tostring () +function nodetypes.box:__tostring () return self.type end -function nodefactory.box.__concat (a, b) +function nodetypes.box.__concat (a, b) return tostring(a) .. tostring(b) end -function nodefactory.box:absolute () - local clone = nodefactory[self.type](self:_tospec()) +function nodetypes.box:absolute () + local clone = nodetypes[self.type](self:_tospec()) for dim in pairs(_dims) do clone[dim] = self[dim]:absolute() end @@ -79,101 +79,101 @@ function nodefactory.box:absolute () return clone end -function nodefactory.box:lineContribution () +function nodetypes.box:lineContribution () -- Regardless of the orientations, "width" is always in the -- writingDirection, and "height" is always in the "pageDirection" return self.misfit and self.height or self.width end -function nodefactory.box:outputYourself () +function nodetypes.box:outputYourself () SU.error(self.type.." with no output routine") end -function nodefactory.box:toText () +function nodetypes.box:toText () return self.type end -function nodefactory.box:isBox () +function nodetypes.box:isBox () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "hbox" or self.type == "zerohbox" or self.type == "alternative" or self.type == "nnode" or self.type == "vbox" end -function nodefactory.box:isNnode () +function nodetypes.box:isNnode () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type=="nnode" end -function nodefactory.box:isGlue () +function nodetypes.box:isGlue () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "glue" end -function nodefactory.box:isVglue () +function nodetypes.box:isVglue () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "vglue" end -function nodefactory.box:isZero () +function nodetypes.box:isZero () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "zerohbox" or self.type == "zerovglue" end -function nodefactory.box:isUnshaped () +function nodetypes.box:isUnshaped () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "unshaped" end -function nodefactory.box:isAlternative () +function nodetypes.box:isAlternative () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "alternative" end -function nodefactory.box:isVbox () +function nodetypes.box:isVbox () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "vbox" end -function nodefactory.box:isInsertion () +function nodetypes.box:isInsertion () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "insertion" end -function nodefactory.box:isMigrating () +function nodetypes.box:isMigrating () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.migrating end -function nodefactory.box:isPenalty () +function nodetypes.box:isPenalty () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "penalty" end -function nodefactory.box:isDiscretionary () +function nodetypes.box:isDiscretionary () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "discretionary" end -function nodefactory.box:isKern () +function nodetypes.box:isKern () SU.warn("Deprecated function, please use boolean is_<type> property to check types", true) return self.type == "kern" end -nodefactory.hbox = pl.class(nodefactory.box) -nodefactory.hbox.type = "hbox" +nodetypes.hbox = pl.class(nodetypes.box) +nodetypes.hbox.type = "hbox" -function nodefactory.hbox:_init (spec) - nodefactory.box._init(self, spec) +function nodetypes.hbox:_init (spec) + nodetypes.box._init(self, spec) end -function nodefactory.hbox:__tostring () +function nodetypes.hbox:__tostring () return "H<" .. tostring(self.width) .. ">^" .. tostring(self.height) .. "-" .. tostring(self.depth) .. "v" end -function nodefactory.hbox:scaledWidth (line) +function nodetypes.hbox:scaledWidth (line) return SU.rationWidth(self:lineContribution(), self.width, line.ratio) end -function nodefactory.hbox:outputYourself (typesetter, line) +function nodetypes.hbox:outputYourself (typesetter, line) local outputWidth = self:scaledWidth(line) if not self.value.glyphString then return end if typesetter.frame:writingDirection() == "RTL" then @@ -187,32 +187,32 @@ function nodefactory.hbox:outputYourself (typesetter, line) end end -nodefactory.zerohbox = pl.class(nodefactory.hbox) -nodefactory.zerohbox.type = "zerohbox" -nodefactory.zerohbox.value = { glyph = 0 } +nodetypes.zerohbox = pl.class(nodetypes.hbox) +nodetypes.zerohbox.type = "zerohbox" +nodetypes.zerohbox.value = { glyph = 0 } -nodefactory.nnode = pl.class(nodefactory.hbox) -nodefactory.nnode.type = "nnode" -nodefactory.nnode.language = "" -nodefactory.nnode.pal = nil -nodefactory.nnode.nodes = {} +nodetypes.nnode = pl.class(nodetypes.hbox) +nodetypes.nnode.type = "nnode" +nodetypes.nnode.language = "" +nodetypes.nnode.pal = nil +nodetypes.nnode.nodes = {} -function nodefactory.nnode:_init (spec) +function nodetypes.nnode:_init (spec) self:super(spec) if 0 == self.depth:tonumber() then self.depth = _maxnode(self.nodes, "depth") end if 0 == self.height:tonumber() then self.height = _maxnode(self.nodes, "height") end if 0 == self.width:tonumber() then self.width = SU.sum(SU.map(function (node) return node.width end, self.nodes)) end end -function nodefactory.nnode:__tostring () +function nodetypes.nnode:__tostring () return "N<" .. tostring(self.width) .. ">^" .. tostring(self.height) .. "-" .. tostring(self.depth) .. "v(" .. self:toText() .. ")" end -function nodefactory.nnode:absolute () +function nodetypes.nnode:absolute () return self end -function nodefactory.nnode:outputYourself (typesetter, line) +function nodetypes.nnode:outputYourself (typesetter, line) -- See typesetter:computeLineRatio() which implements the currently rather messy -- and probably slightly dubious 'hyphenated' logic. -- Example: consider the word "out-put". @@ -236,30 +236,30 @@ function nodefactory.nnode:outputYourself (typesetter, line) end end -function nodefactory.nnode:toText () +function nodetypes.nnode:toText () return self.text end -nodefactory.unshaped = pl.class(nodefactory.nnode) -nodefactory.unshaped.type = "unshaped" +nodetypes.unshaped = pl.class(nodetypes.nnode) +nodetypes.unshaped.type = "unshaped" -function nodefactory.unshaped:_init (spec) +function nodetypes.unshaped:_init (spec) self:super(spec) self.width = nil end -function nodefactory.unshaped:__tostring () +function nodetypes.unshaped:__tostring () return "U(" .. self:toText() .. ")"; end -getmetatable(nodefactory.unshaped).__index = function (_, _) +getmetatable(nodetypes.unshaped).__index = function (_, _) -- if k == "width" then SU.error("Can't get width of unshaped node", true) end -- TODO: No idea why porting to proper Penlight classes this ^^^^^^ started -- killing everything. Perhaps because this function started working and would -- actually need to return rawget(self, k) or something? end -function nodefactory.unshaped:shape () +function nodetypes.unshaped:shape () local node = SILE.shaper:createNnodes(self.text, self.options) for i=1, #node do node[i].parent = self.parent @@ -267,27 +267,27 @@ function nodefactory.unshaped:shape () return node end -function nodefactory.unshaped.outputYourself (_) +function nodetypes.unshaped.outputYourself (_) SU.error("An unshaped node made it to output", true) end -nodefactory.discretionary = pl.class(nodefactory.hbox) +nodetypes.discretionary = pl.class(nodetypes.hbox) -nodefactory.discretionary.type = "discretionary" -nodefactory.discretionary.prebreak = {} -nodefactory.discretionary.postbreak = {} -nodefactory.discretionary.replacement = {} -nodefactory.discretionary.used = false +nodetypes.discretionary.type = "discretionary" +nodetypes.discretionary.prebreak = {} +nodetypes.discretionary.postbreak = {} +nodetypes.discretionary.replacement = {} +nodetypes.discretionary.used = false -function nodefactory.discretionary:__tostring () +function nodetypes.discretionary:__tostring () return "D(" .. SU.concat(self.prebreak, "") .. "|" .. SU.concat(self.postbreak, "") .."|" .. SU.concat(self.replacement, "") .. ")"; end -function nodefactory.discretionary:toText () +function nodetypes.discretionary:toText () return self.used and "-" or "_" end -function nodefactory.discretionary:markAsPrebreak () +function nodetypes.discretionary:markAsPrebreak () self.used = true if self.parent then self.parent.hyphenated = true @@ -295,11 +295,11 @@ function nodefactory.discretionary:markAsPrebreak () self.is_prebreak = true end -function nodefactory.discretionary:cloneAsPostbreak () +function nodetypes.discretionary:cloneAsPostbreak () if not self.used then SU.error("Cannot clone a non-used discretionary (previously marked as prebreak)") end - return SILE.nodefactory.discretionary({ + return SILE.types.node.discretionary({ prebreak = self.prebreak, postbreak = self.postbreak, replacement = self.replacement, @@ -309,7 +309,7 @@ function nodefactory.discretionary:cloneAsPostbreak () }) end -function nodefactory.discretionary:outputYourself (typesetter, line) +function nodetypes.discretionary:outputYourself (typesetter, line) -- See typesetter:computeLineRatio() which implements the currently rather -- messy hyphenated checks. -- Example: consider the word "out-put-ter". @@ -339,229 +339,229 @@ function nodefactory.discretionary:outputYourself (typesetter, line) end end -function nodefactory.discretionary:prebreakWidth () +function nodetypes.discretionary:prebreakWidth () if self.prebw then return self.prebw end self.prebw = SILE.length() for _, node in ipairs(self.prebreak) do self.prebw:___add(node.width) end return self.prebw end -function nodefactory.discretionary:postbreakWidth () +function nodetypes.discretionary:postbreakWidth () if self.postbw then return self.postbw end self.postbw = SILE.length() for _, node in ipairs(self.postbreak) do self.postbw:___add(node.width) end return self.postbw end -function nodefactory.discretionary:replacementWidth () +function nodetypes.discretionary:replacementWidth () if self.replacew then return self.replacew end self.replacew = SILE.length() for _, node in ipairs(self.replacement) do self.replacew:___add(node.width) end return self.replacew end -function nodefactory.discretionary:prebreakHeight () +function nodetypes.discretionary:prebreakHeight () if self.prebh then return self.prebh end self.prebh = _maxnode(self.prebreak, "height") return self.prebh end -function nodefactory.discretionary:postbreakHeight () +function nodetypes.discretionary:postbreakHeight () if self.postbh then return self.postbh end self.postbh = _maxnode(self.postbreak, "height") return self.postbh end -function nodefactory.discretionary:replacementHeight () +function nodetypes.discretionary:replacementHeight () if self.replaceh then return self.replaceh end self.replaceh = _maxnode(self.replacement, "height") return self.replaceh end -function nodefactory.discretionary:replacementDepth () +function nodetypes.discretionary:replacementDepth () if self.replaced then return self.replaced end self.replaced = _maxnode(self.replacement, "depth") return self.replaced end -nodefactory.alternative = pl.class(nodefactory.hbox) +nodetypes.alternative = pl.class(nodetypes.hbox) -nodefactory.alternative.type = "alternative" -nodefactory.alternative.options = {} -nodefactory.alternative.selected = nil +nodetypes.alternative.type = "alternative" +nodetypes.alternative.options = {} +nodetypes.alternative.selected = nil -function nodefactory.alternative:__tostring () +function nodetypes.alternative:__tostring () return "A(" .. SU.concat(self.options, " / ") .. ")" end -function nodefactory.alternative:minWidth () +function nodetypes.alternative:minWidth () local minW = function (a, b) return SU.min(a.width, b.width) end return pl.tablex.reduce(minW, self.options) end -function nodefactory.alternative:deltas () +function nodetypes.alternative:deltas () local minWidth = self:minWidth() local rv = {} for i = 1, #self.options do rv[#rv+1] = self.options[i].width - minWidth end return rv end -function nodefactory.alternative:outputYourself (typesetter, line) +function nodetypes.alternative:outputYourself (typesetter, line) if self.selected then self.options[self.selected]:outputYourself(typesetter, line) end end -nodefactory.glue = pl.class(nodefactory.box) -nodefactory.glue.type = "glue" -nodefactory.glue.discardable = true +nodetypes.glue = pl.class(nodetypes.box) +nodetypes.glue.type = "glue" +nodetypes.glue.discardable = true -function nodefactory.glue:__tostring () +function nodetypes.glue:__tostring () return (self.explicit and "E:" or "") .. "G<" .. tostring(self.width) .. ">" end -function nodefactory.glue.toText (_) +function nodetypes.glue.toText (_) return " " end -function nodefactory.glue:outputYourself (typesetter, line) +function nodetypes.glue:outputYourself (typesetter, line) local outputWidth = SU.rationWidth(self.width:absolute(), self.width:absolute(), line.ratio) typesetter.frame:advanceWritingDirection(outputWidth) end -- A hfillglue is just a glue with infinite stretch. -- (Convenience so callers do not have to know what infinity is.) -nodefactory.hfillglue = pl.class(nodefactory.glue) -function nodefactory.hfillglue:_init (spec) +nodetypes.hfillglue = pl.class(nodetypes.glue) +function nodetypes.hfillglue:_init (spec) self:super(spec) self.width = SILE.length(self.width.length, infinity, self.width.shrink) end -- A hssglue is just a glue with infinite stretch and shrink. -- (Convenience so callers do not have to know what infinity is.) -nodefactory.hssglue = pl.class(nodefactory.glue) -function nodefactory.hssglue:_init (spec) +nodetypes.hssglue = pl.class(nodetypes.glue) +function nodetypes.hssglue:_init (spec) self:super(spec) self.width = SILE.length(self.width.length, infinity, infinity) end -nodefactory.kern = pl.class(nodefactory.glue) -nodefactory.kern.type = "kern" -- Perhaps some smell here, see comment on vkern -nodefactory.kern.discardable = false +nodetypes.kern = pl.class(nodetypes.glue) +nodetypes.kern.type = "kern" -- Perhaps some smell here, see comment on vkern +nodetypes.kern.discardable = false -function nodefactory.kern:__tostring () +function nodetypes.kern:__tostring () return "K<" .. tostring(self.width) .. ">" end -nodefactory.vglue = pl.class(nodefactory.box) -nodefactory.vglue.type = "vglue" -nodefactory.vglue.discardable = true -nodefactory.vglue._default_length = "height" -nodefactory.vglue.adjustment = nil +nodetypes.vglue = pl.class(nodetypes.box) +nodetypes.vglue.type = "vglue" +nodetypes.vglue.discardable = true +nodetypes.vglue._default_length = "height" +nodetypes.vglue.adjustment = nil -function nodefactory.vglue:_init (spec) +function nodetypes.vglue:_init (spec) self.adjustment = SILE.measurement() self:super(spec) end -function nodefactory.vglue:__tostring () +function nodetypes.vglue:__tostring () return (self.explicit and "E:" or "") .. "VG<" .. tostring(self.height) .. ">"; end -function nodefactory.vglue:adjustGlue (adjustment) +function nodetypes.vglue:adjustGlue (adjustment) self.adjustment = adjustment end -function nodefactory.vglue:outputYourself (typesetter, line) +function nodetypes.vglue:outputYourself (typesetter, line) typesetter.frame:advancePageDirection(line.height:absolute() + line.depth:absolute() + self.adjustment) end -function nodefactory.vglue:unbox () +function nodetypes.vglue:unbox () return { self } end -- A vfillglue is just a vglue with infinite stretch. -- (Convenience so callers do not have to know what infinity is.) -nodefactory.vfillglue = pl.class(nodefactory.vglue) -function nodefactory.vfillglue:_init (spec) +nodetypes.vfillglue = pl.class(nodetypes.vglue) +function nodetypes.vfillglue:_init (spec) self:super(spec) self.height = SILE.length(self.width.length, infinity, self.width.shrink) end -- A vssglue is just a vglue with infinite stretch and shrink. -- (Convenience so callers do not have to know what infinity is.) -nodefactory.vssglue = pl.class(nodefactory.vglue) -function nodefactory.vssglue:_init (spec) +nodetypes.vssglue = pl.class(nodetypes.vglue) +function nodetypes.vssglue:_init (spec) self:super(spec) self.height = SILE.length(self.width.length, infinity, infinity) end -nodefactory.zerovglue = pl.class(nodefactory.vglue) +nodetypes.zerovglue = pl.class(nodetypes.vglue) -nodefactory.vkern = pl.class(nodefactory.vglue) +nodetypes.vkern = pl.class(nodetypes.vglue) -- FIXME TODO -- Here we cannot do: --- nodefactory.vkern.type = "vkern" +-- nodetypes.vkern.type = "vkern" -- It cannot be typed as "vkern" as the pagebuilder doesn't check is_vkern. -- So it's just a vglue currrenty, marked as not discardable... --- But on the other hand, nodefactory.kern is typed "kern" and is not a glue... +-- But on the other hand, nodetypes.kern is typed "kern" and is not a glue... -- Frankly, the discardable/explicit flags and the types are too -- entangled and point towards a more general design issue. -- N.B. this vkern node is only used in the linespacing package so far. -nodefactory.vkern.discardable = false +nodetypes.vkern.discardable = false -function nodefactory.vkern:__tostring () +function nodetypes.vkern:__tostring () return "VK<" .. tostring(self.height) .. ">" end -nodefactory.penalty = pl.class(nodefactory.box) -nodefactory.penalty.type = "penalty" -nodefactory.penalty.discardable = true -nodefactory.penalty.penalty = 0 +nodetypes.penalty = pl.class(nodetypes.box) +nodetypes.penalty.type = "penalty" +nodetypes.penalty.discardable = true +nodetypes.penalty.penalty = 0 -function nodefactory.penalty:_init (spec) +function nodetypes.penalty:_init (spec) self:super(spec) if type(spec) ~= "table" then self.penalty = SU.cast("number", spec) end end -function nodefactory.penalty:__tostring () +function nodetypes.penalty:__tostring () return "P(" .. tostring(self.penalty) .. ")"; end -function nodefactory.penalty.outputYourself (_) +function nodetypes.penalty.outputYourself (_) end -function nodefactory.penalty.toText (_) +function nodetypes.penalty.toText (_) return "(!)" end -function nodefactory.penalty:unbox () +function nodetypes.penalty:unbox () return { self } end -nodefactory.vbox = pl.class(nodefactory.box) -nodefactory.vbox.type = "vbox" -nodefactory.vbox.nodes = {} -nodefactory.vbox._default_length = "height" +nodetypes.vbox = pl.class(nodetypes.box) +nodetypes.vbox.type = "vbox" +nodetypes.vbox.nodes = {} +nodetypes.vbox._default_length = "height" -function nodefactory.vbox:_init (spec) +function nodetypes.vbox:_init (spec) self.nodes = {} self:super(spec) self.depth = _maxnode(self.nodes, "depth") self.height = _maxnode(self.nodes, "height") end -function nodefactory.vbox:__tostring () +function nodetypes.vbox:__tostring () return "VB<" .. tostring(self.height) .. "|" .. self:toText() .. "v".. tostring(self.depth) ..")"; end -function nodefactory.vbox:toText () +function nodetypes.vbox:toText () return "VB[" .. SU.concat(SU.map(function (node) return node:toText() end, self.nodes), "") .. "]" end -function nodefactory.vbox:outputYourself (typesetter, line) +function nodetypes.vbox:outputYourself (typesetter, line) typesetter.frame:advancePageDirection(self.height) local initial = true for _, node in ipairs(self.nodes) do @@ -574,14 +574,14 @@ function nodefactory.vbox:outputYourself (typesetter, line) typesetter.frame:newLine() end -function nodefactory.vbox:unbox () +function nodetypes.vbox:unbox () for i = 1, #self.nodes do if self.nodes[i].is_vbox or self.nodes[i].is_vglue then return self.nodes end end return {self} end -function nodefactory.vbox:append (box) +function nodetypes.vbox:append (box) local nodes = box if not box then SU.error("nil box given", true) end if nodes.type then @@ -601,112 +601,112 @@ function nodefactory.vbox:append (box) self.depth = lastdepth end -nodefactory.migrating = pl.class(nodefactory.hbox) -nodefactory.migrating.type = "migrating" -nodefactory.migrating.material = {} -nodefactory.migrating.value = {} -nodefactory.migrating.nodes = {} +nodetypes.migrating = pl.class(nodetypes.hbox) +nodetypes.migrating.type = "migrating" +nodetypes.migrating.material = {} +nodetypes.migrating.value = {} +nodetypes.migrating.nodes = {} -function nodefactory.migrating:__tostring () +function nodetypes.migrating:__tostring () return "<M: " .. tostring(self.material) .. ">" end local _deprecated_nodefactory = {} _deprecated_nodefactory.newHbox = function (spec) - return nodefactory.hbox(spec) + return node.hbox(spec) end _deprecated_nodefactory.newNnode = function (spec) - return nodefactory.nnode(spec) + return node.nnode(spec) end _deprecated_nodefactory.newUnshaped = function (spec) - return nodefactory.unshaped(spec) + return node.unshaped(spec) end _deprecated_nodefactory.newDisc = function (spec) - return nodefactory.discretionary(spec) + return node.discretionary(spec) end _deprecated_nodefactory.disc = function (spec) - return nodefactory.discretionary(spec) + return node.discretionary(spec) end _deprecated_nodefactory.newAlternative = function (spec) - return nodefactory.alternative(spec) + return node.alternative(spec) end _deprecated_nodefactory.newGlue = function (spec) - return nodefactory.glue(spec) + return node.glue(spec) end _deprecated_nodefactory.newKern = function (spec) - return nodefactory.kern(spec) + return node.kern(spec) end _deprecated_nodefactory.newVglue = function (spec) - return nodefactory.vglue(spec) + return node.vglue(spec) end _deprecated_nodefactory.newVKern = function (spec) - return nodefactory.vkern(spec) + return node.vkern(spec) end _deprecated_nodefactory.newPenalty = function (spec) - return nodefactory.penalty(spec) + return node.penalty(spec) end _deprecated_nodefactory.newDiscretionary = function (spec) - return nodefactory.discretionary(spec) + return node.discretionary(spec) end _deprecated_nodefactory.newVbox = function (spec) - return nodefactory.vbox(spec) + return node.vbox(spec) end _deprecated_nodefactory.newMigrating = function (spec) - return nodefactory.migrating(spec) + return node.migrating(spec) end _deprecated_nodefactory.zeroGlue = function () - return nodefactory.glue() + return node.glue() end _deprecated_nodefactory.hfillGlue = function () - return nodefactory.hfillglue() + return node.hfillglue() end _deprecated_nodefactory.vfillGlue = function () - return nodefactory.vfillglue() + return node.vfillglue() end _deprecated_nodefactory.hssGlue = function () - return nodefactory.hssglue() + return node.hssglue() end _deprecated_nodefactory.vssGlue = function () - return nodefactory.vssglue() + return node.vssglue() end _deprecated_nodefactory.zeroHbox = function () - return nodefactory.zerohbox() + return node.zerohbox() end _deprecated_nodefactory.zeroVglue = function () - return nodefactory.zerovglue() + return node.zerovglue() end -setmetatable(nodefactory, { +setmetatable(nodetypes, { __index = function (_, prop) if _deprecated_nodefactory[prop] then - SU.deprecated("SILE.nodefactory." .. prop, "SILE.nodefactory." .. prop:match("n?e?w?(.*)"):lower(), "0.10.0", "0.14.0") + SU.deprecated("SILE.types.node." .. prop, "SILE.types.node." .. prop:match("n?e?w?(.*)"):lower(), "0.10.0", "0.14.0") elseif type(prop) == "number" then -- luacheck: ignore 542 -- Likely at attempt to iterate (or dump) the table, sort of safe to ignore else - SU.error("Attempt to access non-existent SILE.nodefactory." .. prop) + SU.error("Attempt to access non-existent SILE.types.node." .. prop) end end }) -return nodefactory +return nodetypes diff --git a/spec/nodefactory_spec.lua b/types/node_spec.lua similarity index 75% rename from spec/nodefactory_spec.lua rename to types/node_spec.lua index a78ca3475..44314dffe 100644 --- a/spec/nodefactory_spec.lua +++ b/types/node_spec.lua @@ -1,10 +1,10 @@ SILE = require("core.sile") describe("The node factory", function() - it("should exist", function() assert.is.truthy(SILE.nodefactory) end) + it("should exist", function() assert.is.truthy(SILE.types.node) end) describe("hboxes", function() - local hbox = SILE.nodefactory.hbox({ width = 20, height = 30, depth = 3 }) + local hbox = SILE.types.node.hbox({ width = 20, height = 30, depth = 3 }) it("should have width", function () assert.is.equal(20, hbox.width:tonumber()) end) it("should have height", function () assert.is.equal(30, hbox.height:tonumber()) end) it("should have depth", function () assert.is.equal(3, hbox.depth:tonumber()) end) @@ -15,9 +15,9 @@ describe("The node factory", function() end) describe("vboxes", function() - local hbox1 = SILE.nodefactory.hbox({ width = 10, height = 5, depth = 2 }) - local hbox2 = SILE.nodefactory.hbox({ width = 11, height = 6, depth = 3 }) - local vbox = SILE.nodefactory.vbox({ height = 4, depth = 3, nodes = { hbox1, hbox2 } }) + local hbox1 = SILE.types.node.hbox({ width = 10, height = 5, depth = 2 }) + local hbox2 = SILE.types.node.hbox({ width = 11, height = 6, depth = 3 }) + local vbox = SILE.types.node.vbox({ height = 4, depth = 3, nodes = { hbox1, hbox2 } }) it("should have nodes", function () assert.is.equal(2, #vbox.nodes) end) it("should have height", function () assert.is.equal(6, vbox.height:tonumber()) end) it("should have depth", function () assert.is.equal(3, vbox.depth:tonumber()) end) @@ -28,9 +28,9 @@ describe("The node factory", function() end) describe("nnodes", function () - local hbox1 = SILE.nodefactory.hbox({ width = 10, height = 5, depth = 3 }) - local hbox2 = SILE.nodefactory.hbox({ width = 20, height = 10, depth = 5 }) - local nnode = SILE.nodefactory.nnode({ text = "test", nodes = { hbox1, hbox2 } }) + local hbox1 = SILE.types.node.hbox({ width = 10, height = 5, depth = 3 }) + local hbox2 = SILE.types.node.hbox({ width = 20, height = 10, depth = 5 }) + local nnode = SILE.types.node.nnode({ text = "test", nodes = { hbox1, hbox2 } }) it("should have width", function () assert.is.equal(30, nnode.width:tonumber()) end) it("should have depth", function () assert.is.equal(5, nnode.depth:tonumber()) end) it("should have height", function () assert.is.equal(10, nnode.height:tonumber()) end) @@ -40,10 +40,10 @@ describe("The node factory", function() end) describe("discs", function () - local nnode1 = SILE.nodefactory.nnode({ width = 20, height = 30, depth = 3, text = "pre" }) - local nnode2 = SILE.nodefactory.nnode({ width = 20, height = 30, depth = 3, text = "break" }) - local nnode3 = SILE.nodefactory.nnode({ width = 20, height = 30, depth = 3, text = "post" }) - local discretionary = SILE.nodefactory.discretionary({ prebreak = { nnode1, nnode2 }, postbreak = { nnode3, nnode2 } }) + local nnode1 = SILE.types.node.nnode({ width = 20, height = 30, depth = 3, text = "pre" }) + local nnode2 = SILE.types.node.nnode({ width = 20, height = 30, depth = 3, text = "break" }) + local nnode3 = SILE.types.node.nnode({ width = 20, height = 30, depth = 3, text = "post" }) + local discretionary = SILE.types.node.discretionary({ prebreak = { nnode1, nnode2 }, postbreak = { nnode3, nnode2 } }) it("should stringify", function() assert.is.equal("D(N<20pt>^30pt-3ptv(pre)N<20pt>^30pt-3ptv(break)|N<20pt>^30pt-3ptv(post)N<20pt>^30pt-3ptv(break)|)", tostring(discretionary)) end) end) diff --git a/core/units.lua b/types/unit.lua similarity index 88% rename from core/units.lua rename to types/unit.lua index 909c5ed5a..452ecab9f 100644 --- a/core/units.lua +++ b/types/unit.lua @@ -1,16 +1,18 @@ -local units = { +local bits = require("core.parserbits") + +local unittypes = { pt = { relative = false, value = 1 } } -setmetatable(units, { +setmetatable(unittypes, { __newindex = function (self, unit, spec) local def = SU.required(spec, "definition", "registering unit " .. unit) local relative = SU.boolean(spec.relative, false) if type(def) == "string" then - local parsed = SILE.parserBits.measurement:match(def) + local parsed = bits.measurement:match(def) if not parsed then SU.error("Could not parse unit definition '"..def.."'") end if not self[parsed.unit] then SU.error("Unit " .. unit .. " defined in terms of unknown unit " .. parsed.unit) @@ -36,36 +38,36 @@ setmetatable(units, { end }) -units["twip"] = { +unittypes["twip"] = { definition = "0.05pt" } -units["mm"] = { +unittypes["mm"] = { definition = "2.8346457pt" } -units["cm"] = { +unittypes["cm"] = { definition = "10mm" } -units["m"] = { +unittypes["m"] = { definition = "100cm" } -units["hm"] = { +unittypes["hm"] = { definition = "0.01mm" } -units["in"] = { +unittypes["in"] = { definition = "72pt" } -units["ft"] = { +unittypes["ft"] = { definition = "12in" } -- Picas are 1/6 inch, used in Docbook images -units["pc"] = { +unittypes["pc"] = { definition = "0.166666667in" } @@ -81,7 +83,7 @@ local checkFrameDefined = function () end end -units["%pw"] = { +unittypes["%pw"] = { relative = true, definition = function (value) checkPaperDefined() @@ -89,7 +91,7 @@ units["%pw"] = { end } -units["%ph"] = { +unittypes["%ph"] = { relative = true, definition = function (value) checkPaperDefined() @@ -97,7 +99,7 @@ units["%ph"] = { end } -units["%pmin"] = { +unittypes["%pmin"] = { relative = true, definition = function (value) checkPaperDefined() @@ -105,7 +107,7 @@ units["%pmin"] = { end } -units["%pmax"] = { +unittypes["%pmax"] = { relative = true, definition = function (value) checkPaperDefined() @@ -113,7 +115,7 @@ units["%pmax"] = { end } -units["%fw"] = { +unittypes["%fw"] = { relative = true, definition = function (value) checkFrameDefined() @@ -121,7 +123,7 @@ units["%fw"] = { end } -units["%fh"] = { +unittypes["%fh"] = { relative = true, definition = function (value) checkFrameDefined() @@ -129,7 +131,7 @@ units["%fh"] = { end } -units["%fmin"] = { +unittypes["%fmin"] = { relative = true, definition = function (value) checkFrameDefined() @@ -137,7 +139,7 @@ units["%fmin"] = { end } -units["%fmax"] = { +unittypes["%fmax"] = { relative = true, definition = function (value) checkFrameDefined() @@ -145,7 +147,7 @@ units["%fmax"] = { end } -units["%lw"] = { +unittypes["%lw"] = { relative = true, definition = function (value) local lskip = SILE.settings:get("document.lskip") @@ -157,7 +159,7 @@ units["%lw"] = { end } -units["ps"] = { +unittypes["ps"] = { relative = true, definition = function (value) local ps = SILE.settings:get("document.parskip") @@ -166,7 +168,7 @@ units["ps"] = { end } -units["bs"] = { +unittypes["bs"] = { relative = true, definition = function (value) local bs = SILE.settings:get("document.baselineskip") @@ -175,28 +177,28 @@ units["bs"] = { end } -units["em"] = { +unittypes["em"] = { relative = true, definition = function (value) return value * SILE.settings:get("font.size") end } -units["ex"] = { +unittypes["ex"] = { relative = true, definition = function (value) return value * SILE.shaper:measureChar("x").height end } -units["spc"] = { +unittypes["spc"] = { relative = true, definition = function (value) return value * SILE.shaper:measureChar(" ").width end } -units["en"] = { +unittypes["en"] = { relative = true, definition = "0.5em" } @@ -205,7 +207,7 @@ units["en"] = { -- width of a full-width character. In SILE terms it isn't: measuring an "m" in -- a 10pt Japanese font gets you 5 points. So we measure a full-width character -- and use that as a unit. We call it zw following ptex (zenkaku width) -units["zw"] = { +unittypes["zw"] = { relative = true, definition = function (v) local zenkakuchar = SILE.settings:get("document.zenkakuchar") @@ -220,4 +222,4 @@ units["zw"] = { end } -return units +return unittypes From 3df9176670138e592ee3f5d0f277deadf6ab1d4b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 22:36:59 +0300 Subject: [PATCH 302/357] refactor(core): Update API usage for types --- classes/base.lua | 6 +- classes/bible.lua | 28 +++--- classes/book.lua | 16 ++-- classes/docbook.lua | 2 +- classes/letter.lua | 4 +- classes/pecha.lua | 6 +- classes/plain.lua | 88 +++++++++--------- classes/tplain.lua | 2 +- classes/triglot.lua | 2 +- core/break.lua | 28 +++--- core/deprecations.lua | 10 +-- core/font.lua | 2 +- core/frame.lua | 4 +- core/frameparser.lua | 2 +- core/hyphenator-liang.lua | 2 +- core/papersize.lua | 2 +- core/settings.lua | 8 +- core/sile.lua | 6 +- core/utilities/init.lua | 10 +-- documentation/c07-settings.sil | 4 +- documentation/c09-concepts.sil | 24 ++--- documentation/c10-classdesign.sil | 12 +-- documentation/c13-tricks.sil | 8 +- languages/ca.lua | 2 +- languages/fr.lua | 14 +-- languages/ja.lua | 8 +- languages/my.lua | 4 +- languages/pl.lua | 2 +- languages/tr.lua | 2 +- languages/ug.lua | 8 +- languages/unicode.lua | 6 +- outputters/libtexpdf.lua | 2 +- outputters/text.lua | 4 +- packages/autodoc/init.lua | 22 ++--- packages/background/init.lua | 2 +- packages/balanced-frames/init.lua | 4 +- packages/bidi/init.lua | 4 +- packages/boustrophedon/init.lua | 4 +- packages/chordmode/init.lua | 6 +- packages/color-fonts/init.lua | 4 +- packages/color/init.lua | 2 +- packages/complex-spaces/init.lua | 2 +- packages/dropcaps/init.lua | 8 +- packages/footnotes/init.lua | 12 +-- packages/frametricks/init.lua | 20 ++--- packages/grid/init.lua | 4 +- packages/gutenberg/init.lua | 2 +- packages/hanmenkyoshi/init.lua | 4 +- packages/indexer/init.lua | 4 +- packages/infonode/init.lua | 2 +- packages/insertions/init.lua | 58 ++++++------ packages/leaders/init.lua | 10 +-- packages/linespacing/init.lua | 28 +++--- packages/lists/init.lua | 20 ++--- packages/math/base-elements.lua | 124 +++++++++++++------------- packages/math/init.lua | 2 +- packages/pagebuilder-bestfit/init.lua | 2 +- packages/parallel/init.lua | 6 +- packages/pdf/init.lua | 8 +- packages/pdfstructure/init.lua | 6 +- packages/pullquote/init.lua | 6 +- packages/rebox/init.lua | 6 +- packages/retrograde/init.lua | 14 +-- packages/rotate/init.lua | 2 +- packages/ruby/init.lua | 12 +-- packages/rules/init.lua | 8 +- packages/simpletable/init.lua | 4 +- packages/specimen/init.lua | 4 +- packages/svg/init.lua | 4 +- packages/tableofcontents/init.lua | 2 +- packages/tate/init.lua | 16 ++-- packages/verbatim/init.lua | 10 +-- pagebuilders/base.lua | 4 +- pagebuilders/grid.lua | 2 +- shapers/base.lua | 12 +-- shapers/fallback.lua | 2 +- shapers/harfbuzz.lua | 2 +- shapers/pango.lua | 2 +- spec/break_spec.lua | 64 ++++++------- spec/measurements_spec.lua | 6 +- spec/shaper_spec.lua | 6 +- tests/bug-255.sil | 2 +- tests/bug-255b.sil | 4 +- tests/bug-303.sil | 8 +- tests/classes/testsidenote.lua | 6 +- tests/footnote-skip.sil | 4 +- tests/frametricks.sil | 4 +- tests/inc/bug-337.lua | 4 +- types/color_spec.lua | 2 +- types/length.lua | 52 +++++------ types/measurement.lua | 34 +++---- types/node.lua | 22 ++--- types/node_spec.lua | 4 +- typesetters/base.lua | 78 ++++++++-------- typesetters/firstfit.lua | 4 +- typesetters/grid.lua | 26 +++--- typesetters/tate.lua | 6 +- 97 files changed, 573 insertions(+), 573 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index b83a68ff3..b804b5a2f 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -522,7 +522,7 @@ function class:registerCommands () end, "Inserts a penalty node. Option is penalty= for the size of the penalty.") self:registerCommand("discretionary", function (options, _) - local discretionary = SILE.nodefactory.discretionary({}) + local discretionary = SILE.types.node.discretionary({}) if options.prebreak then local hbox = SILE.typesetter:makeHbox({ options.prebreak }) discretionary.prebreak = { hbox } @@ -545,12 +545,12 @@ function class:registerCommands () self:registerCommand("kern", function (options, _) local width = SU.cast("length", options.width):absolute() - SILE.typesetter:pushHorizontal(SILE.nodefactory.kern(width)) + SILE.typesetter:pushHorizontal(SILE.types.node.kern(width)) end, "Inserts a glue node. The width option denotes the glue dimension.") self:registerCommand("skip", function (options, _) options.discardable = SU.boolean(options.discardable, false) - options.height = SILE.length(options.height):absolute() + options.height = SILE.types.length(options.height):absolute() SILE.typesetter:leaveHmode() if options.discardable then SILE.typesetter:pushVglue(options) diff --git a/classes/bible.lua b/classes/bible.lua index 0e572d9e1..cdbd54226 100644 --- a/classes/bible.lua +++ b/classes/bible.lua @@ -192,19 +192,19 @@ end function class:endPage () if (self:oddPage() and SILE.scratch.headers.right) then SILE.typesetNaturally(SILE.getFrame("runningHead"), function () - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.lskip", SILE.nodefactory.glue()) - SILE.settings:set("document.rskip", SILE.nodefactory.glue()) - -- SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue()) + SILE.settings:set("document.rskip", SILE.types.node.glue()) + -- SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.process(SILE.scratch.headers.right) SILE.call("par") end) elseif (not(self:oddPage()) and SILE.scratch.headers.left) then SILE.typesetNaturally(SILE.getFrame("runningHead"), function () - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.lskip", SILE.nodefactory.glue()) - SILE.settings:set("document.rskip", SILE.nodefactory.glue()) - -- SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue()) + SILE.settings:set("document.rskip", SILE.types.node.glue()) + -- SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.process(SILE.scratch.headers.left) SILE.call("par") end) @@ -261,9 +261,9 @@ function class:registerCommands () SILE.call("save-verse-number", options, content) SILE.call("left-running-head", {}, function () SILE.settings:temporarily(function () - SILE.settings:set("document.lskip", SILE.nodefactory.glue()) - SILE.settings:set("document.rskip", SILE.nodefactory.glue()) - -- SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue()) + SILE.settings:set("document.rskip", SILE.types.node.glue()) + -- SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.call("font", { size = "10pt", family = "Gentium" }, function () SILE.call("first-reference") SILE.call("hfill") @@ -274,9 +274,9 @@ function class:registerCommands () end) SILE.call("right-running-head", {}, function () SILE.settings:temporarily(function () - SILE.settings:set("document.lskip", SILE.nodefactory.glue()) - SILE.settings:set("document.rskip", SILE.nodefactory.glue()) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue()) + SILE.settings:set("document.rskip", SILE.types.node.glue()) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.call("font", { size = "10pt", family = "Gentium" }, function () -- SILE.call("font", { style = "italic" }, SILE.scratch.theChapter) SILE.call("hfill") diff --git a/classes/book.lua b/classes/book.lua index 44fe28710..0d623bd0c 100644 --- a/classes/book.lua +++ b/classes/book.lua @@ -55,20 +55,20 @@ function class:endPage () if self:oddPage() and SILE.scratch.headers.right then SILE.typesetNaturally(SILE.getFrame("runningHead"), function () SILE.settings:toplevelState() - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.lskip", SILE.nodefactory.glue()) - SILE.settings:set("document.rskip", SILE.nodefactory.glue()) - -- SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue()) + SILE.settings:set("document.rskip", SILE.types.node.glue()) + -- SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.process(SILE.scratch.headers.right) SILE.call("par") end) elseif not self:oddPage() and SILE.scratch.headers.left then SILE.typesetNaturally(SILE.getFrame("runningHead"), function () SILE.settings:toplevelState() - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.lskip", SILE.nodefactory.glue()) - SILE.settings:set("document.rskip", SILE.nodefactory.glue()) - -- SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue()) + SILE.settings:set("document.rskip", SILE.types.node.glue()) + -- SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.process(SILE.scratch.headers.left) SILE.call("par") end) diff --git a/classes/docbook.lua b/classes/docbook.lua index 4c967f5f8..c3b635c45 100644 --- a/classes/docbook.lua +++ b/classes/docbook.lua @@ -22,7 +22,7 @@ function class:_init (options) -- SILE sensibly does not define a pixels unit because it has no meaning in its frame of reference. However the -- Docbook standard requires them and even defaults to them for bare numbers, even while warning against their use. -- Here we define a px arbitrarily to be the equivalent point unit if output was 300 DPI. - SILE.units.px = { + SILE.types.unit.px = { definition = "0.24pt" } end diff --git a/classes/letter.lua b/classes/letter.lua index d812da98e..a5904e004 100644 --- a/classes/letter.lua +++ b/classes/letter.lua @@ -27,8 +27,8 @@ function class:registerCommands () plain.registerCommands(self) self:registerCommand("letter", function (_, content) - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) SILE.call("raggedright", {}, function () SILE.call("letter:format:date") SILE.call("bigskip") diff --git a/classes/pecha.lua b/classes/pecha.lua index 8138650e6..0b23b6eea 100644 --- a/classes/pecha.lua +++ b/classes/pecha.lua @@ -41,9 +41,9 @@ function class:_init(options) self:loadPackage("rotate") self:registerPostinit(function () SILE.call("language", { main = "bo" }) - SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.lskip", SILE.types.node.hfillglue()) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) end) end diff --git a/classes/plain.lua b/classes/plain.lua index 6300124be..6bf7c8ca5 100644 --- a/classes/plain.lua +++ b/classes/plain.lua @@ -64,7 +64,7 @@ function class:declareSettings () SILE.settings:declare({ parameter = "plain." .. k .. "skipamount", type = "vglue", - default = SILE.nodefactory.vglue(v), + default = SILE.types.node.vglue(v), help = "The amount of a \\" .. k .. "skip" }) end @@ -78,13 +78,13 @@ function class:registerCommands () if #SILE.typesetter.state.nodes ~= 0 then SU.warn("\\noindent called after nodes already received in a paragraph, the setting will have no effect because the parindent (if any) has already been output") end - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) SILE.process(content) end, "Do not add an indent to the start of this paragraph") self:registerCommand("neverindent", function (_, content) - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) SILE.process(content) end, "Turn off all indentation") @@ -101,25 +101,25 @@ function class:registerCommands () end self:registerCommand("hfill", function (_, _) - SILE.typesetter:pushExplicitGlue(SILE.nodefactory.hfillglue()) + SILE.typesetter:pushExplicitGlue(SILE.types.node.hfillglue()) end, "Add a huge horizontal glue") self:registerCommand("vfill", function (_, _) SILE.typesetter:leaveHmode() - SILE.typesetter:pushExplicitVglue(SILE.nodefactory.vfillglue()) + SILE.typesetter:pushExplicitVglue(SILE.types.node.vfillglue()) end, "Add huge vertical glue") self:registerCommand("hss", function (_, _) SILE.typesetter:initline() - SILE.typesetter:pushGlue(SILE.nodefactory.hssglue()) - table.insert(SILE.typesetter.state.nodes, SILE.nodefactory.zerohbox()) + SILE.typesetter:pushGlue(SILE.types.node.hssglue()) + table.insert(SILE.typesetter.state.nodes, SILE.types.node.zerohbox()) end, "Add glue which stretches and shrinks horizontally (good for centering)") self:registerCommand("vss", function (_, _) - SILE.typesetter:pushExplicitVglue(SILE.nodefactory.vssglue()) + SILE.typesetter:pushExplicitVglue(SILE.types.node.vssglue()) end, "Add glue which stretches and shrinks vertically") - local _thinspacewidth = SILE.measurement(0.16667, "em") + local _thinspacewidth = SILE.types.measurement(0.16667, "em") self:registerCommand("thinspace", function (_, _) SILE.call("glue", { width = _thinspacewidth }) @@ -130,7 +130,7 @@ function class:registerCommands () end) self:registerCommand("enspace", function (_, _) - SILE.call("glue", { width = SILE.measurement(1, "en") }) + SILE.call("glue", { width = SILE.types.measurement(1, "en") }) end) self:registerCommand("relax", function (_, _) @@ -140,7 +140,7 @@ function class:registerCommands () SILE.call("enspace") end) - local _quadwidth = SILE.measurement(1, "em") + local _quadwidth = SILE.types.measurement(1, "em") self:registerCommand("quad", function (_, _) SILE.call("glue", { width = _quadwidth }) @@ -253,14 +253,14 @@ function class:registerCommands () SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected") end SILE.settings:temporarily(function () - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue(lskip.width.length)) - SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue(rskip.width.length)) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue() + SILE.settings:set("document.parindent", SILE.types.node.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.lskip", SILE.types.node.hfillglue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.types.node.hfillglue(rskip.width.length)) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) + SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0)) SILE.process(content) SILE.call("par") end) @@ -268,12 +268,12 @@ function class:registerCommands () self:registerCommand("raggedright", function (_, content) SILE.settings:temporarily(function () - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() - SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width.length)) - SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue(rskip.width.length)) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue() + SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.types.node.hfillglue(rskip.width.length)) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) + SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0)) SILE.process(content) SILE.call("par") end) @@ -281,12 +281,12 @@ function class:registerCommands () self:registerCommand("raggedleft", function (_, content) SILE.settings:temporarily(function () - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() - SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue(lskip.width.length)) - SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width.length)) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue() + SILE.settings:set("document.lskip", SILE.types.node.hfillglue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width.length)) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) + SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0)) SILE.process(content) SILE.call("par") end) @@ -294,11 +294,11 @@ function class:registerCommands () self:registerCommand("justified", function (_, content) SILE.settings:temporarily(function () - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue() -- Keep the fixed part of the margins for nesting but remove the stretchability. - SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width.length)) - SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width.length)) + SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width.length)) + SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width.length)) -- Reset parfillskip to its default value, in case the surrounding context -- is ragged and cancelled it. SILE.settings:set("typesetter.parfillskip", nil, false, true) @@ -332,13 +332,13 @@ function class:registerCommands () SILE.call("smallskip") SILE.typesetter:leaveHmode() SILE.settings:temporarily(function () - local indent = SILE.measurement("2em"):absolute() - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + local indent = SILE.types.measurement("2em"):absolute() + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue() -- We keep the stretcheability of the lskip and rskip: honoring text alignment -- from the parent context. - SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width + indent)) - SILE.settings:set("document.rskip", SILE.nodefactory.glue(rskip.width + indent)) + SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width + indent)) + SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width + indent)) SILE.settings:set("font.size", SILE.settings:get("font.size") * 0.95) SILE.process(content) SILE.typesetter:leaveHmode() @@ -356,10 +356,10 @@ function class:registerCommands () class if you need to maintain exact output past SILE v0.16.0.]]) SILE.call("smallskip") SILE.call("par") - local margin = SILE.measurement(2.5, "em") + local margin = SILE.types.measurement(2.5, "em") SILE.settings:set("document.lskip", margin) SILE.settings:set("document.lskip", margin) - SILE.call("font", { size = SILE.measurement(0.8, "em") }, function () + SILE.call("font", { size = SILE.types.measurement(0.8, "em") }, function () SILE.call("noindent") SILE.process(content) end) @@ -407,7 +407,7 @@ function class:registerCommands () self:registerCommand("vbox", function (options, content) local vbox SILE.settings:temporarily(function () - if options.width then SILE.settings:set("typesetter.breakwidth", SILE.length(options.width)) end + if options.width then SILE.settings:set("typesetter.breakwidth", SILE.types.length(options.width)) end SILE.typesetter:pushState() SILE.process(content) SILE.typesetter:leaveHmode(1) diff --git a/classes/tplain.lua b/classes/tplain.lua index f1c6ec189..6a6db9f0a 100644 --- a/classes/tplain.lua +++ b/classes/tplain.lua @@ -24,7 +24,7 @@ function class:_t_common () end) self.defaultFrameset.content.tate = self.options.layout == "tate" self:declareHanmenFrame("content", self.defaultFrameset.content) - SILE.settings:set("document.parindent", SILE.nodefactory.glue("10pt")) + SILE.settings:set("document.parindent", SILE.types.node.glue("10pt")) end function class:_init (options) diff --git a/classes/triglot.lua b/classes/triglot.lua index eaf1bc4be..8590406c4 100644 --- a/classes/triglot.lua +++ b/classes/triglot.lua @@ -44,7 +44,7 @@ function class:_init (options) }) SILE.settings:set("linebreak.tolerance", 5000) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) end diff --git a/core/break.lua b/core/break.lua index 1f041885a..0894e6e6b 100644 --- a/core/break.lua +++ b/core/break.lua @@ -51,12 +51,12 @@ local debugging = false function lineBreak:init() self:trimGlue() -- 842 -- 849 - self.activeWidth = SILE.length() - self.curActiveWidth = SILE.length() - self.breakWidth = SILE.length() + self.activeWidth = SILE.types.length() + self.curActiveWidth = SILE.types.length() + self.breakWidth = SILE.types.length() -- 853 - local rskip = (SILE.settings:get("document.rskip") or SILE.nodefactory.glue()).width:absolute() - local lskip = (SILE.settings:get("document.lskip") or SILE.nodefactory.glue()).width:absolute() + local rskip = (SILE.settings:get("document.rskip") or SILE.types.node.glue()).width:absolute() + local lskip = (SILE.settings:get("document.lskip") or SILE.types.node.glue()).width:absolute() self.background = rskip + lskip -- 860 self.bestInClass = {} @@ -72,7 +72,7 @@ end function lineBreak:trimGlue() -- 842 local nodes = self.nodes if nodes[#nodes].is_glue then nodes[#nodes] = nil end - nodes[#nodes+1] = SILE.nodefactory.penalty(inf_bad) + nodes[#nodes+1] = SILE.types.node.penalty(inf_bad) end -- NOTE FOR DEVELOPERS: this method is called when the linebreak.parShape @@ -100,9 +100,9 @@ end local parShapeCache = {} local grantLeftoverWidth = function (hsize, l, w, r) - local width = SILE.measurement(w or hsize) - if not w and l then width = width - SILE.measurement(l) end - if not w and r then width = width - SILE.measurement(r) end + local width = SILE.types.measurement(w or hsize) + if not w and l then width = width - SILE.types.measurement(l) end + if not w and r then width = width - SILE.types.measurement(r) end local remaining = hsize:tonumber() - width:tonumber() local left = SU.cast("number", l or (r and (remaining - SU.cast("number", r))) or 0) local right = SU.cast("number", r or (l and (remaining - SU.cast("number", l))) or remaining) @@ -162,7 +162,7 @@ function lineBreak:tryBreak() -- 855 self.prev_r = self.activeListHead self.old_l = 0 self.r = nil - self.curActiveWidth = SILE.length(self.activeWidth) + self.curActiveWidth = SILE.types.length(self.activeWidth) while true do while true do -- allows "break" to function as "continue" self.r = self.prev_r.next @@ -328,7 +328,7 @@ function lineBreak:deactivateR() -- 886 self.r = self.activeListHead.next if self.r.type == "delta" then self.activeWidth:___add(self.r.width) - self.curActiveWidth = SILE.length(self.activeWidth) + self.curActiveWidth = SILE.types.length(self.activeWidth) self.activeListHead.next = self.r.next end if debugging then SU.debug("break", " Deactivate, branch 1"); end @@ -405,7 +405,7 @@ function lineBreak:createNewActiveNodes(breakType) -- 862 if self.no_break_yet then -- 863 self.no_break_yet = false - self.breakWidth = SILE.length(self.background) + self.breakWidth = SILE.types.length(self.background) local place = self.place local node = self.nodes[place] if node and node.is_discretionary then -- 866 @@ -429,7 +429,7 @@ function lineBreak:createNewActiveNodes(breakType) -- 862 self.prev_r.width:___sub(self.curActiveWidth) self.prev_r.width:___add(self.breakWidth) elseif self.prev_r == self.activeListHead then - self.activeWidth = SILE.length(self.breakWidth) + self.activeWidth = SILE.types.length(self.breakWidth) else local newDelta = { next = self.r, type = "delta", width = self.breakWidth - self.curActiveWidth } if debugging then SU.debug("break", "Added new delta node = " .. tostring(newDelta.width)) end @@ -605,7 +605,7 @@ function lineBreak:doBreak (nodes, hsize, sideways) } -- Not doing 1630 - self.activeWidth = SILE.length(self.background) + self.activeWidth = SILE.types.length(self.background) self.place = 1 while self.nodes[self.place] and self.activeListHead.next ~= self.activeListHead do diff --git a/core/deprecations.lua b/core/deprecations.lua index d3c20bc28..f5154110a 100644 --- a/core/deprecations.lua +++ b/core/deprecations.lua @@ -54,15 +54,15 @@ SILE.defaultTypesetter = function () end SILE.toPoints = function (_, _) - SU.deprecated("SILE.toPoints", "SILE.measurement():tonumber", "0.10.0", "0.13.1") + SU.deprecated("SILE.toPoints", "SILE.types.measurement():tonumber", "0.10.0", "0.13.1") end SILE.toMeasurement = function (_, _) - SU.deprecated("SILE.toMeasurement", "SILE.measurement", "0.10.0", "0.13.1") + SU.deprecated("SILE.toMeasurement", "SILE.types.measurement", "0.10.0", "0.13.1") end SILE.toAbsoluteMeasurement = function (_, _) - SU.deprecated("SILE.toAbsoluteMeasurement", "SILE.measurement():absolute", "0.10.0", "0.13.1") + SU.deprecated("SILE.toAbsoluteMeasurement", "SILE.types.measurement():absolute", "0.10.0", "0.13.1") end SILE.readFile = function (filename) @@ -118,9 +118,9 @@ SILE.units = setmetatable({}, { }) SILE.colorparser = function (input) - SU.deprecated("SILE.colorparser", "SILE.color", "0.14.0", "0.16.0", + SU.deprecated("SILE.colorparser", "SILE.types.color", "0.14.0", "0.16.0", [[Color results are now color objects, not just tables with relevant values.]]) - return SILE.color(input) + return SILE.types.color(input) end function SILE.doTexlike (doc) diff --git a/core/font.lua b/core/font.lua index 10a059e41..9da62ba07 100644 --- a/core/font.lua +++ b/core/font.lua @@ -77,7 +77,7 @@ SILE.fontCache = {} local _key = function (options) return table.concat({ options.family, - ("%g"):format(SILE.measurement(options.size):tonumber()), + ("%g"):format(SILE.types.measurement(options.size):tonumber()), ("%d"):format(options.weight or 0), options.style, options.variant, diff --git a/core/frame.lua b/core/frame.lua index ce7c6a338..41c697160 100644 --- a/core/frame.lua +++ b/core/frame.lua @@ -35,7 +35,7 @@ SILE.framePrototype = pl.class({ self.variables[method] = cassowary.Variable({ name = spec.id .. "_" .. method }) self[method] = function (instance_self) instance_self:solve() - return SILE.measurement(instance_self.variables[method].value) + return SILE.types.measurement(instance_self.variables[method].value) end end -- Add definitions of width and height @@ -49,7 +49,7 @@ SILE.framePrototype = pl.class({ -- This gets called by us in typesetter before we start to use the frame init = function (self, typesetter) - self.state = { totals = { height = SILE.measurement(0) } } + self.state = { totals = { height = SILE.types.measurement(0) } } self:enter(typesetter) self:newLine(typesetter) if self:pageAdvanceDirection() == "TTB" then diff --git a/core/frameparser.lua b/core/frameparser.lua index 962378ade..287991c4e 100644 --- a/core/frameparser.lua +++ b/core/frameparser.lua @@ -4,7 +4,7 @@ local cassowary = require("cassowary") local P, C, V = lpeg.P, lpeg.C, lpeg.V local function resolveMeasurement (str) - return SILE.measurement(str):tonumber() + return SILE.types.measurement(str):tonumber() end local functionOfFrame = function (dim, id) diff --git a/core/hyphenator-liang.lua b/core/hyphenator-liang.lua index a6bd30b65..d64493d8a 100644 --- a/core/hyphenator-liang.lua +++ b/core/hyphenator-liang.lua @@ -97,7 +97,7 @@ SILE._hyphenators = {} local function defaultHyphenateSegments (node, segments, _) local hyphen = SILE.shaper:createNnodes(SILE.settings:get("font.hyphenchar"), node.options) - return SILE.nodefactory.discretionary({ prebreak = hyphen }), segments + return SILE.types.node.discretionary({ prebreak = hyphen }), segments end local initHyphenator = function (lang) diff --git a/core/papersize.lua b/core/papersize.lua index f1b9c4a04..499b88888 100644 --- a/core/papersize.lua +++ b/core/papersize.lua @@ -67,7 +67,7 @@ setmetatable(papersize, { local geometry local _, _, x, y = string.find(size, "(.+)%s+x%s+(.+)") if x and y then - geometry = { SILE.measurement(x):tonumber(), SILE.measurement(y):tonumber() } + geometry = { SILE.types.measurement(x):tonumber(), SILE.types.measurement(y):tonumber() } else local preset_name = string.lower(size:gsub("[-%s]+", "")) geometry = self[preset_name] diff --git a/core/settings.lua b/core/settings.lua index c63d5f411..f43a028cd 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -21,28 +21,28 @@ function settings:_init() self:declare({ parameter = "document.parindent", type = "glue", - default = SILE.nodefactory.glue("1bs"), + default = SILE.types.node.glue("1bs"), help = "Glue at start of paragraph" }) self:declare({ parameter = "document.baselineskip", type = "vglue", - default = SILE.nodefactory.vglue("1.2em plus 1pt"), + default = SILE.types.node.vglue("1.2em plus 1pt"), help = "Leading" }) self:declare({ parameter = "document.lineskip", type = "vglue", - default = SILE.nodefactory.vglue("1pt"), + default = SILE.types.node.vglue("1pt"), help = "Leading" }) self:declare({ parameter = "document.parskip", type = "vglue", - default = SILE.nodefactory.vglue("0pt plus 1pt"), + default = SILE.types.node.vglue("0pt plus 1pt"), help = "Leading" }) diff --git a/core/sile.lua b/core/sile.lua index 7a94c6412..14d08ac10 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -469,10 +469,10 @@ end function SILE.registerUnit (unit, spec) -- If a unit exists already, clear it first so we get fresh meta table entries, see #1607 - if SILE.units[unit] then - SILE.units[unit] = nil + if SILE.types.unit[unit] then + SILE.types.unit[unit] = nil end - SILE.units[unit] = spec + SILE.types.unit[unit] = spec end function SILE.paperSizeParser (size) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 73ab0e299..0d31bb30f 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -310,11 +310,11 @@ utilities.cast = function (wantedType, value) wantedType = string.lower(wantedType) if wantedType:match(actualType) then return value elseif actualType == "nil" and wantedType:match("nil") then return nil - elseif wantedType:match("length") then return SILE.length(value) - elseif wantedType:match("measurement") then return SILE.measurement(value) - elseif wantedType:match("vglue") then return SILE.nodefactory.vglue(value) - elseif wantedType:match("glue") then return SILE.nodefactory.glue(value) - elseif wantedType:match("kern") then return SILE.nodefactory.kern(value) + elseif wantedType:match("length") then return SILE.types.length(value) + elseif wantedType:match("measurement") then return SILE.types.measurement(value) + elseif wantedType:match("vglue") then return SILE.types.node.vglue(value) + elseif wantedType:match("glue") then return SILE.types.node.glue(value) + elseif wantedType:match("kern") then return SILE.types.node.kern(value) elseif actualType == "nil" then SU.error("Cannot cast nil to " .. wantedType) elseif wantedType:match("boolean") then return SU.boolean(value) elseif wantedType:match("string") then return tostring(value) diff --git a/documentation/c07-settings.sil b/documentation/c07-settings.sil index 65014a6bc..d0930c129 100644 --- a/documentation/c07-settings.sil +++ b/documentation/c07-settings.sil @@ -401,8 +401,8 @@ following SILE functions access the settings system from inside Lua: You should note that, while in the SILE layer, the \autodoc:command{\set} command does its best to turn the textual description of a type into the appropriate Lua type for the value. \code{SILE.settings:set} does not do that; it expects the value -to be of the appropriate type: lengths need to be a \code{SILE.length} object, -glue must be \code{SILE.nodefactory.glue} and so on.}} +to be of the appropriate type: lengths need to be a \code{SILE.types.length} object, +glue must be \code{SILE.types.node.glue} and so on.}} \item{\code{SILE.settings:get(\em{⟨parameter⟩})}: retrieves the current setting of the parameter.} diff --git a/documentation/c09-concepts.sil b/documentation/c09-concepts.sil index 8c41bc8a8..b5142d1eb 100644 --- a/documentation/c09-concepts.sil +++ b/documentation/c09-concepts.sil @@ -11,21 +11,21 @@ we will also explain how to interact with these components at the Lua level.} Before dabbling into more advanced topics, let’s introduce “measurements” and “lengths” in SILE, the two available Lua constructs for representing dimensions. -Measurements are specified in terms of \code{SILE.measurement} objects. +Measurements are specified in terms of \code{SILE.types.measurement} objects. It is a basic construct with an amount and a unit. Let us illustrate two common ways for creating such an object in Lua (from a string, with same syntax as in command parameters; or from a Lua table). \begin[type=autodoc:codeblock]{raw} -local m1 = SILE.measurement("10pt") -local m2 = SILE.measurement({ amount = 10, unit = "pt" }) +local m1 = SILE.types.measurement("10pt") +local m2 = SILE.types.measurement({ amount = 10, unit = "pt" }) \end{raw} -SILE also provides a more advanced construct specified in terms of \code{SILE.length} objects; +SILE also provides a more advanced construct specified in terms of \code{SILE.types.length} objects; these are “three-dimensional” dimensions, in that they consist in a base measurement plus stretch and shrink measurements. -They are therefore composed of three \code{SILE.measurement}. +They are therefore composed of three \code{SILE.types.measurement}. \begin[type=autodoc:codeblock]{raw} -local l1 = SILE.length("10pt plus 2pt minus 1pt") -local l2 = SILE.length({ length = "1Opt", stretch = "2pt", shrink = "1pt" }) +local l1 = SILE.types.length("10pt plus 2pt minus 1pt") +local l2 = SILE.types.length({ length = "1Opt", stretch = "2pt", shrink = "1pt" }) \end{raw} Both of these are used for various purposes. @@ -35,8 +35,8 @@ casting a length to a measurement returns just the base measurement and discards casting a measurement to a length sets its stretch and shrink properties to zero. \begin[type=autodoc:codeblock]{raw} -local l3 = SILE.length(SILE.measurement("10pt")) -- 10pt, without stretch and shrink -local m3 = SILE.measurement(SILE.length("10pt plus 2pt minus 1pt")) -- 10pt +local l3 = SILE.types.length(SILE.types.measurement("10pt")) -- 10pt, without stretch and shrink +local m3 = SILE.types.measurement(SILE.types.length("10pt plus 2pt minus 1pt")) -- 10pt \end{raw} Proper casting is important, for your code to remain portable across the various versions of the Lua language. @@ -81,12 +81,12 @@ One reason for doing so would be to explicitly avoid material being broken up by another reason for doing so would be that once you box some material up, you then know how wide or tall it is. The \autodoc:command{\hbox} and \autodoc:command{\vbox} commands put their contents into a box. -At a Lua coding level, SILE’s Lua interface contains a \code{nodefactory} for creating boxes and glue. +At a Lua coding level, SILE’s Lua interface contains a \code{types.node} for creating boxes and glue. Here is one way (among others) for you to construct horizontal and vertical glue: \begin[type=autodoc:codeblock]{raw} -local glue = SILE.nodefactory.glue({ width = l }) -local vglue = SILE.nodefactory.vglue({ height = l }) +local glue = SILE.types.node.glue({ width = l }) +local vglue = SILE.types.node.vglue({ height = l }) \end{raw} \section{Kerns} diff --git a/documentation/c10-classdesign.sil b/documentation/c10-classdesign.sil index 1f4a703f3..e3688a455 100644 --- a/documentation/c10-classdesign.sil +++ b/documentation/c10-classdesign.sil @@ -125,13 +125,13 @@ So a command be it, without any option this time, but playing with vertical skip self:registerCommand("blockquote", function (_, content) SILE.call("smallskip") SILE.settings:temporarily(function () - local indent = SILE.measurement("2em"):absolute() - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - local rskip = SILE.settings:get("document.rskip") or SILE.nodefactory.glue() + local indent = SILE.types.measurement("2em"):absolute() + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue() SILE.settings:set("document.lskip", - SILE.nodefactory.glue(lskip.width + indent)) + SILE.types.node.glue(lskip.width + indent)) SILE.settings:set("document.rskip", - SILE.nodefactory.glue(rskip.width + indent)) + SILE.types.node.glue(rskip.width + indent)) SILE.process(content) SILE.typesetter:leaveHmode() -- gather paragraphs now. end) @@ -161,7 +161,7 @@ function package:declareSettings () SILE.settings:declare({ parameter = "mypkg.blockindent", type = "measurement", - default = SILE.measurement("2em"), + default = SILE.types.measurement("2em"), help = "Blockquote indentation" }) end diff --git a/documentation/c13-tricks.sil b/documentation/c13-tricks.sil index ce2a636e4..d3e0c0cbe 100644 --- a/documentation/c13-tricks.sil +++ b/documentation/c13-tricks.sil @@ -149,7 +149,7 @@ We add some infinitely tall glue to the other typesetter’s queue to help the p \begin[type=autodoc:codeblock]{raw} function diglot:finish () - table.insert(SILE.typesetter.other.state.outputQueue, SILE.nodefactory.vfillglue()) + table.insert(SILE.typesetter.other.state.outputQueue, SILE.types.node.vfillglue()) SILE.typesetter.other:chuck() plain.finish(self) end @@ -313,13 +313,13 @@ Now we can output the cross-reference itself. \begin[type=autodoc:codeblock]{raw} SILE.settings:temporarily(function() - SILE.settings:set("document.baselineskip", SILE.nodefactory.vglue("7pt")) + SILE.settings:set("document.baselineskip", SILE.types.node.vglue("7pt")) SILE.call("font", {size = "6pt", family="Helvetica", weight="800"}, {}) self.innerTypesetter:typeset(SILE.scratch.chapter..":"..SILE.scratch.verse.." ") SILE.call("font", {size = "6pt", family="Helvetica", weight="200"}, {}) self.innerTypesetter:typeset(xref) self.innerTypesetter:leaveHmode() - self.innerTypesetter:pushVglue({ height = SILE.length({length = 4})}) + self.innerTypesetter:pushVglue({ height = SILE.types.length({length = 4})}) end) end \end{raw} @@ -448,7 +448,7 @@ If you call SILE with no input file names, it enters the REPL: \begin{autodoc:codeblock} \sileversion -> \em{l = SILE.length.parse("22mm")} +> \em{l = SILE.types.length.parse("22mm")} > \em{l.length} 62.3622054 \end{autodoc:codeblock} diff --git a/languages/ca.lua b/languages/ca.lua index e3a4a7cca..c7aa40678 100644 --- a/languages/ca.lua +++ b/languages/ca.lua @@ -33,7 +33,7 @@ SILE.hyphenator.languages["ca"].hyphenateSegments = function (node, segments, j) else hyphen = SILE.shaper:createNnodes(hyphenChar, node.options) end - local discretionary = SILE.nodefactory.discretionary({ replacement = replacement, prebreak = hyphen }) + local discretionary = SILE.types.node.discretionary({ replacement = replacement, prebreak = hyphen }) return discretionary, segments end diff --git a/languages/fr.lua b/languages/fr.lua index a85542358..f42e92a2d 100644 --- a/languages/fr.lua +++ b/languages/fr.lua @@ -12,9 +12,9 @@ local computeSpaces = function() local stretch = SILE.settings:get("shaper.spacestretchfactor") local shrink = SILE.settings:get("shaper.spaceshrinkfactor") return { - colonspace = SILE.length(enlargement.."spc plus "..stretch.."spc minus "..shrink.."spc"), - thinspace = SILE.length((0.5 * enlargement).."spc"), - guillspace = SILE.length((0.8 * enlargement).."spc plus "..(0.3 * stretch).."spc minus "..(0.8 * shrink).."spc") + colonspace = SILE.types.length(enlargement.."spc plus "..stretch.."spc minus "..shrink.."spc"), + thinspace = SILE.types.length((0.5 * enlargement).."spc"), + guillspace = SILE.types.length((0.8 * enlargement).."spc plus "..(0.3 * stretch).."spc minus "..(0.8 * shrink).."spc") } end @@ -25,21 +25,21 @@ local spaces = computeSpaces() SILE.settings:declare({ parameter = "languages.fr.colonspace", type = "kern", - default = SILE.nodefactory.kern(spaces.colonspace), + default = SILE.types.node.kern(spaces.colonspace), help = "The amount of space before a colon, theoretically a non-breakable, shrinkable, stretchable inter-word space" }) SILE.settings:declare({ parameter = "languages.fr.thinspace", type = "kern", - default = SILE.nodefactory.kern(spaces.thinspace), + default = SILE.types.node.kern(spaces.thinspace), help = "The amount of space before high punctuations, theoretically a fixed, non-breakable space, around half the inter-word space" }) SILE.settings:declare({ parameter = "languages.fr.guillspace", type = "kern", - default = SILE.nodefactory.kern(spaces.guillspace), + default = SILE.types.node.kern(spaces.guillspace), help = "The amount of space applying to guillemets, theoretically smaller than a non-breakable inter-word space, with reduced stretchability" }) @@ -53,7 +53,7 @@ SILE.settings:declare({ local getSpaceGlue = function(options, parameter) local sg if SILE.settings:get("languages.fr.debugspace") then - sg = SILE.nodefactory.kern("5spc") + sg = SILE.types.node.kern("5spc") else sg = SILE.settings:get(parameter) end diff --git a/languages/ja.lua b/languages/ja.lua index 8a8b6ebfb..9a388c598 100644 --- a/languages/ja.lua +++ b/languages/ja.lua @@ -125,7 +125,7 @@ local function shrinkability (before, after) return 0 end --- local okbreak = SILE.nodefactory.penalty(0) +-- local okbreak = SILE.types.node.penalty(0) SILE.nodeMakers.ja = pl.class(SILE.nodeMakers.base) @@ -145,17 +145,17 @@ function SILE.nodeMakers.ja:iterator (items) db = db .. " S" coroutine.yield(SILE.shaper:makeSpaceNode(options, item)) else - local length = SILE.length( + local length = SILE.types.length( intercharacterspace(lastcp, thiscp), stretchability(lastcp, thiscp), shrinkability(lastcp, thiscp) ):absolute() if breakAllowed(lastcp, thiscp) then db = db .." G ".. tostring(length) - coroutine.yield(SILE.nodefactory.glue(length)) + coroutine.yield(SILE.types.node.glue(length)) elseif length.length ~= 0 or length.stretch ~= 0 or length.shrink ~= 0 then db = db .." K ".. tostring(length) - coroutine.yield(SILE.nodefactory.kern(length)) + coroutine.yield(SILE.types.node.kern(length)) else db = db .. " N" end if jisClass(thiscp) == 5 or jisClass(thiscp) == 6 then diff --git a/languages/my.lua b/languages/my.lua index 6050c47ac..285e2ded4 100644 --- a/languages/my.lua +++ b/languages/my.lua @@ -33,8 +33,8 @@ end -- "Syllable Based Dual Weight Algorithm for Line Breaking in Myanmar Unicode" -- Keith Stribley, http://thanlwinsoft.github.io/www.thanlwinsoft.org/ThanLwinSoft/MyanmarUnicode/Parsing/my2weightLineBreakAlg1_1.pdf -local p2 = SILE.nodefactory.penalty({ penalty = -25 }) -local p1 = SILE.nodefactory.penalty({ penalty = -50 }) +local p2 = SILE.types.node.penalty({ penalty = -25 }) +local p1 = SILE.types.node.penalty({ penalty = -50 }) local penaltyFor = function (ca, cb) if ca == "WJ" or ca == "LQ" then return end diff --git a/languages/pl.lua b/languages/pl.lua index 7a09c768c..f3c4a5f02 100644 --- a/languages/pl.lua +++ b/languages/pl.lua @@ -7,7 +7,7 @@ function SILE.nodeMakers.pl:handleWordBreak (item) self:addToken(item.text, item) self:makeToken() if self.lastnode ~= "discretionary" then - coroutine.yield(SILE.nodefactory.discretionary({ + coroutine.yield(SILE.types.node.discretionary({ postbreak = SILE.shaper:createNnodes("-", self.options) })) self.lastnode = "discretionary" diff --git a/languages/tr.lua b/languages/tr.lua index cf2b9329a..a866fa601 100644 --- a/languages/tr.lua +++ b/languages/tr.lua @@ -30,7 +30,7 @@ SILE.hyphenator.languages["tr"].hyphenateSegments = function (node, segments, j) hyphenChar = SILE.settings:get("font.hyphenchar") end local hyphen = SILE.shaper:createNnodes(hyphenChar, node.options) - return SILE.nodefactory.discretionary({ replacement = replacement, prebreak = hyphen }), segments + return SILE.types.node.discretionary({ replacement = replacement, prebreak = hyphen }), segments end SILE.hyphenator.languages["tr"].patterns = diff --git a/languages/ug.lua b/languages/ug.lua index 982f54d0d..4fb1073fb 100644 --- a/languages/ug.lua +++ b/languages/ug.lua @@ -12,7 +12,7 @@ SILE.settings:declare({ parameter = "languages.ug.hyphenoffset", help = "Space added between text and hyphen", type = "glue or nil", - default = SILE.nodefactory.glue("1pt") + default = SILE.types.node.glue("1pt") }) local transliteration = { @@ -150,15 +150,15 @@ SILE.hyphenator.languages.ug = function(n) local prebreak = SILE.shaper:createNnodes(items[1] .. (lastjoinable(items[1]) and zwj or ""), state) if SILE.settings:get("languages.ug.hyphenoffset") then local w = SILE.settings:get("languages.ug.hyphenoffset").width - prebreak[#prebreak+1] = SILE.nodefactory.kern({ width = w }) + prebreak[#prebreak+1] = SILE.types.node.kern({ width = w }) end local hnodes = SILE.shaper:createNnodes(hyphen, state) prebreak[#prebreak+1] = hnodes[1] local postbreak = SILE.shaper:createNnodes((lastjoinable(items[1]) and zwj or "")..items[2], state) - local d = SILE.nodefactory.discretionary({ + local d = SILE.types.node.discretionary({ replacement = {n}, prebreak = prebreak, postbreak = postbreak }) - return { SILE.nodefactory.zerohbox(), d } + return { SILE.types.node.zerohbox(), d } end diff --git a/languages/unicode.lua b/languages/unicode.lua index 01cd8ed05..b98b624f0 100644 --- a/languages/unicode.lua +++ b/languages/unicode.lua @@ -45,7 +45,7 @@ SILE.nodeMakers.base = pl.class({ makePenalty = function (self, p) if self.lastnode ~= "penalty" and self.lastnode ~= "glue" then - coroutine.yield( SILE.nodefactory.penalty({ penalty = p or 0 }) ) + coroutine.yield( SILE.types.node.penalty({ penalty = p or 0 }) ) end self.lastnode = "penalty" end, @@ -53,7 +53,7 @@ SILE.nodeMakers.base = pl.class({ makeNonBreakingSpace = function (self) -- Unicode Line Breaking Algorithm (UAX 14) specifies that U+00A0 -- (NO-BREAK SPACE) is expanded or compressed like a normal space. - coroutine.yield(SILE.nodefactory.kern(SILE.shaper:measureSpace(self.options))) + coroutine.yield(SILE.types.node.kern(SILE.shaper:measureSpace(self.options))) self.lastnode = "glue" self.lasttype = "sp" end, @@ -149,7 +149,7 @@ function SILE.nodeMakers.unicode:letterspace () if self.lastnode and self.lastnode ~= "glue" then local w = SILE.settings:get("document.letterspaceglue").width SU.debug("tokenizer", "Letter space glue:", w) - coroutine.yield(SILE.nodefactory.kern({ width = w })) + coroutine.yield(SILE.types.node.kern({ width = w })) self.lastnode = "glue" self.lasttype = "sp" end diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index b18949744..d7932cd94 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -245,7 +245,7 @@ function outputter:debugHbox (hbox, scaledWidth) self:drawRule(x-_dl/2, y-hbox.height-_dl/2, _dl, hbox.height+hbox.depth+_dl) self:drawRule(x-_dl/2, y-_dl/2, scaledWidth+_dl, _dl) self:drawRule(x+scaledWidth-_dl/2, y-hbox.height-_dl/2, _dl, hbox.height+hbox.depth+_dl) - if hbox.depth > SILE.length(0) then + if hbox.depth > SILE.types.length(0) then self:drawRule(x-_dl/2, y+hbox.depth-_dl/2, scaledWidth+_dl, _dl) end self:popColor() diff --git a/outputters/text.lua b/outputters/text.lua index 6bf74f7d8..863e4e9e4 100644 --- a/outputters/text.lua +++ b/outputters/text.lua @@ -46,8 +46,8 @@ end function outputter:setCursor (x, y, relative) self:_ensureInit() - local bs = SILE.measurement("0.8bs"):tonumber() - local spc = SILE.measurement("0.8spc"):tonumber() + local bs = SILE.types.measurement("0.8bs"):tonumber() + local spc = SILE.types.measurement("0.8spc"):tonumber() local offset = relative and { x = cursorX, y = cursorY } or { x = 0, y = 0 } local newx, newy = offset.x + x, offset.y - y if started then diff --git a/packages/autodoc/init.lua b/packages/autodoc/init.lua index ea1e7f8ee..eea8f678d 100644 --- a/packages/autodoc/init.lua +++ b/packages/autodoc/init.lua @@ -323,14 +323,14 @@ function package:registerCommands () -- (and try to better enforce novbreak points of insertion) SILE.call("verbatim:font") -- Rather than absolutizing 4 different values, just do it once and cache it - local ex = SILE.measurement("1ex"):absolute() + local ex = SILE.types.measurement("1ex"):absolute() SILE.typesetter:leaveHmode() SILE.settings:set("typesetter.parseppattern", "\n") SILE.settings:set("typesetter.obeyspaces", true) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.parskip", SILE.nodefactory.vglue(0.3*ex)) - SILE.settings:set("document.baselineskip", SILE.nodefactory.glue(2.3*ex)) - SILE.settings:set("document.spaceskip", SILE.length("1spc")) + SILE.settings:set("document.parindent", SILE.types.node.glue()) + SILE.settings:set("document.parskip", SILE.types.node.vglue(0.3*ex)) + SILE.settings:set("document.baselineskip", SILE.types.node.glue(2.3*ex)) + SILE.settings:set("document.spaceskip", SILE.types.length("1spc")) SILE.settings:set("shaper.variablespaces", false) SILE.settings:set("document.language", "und") SILE.typesetter:leaveHmode() @@ -365,12 +365,12 @@ function package:registerCommands () self:registerCommand("autodoc:note", function(_, content) -- Replacing the \note command from the original SILE manual... - local linedimen = SILE.length("0.75em") - local linethickness = SILE.length("0.3pt") - local ls = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() + local linedimen = SILE.types.length("0.75em") + local linethickness = SILE.types.length("0.3pt") + local ls = SILE.settings:get("document.lskip") or SILE.types.node.glue() local p = SILE.settings:get("document.parindent") local leftindent = (p.width:absolute() + ls.width:absolute()).length -- fixed part - local innerindent = SILE.measurement("1em"):absolute() + local innerindent = SILE.types.measurement("1em"):absolute() SILE.settings:temporarily(function () SILE.settings:set("document.lskip", leftindent) SILE.settings:set("document.rskip", leftindent) @@ -386,8 +386,8 @@ function package:registerCommands () SILE.call("noindent") SILE.call("novbreak") SILE.settings:temporarily(function () - SILE.settings:set("document.lskip", SILE.nodefactory.glue(leftindent + innerindent)) - SILE.settings:set("document.rskip", SILE.nodefactory.glue(leftindent + innerindent)) + SILE.settings:set("document.lskip", SILE.types.node.glue(leftindent + innerindent)) + SILE.settings:set("document.rskip", SILE.types.node.glue(leftindent + innerindent)) SILE.call("font", { size = "0.95em", style = "italic "}, content) SILE.call("novbreak") end) diff --git a/packages/background/init.lua b/packages/background/init.lua index 10e7a7117..41661cb5c 100644 --- a/packages/background/init.lua +++ b/packages/background/init.lua @@ -40,7 +40,7 @@ function package:registerCommands () local allpages = SU.boolean(options.allpages, true) background.allpages = allpages - local color = options.color and SILE.color(options.color) + local color = options.color and SILE.types.color(options.color) local src = options.src if src then background.bg = src and SILE.resolveFile(src) or SU.error("Couldn't find file "..src) diff --git a/packages/balanced-frames/init.lua b/packages/balanced-frames/init.lua index 1c3d10492..2a9a70394 100644 --- a/packages/balanced-frames/init.lua +++ b/packages/balanced-frames/init.lua @@ -12,7 +12,7 @@ local function buildPage (typesetter, independent) if not (frame.balanced == true) then return unbalanced_buildPage(typesetter, independent) end local colCount = 0 - local target = SILE.length() + local target = SILE.types.length() while frame and frame.balanced == true do target = target + frame:height() colCount = colCount + 1 @@ -25,7 +25,7 @@ local function buildPage (typesetter, independent) -- of frame space on the page, and there are no magic requests to balance the -- columns, then we have a full page. Just send it out normally. local q = typesetter.state.outputQueue - local totalHeight = SILE.length() + local totalHeight = SILE.types.length() local mustBalance = 0 for i = 1, #q do totalHeight = totalHeight + q[i].height + q[i].depth diff --git a/packages/bidi/init.lua b/packages/bidi/init.lua index b9eab110a..9bd275607 100644 --- a/packages/bidi/init.lua +++ b/packages/bidi/init.lua @@ -82,8 +82,8 @@ end local splitNodeAtPos = function (n, splitstart, p) if n.is_unshaped then local utf8chars = SU.splitUtf8(n.text) - local n2 = SILE.nodefactory.unshaped({ text = "", options = pl.tablex.copy(n.options) }) - local n1 = SILE.nodefactory.unshaped({ text = "", options = pl.tablex.copy(n.options) }) + local n2 = SILE.types.node.unshaped({ text = "", options = pl.tablex.copy(n.options) }) + local n1 = SILE.types.node.unshaped({ text = "", options = pl.tablex.copy(n.options) }) for i = splitstart, #utf8chars do if i <= p then n1.text = n1.text .. utf8chars[i] else n2.text = n2.text .. utf8chars[i] diff --git a/packages/boustrophedon/init.lua b/packages/boustrophedon/init.lua index c77dfbfbd..9dbe95396 100644 --- a/packages/boustrophedon/init.lua +++ b/packages/boustrophedon/init.lua @@ -13,7 +13,7 @@ function package:_init (options) node:addToken(items[i].text, items[i]) node:makeToken() node:makePenalty() - coroutine.yield(SILE.nodefactory.glue("0pt plus 2pt")) + coroutine.yield(SILE.types.node.glue("0pt plus 2pt")) end end) end @@ -44,7 +44,7 @@ function package:registerCommands () end end if startdir == dir then - local restore = SILE.nodefactory.vbox({}) + local restore = SILE.types.node.vbox({}) restore.outputYourself = function (_, typesetter, _) typesetter.frame.direction = startdir typesetter.frame:newLine() diff --git a/packages/chordmode/init.lua b/packages/chordmode/init.lua index 60f71ac14..613c6ae4f 100644 --- a/packages/chordmode/init.lua +++ b/packages/chordmode/init.lua @@ -14,7 +14,7 @@ function package.declareSettings (_) SILE.settings:declare({ parameter = "chordmode.offset", type = "length", - default = SILE.length("2ex"), + default = SILE.types.length("2ex"), help = "Vertical offset between the chord name and the text." }) @@ -27,7 +27,7 @@ function package:registerCommands () SILE.call("chordmode:chordfont", {}, { options.name }) end) local origWidth = chordBox.width - chordBox.width = SILE.length() + chordBox.width = SILE.types.length() SILE.call("raise", { height = SILE.settings:get("chordmode.offset") }, function () SILE.typesetter:pushHbox(chordBox) @@ -35,7 +35,7 @@ function package:registerCommands () local lyricBox = SILE.call("hbox", {}, content) if lyricBox.width < origWidth then - lyricBox.width = origWidth + SILE.length("0.5em"):absolute() + lyricBox.width = origWidth + SILE.types.length("0.5em"):absolute() end local chordLineHeight = chordBox.height + SILE.settings:get("chordmode.offset"):absolute() if chordLineHeight > lyricBox.height then diff --git a/packages/color-fonts/init.lua b/packages/color-fonts/init.lua index d6955bab7..d0ae4f63e 100644 --- a/packages/color-fonts/init.lua +++ b/packages/color-fonts/init.lua @@ -79,7 +79,7 @@ function package:_init () for i=1, #run do options = pl.tablex.deepcopy(options) if run[i].color then - nodes[#nodes+1] = SILE.nodefactory.hbox({ + nodes[#nodes+1] = SILE.types.node.hbox({ outputYourself = function () SILE.outputter:pushColor(run[i].color) end }) end @@ -87,7 +87,7 @@ function package:_init () nodes[#nodes+1] = node end if run[i].color then - nodes[#nodes+1] = SILE.nodefactory.hbox({ + nodes[#nodes+1] = SILE.types.node.hbox({ outputYourself = function () SILE.outputter:popColor() end }) end diff --git a/packages/color/init.lua b/packages/color/init.lua index 4c1dfd279..8034ad43c 100644 --- a/packages/color/init.lua +++ b/packages/color/init.lua @@ -6,7 +6,7 @@ package._name = "color" function package:registerCommands () self:registerCommand("color", function (options, content) - local color = SILE.color(options.color or "black") + local color = SILE.types.color(options.color or "black") -- This is a bit of a hack to use a liner. -- (Due to how the color stack is currently handled) -- If the content spans multiple lines, and a page break occurs in between, diff --git a/packages/complex-spaces/init.lua b/packages/complex-spaces/init.lua index 81a4208ea..92bda3bee 100644 --- a/packages/complex-spaces/init.lua +++ b/packages/complex-spaces/init.lua @@ -21,7 +21,7 @@ function package:_init () local myoptions = pl.tablex.deepcopy(options) myoptions.language = "x-spaces-are-nodes" local nnodes = SILE.shaper:createNnodes( " ", myoptions) - return SILE.nodefactory.discretionary({ replacement=nnodes }) + return SILE.types.node.discretionary({ replacement=nnodes }) end return SILE.shaper.noncomplex_SpaceNode(_, options, item) end diff --git a/packages/dropcaps/init.lua b/packages/dropcaps/init.lua index ac7b6bccd..7ce03d86d 100644 --- a/packages/dropcaps/init.lua +++ b/packages/dropcaps/init.lua @@ -58,7 +58,7 @@ local function getToleranceDepth () bsratio = computeBaselineRatio() SU.debug("dropcaps", "Using computed descender baseline ratio", bsratio) end - return bsratio * SILE.measurement("1bs"):tonumber() + return bsratio * SILE.types.measurement("1bs"):tonumber() end function package:registerCommands () @@ -97,7 +97,7 @@ function package:registerCommands () -- Note this only works for the default linespace mechanism. -- We determine the height of the first line by measuring the size the initial content *would have* been. local tmpHbox = shapeHbox(options, content) - local extraHeight = SILE.measurement((lines - 1).."bs"):tonumber() + local extraHeight = SILE.types.measurement((lines - 1).."bs"):tonumber() local curHeight = tmpHbox.height:tonumber() + depthAdjustment local targetHeight = (curHeight - depthAdjustment) * scale + extraHeight if strict then @@ -108,7 +108,7 @@ function package:registerCommands () -- Now we need to figure out how to scale the dropcap font to get an initial of targetHeight. -- From that we can also figure out the width it will be at that height. - local curSize = SILE.measurement(SILE.settings:get("font.size")):tonumber() + local curSize = SILE.types.measurement(SILE.settings:get("font.size")):tonumber() local curWidth = tmpHbox.width:tonumber() options.size = size and size:tonumber() or (targetHeight / curHeight * curSize) local targetWidth = curWidth / curSize * options.size @@ -129,7 +129,7 @@ function package:registerCommands () local toleranceDepth = getToleranceDepth() if extraDepth > toleranceDepth then SU.debug("dropcaps", "Extra depth", extraDepth, "> tolerance", toleranceDepth) - local extraLines = math.ceil((extraDepth - toleranceDepth) / SILE.measurement("1bs"):tonumber()) + local extraLines = math.ceil((extraDepth - toleranceDepth) / SILE.types.measurement("1bs"):tonumber()) lines = lines + extraLines SU.debug("dropcaps", "Extra lines needed to fit", extraLines) else diff --git a/packages/footnotes/init.lua b/packages/footnotes/init.lua index 4adb97888..3e40ce87d 100644 --- a/packages/footnotes/init.lua +++ b/packages/footnotes/init.lua @@ -15,9 +15,9 @@ function package:_init (options) self.class:initInsertionClass("footnote", { insertInto = options.insertInto or "footnotes", stealFrom = options.stealFrom or { "content" }, - maxHeight = SILE.length("75%ph"), - topBox = SILE.nodefactory.vglue("2ex"), - interInsertionSkip = SILE.length("1ex"), + maxHeight = SILE.types.length("75%ph"), + topBox = SILE.types.node.vglue("2ex"), + interInsertionSkip = SILE.types.length("1ex"), }) end @@ -41,10 +41,10 @@ function package:registerCommands () self:registerCommand("footnote:options", function (options, _) if options["maxHeight"] then - SILE.scratch.insertions.classes.footnote.maxHeight = SILE.length(options["maxHeight"]) + SILE.scratch.insertions.classes.footnote.maxHeight = SILE.types.length(options["maxHeight"]) end if options["interInsertionSkip"] then - SILE.scratch.insertions.classes.footnote.interInsertionSkip = SILE.length(options["interInsertionSkip"]) + SILE.scratch.insertions.classes.footnote.interInsertionSkip = SILE.types.length(options["interInsertionSkip"]) end end) @@ -54,7 +54,7 @@ function package:registerCommands () local frame = opts.insertInto and SILE.getFrame(opts.insertInto.frame) local oldGetTargetLength = SILE.typesetter.getTargetLength local oldFrame = SILE.typesetter.frame - SILE.typesetter.getTargetLength = function () return SILE.length(0xFFFFFF) end + SILE.typesetter.getTargetLength = function () return SILE.types.length(0xFFFFFF) end SILE.settings:pushState() -- Restore the settings to the top of the queue, which should be the document #986 SILE.settings:toplevelState() diff --git a/packages/frametricks/init.lua b/packages/frametricks/init.lua index 6b1ae6754..71fe4636e 100644 --- a/packages/frametricks/init.lua +++ b/packages/frametricks/init.lua @@ -5,7 +5,7 @@ package._name = "frametricks" local breakFrameHorizontalAt = function (offset) local cFrame = SILE.typesetter.frame - if not offset or not (offset > SILE.length(0)) then + if not offset or not (offset > SILE.types.length(0)) then SILE.typesetter:chuck() offset = SILE.typesetter.frame.state.cursorX end @@ -32,10 +32,10 @@ end local shiftframeedge = function (frame, options) if options.left then - frame:constrain("left", frame:left() + SILE.length(options.left)) + frame:constrain("left", frame:left() + SILE.types.length(options.left)) end if options.right then - frame:constrain("right", frame:right() + SILE.length(options.right)) + frame:constrain("right", frame:right() + SILE.types.length(options.right)) end end @@ -103,7 +103,7 @@ function package.breakFrameVertical (_, after) if after then totalHeight = after else - totalHeight = SILE.length(0) + totalHeight = SILE.types.length(0) SILE.typesetter:leaveHmode(1) local queue = SILE.typesetter.state.outputQueue for i = 1, #queue do @@ -209,22 +209,22 @@ function package:registerCommands () SILE.typesetter:leaveHmode() local hbox = SILE.typesetter:makeHbox(content) -- HACK What about migrating nodes here? local heightOfPageSoFar = SILE.pagebuilder:collateVboxes(SILE.typesetter.state.outputQueue).height - local overshoot = SILE.length(heightOfPageSoFar + hbox.height - SILE.typesetter:getTargetLength()) - if overshoot > SILE.length(0) then + local overshoot = SILE.types.length(heightOfPageSoFar + hbox.height - SILE.typesetter:getTargetLength()) + if overshoot > SILE.types.length(0) then SILE.call("eject") SILE.typesetter:leaveHmode() end self:breakFrameVertical() - local boundary = hbox.width + SILE.length(options.rightboundary):absolute() + local boundary = hbox.width + SILE.types.length(options.rightboundary):absolute() breakFrameHorizontalAt(boundary) SILE.typesetNaturally(SILE.typesetter.frame.previous, function () table.insert(SILE.typesetter.state.nodes, hbox) end) - -- SILE.settings:set("document.baselineskip", SILE.length("1ex") - SILE.settings:get("document.baselineskip").height) + -- SILE.settings:set("document.baselineskip", SILE.types.length("1ex") - SILE.settings:get("document.baselineskip").height) -- undoSkip.stretch = hbox.height -- SILE.typesetter:pushHbox({ value = {} }) -- SILE.typesetter:pushVglue({ height = undoSkip }) - self:breakFrameVertical(hbox.height + SILE.length(options.bottomboundary):absolute()) + self:breakFrameVertical(hbox.height + SILE.types.length(options.bottomboundary):absolute()) shiftframeedge(SILE.getFrame(SILE.typesetter.frame.next), { left = -boundary }) --SILE.outputter:debugFrame(SILE.typesetter.frame) end, "Sets the given content in its own frame, flowing the remaining content around it") @@ -243,7 +243,7 @@ function package:registerCommands () SU.error("Can't find frame "..options.frame.." to fit") end local frame = SILE.frames[options.frame] - local height = SILE.length() + local height = SILE.types.length() SILE.typesetNaturally(frame, function () SILE.typesetter:leaveHmode() for i = 1, #SILE.typesetter.state.outputQueue do diff --git a/packages/grid/init.lua b/packages/grid/init.lua index 9df14d28c..efed7a079 100644 --- a/packages/grid/init.lua +++ b/packages/grid/init.lua @@ -8,7 +8,7 @@ local oldPagebuilderType, oldTypesetterType local function startGridInFrame (typesetter) if not SILE.typesetter.state.grid then return end -- Ensure the frame hook isn't effective when grid is off local queue = typesetter.state.outputQueue - typesetter.frame.state.totals.gridCursor = SILE.measurement(0) + typesetter.frame.state.totals.gridCursor = SILE.types.measurement(0) if #queue == 0 then typesetter.state.previousVbox = typesetter:pushVbox() return @@ -17,7 +17,7 @@ local function startGridInFrame (typesetter) table.remove(queue, 1) end if queue[1] then - table.insert(queue, 1, SILE.nodefactory.vbox()) + table.insert(queue, 1, SILE.types.node.vbox()) table.insert(queue, 2, SILE.typesetter:leadingFor(queue[2], queue[1])) end end diff --git a/packages/gutenberg/init.lua b/packages/gutenberg/init.lua index a48944485..82aab67c4 100644 --- a/packages/gutenberg/init.lua +++ b/packages/gutenberg/init.lua @@ -18,7 +18,7 @@ function package:registerCommands () end table.insert(alts, hbox) end - local alternative = SILE.nodefactory.alternative({ + local alternative = SILE.types.node.alternative({ options = alts, selected = 1 }) diff --git a/packages/hanmenkyoshi/init.lua b/packages/hanmenkyoshi/init.lua index cf21bdb08..8feaa2dac 100644 --- a/packages/hanmenkyoshi/init.lua +++ b/packages/hanmenkyoshi/init.lua @@ -58,8 +58,8 @@ local declareHanmenFrame = function (class, id, spec) spec.hanmen.linegap * ( spec.hanmen.linecount -1 ) end local skip = spec.hanmen.linegap + spec.hanmen.gridsize - SILE.settings:set("document.baselineskip", SILE.nodefactory.vglue(skip)) - SILE.settings:set("document.parskip", SILE.nodefactory.vglue()) + SILE.settings:set("document.baselineskip", SILE.types.node.vglue(skip)) + SILE.settings:set("document.parskip", SILE.types.node.vglue()) local frame = SILE.newFrame(spec, spec.tate and SILE.tateFramePrototype or SILE.framePrototype) if spec.id then class.pageTemplate.frames[spec.id] = frame diff --git a/packages/indexer/init.lua b/packages/indexer/init.lua index 3254e87a8..12d938d1c 100644 --- a/packages/indexer/init.lua +++ b/packages/indexer/init.lua @@ -68,8 +68,8 @@ function package:registerCommands () self:registerCommand("index:item", function (options, content) SILE.settings:temporarily(function () - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) SILE.call("code", {}, content) -- Ideally, leaders SILE.call("hss") diff --git a/packages/infonode/init.lua b/packages/infonode/init.lua index 40f65ff5e..2d8b2599e 100644 --- a/packages/infonode/init.lua +++ b/packages/infonode/init.lua @@ -9,7 +9,7 @@ package._name = "infonode" -- Check out SILE.scratch.info.thispage in your end-of-page routine and see what nodes -- are there. -local _info = pl.class(SILE.nodefactory.zerohbox) +local _info = pl.class(SILE.types.node.zerohbox) _info.type = "info" function _info:__tostring () diff --git a/packages/insertions/init.lua b/packages/insertions/init.lua index 14fe0273f..cc40a3743 100644 --- a/packages/insertions/init.lua +++ b/packages/insertions/init.lua @@ -63,7 +63,7 @@ local initInsertionClass = function (_, classname, options) options.insertInto = { frame = options.insertInto, ratio = 1 } end - options.maxHeight = SILE.length(options.maxHeight) + options.maxHeight = SILE.types.length(options.maxHeight) SILE.scratch.insertions.classes[classname] = options end @@ -77,21 +77,21 @@ typesetter and frame. --]] local insertionsThisPage = {} -SILE.nodefactory.insertionlist = pl.class(SILE.nodefactory.vbox) +SILE.types.node.insertionlist = pl.class(SILE.types.node.vbox) -SILE.nodefactory.insertionlist.type = "insertionlist" -SILE.nodefactory.insertionlist.frame = nil +SILE.types.node.insertionlist.type = "insertionlist" +SILE.types.node.insertionlist.frame = nil -function SILE.nodefactory.insertionlist:_init (spec) - SILE.nodefactory.vbox._init(self, spec) +function SILE.types.node.insertionlist:_init (spec) + SILE.types.node.vbox._init(self, spec) self.typesetter = SILE.typesetters.base() end -function SILE.nodefactory.insertionlist:__tostring () +function SILE.types.node.insertionlist:__tostring () return "PI<" .. self.nodes .. ">" end -function SILE.nodefactory.insertionlist:outputYourself () +function SILE.types.node.insertionlist:outputYourself () self.typesetter:initFrame(SILE.getFrame(self.frame)) for _, node in ipairs(self.nodes) do node:outputYourself(self.typesetter, node) @@ -100,7 +100,7 @@ end local thisPageInsertionBoxForClass = function (class) if not insertionsThisPage[class] then - insertionsThisPage[class] = SILE.nodefactory.insertionlist({ + insertionsThisPage[class] = SILE.types.node.insertionlist({ frame = SILE.scratch.insertions.classes[class].insertInto.frame }) end @@ -116,28 +116,28 @@ So we stick the material into an insertion vbox, and when the pagebuilder sees this, magic will happen. --]] -SILE.nodefactory.insertion = pl.class(SILE.nodefactory.vbox) +SILE.types.node.insertion = pl.class(SILE.types.node.vbox) -SILE.nodefactory.insertion.discardable = true -SILE.nodefactory.insertion.type = "insertion" -SILE.nodefactory.insertion.seen = false +SILE.types.node.insertion.discardable = true +SILE.types.node.insertion.type = "insertion" +SILE.types.node.insertion.seen = false -function SILE.nodefactory.insertion:__tostring () +function SILE.types.node.insertion:__tostring () return "I<"..self.nodes[1].."...>" end -function SILE.nodefactory.insertion.outputYourself (_) +function SILE.types.node.insertion.outputYourself (_) end -- And some utility methods to make the insertion processing code -- easier to read. -function SILE.nodefactory.insertion:dropDiscardables () +function SILE.types.node.insertion:dropDiscardables () while #self.nodes > 1 and self.nodes[#self.nodes].discardable do self.nodes[#self.nodes] = nil end end -function SILE.nodefactory.insertion:split (materialToSplit, maxsize) +function SILE.types.node.insertion:split (materialToSplit, maxsize) local firstpage = SILE.pagebuilder:findBestBreak({ vboxlist = materialToSplit, target = maxsize, @@ -149,8 +149,8 @@ function SILE.nodefactory.insertion:split (materialToSplit, maxsize) self:append(materialToSplit) self.contentHeight = self.height self.contentDepth = self.depth - self.depth = SILE.length(0) - self.height = SILE.length(0) + self.depth = SILE.types.length(0) + self.height = SILE.types.length(0) return SILE.pagebuilder:collateVboxes(firstpage) end end @@ -168,7 +168,7 @@ entered yet. local initShrinkage = function (frame) if not frame.state or not frame.state.totals then frame:init() end - if not frame.state.totals.shrinkage then frame.state.totals.shrinkage = SILE.measurement(0) end + if not frame.state.totals.shrinkage then frame.state.totals.shrinkage = SILE.types.measurement(0) end end local nextInterInsertionSkip = function (class) @@ -178,12 +178,12 @@ local nextInterInsertionSkip = function (class) if options["topBox"] then return options["topBox"]:absolute() elseif options["topSkip"] then - return SILE.nodefactory.vglue(options["topSkip"]:tonumber()) + return SILE.types.node.vglue(options["topSkip"]:tonumber()) end else local skipSize = options["interInsertionSkip"]:tonumber() skipSize = skipSize - stuffSoFar.nodes[#stuffSoFar.nodes].depth:tonumber() - return SILE.nodefactory.vglue(skipSize) + return SILE.types.node.vglue(skipSize) end end @@ -204,10 +204,10 @@ local insert = function (_, classname, vbox) local insertion = SILE.scratch.insertions.classes[classname] if not insertion then SU.error("Uninitialized insertion class " .. classname) end SILE.typesetter:pushMigratingMaterial({ - SILE.nodefactory.penalty(SILE.settings:get("insertion.penalty")) + SILE.types.node.penalty(SILE.settings:get("insertion.penalty")) }) SILE.typesetter:pushMigratingMaterial({ - SILE.nodefactory.insertion({ + SILE.types.node.insertion({ class = classname, nodes = vbox.nodes, -- actual height and depth must remain zero for page glue calculations @@ -256,7 +256,7 @@ function package:_init () if stealPosition == "bottom" then frame:relax("bottom") else frame:relax("top") end SU.debug("insertions", "Constraining height of", fName, "by", frame.state.totals.shrinkage, "to", newHeight) frame:constrain("height", newHeight) - frame.state.totals.shrinkage = SILE.measurement(0) + frame.state.totals.shrinkage = SILE.types.measurement(0) end end end @@ -306,7 +306,7 @@ function package:_init () -- We look into the page's insertion box and choose the appropriate skip, -- so we know how high the whole insertion is. local topBox = nextInterInsertionSkip(ins.class) - local insertionsHeight = SILE.length() + local insertionsHeight = SILE.types.length() insertionsHeight:___add(ins.contentHeight) insertionsHeight:___add(topBox.height) insertionsHeight:___add(topBox.depth) @@ -322,7 +322,7 @@ function package:_init () local effectOnThisFrame = options.stealFrom[SILE.typesetter.frame.id] if effectOnThisFrame then effectOnThisFrame = insertionsHeight * effectOnThisFrame - else effectOnThisFrame = SILE.measurement(0) end + else effectOnThisFrame = SILE.types.measurement(0) end local newTarget = target - effectOnThisFrame @@ -374,7 +374,7 @@ function package:_init () the penalty (and break the page) and then consider the rest of the insertion. --]] - table.insert(vboxlist, i, SILE.nodefactory.penalty(-20000)) + table.insert(vboxlist, i, SILE.types.node.penalty(-20000)) return target -- Who cares? The penalty is going to cause a split. end @@ -409,7 +409,7 @@ function package:_init () local lastbox = i while not vboxlist[lastbox].is_vbox do lastbox = lastbox - 1 end while not (vboxlist[i].is_penalty and vboxlist[i].penalty == -20000) do - table.insert(vboxlist, lastbox, SILE.nodefactory.penalty(-20000)) + table.insert(vboxlist, lastbox, SILE.types.node.penalty(-20000)) end return target end diff --git a/packages/leaders/init.lua b/packages/leaders/init.lua index 7fe989982..963b29bc2 100644 --- a/packages/leaders/init.lua +++ b/packages/leaders/init.lua @@ -23,7 +23,7 @@ local widthToFrameEdge = function (frame) return w end -local leader = pl.class(SILE.nodefactory.glue) +local leader = pl.class(SILE.types.node.glue) function leader:outputYourself (typesetter, line) local outputWidth = SU.rationWidth(self.width, self.width, line.ratio):tonumber() @@ -86,7 +86,7 @@ end function package:registerCommands () self:registerCommand("leaders", function(options, content) - local width = options.width and SU.cast("glue", options.width) or SILE.nodefactory.hfillglue() + local width = options.width and SU.cast("glue", options.width) or SILE.types.node.hfillglue() local hbox, hlist = SILE.typesetter:makeHbox(content) if #hlist > 0 then SU.error("Forbidden migrating content in leaders") @@ -102,10 +102,10 @@ function package:registerCommands () -- though in older times it was sometimes up to 1em and could be distributed -- differently. Anyhow, it is also the approach taken by LaTeX, with a -- \@dotsep space of 4.5mu (where 18mu = 1em, so indeed leading to 0.25em). - SILE.call("leaders", { width = SILE.nodefactory.hfillglue() }, function() - SILE.call("kern", { width = SILE.length("0.25em") }) + SILE.call("leaders", { width = SILE.types.node.hfillglue() }, function() + SILE.call("kern", { width = SILE.types.length("0.25em") }) SILE.typesetter:typeset(".") - SILE.call("kern", {width = SILE.length("0.25em") }) + SILE.call("kern", {width = SILE.types.length("0.25em") }) end) end) diff --git a/packages/linespacing/init.lua b/packages/linespacing/init.lua index 0af66972f..a9a5d13b7 100644 --- a/packages/linespacing/init.lua +++ b/packages/linespacing/init.lua @@ -8,7 +8,7 @@ local metrics = require("fontmetrics") local metricscache = {} local getLineMetrics = function (l) - local linemetrics = { ascender = 0, descender = 0, lineheight = SILE.length() } + local linemetrics = { ascender = 0, descender = 0, lineheight = SILE.types.length() } if not l or not l.nodes then return linemetrics end for i = 1, #(l.nodes) do local node = l.nodes[i] @@ -39,8 +39,8 @@ local linespacingLeading = function (_, vbox, previous) local firstline = SILE.settings:get("linespacing.minimumfirstlineposition"):absolute() if not previous then if firstline.length:tonumber() > 0 then - local toAdd = SILE.length(firstline.length - vbox.height) - return SILE.nodefactory.vkern(toAdd) + local toAdd = SILE.types.length(firstline.length - vbox.height) + return SILE.types.node.vkern(toAdd) else return nil end @@ -52,14 +52,14 @@ local linespacingLeading = function (_, vbox, previous) if method == "fit-glyph" then local extra = SILE.settings:get("linespacing.fit-glyph.extra-space"):absolute() - local toAdd = SILE.length(extra) - return SILE.nodefactory.vglue(toAdd) + local toAdd = SILE.types.length(extra) + return SILE.types.node.vglue(toAdd) end if method == "fixed" then local btob = SILE.settings:get("linespacing.fixed.baselinedistance"):absolute() - local toAdd = SILE.length(btob.length - (vbox.height + previous.depth), btob.stretch, btob.shrink) - return SILE.nodefactory.vglue(toAdd) + local toAdd = SILE.types.length(btob.length - (vbox.height + previous.depth), btob.stretch, btob.shrink) + return SILE.types.node.vglue(toAdd) end -- For these methods, we need to read the font metrics @@ -75,7 +75,7 @@ local linespacingLeading = function (_, vbox, previous) local extra = SILE.settings:get("linespacing.fit-font.extra-space"):absolute() local btob = prevmetrics.descender + thismetrics.ascender + extra local toAdd = btob - (vbox.height + (previous and previous.depth or 0)) - return SILE.nodefactory.vglue(toAdd) + return SILE.types.node.vglue(toAdd) end if method == "css" then @@ -85,7 +85,7 @@ local linespacingLeading = function (_, vbox, previous) previous.height = previous.height + leading / 2 previous.depth = previous.depth + leading / 2 end - return SILE.nodefactory.vglue() + return SILE.types.node.vglue() end @@ -110,32 +110,32 @@ function package.declareSettings (_) SILE.settings:declare({ parameter = "linespacing.fixed.baselinedistance", - default = SILE.length("1.2em"), + default = SILE.types.length("1.2em"), type = "length", help = "Distance from baseline to baseline in the case of fixed line spacing" }) SILE.settings:declare({ parameter = "linespacing.minimumfirstlineposition", - default = SILE.length(0), + default = SILE.types.length(0), type = "length" }) SILE.settings:declare({ parameter = "linespacing.fit-glyph.extra-space", - default = SILE.length(0), + default = SILE.types.length(0), type = "length" }) SILE.settings:declare({ parameter = "linespacing.fit-font.extra-space", - default = SILE.length(0), + default = SILE.types.length(0), type = "length" }) SILE.settings:declare({ parameter = "linespacing.css.line-height", - default = SILE.length("1.2em"), + default = SILE.types.length("1.2em"), type = "length" }) diff --git a/packages/lists/init.lua b/packages/lists/init.lua index e7b943ffe..cf3e9ecad 100644 --- a/packages/lists/init.lua +++ b/packages/lists/init.lua @@ -121,7 +121,7 @@ function package:doItem (options, content) -- appearing twice in output... but we can avoid it: -- reboxing an hbox was dumb anyway. We just need to fix its width before -- reinserting it in the text flow. - mark.width = SILE.length(stepback) + mark.width = SILE.types.length(stepback) SILE.typesetter:pushHbox(mark) SILE.process(content) end @@ -147,7 +147,7 @@ function package.doNestedList (_, listType, options, content) end -- indent - local baseIndent = (depth == 1) and SILE.settings:get("document.parindent").width:absolute() or SILE.measurement("0pt") + local baseIndent = (depth == 1) and SILE.settings:get("document.parindent").width:absolute() or SILE.types.measurement("0pt") local listIndent = SILE.settings:get("lists."..listType..".leftmargin"):absolute() -- processing @@ -156,11 +156,11 @@ function package.doNestedList (_, listType, options, content) end SILE.settings:temporarily(function () SILE.settings:set("lists.current."..listType..".depth", depth) - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) SILE.settings:set("document.parskip", SILE.settings:get("lists.parskip")) - local lskip = SILE.settings:get("document.lskip") or SILE.nodefactory.glue() - SILE.settings:set("document.lskip", SILE.nodefactory.glue(lskip.width + (baseIndent + listIndent))) + local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue() + SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width + (baseIndent + listIndent))) local counter = options.start and (SU.cast("integer", options.start) - 1) or 0 for i = 1, #content do @@ -234,28 +234,28 @@ function package.declareSettings (_) SILE.settings:declare({ parameter = "lists.enumerate.leftmargin", type = "measurement", - default = SILE.measurement("2em"), + default = SILE.types.measurement("2em"), help = "Left margin (indentation) for enumerations" }) SILE.settings:declare({ parameter = "lists.enumerate.labelindent", type = "measurement", - default = SILE.measurement("0.5em"), + default = SILE.types.measurement("0.5em"), help = "Label indentation for enumerations" }) SILE.settings:declare({ parameter = "lists.itemize.leftmargin", type = "measurement", - default = SILE.measurement("1.5em"), + default = SILE.types.measurement("1.5em"), help = "Left margin (indentation) for bullet lists (itemize)" }) SILE.settings:declare({ parameter = "lists.parskip", type = "vglue", - default = SILE.nodefactory.vglue("0pt plus 1pt"), + default = SILE.types.node.vglue("0pt plus 1pt"), help = "Leading between paragraphs and items in a list" }) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index bfc7b1640..61a558235 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -192,7 +192,7 @@ local function getRightMostGlyphId(node) end end --- Compares two SILE length, without considering shrink or stretch values, and +-- Compares two SILE.types.length, without considering shrink or stretch values, and -- returns the biggest. local function maxLength(...) local arg = {...} @@ -237,8 +237,8 @@ function elements.mbox:_init () nodefactory.hbox._init(self) self.font = {} self.children = {} -- The child nodes - self.relX = SILE.length(0) -- x position relative to its parent box - self.relY = SILE.length(0) -- y position relative to its parent box + self.relX = SILE.types.length(0) -- x position relative to its parent box + self.relY = SILE.types.length(0) -- y position relative to its parent box self.value = {} self.mode = mathMode.display self.atom = atomType.ordinary @@ -437,11 +437,11 @@ function elements.stackbox:shape () -- 1. set self.width to max element width -- 2. set self.height -- And finally set children's relative coordinates - self.height = SILE.length(0) - self.depth = SILE.length(0) + self.height = SILE.types.length(0) + self.depth = SILE.types.length(0) if self.direction == "H" then for i, n in ipairs(self.children) do - n.relY = SILE.length(0) + n.relY = SILE.types.length(0) self.height = i == 1 and n.height or maxLength(self.height, n.height) self.depth = i == 1 and n.depth or maxLength(self.depth, n.depth) end @@ -453,14 +453,14 @@ function elements.stackbox:shape () end end -- Set self.width - self.width = SILE.length(0) + self.width = SILE.types.length(0) for i, n in ipairs(self.children) do n.relX = self.width self.width = i == 1 and n.width or self.width + n.width end else -- self.direction == "V" for i, n in ipairs(self.children) do - n.relX = SILE.length(0) + n.relX = SILE.types.length(0) self.width = i == 1 and n.width or maxLength(self.width, n.width) end -- Set self.height and self.depth @@ -531,12 +531,12 @@ function elements.subscript:shape () local constants = mathMetrics.constants local scaleDown = self:getScaleDown() if self.base then - self.base.relX = SILE.length(0) - self.base.relY = SILE.length(0) + self.base.relX = SILE.types.length(0) + self.base.relY = SILE.types.length(0) -- Use widthForSubscript of base, if available self.width = self.base.widthForSubscript or self.base.width else - self.width = SILE.length(0) + self.width = SILE.types.length(0) end local itCorr = self:calculateItalicsCorrection() * scaleDown local subShift @@ -550,7 +550,7 @@ function elements.subscript:shape () subShift = 0 end self.sub.relX = self.width + subShift - self.sub.relY = SILE.length(math.max( + self.sub.relY = SILE.types.length(math.max( constants.subscriptShiftDown * scaleDown, --self.base.depth + constants.subscriptBaselineDropMin * scaleDown, (self.sub.height - constants.subscriptTopMax * scaleDown):tonumber() @@ -570,7 +570,7 @@ function elements.subscript:shape () supShift = itCorr end self.sup.relX = self.width + supShift - self.sup.relY = SILE.length(math.max( + self.sup.relY = SILE.types.length(math.max( isCrampedMode(self.mode) and constants.superscriptShiftUpCramped * scaleDown or constants.superscriptShiftUp * scaleDown, -- or cramped @@ -601,18 +601,18 @@ function elements.subscript:shape () end end self.width = self.width + maxLength( - self.sub and self.sub.width + subShift or SILE.length(0), - self.sup and self.sup.width + supShift or SILE.length(0) + self.sub and self.sub.width + subShift or SILE.types.length(0), + self.sup and self.sup.width + supShift or SILE.types.length(0) ) + constants.spaceAfterScript * scaleDown self.height = maxLength( - self.base and self.base.height or SILE.length(0), - self.sub and (self.sub.height - self.sub.relY) or SILE.length(0), - self.sup and (self.sup.height - self.sup.relY) or SILE.length(0) + self.base and self.base.height or SILE.types.length(0), + self.sub and (self.sub.height - self.sub.relY) or SILE.types.length(0), + self.sup and (self.sup.height - self.sup.relY) or SILE.types.length(0) ) self.depth = maxLength( - self.base and self.base.depth or SILE.length(0), - self.sub and (self.sub.depth + self.sub.relY) or SILE.length(0), - self.sup and (self.sup.depth + self.sup.relY) or SILE.length(0) + self.base and self.base.depth or SILE.types.length(0), + self.sub and (self.sub.depth + self.sub.relY) or SILE.types.length(0), + self.sup and (self.sup.depth + self.sup.relY) or SILE.types.length(0) ) end @@ -656,15 +656,15 @@ function elements.underOver:shape () local scaleDown = self:getScaleDown() -- Determine relative Ys if self.base then - self.base.relY = SILE.length(0) + self.base.relY = SILE.types.length(0) end if self.sub then - self.sub.relY = self.base.depth + SILE.length(math.max( + self.sub.relY = self.base.depth + SILE.types.length(math.max( (self.sub.height + constants.lowerLimitGapMin * scaleDown):tonumber(), constants.lowerLimitBaselineDropMin * scaleDown)) end if self.sup then - self.sup.relY = 0 - self.base.height - SILE.length(math.max( + self.sup.relY = 0 - self.base.height - SILE.types.length(math.max( (constants.upperLimitGapMin * scaleDown + self.sup.depth):tonumber(), constants.upperLimitBaselineRiseMin * scaleDown)) end @@ -699,7 +699,7 @@ function elements.underOver:shape () b = nil end end - widest.relX = SILE.length(0) + widest.relX = SILE.types.length(0) local c = widest.width / 2 if a then a.relX = c - a.width / 2 end if b then b.relX = c - b.width / 2 end @@ -708,9 +708,9 @@ function elements.underOver:shape () if self.sub then self.sub.relX = self.sub.relX - itCorr / 2 end -- Determine width and height self.width = maxLength( - self.base and self.base.width or SILE.length(0), - self.sub and self.sub.width or SILE.length(0), - self.sup and self.sup.width or SILE.length(0) + self.base and self.base.width or SILE.types.length(0), + self.sub and self.sub.width or SILE.types.length(0), + self.sup and self.sup.width or SILE.types.length(0) ) if self.sup then self.height = 0 - self.sup.relY + self.sup.height @@ -777,14 +777,14 @@ local function getStandardLength (value) direction = -1 end if value == "thin" then - return SILE.length("3mu") * direction + return SILE.types.length("3mu") * direction elseif value == "med" then - return SILE.length("4mu plus 2mu minus 4mu") * direction + return SILE.types.length("4mu plus 2mu minus 4mu") * direction elseif value == "thick" then - return SILE.length("5mu plus 5mu") * direction + return SILE.types.length("5mu plus 5mu") * direction end end - return SILE.length(value) + return SILE.types.length(value) end function elements.space:_init (width, height, depth) @@ -900,8 +900,8 @@ function elements.text:shape () for i = 1, #glyphs do table.insert(self.value.glyphString, glyphs[i].gid) end - self.width = SILE.length(0) - self.widthForSubscript = SILE.length(0) + self.width = SILE.types.length(0) + self.widthForSubscript = SILE.types.length(0) for i = #glyphs, 1, -1 do self.width = self.width + glyphs[i].glyphAdvance end @@ -912,13 +912,13 @@ function elements.text:shape () self.width = self.width + itCorr * self:getScaleDown() end for i = 1, #glyphs do - self.height = i == 1 and SILE.length(glyphs[i].height) or SILE.length(math.max(self.height:tonumber(), glyphs[i].height)) - self.depth = i == 1 and SILE.length(glyphs[i].depth) or SILE.length(math.max(self.depth:tonumber(), glyphs[i].depth)) + self.height = i == 1 and SILE.types.length(glyphs[i].height) or SILE.types.length(math.max(self.height:tonumber(), glyphs[i].height)) + self.depth = i == 1 and SILE.types.length(glyphs[i].depth) or SILE.types.length(math.max(self.depth:tonumber(), glyphs[i].depth)) end else - self.width = SILE.length(0) - self.height = SILE.length(0) - self.depth = SILE.length(0) + self.width = SILE.types.length(0) + self.height = SILE.types.length(0) + self.depth = SILE.types.length(0) end end @@ -970,9 +970,9 @@ function elements.text:stretchyReshape (depth, height) glyphs[1].height = dimen.height glyphs[1].depth = dimen.depth glyphs[1].glyphAdvance = dimen.glyphAdvance - self.width = SILE.length(dimen.glyphAdvance) - self.depth = SILE.length(dimen.depth) - self.height = SILE.length(dimen.height) + self.width = SILE.types.length(dimen.glyphAdvance) + self.depth = SILE.types.length(dimen.depth) + self.height = SILE.types.length(dimen.height) SILE.shaper:preAddNodes(glyphs, self.value) self.value.items = glyphs self.value.glyphString = {glyphs[1].gid} @@ -986,7 +986,7 @@ function elements.text:output (x, y, line) if isDisplayMode(self.mode) and self.atom == atomType.bigOperator and self.value.items[1].fontDepth then - compensatedY = SILE.length(y.length + self.value.items[1].depth - self.value.items[1].fontDepth) + compensatedY = SILE.types.length(y.length + self.value.items[1].depth - self.value.items[1].fontDepth) else compensatedY = y end @@ -1027,7 +1027,7 @@ function elements.fraction:shape () else widest, other = self.numerator, self.denominator end - widest.relX = SILE.length(0) + widest.relX = SILE.types.length(0) other.relX = (widest.width - other.width) / 2 self.width = widest.width -- Determine relative ordinates and height @@ -1036,24 +1036,24 @@ function elements.fraction:shape () self.axisHeight = constants.axisHeight * scaleDown self.ruleThickness = constants.fractionRuleThickness * scaleDown if isDisplayMode(self.mode) then - self.numerator.relY = -self.axisHeight - self.ruleThickness/2 - SILE.length(math.max( + self.numerator.relY = -self.axisHeight - self.ruleThickness/2 - SILE.types.length(math.max( (constants.fractionNumDisplayStyleGapMin*scaleDown + self.numerator.depth):tonumber(), constants.fractionNumeratorDisplayStyleShiftUp * scaleDown - self.axisHeight - self.ruleThickness/2)) else - self.numerator.relY = -self.axisHeight - self.ruleThickness/2 - SILE.length(math.max( + self.numerator.relY = -self.axisHeight - self.ruleThickness/2 - SILE.types.length(math.max( (constants.fractionNumeratorGapMin*scaleDown + self.numerator.depth):tonumber(), constants.fractionNumeratorShiftUp * scaleDown - self.axisHeight - self.ruleThickness/2)) end if isDisplayMode(self.mode) then - self.denominator.relY = -self.axisHeight + self.ruleThickness/2 + SILE.length(math.max( + self.denominator.relY = -self.axisHeight + self.ruleThickness/2 + SILE.types.length(math.max( (constants.fractionDenomDisplayStyleGapMin * scaleDown + self.denominator.height):tonumber(), constants.fractionDenominatorDisplayStyleShiftDown * scaleDown + self.axisHeight - self.ruleThickness/2)) else - self.denominator.relY = -self.axisHeight + self.ruleThickness/2 + SILE.length(math.max( + self.denominator.relY = -self.axisHeight + self.ruleThickness/2 + SILE.types.length(math.max( (constants.fractionDenominatorGapMin * scaleDown + self.denominator.height):tonumber(), constants.fractionDenominatorShiftDown * scaleDown @@ -1115,10 +1115,10 @@ function elements.table:_init (children, options) self.ncols = math.max(pl.utils.unpack(mapList(function(_, row) return #row.children end, self.children))) SU.debug("math", "self.ncols =", self.ncols) - self.rowspacing = self.options.rowspacing and SILE.length(self.options.rowspacing) - or SILE.length("7pt") - self.columnspacing = self.options.columnspacing and SILE.length(self.options.columnspacing) - or SILE.length("6pt") + self.rowspacing = self.options.rowspacing and SILE.types.length(self.options.rowspacing) + or SILE.types.length("7pt") + self.columnspacing = self.options.columnspacing and SILE.types.length(self.options.columnspacing) + or SILE.types.length("6pt") -- Pad rows that do not have enough cells by adding cells to the -- right. for i,row in ipairs(self.children) do @@ -1167,30 +1167,30 @@ function elements.table:shape () -- height (resp. depth) among its elements. Then we only need to add it to -- the table's height and center every cell vertically. for _,row in ipairs(self.children) do - row.height = SILE.length(0) - row.depth = SILE.length(0) + row.height = SILE.types.length(0) + row.depth = SILE.types.length(0) for _,cell in ipairs(row.children) do row.height = maxLength(row.height, cell.height) row.depth = maxLength(row.depth, cell.depth) end end - self.vertSize = SILE.length(0) + self.vertSize = SILE.types.length(0) for i, row in ipairs(self.children) do self.vertSize = self.vertSize + row.height + row.depth + - (i == self.nrows and SILE.length(0) or self.rowspacing) -- Spacing + (i == self.nrows and SILE.types.length(0) or self.rowspacing) -- Spacing end - local rowHeightSoFar = SILE.length(0) + local rowHeightSoFar = SILE.types.length(0) for i, row in ipairs(self.children) do row.relY = rowHeightSoFar + row.height - self.vertSize rowHeightSoFar = rowHeightSoFar + row.height + row.depth + - (i == self.nrows and SILE.length(0) or self.rowspacing) -- Spacing + (i == self.nrows and SILE.types.length(0) or self.rowspacing) -- Spacing end - self.width = SILE.length(0) - local thisColRelX = SILE.length(0) + self.width = SILE.types.length(0) + local thisColRelX = SILE.types.length(0) -- For every column... for i = 1,self.ncols do -- Determine its width - local columnWidth = SILE.length(0) + local columnWidth = SILE.types.length(0) for j = 1,self.nrows do if self.children[j].children[i].width > columnWidth then columnWidth = self.children[j].children[i].width @@ -1210,7 +1210,7 @@ function elements.table:shape () end end thisColRelX = thisColRelX + columnWidth + - (i == self.ncols and SILE.length(0) or self.columnspacing) -- Spacing + (i == self.ncols and SILE.types.length(0) or self.columnspacing) -- Spacing end self.width = thisColRelX -- Center myself vertically around the axis, and update relative Ys of rows accordingly diff --git a/packages/math/init.lua b/packages/math/init.lua index 8e7229fa2..761cc3ea5 100644 --- a/packages/math/init.lua +++ b/packages/math/init.lua @@ -54,7 +54,7 @@ function package.declareSettings (_) SILE.settings:declare({ parameter = "math.displayskip", type = "VGlue", - default = SILE.nodefactory.vglue("2ex plus 1pt") + default = SILE.types.node.vglue("2ex plus 1pt") }) end diff --git a/packages/pagebuilder-bestfit/init.lua b/packages/pagebuilder-bestfit/init.lua index 7819065dc..917c67543 100644 --- a/packages/pagebuilder-bestfit/init.lua +++ b/packages/pagebuilder-bestfit/init.lua @@ -11,7 +11,7 @@ function package:_init () -- Find last penalty local q = typesetter.state.outputQueue local lastpenalty = -1 - local cHeight = SILE.length() + local cHeight = SILE.types.length() for j = #q,1,-1 do if q[j].is_penalty and lastpenalty == -1 then lastpenalty = q[j].penalty diff --git a/packages/parallel/init.lua b/packages/parallel/init.lua index 70bc7f6d3..55c9ff605 100644 --- a/packages/parallel/init.lua +++ b/packages/parallel/init.lua @@ -76,7 +76,7 @@ from another package, responsible for correct initialization.]]) end -- Fixed leading here is obviously a bug, but n-way leading calculations -- get very complicated... - -- typesetterPool[frame].leadingFor = function() return SILE.nodefactory.vglue(SILE.settings:get("document.lineskip")) end + -- typesetterPool[frame].leadingFor = function() return SILE.types.node.vglue(SILE.settings:get("document.lineskip")) end local fontcommand = frame .. ":font" self:registerCommand(frame, function (_, _) -- \left ... SILE.typesetter = typesetterPool[frame] @@ -113,7 +113,7 @@ function package:registerCommands () self:registerCommand("sync", function (_, _) local anybreak = false - local maxheight = SILE.length() + local maxheight = SILE.types.length() SU.debug("parallel", "Trying a sync") allTypesetters(function (_, typesetter) SU.debug("parallel", "Leaving hmode on", typesetter.id) @@ -133,7 +133,7 @@ function package:registerCommands () end allTypesetters(function (frame, typesetter) - calculations[frame].heightOfNewMaterial = SILE.length() + calculations[frame].heightOfNewMaterial = SILE.types.length() for i = calculations[frame].mark + 1, #typesetter.state.outputQueue do local thisHeight = typesetter.state.outputQueue[i].height + typesetter.state.outputQueue[i].depth calculations[frame].heightOfNewMaterial = calculations[frame].heightOfNewMaterial + thisHeight diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index fbe58658b..d8af25e96 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -30,9 +30,9 @@ function package:registerCommands () local level = SU.cast("integer", options.level or 1) SILE.typesetter:pushHbox({ value = nil, - height = SILE.measurement(0), - width = SILE.measurement(0), - depth = SILE.measurement(0), + height = SILE.types.measurement(0), + width = SILE.types.measurement(0), + depth = SILE.types.measurement(0), outputYourself = function () SILE.outputter:setBookmark(dest, title, level) end @@ -45,7 +45,7 @@ function package:registerCommands () local dest = SU.required(options, "dest", "pdf:link") local external = SU.boolean(options.external, false) local borderwidth = options.borderwidth and SU.cast("measurement", options.borderwidth):tonumber() or 0 - local bordercolor = SILE.color(options.bordercolor or "blue") + local bordercolor = SILE.types.color(options.bordercolor or "blue") local borderoffset = SU.cast("measurement", options.borderoffset or "1pt"):tonumber() local opts = { external = external, diff --git a/packages/pdfstructure/init.lua b/packages/pdfstructure/init.lua index 4749993b5..517517f40 100644 --- a/packages/pdfstructure/init.lua +++ b/packages/pdfstructure/init.lua @@ -128,9 +128,9 @@ function package:registerCommands () end SILE.typesetter:pushHbox({ value = nil, - height = SILE.measurement(0), - width = SILE.measurement(0), - depth = SILE.measurement(0), + height = SILE.types.measurement(0), + width = SILE.types.measurement(0), + depth = SILE.types.measurement(0), outputYourself = function (_, _, _) SILE.outputter:drawRaw (content[1]) end diff --git a/packages/pullquote/init.lua b/packages/pullquote/init.lua index 251b1c0ee..fa82f5f2c 100644 --- a/packages/pullquote/init.lua +++ b/packages/pullquote/init.lua @@ -13,7 +13,7 @@ local typesetMark = function (open, setback, scale, color, mark) SILE.typesetter:pushGlue({ width = -setback }) SILE.call("rebox", { width = setback, height = 0 }, { mark }) else - SILE.typesetter:pushGlue(SILE.nodefactory.hfillglue()) + SILE.typesetter:pushGlue(SILE.types.node.hfillglue()) local hbox = SILE.typesetter:makeHbox({ mark }) -- for measuring SILE.typesetter:pushGlue({ width = setback - hbox.width }) SILE.call("rebox", { width = hbox.width, height = 0 }, { mark }) @@ -52,8 +52,8 @@ function package:registerCommands () SILE.settings:temporarily(function () SILE.call("pullquote:font") local setback = SU.cast("length", options.setback or "2em"):absolute() - SILE.settings:set("document.rskip", SILE.nodefactory.glue(setback)) - SILE.settings:set("document.lskip", SILE.nodefactory.glue(setback)) + SILE.settings:set("document.rskip", SILE.types.node.glue(setback)) + SILE.settings:set("document.lskip", SILE.types.node.glue(setback)) SILE.call("noindent") typesetMark(true, setback, scale, color, "“") SILE.call("indent") diff --git a/packages/rebox/init.lua b/packages/rebox/init.lua index ce75c7086..eba054834 100644 --- a/packages/rebox/init.lua +++ b/packages/rebox/init.lua @@ -7,9 +7,9 @@ function package:registerCommands () self:registerCommand("rebox", function (options, content) local hbox, hlist = SILE.typesetter:makeHbox(content) - if options.width then hbox.width = SILE.length(options.width) end - if options.height then hbox.height = SILE.length(options.height) end - if options.depth then hbox.depth = SILE.length(options.depth) end + if options.width then hbox.width = SILE.types.length(options.width) end + if options.height then hbox.height = SILE.types.length(options.height) end + if options.depth then hbox.depth = SILE.types.length(options.depth) end if options.phantom then hbox.outputYourself = function (node, typesetter, line) typesetter.frame:advanceWritingDirection(node:scaledWidth(line)) diff --git a/packages/retrograde/init.lua b/packages/retrograde/init.lua index e3bb81ef4..c678f36d5 100644 --- a/packages/retrograde/init.lua +++ b/packages/retrograde/init.lua @@ -22,9 +22,9 @@ package.default_settings = { } local function _v14_aligns (content) - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0)) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) + SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0)) SILE.process(content) SILE.call("par") end @@ -37,8 +37,8 @@ package.shim_commands = { SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected") end SILE.settings:temporarily(function () - SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) - SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) + SILE.settings:set("document.rskip", SILE.types.node.hfillglue()) + SILE.settings:set("document.lskip", SILE.types.node.hfillglue()) _v14_aligns(content) end) end @@ -46,7 +46,7 @@ package.shim_commands = { ["raggedright"] = function (_) return function (_, content) SILE.settings:temporarily(function () - SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) + SILE.settings:set("document.rskip", SILE.types.node.hfillglue()) _v14_aligns(content) end) end @@ -54,7 +54,7 @@ package.shim_commands = { ["raggedleft"] = function (_) return function (_, content) SILE.settings:temporarily(function () - SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) + SILE.settings:set("document.lskip", SILE.types.node.hfillglue()) _v14_aligns(content) end) end diff --git a/packages/rotate/init.lua b/packages/rotate/init.lua index 6aad18cca..50abd5931 100644 --- a/packages/rotate/init.lua +++ b/packages/rotate/init.lua @@ -97,7 +97,7 @@ function package:registerCommands () depth = 0.5*(h-h*ct-w*st) end depth = -depth - if depth < SILE.length(0) then depth = SILE.length(0) end + if depth < SILE.types.length(0) then depth = SILE.types.length(0) end SILE.typesetter:pushHbox({ value = { orig = origbox, theta = theta}, height = height, diff --git a/packages/ruby/init.lua b/packages/ruby/init.lua index 98d64f0ca..1598e4bc6 100644 --- a/packages/ruby/init.lua +++ b/packages/ruby/init.lua @@ -40,14 +40,14 @@ function package.declareSettings (_) SILE.settings:declare({ parameter = "ruby.height", type = "measurement", - default = SILE.measurement("1zw"), + default = SILE.types.measurement("1zw"), help = "Vertical offset between the ruby and the main text" }) SILE.settings:declare({ parameter = "ruby.latinspacer", type = "glue", - default = SILE.nodefactory.glue("0.25em"), + default = SILE.types.node.glue("0.25em"), help = "Glue added between consecutive Latin ruby" }) @@ -103,17 +103,17 @@ function package:registerCommands () if cbox:lineContribution() > rubybox:lineContribution() then SU.debug("ruby", "Base is longer, offsetting ruby to fit") -- This is actually the offset against the base - rubybox.width = SILE.length(cbox:lineContribution() - rubybox:lineContribution())/2 + rubybox.width = SILE.types.length(cbox:lineContribution() - rubybox:lineContribution())/2 else local diff = rubybox:lineContribution() - cbox:lineContribution() - local to_insert = SILE.length(diff / 2) + local to_insert = SILE.types.length(diff / 2) SU.debug("ruby", "Ruby is longer, inserting", to_insert, "either side of base") cbox.width = rubybox:lineContribution() rubybox.height = 0 rubybox.width = 0 -- add spaces at beginning and end - table.insert(cbox.value, 1, SILE.nodefactory.glue(to_insert)) - table.insert(cbox.value, SILE.nodefactory.glue(to_insert)) + table.insert(cbox.value, 1, SILE.types.node.glue(to_insert)) + table.insert(cbox.value, SILE.types.node.glue(to_insert)) end SILE.scratch.lastRubyBox = rubybox SILE.scratch.lastRubyText = reading diff --git a/packages/rules/init.lua b/packages/rules/init.lua index 3366f6021..229840f57 100644 --- a/packages/rules/init.lua +++ b/packages/rules/init.lua @@ -27,9 +27,9 @@ end -- \hfill (from the "plain" class) and \leaders (from the "leaders" package) use glues, -- so we behave the same for hrulefill. -local hrulefillglue = pl.class(SILE.nodefactory.hfillglue) -hrulefillglue.raise = SILE.measurement() -hrulefillglue.thickness = SILE.measurement("0.2pt") +local hrulefillglue = pl.class(SILE.types.node.hfillglue) +hrulefillglue.raise = SILE.types.measurement() +hrulefillglue.thickness = SILE.types.measurement("0.2pt") function hrulefillglue:outputYourself (typesetter, line) local outputWidth = SU.rationWidth(self.width, self.width, line.ratio):tonumber() @@ -99,7 +99,7 @@ function package:registerCommands () SILE.typesetter:pushExplicitGlue(hrulefillglue({ raise = raise, - thickness = thickness or SILE.measurement("0.2pt"), + thickness = thickness or SILE.types.measurement("0.2pt"), })) end, "Add a huge horizontal hrule glue") diff --git a/packages/simpletable/init.lua b/packages/simpletable/init.lua index f762ca7ac..f92af0892 100644 --- a/packages/simpletable/init.lua +++ b/packages/simpletable/init.lua @@ -52,7 +52,7 @@ function package:_init (options) local tbl = {} table.insert(SILE.scratch.simpletable.tables, tbl) SILE.settings:temporarily(function () - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) SILE.process(content) end) SILE.typesetter:leaveHmode() @@ -75,7 +75,7 @@ function package:_init (options) until not stuffInThisColumn -- Now set each row at the given column width SILE.settings:temporarily(function () - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) for row = 1, #tbl do for colno = 1, #(tbl[row]) do local hbox = tbl[row][colno].hbox diff --git a/packages/specimen/init.lua b/packages/specimen/init.lua index 83f631ac6..a9203f2fb 100644 --- a/packages/specimen/init.lua +++ b/packages/specimen/init.lua @@ -16,8 +16,8 @@ function package:registerCommands () for i = 1 , maxg - 1 do local wd = metrics.glyphwidth(i, face) SILE.typesetter:pushHbox({ - height= SILE.length(1.2 * fontoptions.size), - width= SILE.length(wd * fontoptions.size), + height= SILE.types.length(1.2 * fontoptions.size), + width= SILE.types.length(wd * fontoptions.size), depth= 0, value= { options = fontoptions, glyphString = { i } }, }) diff --git a/packages/svg/init.lua b/packages/svg/init.lua index 617c033a1..91a162ee4 100644 --- a/packages/svg/init.lua +++ b/packages/svg/init.lua @@ -18,8 +18,8 @@ local _drawSVG = function (svgdata, width, height, density, drop) elseif height then scalefactor = height:tonumber() / svgheight end - width = SILE.measurement(svgwidth * scalefactor) - height = SILE.measurement(svgheight * scalefactor) + width = SILE.types.measurement(svgwidth * scalefactor) + height = SILE.types.measurement(svgheight * scalefactor) scalefactor = scalefactor * density / 72 SILE.typesetter:pushHbox({ value = nil, diff --git a/packages/tableofcontents/init.lua b/packages/tableofcontents/init.lua index 5d2f08129..38f4ac7b0 100644 --- a/packages/tableofcontents/init.lua +++ b/packages/tableofcontents/init.lua @@ -140,7 +140,7 @@ function package:registerCommands () self:registerCommand("tableofcontents:item", function (options, content) SILE.settings:temporarily(function () - SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue()) + SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue()) SILE.call("tableofcontents:level" .. options.level .. "item", { }, _linkWrapper(options.link, function () diff --git a/packages/tate/init.lua b/packages/tate/init.lua index cae802fe5..eb8605039 100644 --- a/packages/tate/init.lua +++ b/packages/tate/init.lua @@ -25,21 +25,21 @@ end local outputLatinInTate = function (self, typesetter, line) -- My baseline moved - typesetter.frame:advanceWritingDirection(SILE.measurement("-0.5zw")) - typesetter.frame:advancePageDirection(SILE.measurement("0.25zw")) + typesetter.frame:advanceWritingDirection(SILE.types.measurement("-0.5zw")) + typesetter.frame:advancePageDirection(SILE.types.measurement("0.25zw")) local vorigin = -typesetter.frame.state.cursorY self:oldOutputYourself(typesetter,line) typesetter.frame.state.cursorY = -vorigin typesetter.frame:advanceWritingDirection(self:lineContribution()) -- My baseline moved - typesetter.frame:advanceWritingDirection(SILE.measurement("0.5zw") ) - typesetter.frame:advancePageDirection(-SILE.measurement("0.25zw")) + typesetter.frame:advanceWritingDirection(SILE.types.measurement("0.5zw") ) + typesetter.frame:advancePageDirection(-SILE.types.measurement("0.25zw")) end local outputTateChuYoko = function (self, typesetter, line) -- My baseline moved - local em = SILE.measurement("1zw") + local em = SILE.types.measurement("1zw") typesetter.frame:advanceWritingDirection(-em + em/4 - self:lineContribution()/2) typesetter.frame:advancePageDirection(2*self.height - self.width/2) self:oldOutputYourself(typesetter,line) @@ -83,7 +83,7 @@ function package:registerCommands () end) SILE.typesetter = oldT SILE.typesetter:pushGlue({ - width = SILE.length("0.5zw", "0.25zw", "0.25zw"):absolute() + width = SILE.types.length("0.5zw", "0.25zw", "0.25zw"):absolute() }) for i = 1, #nodes do if SILE.typesetter.frame:writingDirection() ~= "TTB" or nodes[i].is_glue then @@ -107,7 +107,7 @@ function package:registerCommands () self:registerCommand("tate-chu-yoko", function (_, content) if SILE.typesetter.frame:writingDirection() ~= "TTB" then return SILE.process(content) end -- SILE.typesetter:pushGlue({ - -- width = SILE.length.new({length = SILE.toPoints("0.5zw"), + -- width = SILE.types.length.new({length = SILE.toPoints("0.5zw"), -- stretch = SILE.toPoints("0.25zw"), -- shrink = SILE.toPoints("0.25zw") -- }) @@ -124,7 +124,7 @@ function package:registerCommands () end) -- SILE.typesetter:pushGlue({ - -- width = SILE.length.new({length = SILE.toPoints("0.5zw"), + -- width = SILE.types.length.new({length = SILE.toPoints("0.5zw"), -- stretch = SILE.toPoints("0.25zw"), -- shrink = SILE.toPoints("0.25zw") -- }) diff --git a/packages/verbatim/init.lua b/packages/verbatim/init.lua index 19c630df3..1090b2f2c 100644 --- a/packages/verbatim/init.lua +++ b/packages/verbatim/init.lua @@ -17,12 +17,12 @@ function package:registerCommands () SILE.settings:temporarily(function() SILE.settings:set("typesetter.parseppattern", "\n") SILE.settings:set("typesetter.obeyspaces", true) - SILE.settings:set("document.rskip", SILE.nodefactory.glue("0 plus 10000pt")) - SILE.settings:set("document.parindent", SILE.nodefactory.glue("0")) - SILE.settings:set("document.baselineskip", SILE.nodefactory.vglue("0")) - SILE.settings:set("document.lineskip", SILE.nodefactory.vglue("2pt")) + SILE.settings:set("document.rskip", SILE.types.node.glue("0 plus 10000pt")) + SILE.settings:set("document.parindent", SILE.types.node.glue("0")) + SILE.settings:set("document.baselineskip", SILE.types.node.vglue("0")) + SILE.settings:set("document.lineskip", SILE.types.node.vglue("2pt")) SILE.call("verbatim:font") - SILE.settings:set("document.spaceskip", SILE.length("1spc")) + SILE.settings:set("document.spaceskip", SILE.types.length("1spc")) SILE.settings:set("shaper.variablespaces", false) SILE.settings:set("document.language", "und") SILE.process(content) diff --git a/pagebuilders/base.lua b/pagebuilders/base.lua index 65dc083d4..1c2da15c2 100644 --- a/pagebuilders/base.lua +++ b/pagebuilders/base.lua @@ -10,7 +10,7 @@ function pagebuilder:_init () end function pagebuilder.collateVboxes (_, vboxlist) - local output = SILE.nodefactory.vbox() + local output = SILE.types.node.vbox() output:append(vboxlist) return output end @@ -27,7 +27,7 @@ function pagebuilder:findBestBreak (options) local restart = options.restart or false local force = options.force or false local i = 0 - local totalHeight = SILE.length() + local totalHeight = SILE.types.length() local bestBreak = nil local started = false if restart and restart.target == target then diff --git a/pagebuilders/grid.lua b/pagebuilders/grid.lua index 1f038949d..1659761ec 100644 --- a/pagebuilders/grid.lua +++ b/pagebuilders/grid.lua @@ -11,7 +11,7 @@ function pagebuilder.findBestBreak (_, options) local vboxlist = SU.required(options, "vboxlist", "in findBestBreak") local target = SU.required(options, "target", "in findBestBreak") local i = 0 - local totalHeight = SILE.length() + local totalHeight = SILE.types.length() local bestBreak = 0 SU.debug("pagebuilder", "Page builder for frame", SILE.typesetter.frame.id, "called with", #vboxlist, "nodes,", target) if SU.debugging("vboxes") then diff --git a/shapers/base.lua b/shapers/base.lua index d0f347449..6c67694f3 100644 --- a/shapers/base.lua +++ b/shapers/base.lua @@ -30,7 +30,7 @@ local function shapespace (spacewidth) local length = spacewidth * SILE.settings:get("shaper.spaceenlargementfactor") local stretch = absoluteSpaceWidth * SILE.settings:get("shaper.spacestretchfactor") local shrink = absoluteSpaceWidth * SILE.settings:get("shaper.spaceshrinkfactor") - return SILE.length(length, stretch, shrink) + return SILE.types.length(length, stretch, shrink) end local shaper = pl.class() @@ -55,7 +55,7 @@ function shaper:measureSpace (options) local items, width = self:shapeToken(" ", options) if not width and not items[1] then SU.warn("Could not measure the width of a space") - return SILE.length() + return SILE.types.length() end return shapespace(width and width.length or items[1].width) end @@ -130,14 +130,14 @@ function shaper:formNnode (contents, token, options) end self:addShapedGlyphToNnodeValue(nnodeValue, glyph) end - table.insert(nnodeContents, SILE.nodefactory.hbox({ + table.insert(nnodeContents, SILE.types.node.hbox({ depth = totalDepth, height = totalHeight, misfit = misfit, - width = SILE.length(totalWidth), + width = SILE.types.length(totalWidth), value = nnodeValue })) - return SILE.nodefactory.nnode({ + return SILE.types.node.nnode({ nodes = nnodeContents, text = token, misfit = misfit, @@ -153,7 +153,7 @@ function shaper.makeSpaceNode (_, options, item) else width = SILE.shaper:measureSpace(options) end - return SILE.nodefactory.glue(width) + return SILE.types.node.glue(width) end function shaper.debugVersions (_) end diff --git a/shapers/fallback.lua b/shapers/fallback.lua index 9c9e4bf84..be0a43017 100644 --- a/shapers/fallback.lua +++ b/shapers/fallback.lua @@ -57,7 +57,7 @@ function fallbackQueue:addRun (offset, start) end) local options = self:nextFallback() if not options then return false end - options.size = SILE.measurement(options.size):tonumber() + options.size = SILE.types.measurement(options.size):tonumber() self.pending = { options = options, offset = offset, diff --git a/shapers/harfbuzz.lua b/shapers/harfbuzz.lua index b65116b42..ca6d78314 100644 --- a/shapers/harfbuzz.lua +++ b/shapers/harfbuzz.lua @@ -82,7 +82,7 @@ function shaper.getFace (opts) if not face or not face.filename then SU.error("Couldn't find face '"..opts.family.."'") end if SILE.makeDeps then SILE.makeDeps:add(face.filename) end face.variations = opts.variations or "" - face.pointsize = ("%g"):format(SILE.measurement(opts.size):tonumber()) + face.pointsize = ("%g"):format(SILE.types.measurement(opts.size):tonumber()) face.weight = ("%d"):format(opts.weight or 0) -- Try instanciating the font, hb.instanciate() will return nil if it is not diff --git a/shapers/pango.lua b/shapers/pango.lua index 8c207d06c..6120b2ab4 100644 --- a/shapers/pango.lua +++ b/shapers/pango.lua @@ -53,7 +53,7 @@ function shaper:shapeToken (text, options) local pal = SILE.font.cache(options, self.getFace) local rv = {} local items = pangolgi.itemize(pango_context, text, 0, string.len(text), pal, nil) - local twidth = SILE.length() + local twidth = SILE.types.length() for i = 1,#items do local item = items[i] local pgs = _shape(text, item) -- local text = string.sub(text,1+items[i].offset, items[i].length) diff --git a/spec/break_spec.lua b/spec/break_spec.lua index b86d4ddb4..9efd22729 100644 --- a/spec/break_spec.lua +++ b/spec/break_spec.lua @@ -7,68 +7,68 @@ describe("SILE.linebreak", function() -- This is a list of boxes, with their dimensions, extracted from a specially hacked version of TeX. local hlist = {} - local function nnode(spec) table.insert(hlist, SILE.nodefactory.nnode(spec)) end - local function glue(spec) table.insert(hlist, SILE.nodefactory.glue(spec)) end + local function nnode(spec) table.insert(hlist, SILE.types.node.nnode(spec)) end + local function glue(spec) table.insert(hlist, SILE.types.node.glue(spec)) end nnode({ text ="To", height = 6.15234, depth = 0.14647, width = 10.14648 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="Sherlock", height = 7.56836, depth = 0.14647, width = 35.82031 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="Holmes", height = 7.56836, depth = 0.14647, width = 30.79102 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="she", height = 7.56836, depth = 0.14647, width = 13.99902 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="is", height = 6.6211, depth = 0.14647, width = 6.57227 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="always", height = 7.56836, depth = 2.44139, width = 27.59766 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="the", height = 7.56836, depth = 0.14647, width = 13.5791 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="woman", height = 4.6875, depth = 0.1953, width = 32.37305 }) - glue({ width = SILE.length({ length = 2.93619, stretch = 3.30322, shrink = 0.24467 }) }) + glue({ width = SILE.types.length({ length = 2.93619, stretch = 3.30322, shrink = 0.24467 }) }) nnode({ text ="I", height = 6.15234, depth = 0.0, width = 2.97852 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.09996, shrink = 0.73477 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.09996, shrink = 0.73477 }) }) nnode({ text ="have", height = 7.56836, depth = 0.14647, width = 19.26758 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="seldom", height = 7.56836, depth = 0.14647, width = 29.45313 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="heard", height = 7.56836, depth = 0.14647, width = 23.78906 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="him", height = 7.56836, depth = 0.0, width = 16.25977 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="mention", height = 6.6211, depth = 0.14647, width = 34.86816 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="her", height = 7.56836, depth = 0.14647, width = 14.09668 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="under", height = 7.56836, depth = 0.14647, width = 24.59473 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="any", height = 4.6875, depth = 2.44139, width = 15.03906 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="other", height = 7.56836, depth = 0.14647, width = 22.56836 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="name", height = 4.6875, depth = 0.1953, width = 25.04883 }) - glue({ width = SILE.length({ length = 2.93619, stretch = 3.30322, shrink = 0.24467 }) }) + glue({ width = SILE.types.length({ length = 2.93619, stretch = 3.30322, shrink = 0.24467 }) }) nnode({ text ="In", height = 6.15234, depth = 0.0, width = 8.4961 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="his", height = 7.56836, depth = 0.14647, width = 12.08984 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="eyes", height = 4.6875, depth = 2.44139, width = 17.83691 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="she", height = 7.56836, depth = 0.14647, width = 13.99902 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="eclipses", height = 7.56836, depth = 2.34373, width = 31.9043 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="and", height = 7.56836, depth = 0.14647, width = 15.30762 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="predominates", height = 7.56836, depth = 2.34373, width = 56.7334 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="the", height = 7.56836, depth = 0.14647, width = 13.5791 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="whole", height = 7.56836, depth = 0.14647, width = 24.93652 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="of", height = 7.56836, depth = 0.14647, width = 8.13965 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="her", height = 7.56836, depth = 0.14647, width = 14.09668 }) - glue({ width = SILE.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) + glue({ width = SILE.types.length({ length = 2.20215, stretch = 1.10107, shrink = 0.73404 }) }) nnode({ text ="sex.", height = 4.6875, depth = 0.1953, width = 15.6543 }) it("should sleuth the right break point", function() diff --git a/spec/measurements_spec.lua b/spec/measurements_spec.lua index e4b9eec16..e0341827b 100644 --- a/spec/measurements_spec.lua +++ b/spec/measurements_spec.lua @@ -31,7 +31,7 @@ describe("The measurement convertor", function() it("should exist", function() assert.is.truthy(SILE.toPoints) end) - it("should work for points, units explicit", function () assert.is.equal(20, SILE.measurement(20, "pt"):tonumber()) end) - it("should work for points, units implicit", function () assert.is.equal(20, SILE.measurement("20pt"):tonumber()) end) - it("should work for inches, units implicit", function () assert.is.equal(14.4, SILE.measurement("0.2in"):tonumber()) end) + it("should work for points, units explicit", function () assert.is.equal(20, SILE.types.measurement(20, "pt"):tonumber()) end) + it("should work for points, units implicit", function () assert.is.equal(20, SILE.types.measurement("20pt"):tonumber()) end) + it("should work for inches, units implicit", function () assert.is.equal(14.4, SILE.types.measurement("0.2in"):tonumber()) end) end) diff --git a/spec/shaper_spec.lua b/spec/shaper_spec.lua index bfb1211ed..22b981a4d 100644 --- a/spec/shaper_spec.lua +++ b/spec/shaper_spec.lua @@ -8,10 +8,10 @@ describe("SILE.shapers.base", function() SILE.settings:set("shaper.variablespaces", true) SILE.settings:set("shaper.spacestretchfactor", 2) SILE.settings:set("shaper.spaceshrinkfactor", 2) - local negative_glue = SILE.nodefactory.glue("-4pt") + local negative_glue = SILE.types.node.glue("-4pt") local space = SILE.shaper:makeSpaceNode({}, negative_glue) - assert.is.truthy(space.width.stretch > SILE.measurement(0)) - assert.is.truthy(space.width.shrink > SILE.measurement(0)) + assert.is.truthy(space.width.stretch > SILE.types.measurement(0)) + assert.is.truthy(space.width.shrink > SILE.types.measurement(0)) end) end) diff --git a/tests/bug-255.sil b/tests/bug-255.sil index 3ea12f0d8..66703138f 100644 --- a/tests/bug-255.sil +++ b/tests/bug-255.sil @@ -5,7 +5,7 @@ SILE.registerCommand("donothing", function (options, content) SILE.settings:pushState() SILE.settings:temporarily(function () - SILE.settings:set("document.lskip", SILE.nodefactory.glue("0pt")) + SILE.settings:set("document.lskip", SILE.types.node.glue("0pt")) SILE.process(content) SILE.call("par") end) diff --git a/tests/bug-255b.sil b/tests/bug-255b.sil index 707bedd3e..6c0ff4af8 100644 --- a/tests/bug-255b.sil +++ b/tests/bug-255b.sil @@ -5,8 +5,8 @@ SILE.registerCommand("donothing", function(o,c) SILE.settings:pushState() SILE.settings:temporarily(function() - SILE.settings:set("document.lskip", SILE.nodefactory.glue("20pt")) - SILE.settings:set("document.rskip", SILE.nodefactory.glue("20pt")) + SILE.settings:set("document.lskip", SILE.types.node.glue("20pt")) + SILE.settings:set("document.rskip", SILE.types.node.glue("20pt")) SILE.process(c) SILE.call("par") end) diff --git a/tests/bug-303.sil b/tests/bug-303.sil index c9ca7ec51..f52ba7f43 100644 --- a/tests/bug-303.sil +++ b/tests/bug-303.sil @@ -4,10 +4,10 @@ SILE.registerCommand("poetry", function(options, content) SILE.settings:temporarily(function() SILE.typesetter:leaveHmode() - SILE.settings:set("document.lskip", SILE.nodefactory.glue("1em")) - SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) - SILE.settings:set("current.parindent", SILE.nodefactory.glue()) - SILE.settings:set("document.parindent", SILE.nodefactory.glue()) + SILE.settings:set("document.lskip", SILE.types.node.glue("1em")) + SILE.settings:set("document.rskip", SILE.types.node.hfillglue()) + SILE.settings:set("current.parindent", SILE.types.node.glue()) + SILE.settings:set("document.parindent", SILE.types.node.glue()) SILE.process(content) SILE.call("par") end) diff --git a/tests/classes/testsidenote.lua b/tests/classes/testsidenote.lua index bcc923680..cc9bdb81e 100644 --- a/tests/classes/testsidenote.lua +++ b/tests/classes/testsidenote.lua @@ -13,9 +13,9 @@ function testsidenote:_init (options) self:loadPackage("insertions") self:loadPackage("footnotes") self:initInsertionClass("footnote", { - maxHeight = SILE.length("75%ph"):absolute(), - topBox = SILE.nodefactory.zerovglue(), - interInsertionSkip = SILE.length("1ex"), + maxHeight = SILE.types.length("75%ph"):absolute(), + topBox = SILE.types.node.zerovglue(), + interInsertionSkip = SILE.types.length("1ex"), insertInto = { frame = "sidenotes", ratio = 0 }, stealFrom = { }, }) diff --git a/tests/footnote-skip.sil b/tests/footnote-skip.sil index 4babbb28d..3d50961c6 100644 --- a/tests/footnote-skip.sil +++ b/tests/footnote-skip.sil @@ -3,8 +3,8 @@ \use[module=packages.lorem] \use[module=packages.rules] \begin{script} -SILE.scratch.insertions.classes.footnote.topSkip = SILE.length("5pt") -SILE.scratch.insertions.classes.footnote.interInsertionSkip = SILE.length("24pt") +SILE.scratch.insertions.classes.footnote.topSkip = SILE.types.length("5pt") +SILE.scratch.insertions.classes.footnote.interInsertionSkip = SILE.types.length("24pt") \end{script} \lorem[words=50]\footnote{\hrule[width=2pt, height=19.82421875pt]} diff --git a/tests/frametricks.sil b/tests/frametricks.sil index 9415b10eb..7ec8628af 100644 --- a/tests/frametricks.sil +++ b/tests/frametricks.sil @@ -4,11 +4,11 @@ \makecolumns[columns=2] \font[size=15pt] \set[parameter=document.baselineskip,value=3ex] -\script{SU.debug("float", "Frame Pre:", SILE.length("100%fw"):absolute())} +\script{SU.debug("float", "Frame Pre:", SILE.types.length("100%fw"):absolute())} \begin{raggedright} \float[rightboundary=5pt,bottomboundary=1ex]{\font[size=54pt]{T}}o Sherlock Holmes she is always \em{the woman}. I have seldom heard him mention her under any other name. In his eyes she eclipses and predominates the whole of her sex. It was not that he felt any emotion akin to love for Irene Adler. All emotions, and that one particularly, were abhorrent to his cold, precise but admirably balanced mind. He was, I take it, the most perfect reasoning and observing machine that the world has seen, but as a lover he would have placed himself in a false position. -\script{SU.debug("float", "Frame Post:", SILE.length("100%fw"):absolute())} +\script{SU.debug("float", "Frame Post:", SILE.types.length("100%fw"):absolute())} He never spoke of the softer passions, save with a gibe and a sneer. They were admirable things for the observer -- excellent for drawing the veil from men's motives and actions. But for the trained teasoner to admit such intru \end{raggedright} diff --git a/tests/inc/bug-337.lua b/tests/inc/bug-337.lua index 82e9dad7f..f15d10d41 100644 --- a/tests/inc/bug-337.lua +++ b/tests/inc/bug-337.lua @@ -41,8 +41,8 @@ end function package:registerCommands () self.class:registerCommand("printPageInPoints", function() - local w = SILE.measurement("100%pw"):tonumber() - local h = SILE.measurement("100%ph"):tonumber() + local w = SILE.types.measurement("100%pw"):tonumber() + local h = SILE.types.measurement("100%ph"):tonumber() SILE.typesetter:typeset(("%.0fpt × %.0fpt"):format(w, h)) end) diff --git a/types/color_spec.lua b/types/color_spec.lua index ff7b29ee8..74591c7fc 100644 --- a/types/color_spec.lua +++ b/types/color_spec.lua @@ -2,7 +2,7 @@ SILE = require("core.sile") SU.warn = function () end describe("The color parser", function() - local parse = SILE.color + local parse = SILE.types.color local rebecca = { b = 0.6, g = 0.2, diff --git a/types/length.lua b/types/length.lua index ede6dcb4b..a1e6d21a0 100644 --- a/types/length.lua +++ b/types/length.lua @@ -12,21 +12,21 @@ return pl.class({ _init = function (self, spec, stretch, shrink) if stretch or shrink then - self.length = SILE.measurement(spec or 0) - self.stretch = SILE.measurement(stretch or 0) - self.shrink = SILE.measurement(shrink or 0) + self.length = SILE.types.measurement(spec or 0) + self.stretch = SILE.types.measurement(stretch or 0) + self.shrink = SILE.types.measurement(shrink or 0) elseif type(spec) == "number" then - self.length = SILE.measurement(spec) + self.length = SILE.types.measurement(spec) elseif SU.type(spec) == "measurement" then self.length = spec elseif SU.type(spec) == "glue" then - self.length = SILE.measurement(spec.width.length or 0) - self.stretch = SILE.measurement(spec.width.stretch or 0) - self.shrink = SILE.measurement(spec.width.shrink or 0) + self.length = SILE.types.measurement(spec.width.length or 0) + self.stretch = SILE.types.measurement(spec.width.stretch or 0) + self.shrink = SILE.types.measurement(spec.width.shrink or 0) elseif type(spec) == "table" then - self.length = SILE.measurement(spec.length or 0) - self.stretch = SILE.measurement(spec.stretch or 0) - self.shrink = SILE.measurement(spec.shrink or 0) + self.length = SILE.types.measurement(spec.length or 0) + self.stretch = SILE.types.measurement(spec.stretch or 0) + self.shrink = SILE.types.measurement(spec.shrink or 0) elseif type(spec) == "string" then local amount = tonumber(spec) if type(amount) == "number" then @@ -37,13 +37,13 @@ return pl.class({ self:_init(parsed) end end - if not self.length then self.length = SILE.measurement() end - if not self.stretch then self.stretch = SILE.measurement() end - if not self.shrink then self.shrink = SILE.measurement() end + if not self.length then self.length = SILE.types.measurement() end + if not self.stretch then self.stretch = SILE.types.measurement() end + if not self.shrink then self.shrink = SILE.types.measurement() end end, absolute = function (self) - return SILE.length(self.length:tonumber(), self.stretch:tonumber(), self.shrink:tonumber()) + return SILE.types.length(self.length:tonumber(), self.stretch:tonumber(), self.shrink:tonumber()) end, negate = function (self) @@ -59,23 +59,23 @@ return pl.class({ end, new = function (_) - SU.deprecated("SILE.length.new", "SILE.length", "0.10.0") + SU.deprecated("SILE.length.new", "SILE.types.length", "0.10.0") end, make = function (_) - SU.deprecated("SILE.length.make", "SILE.length", "0.10.0") + SU.deprecated("SILE.length.make", "SILE.types.length", "0.10.0") end, parse = function (_) - SU.deprecated("SILE.length.parse", "SILE.length", "0.10.0") + SU.deprecated("SILE.length.parse", "SILE.types.length", "0.10.0") end, fromLengthOrNumber = function (_, _) - SU.deprecated("SILE.length.fromLengthOrNumber", "SILE.length", "0.10.0") + SU.deprecated("SILE.length.fromLengthOrNumber", "SILE.types.length", "0.10.0") end, __index = function (_, key) - SU.deprecated("SILE.length." .. key, "SILE.length", "0.10.0") + SU.deprecated("SILE.length." .. key, "SILE.types.length", "0.10.0") end, __tostring = function (self) @@ -88,12 +88,12 @@ return pl.class({ __add = function (self, other) if type(self) == "number" then self, other = other, self end other = SU.cast("length", other) - return SILE.length(self.length + other.length, + return SILE.types.length(self.length + other.length, self.stretch + other.stretch, self.shrink + other.shrink) end, - -- See usage comments on SILE.measurement:___add() + -- See usage comments on SILE.types.measurement:___add() ___add = function (self, other) if SU.type(other) ~= "length" then self.length:___add(other) @@ -106,7 +106,7 @@ return pl.class({ end, __sub = function (self, other) - local result = SILE.length(self) + local result = SILE.types.length(self) other = SU.cast("length", other) result.length = result.length - other.length result.stretch = result.stretch - other.stretch @@ -114,7 +114,7 @@ return pl.class({ return result end, - -- See usage comments on SILE.measurement:___add() + -- See usage comments on SILE.types.measurement:___add() ___sub = function (self, other) self.length:___sub(other.length) self.stretch:___sub(other.stretch) @@ -125,7 +125,7 @@ return pl.class({ __mul = function (self, other) if type(self) == "number" then self, other = other, self end _error_if_not_number(other) - local result = SILE.length(self) + local result = SILE.types.length(self) result.length = result.length * other result.stretch = result.stretch * other result.shrink = result.shrink * other @@ -133,7 +133,7 @@ return pl.class({ end, __div = function (self, other) - local result = SILE.length(self) + local result = SILE.types.length(self) _error_if_not_number(other) result.length = result.length / other result.stretch = result.stretch / other @@ -142,7 +142,7 @@ return pl.class({ end, __unm = function (self) - local result = SILE.length(self) + local result = SILE.types.length(self) result.length = result.length:__unm() return result end, diff --git a/types/measurement.lua b/types/measurement.lua index 3254affe5..36d1af0d0 100644 --- a/types/measurement.lua +++ b/types/measurement.lua @@ -64,14 +64,14 @@ local measurement = pl.class({ if not parsed then SU.error("Could not parse measurement '"..amount.."'") end self.amount, self.unit = parsed.amount, parsed.unit end - local _su = SILE.units[self.unit] + local _su = SILE.types.unit[self.unit] if not _su then SU.error("Unknown unit: " .. unit) end self.relative = _su.relative if self.unit == "pt" then self._mutable = true end end, absolute = function (self) - return SILE.measurement(self:tonumber()) + return SILE.types.measurement(self:tonumber()) end, tostring = function (self) @@ -79,7 +79,7 @@ local measurement = pl.class({ end, tonumber = function (self) - local def = SILE.units[self.unit] + local def = SILE.types.unit[self.unit] local amount = def.converter and def.converter(self.amount) or (self.amount * def.value) return amount end, @@ -94,10 +94,10 @@ local measurement = pl.class({ __add = function (self, other) if _similarunit(self, other) then - return SILE.measurement(_amount(self) + _amount(other), _unit(self, other)) + return SILE.types.measurement(_amount(self) + _amount(other), _unit(self, other)) else _error_if_relative(self, other) - return SILE.measurement(_tonumber(self) + _tonumber(other)) + return SILE.types.measurement(_tonumber(self) + _tonumber(other)) end end, @@ -116,14 +116,14 @@ local measurement = pl.class({ __sub = function (self, other) if _similarunit(self, other) then - return SILE.measurement(_amount(self) - _amount(other), _unit(self, other)) + return SILE.types.measurement(_amount(self) - _amount(other), _unit(self, other)) else _error_if_relative(self, other) - return SILE.measurement(_tonumber(self) - _tonumber(other)) + return SILE.types.measurement(_tonumber(self) - _tonumber(other)) end end, - -- See usage comments on SILE.measurement:___add() + -- See usage comments on SILE.types.measurement:___add() ___sub = function (self, other) _error_if_immutable(self) self.amount = self.amount - _pt_amount(other) @@ -132,42 +132,42 @@ local measurement = pl.class({ __mul = function (self, other) if _hardnumber(self, other) then - return SILE.measurement(_amount(self) * _amount(other), _unit(self, other)) + return SILE.types.measurement(_amount(self) * _amount(other), _unit(self, other)) else _error_if_relative(self, other) - return SILE.measurement(_tonumber(self) * _tonumber(other)) + return SILE.types.measurement(_tonumber(self) * _tonumber(other)) end end, __pow = function (self, other) if _hardnumber(self, other) then - return SILE.measurement(_amount(self) ^ _amount(other), self.unit) + return SILE.types.measurement(_amount(self) ^ _amount(other), self.unit) else _error_if_relative(self, other) - return SILE.measurement(_tonumber(self) ^ _tonumber(other)) + return SILE.types.measurement(_tonumber(self) ^ _tonumber(other)) end end, __div = function (self, other) if _hardnumber(self, other) then - return SILE.measurement(_amount(self) / _amount(other), self.unit) + return SILE.types.measurement(_amount(self) / _amount(other), self.unit) else _error_if_relative(self, other) - return SILE.measurement(_tonumber(self) / _tonumber(other)) + return SILE.types.measurement(_tonumber(self) / _tonumber(other)) end end, __mod = function (self, other) if _hardnumber(self, other) then - return SILE.measurement(_amount(self) % _amount(other), self.unit) + return SILE.types.measurement(_amount(self) % _amount(other), self.unit) else _error_if_relative(self, other) - return SILE.measurement(_tonumber(self) % _tonumber(other)) + return SILE.types.measurement(_tonumber(self) % _tonumber(other)) end end, __unm = function (self) - local ret = SILE.measurement(self) + local ret = SILE.types.measurement(self) ret.amount = self.amount * -1 return ret end, diff --git a/types/node.lua b/types/node.lua index 50f5cb4fe..bec3c81d4 100644 --- a/types/node.lua +++ b/types/node.lua @@ -2,7 +2,7 @@ local nodetypes = {} -- This infinity needs to be smaller than an actual infinity but bigger than the infinite stretch -- added by the typesetter. See https://github.com/sile-typesetter/sile/issues/227 -local infinity = SILE.measurement(1e13) +local infinity = SILE.types.measurement(1e13) local function _maxnode (nodes, dim) local dims = SU.map(function (node) @@ -11,7 +11,7 @@ local function _maxnode (nodes, dim) -- return node[dim] return SU.cast("length", node[dim]) end, nodes) - return SU.max(SILE.length(0), pl.utils.unpack(dims)) + return SU.max(SILE.types.length(0), pl.utils.unpack(dims)) end local _dims = pl.Set { "width", "height", "depth" } @@ -43,7 +43,7 @@ function nodetypes.box:_init (spec) SU.error("Unimplemented, creating " .. self.type .. " node from " .. SU.type(spec), 1) end for dim in pairs(_dims) do - if not self[dim] then self[dim] = SILE.length() end + if not self[dim] then self[dim] = SILE.types.length() end end self["is_"..self.type] = true self.is_box = self.is_hbox or self.is_vbox or self.is_zerohbox or self.is_alternative or self.is_nnode @@ -341,21 +341,21 @@ end function nodetypes.discretionary:prebreakWidth () if self.prebw then return self.prebw end - self.prebw = SILE.length() + self.prebw = SILE.types.length() for _, node in ipairs(self.prebreak) do self.prebw:___add(node.width) end return self.prebw end function nodetypes.discretionary:postbreakWidth () if self.postbw then return self.postbw end - self.postbw = SILE.length() + self.postbw = SILE.types.length() for _, node in ipairs(self.postbreak) do self.postbw:___add(node.width) end return self.postbw end function nodetypes.discretionary:replacementWidth () if self.replacew then return self.replacew end - self.replacew = SILE.length() + self.replacew = SILE.types.length() for _, node in ipairs(self.replacement) do self.replacew:___add(node.width) end return self.replacew end @@ -434,7 +434,7 @@ end nodetypes.hfillglue = pl.class(nodetypes.glue) function nodetypes.hfillglue:_init (spec) self:super(spec) - self.width = SILE.length(self.width.length, infinity, self.width.shrink) + self.width = SILE.types.length(self.width.length, infinity, self.width.shrink) end -- A hssglue is just a glue with infinite stretch and shrink. @@ -442,7 +442,7 @@ end nodetypes.hssglue = pl.class(nodetypes.glue) function nodetypes.hssglue:_init (spec) self:super(spec) - self.width = SILE.length(self.width.length, infinity, infinity) + self.width = SILE.types.length(self.width.length, infinity, infinity) end nodetypes.kern = pl.class(nodetypes.glue) @@ -485,7 +485,7 @@ end nodetypes.vfillglue = pl.class(nodetypes.vglue) function nodetypes.vfillglue:_init (spec) self:super(spec) - self.height = SILE.length(self.width.length, infinity, self.width.shrink) + self.height = SILE.types.length(self.width.length, infinity, self.width.shrink) end -- A vssglue is just a vglue with infinite stretch and shrink. @@ -493,7 +493,7 @@ end nodetypes.vssglue = pl.class(nodetypes.vglue) function nodetypes.vssglue:_init (spec) self:super(spec) - self.height = SILE.length(self.width.length, infinity, infinity) + self.height = SILE.types.length(self.width.length, infinity, infinity) end nodetypes.zerovglue = pl.class(nodetypes.vglue) @@ -589,7 +589,7 @@ function nodetypes.vbox:append (box) end self.height = self.height:absolute() self.height:___add(self.depth) - local lastdepth = SILE.length() + local lastdepth = SILE.types.length() for i = 1, #nodes do table.insert(self.nodes, nodes[i]) self.height:___add(nodes[i].height) diff --git a/types/node_spec.lua b/types/node_spec.lua index 44314dffe..0fefc5426 100644 --- a/types/node_spec.lua +++ b/types/node_spec.lua @@ -48,7 +48,7 @@ describe("The node factory", function() end) describe("glues", function () - local glue = SILE.nodefactory.glue({ width = SILE.length({ length = 3, stretch = 2, shrink = 2 }) }) + local glue = SILE.nodefactory.glue({ width = SILE.types.length({ length = 3, stretch = 2, shrink = 2 }) }) it("should have width", function () assert.is.equal(3, glue.width:tonumber()) end) it("should be discardable", function () assert.is.truthy(glue.discardable) end) it("should stringify", function() assert.is.equal("G<3pt plus 2pt minus 2pt>", tostring(glue)) end) @@ -56,7 +56,7 @@ describe("The node factory", function() describe("vboxs", function () local nnode1 = SILE.nodefactory.nnode({ width = 20, height = 30, depth = 3, text = "one" }) - local glue = SILE.nodefactory.glue({ width = SILE.length({ length = 3, stretch = 2, shrink = 2}) }) + local glue = SILE.nodefactory.glue({ width = SILE.types.length({ length = 3, stretch = 2, shrink = 2}) }) local nnode2 = SILE.nodefactory.nnode({ width = 20, height = 30, depth = 7, text = "two" }) local nnode3 = SILE.nodefactory.nnode({ width = 20, height = 30, depth = 2, text = "three" }) local vbox = SILE.nodefactory.vbox({ nodes = { nnode1, glue, nnode2, glue, nnode3 } }) diff --git a/typesetters/base.lua b/typesetters/base.lua index 65d7ba64d..27f69cf54 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -19,8 +19,8 @@ local supereject_penalty = 2 * -inf_bad -- Local helper class to compare pairs of margins local _margins = pl.class({ - lskip = SILE.nodefactory.glue(), - rskip = SILE.nodefactory.glue(), + lskip = SILE.types.node.glue(), + rskip = SILE.types.node.glue(), _init = function (self, lskip, rskip) self.lskip, self.rskip = lskip, rskip @@ -100,7 +100,7 @@ function typesetter.declareSettings(_) SILE.settings:declare({ parameter = "typesetter.parfillskip", type = "glue", - default = SILE.nodefactory.glue("0pt plus 10000pt"), + default = SILE.types.node.glue("0pt plus 10000pt"), help = "Glue added at the end of a paragraph" }) @@ -114,14 +114,14 @@ function typesetter.declareSettings(_) SILE.settings:declare({ parameter = "typesetter.underfulltolerance", type = "length or nil", - default = SILE.length("1em"), + default = SILE.types.length("1em"), help = "Amount a page can be underfull without warning" }) SILE.settings:declare({ parameter = "typesetter.overfulltolerance", type = "length or nil", - default = SILE.length("5pt"), + default = SILE.types.length("5pt"), help = "Amount a page can be overfull without warning" }) @@ -234,25 +234,25 @@ end function typesetter:pushHbox (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushHorizontal() to pass a premade node instead of a spec") end local ntype = SU.type(spec) - local node = (ntype == "hbox" or ntype == "zerohbox") and spec or SILE.nodefactory.hbox(spec) + local node = (ntype == "hbox" or ntype == "zerohbox") and spec or SILE.types.node.hbox(spec) return self:pushHorizontal(node) end function typesetter:pushUnshaped (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushHorizontal() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "unshaped" and spec or SILE.nodefactory.unshaped(spec) + local node = SU.type(spec) == "unshaped" and spec or SILE.types.node.unshaped(spec) return self:pushHorizontal(node) end function typesetter:pushGlue (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushHorizontal() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "glue" and spec or SILE.nodefactory.glue(spec) + local node = SU.type(spec) == "glue" and spec or SILE.types.node.glue(spec) return self:pushHorizontal(node) end function typesetter:pushExplicitGlue (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushHorizontal() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "glue" and spec or SILE.nodefactory.glue(spec) + local node = SU.type(spec) == "glue" and spec or SILE.types.node.glue(spec) node.explicit = true node.discardable = false return self:pushHorizontal(node) @@ -260,30 +260,30 @@ end function typesetter:pushPenalty (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushHorizontal() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "penalty" and spec or SILE.nodefactory.penalty(spec) + local node = SU.type(spec) == "penalty" and spec or SILE.types.node.penalty(spec) return self:pushHorizontal(node) end function typesetter:pushMigratingMaterial (material) - local node = SILE.nodefactory.migrating({ material = material }) + local node = SILE.types.node.migrating({ material = material }) return self:pushHorizontal(node) end function typesetter:pushVbox (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushVertical() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "vbox" and spec or SILE.nodefactory.vbox(spec) + local node = SU.type(spec) == "vbox" and spec or SILE.types.node.vbox(spec) return self:pushVertical(node) end function typesetter:pushVglue (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushVertical() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "vglue" and spec or SILE.nodefactory.vglue(spec) + local node = SU.type(spec) == "vglue" and spec or SILE.types.node.vglue(spec) return self:pushVertical(node) end function typesetter:pushExplicitVglue (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushVertical() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "vglue" and spec or SILE.nodefactory.vglue(spec) + local node = SU.type(spec) == "vglue" and spec or SILE.types.node.vglue(spec) node.explicit = true node.discardable = false return self:pushVertical(node) @@ -291,7 +291,7 @@ end function typesetter:pushVpenalty (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushVertical() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "penalty" and spec or SILE.nodefactory.penalty(spec) + local node = SU.type(spec) == "penalty" and spec or SILE.types.node.penalty(spec) return self:pushVertical(node) end @@ -308,7 +308,7 @@ function typesetter:typeset (text) local warnedshy = false for token2 in SU.gtoke(token.string, luautf8.char(0x00AD)) do if token2.separator then -- soft hyphen support - local discretionary = SILE.nodefactory.discretionary({}) + local discretionary = SILE.types.node.discretionary({}) local hbox = SILE.typesetter:makeHbox({ SILE.settings:get("font.hyphenchar") }) discretionary.prebreak = { hbox } table.insert(SILE.typesetter.state.nodes, discretionary) @@ -335,7 +335,7 @@ end function typesetter:initline () if self.state.hmodeOnly then return end -- https://github.com/sile-typesetter/sile/issues/1718 if (#self.state.nodes == 0) then - self.state.nodes[#self.state.nodes+1] = SILE.nodefactory.zerohbox() + self.state.nodes[#self.state.nodes+1] = SILE.types.node.zerohbox() SILE.documentState.documentClass.newPar(self) end end @@ -354,13 +354,13 @@ local speakerChangeReplacement = luautf8.char(0x2014) .. " " -- Special unshaped node subclass to handle space after a speaker change in dialogues -- introduced by an em-dash. -local speakerChangeNode = pl.class(SILE.nodefactory.unshaped) +local speakerChangeNode = pl.class(SILE.types.node.unshaped) function speakerChangeNode:shape() local node = self._base.shape(self) local spc = node[2] if spc and spc.is_glue then -- Switch the variable space glue to a fixed kern - node[2] = SILE.nodefactory.kern({ width = spc.width.length }) + node[2] = SILE.types.node.kern({ width = spc.width.length }) node[2].parent = self.parent else -- Should not occur: @@ -532,9 +532,9 @@ function typesetter.shapeAllNodes (_, nodelist, inplace) -- a glue too. -- Otherwise, the font change is considered to occur at a non-breaking -- point (e.g. "\em{proof}!") and the correction shall be a kern. - local makeItCorrNode = isGlue and SILE.nodefactory.glue or SILE.nodefactory.kern + local makeItCorrNode = isGlue and SILE.types.node.glue or SILE.types.node.kern newNodelist[#newNodelist+1] = makeItCorrNode({ - width = SILE.length(itCorrOffset), + width = SILE.types.length(itCorrOffset), subtype = "itcorr" }) end @@ -600,7 +600,7 @@ function typesetter:boxUpNodes () nodes[#nodes+1] = node end end - local vbox = SILE.nodefactory.vbox({ nodes = nodes, ratio = line.ratio }) + local vbox = SILE.types.node.vbox({ nodes = nodes, ratio = line.ratio }) local pageBreakPenalty = 0 if (#lines > 1 and index == 1) then pageBreakPenalty = SILE.settings:get("typesetter.widowpenalty") @@ -613,7 +613,7 @@ function typesetter:boxUpNodes () self.state.previousVbox = vbox if pageBreakPenalty > 0 then SU.debug("typesetter", "adding penalty of", pageBreakPenalty, "after", vbox) - vboxes[#vboxes+1] = SILE.nodefactory.penalty(pageBreakPenalty) + vboxes[#vboxes+1] = SILE.types.node.penalty(pageBreakPenalty) end end return vboxes @@ -678,8 +678,8 @@ end function typesetter:setVerticalGlue (pageNodeList, target) local glues = {} - local gTotal = SILE.length() - local totalHeight = SILE.length() + local gTotal = SILE.types.length() + local totalHeight = SILE.types.length() local pastTop = false for _, node in ipairs(pageNodeList) do @@ -805,7 +805,7 @@ function typesetter:pushBack () local discardedFistInitLine = false if (#self.state.nodes == 0) then -- Setup queue but avoid calling newPar - self.state.nodes[#self.state.nodes+1] = SILE.nodefactory.zerohbox() + self.state.nodes[#self.state.nodes+1] = SILE.types.node.zerohbox() end for i, node in ipairs(vbox.nodes) do if node.is_glue and not node.discardable then @@ -897,7 +897,7 @@ function typesetter.leadingFor (_, vbox, previous) SU.debug("typesetter", " Considering leading between two lines:") SU.debug("typesetter", " 1)", previous) SU.debug("typesetter", " 2)", vbox) - if not previous then return SILE.nodefactory.vglue() end + if not previous then return SILE.types.node.vglue() end local prevDepth = previous.depth SU.debug("typesetter", " Depth of previous line was", prevDepth) local bls = SILE.settings:get("document.baselineskip") @@ -907,9 +907,9 @@ function typesetter.leadingFor (_, vbox, previous) -- the lineskip setting is a vglue, but we need a version absolutized at this point, see #526 local lead = SILE.settings:get("document.lineskip").height:absolute() if depth > lead then - return SILE.nodefactory.vglue(SILE.length(depth.length, bls.height.stretch, bls.height.shrink)) + return SILE.types.node.vglue(SILE.types.length(depth.length, bls.height.stretch, bls.height.shrink)) else - return SILE.nodefactory.vglue(lead) + return SILE.types.node.vglue(lead) end end @@ -1087,23 +1087,23 @@ end function typesetter:addrlskip (slice, margins, hangLeft, hangRight) local LTR = self.frame:writingDirection() == "LTR" local rskip = margins[LTR and "rskip" or "lskip"] - if not rskip then rskip = SILE.nodefactory.glue(0) end + if not rskip then rskip = SILE.types.node.glue(0) end if hangRight and hangRight > 0 then - rskip = SILE.nodefactory.glue({ width = rskip.width:tonumber() + hangRight }) + rskip = SILE.types.node.glue({ width = rskip.width:tonumber() + hangRight }) end rskip.value = "margin" -- while slice[#slice].discardable do table.remove(slice, #slice) end table.insert(slice, rskip) - table.insert(slice, SILE.nodefactory.zerohbox()) + table.insert(slice, SILE.types.node.zerohbox()) local lskip = margins[LTR and "lskip" or "rskip"] - if not lskip then lskip = SILE.nodefactory.glue(0) end + if not lskip then lskip = SILE.types.node.glue(0) end if hangLeft and hangLeft > 0 then - lskip = SILE.nodefactory.glue({ width = lskip.width:tonumber() + hangLeft }) + lskip = SILE.types.node.glue({ width = lskip.width:tonumber() + hangLeft }) end lskip.value = "margin" while slice[1].discardable do table.remove(slice, 1) end table.insert(slice, 1, lskip) - table.insert(slice, 1, SILE.nodefactory.zerohbox()) + table.insert(slice, 1, SILE.types.node.zerohbox()) end function typesetter:breakpointsToLines (breakpoints) @@ -1192,7 +1192,7 @@ function typesetter:breakpointsToLines (breakpoints) end function typesetter.computeLineRatio (_, breakwidth, slice) - local naturalTotals = SILE.length() + local naturalTotals = SILE.types.length() -- From the line end, account for the margin but skip any trailing -- glues (spaces to ignore) and zero boxes until we reach actual content. @@ -1295,8 +1295,8 @@ function typesetter:makeHbox (content) local nodes = self:shapeAllNodes(self.state.nodes, false) -- Then we can process and measure the nodes. - local l = SILE.length() - local h, d = SILE.length(), SILE.length() + local l = SILE.types.length() + local h, d = SILE.types.length(), SILE.types.length() for i = 1, #nodes do local node = nodes[i] if node.is_migrating then @@ -1327,7 +1327,7 @@ function typesetter:makeHbox (content) end self:popState() - local hbox = SILE.nodefactory.hbox({ + local hbox = SILE.types.node.hbox({ height = h, width = l, depth = d, diff --git a/typesetters/firstfit.lua b/typesetters/firstfit.lua index 0eae7af57..8844f37cc 100644 --- a/typesetters/firstfit.lua +++ b/typesetters/firstfit.lua @@ -5,7 +5,7 @@ typesetter._name = "firstfit" function typesetter:breakIntoLines (nl, breakWidth) local breaks = {} - local length = SILE.length() + local length = SILE.types.length() for i = 1,#nl do local n = nl[i] if n.is_box then SU.debug("break", n .. " " .. tostring(n:lineContribution())) @@ -22,7 +22,7 @@ function typesetter:breakIntoLines (nl, breakWidth) if length:tonumber() >= breakWidth:tonumber() then SU.debug("break", "Breaking!") breaks[#breaks+1] = { position = i, width = breakWidth} - length = SILE.length() + length = SILE.types.length() end end end diff --git a/typesetters/grid.lua b/typesetters/grid.lua index 6e6efbf44..6683c79f7 100644 --- a/typesetters/grid.lua +++ b/typesetters/grid.lua @@ -4,25 +4,25 @@ local typesetter = pl.class(base) typesetter._name = "grid" local function makeUp (spacing, totals) - local toadd = (spacing - SILE.measurement(totals.gridCursor)) % spacing + local toadd = (spacing - SILE.types.measurement(totals.gridCursor)) % spacing totals.gridCursor = totals.gridCursor + toadd SU.debug("typesetter", "Makeup height =", toadd) - return SILE.nodefactory.vglue({ discardable = false, gridleading = true, height = toadd }) + return SILE.types.node.vglue({ discardable = false, gridleading = true, height = toadd }) end function typesetter:_init(frame) base._init(self, frame) - self.options = { spacing = SILE.measurement("1bs") } + self.options = { spacing = SILE.types.measurement("1bs") } end function typesetter:leadingFor (vbox, previous) SU.debug("typesetter", " Considering leading between two lines (grid mode):") SU.debug("typesetter", " 1)", previous) SU.debug("typesetter", " 2)", vbox) - if not previous then return SILE.nodefactory.vglue() end + if not previous then return SILE.types.node.vglue() end SU.debug("typesetter", " Depth of previous line was", previous.depth) local totals = self.frame.state.totals - local oldCursor = SILE.measurement(totals.gridCursor) + local oldCursor = SILE.types.measurement(totals.gridCursor) totals.gridCursor = oldCursor + vbox.height:absolute() + previous.depth SU.debug("typesetter", " Cursor change =", totals.gridCursor - oldCursor) return makeUp(self.options.spacing, self.frame.state.totals) @@ -30,11 +30,11 @@ end function typesetter:pushVglue (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushVertical() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "vglue" and spec or SILE.nodefactory.vglue(spec) - node.height.stretch = SILE.measurement() - node.height.shrink = SILE.measurement() + local node = SU.type(spec) == "vglue" and spec or SILE.types.node.vglue(spec) + node.height.stretch = SILE.types.measurement() + node.height.shrink = SILE.types.measurement() local totals = self.frame.state.totals - totals.gridCursor = totals.gridCursor + SILE.measurement(node.height):absolute() + totals.gridCursor = totals.gridCursor + SILE.types.measurement(node.height):absolute() self:pushVertical(node) self:pushVertical(makeUp(self.options.spacing, self.frame.state.totals)) return node @@ -42,13 +42,13 @@ end function typesetter:pushExplicitVglue (spec) -- if SU.type(spec) ~= "table" then SU.warn("Please use pushVertical() to pass a premade node instead of a spec") end - local node = SU.type(spec) == "vglue" and spec or SILE.nodefactory.vglue(spec) + local node = SU.type(spec) == "vglue" and spec or SILE.types.node.vglue(spec) node.explicit = true node.discardable = false - node.height.stretch = SILE.measurement() - node.height.shrink = SILE.measurement() + node.height.stretch = SILE.types.measurement() + node.height.shrink = SILE.types.measurement() local totals = self.frame.state.totals - totals.gridCursor = totals.gridCursor + SILE.measurement(node.height):absolute() + totals.gridCursor = totals.gridCursor + SILE.types.measurement(node.height):absolute() self:pushVertical(node) self:pushVertical(makeUp(self.options.spacing, self.frame.state.totals)) return node diff --git a/typesetters/tate.lua b/typesetters/tate.lua index a6725e359..203c03b0f 100644 --- a/typesetters/tate.lua +++ b/typesetters/tate.lua @@ -4,11 +4,11 @@ local typesetter = pl.class(base) typesetter._name = "tate" function typesetter.leadingFor (_, v) - v.height = SILE.length("1zw"):absolute() + v.height = SILE.types.length("1zw"):absolute() local bls = SILE.settings:get("document.baselineskip") local d = bls.height:absolute() - v.height - local len = SILE.length(d.length, bls.height.stretch, bls.height.shrink) - return SILE.nodefactory.vglue({ height = len }) + local len = SILE.types.length(d.length, bls.height.stretch, bls.height.shrink) + return SILE.types.node.vglue({ height = len }) end return typesetter From 5b6d913cca8812fd9046fe9e15db12b1724e832d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 4 Feb 2024 12:12:13 +0300 Subject: [PATCH 303/357] chore(tooling): Add types as possible commit scope --- .commitlintrc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.commitlintrc.yml b/.commitlintrc.yml index 12a25a8fb..7933d173f 100644 --- a/.commitlintrc.yml +++ b/.commitlintrc.yml @@ -53,6 +53,7 @@ rules: - settings - shapers - tooling + - types - typesetters - utilities help: | From 14e0a084edae1ba624307580292edb7022a6798f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 4 Feb 2024 12:10:19 +0300 Subject: [PATCH 304/357] chore(types): Remove compatability shim leaving just deprecation notice --- types/node.lua | 110 +++++++++++-------------------------------------- 1 file changed, 24 insertions(+), 86 deletions(-) diff --git a/types/node.lua b/types/node.lua index bec3c81d4..f34383b38 100644 --- a/types/node.lua +++ b/types/node.lua @@ -611,98 +611,36 @@ function nodetypes.migrating:__tostring () return "<M: " .. tostring(self.material) .. ">" end -local _deprecated_nodefactory = {} - -_deprecated_nodefactory.newHbox = function (spec) - return node.hbox(spec) -end - -_deprecated_nodefactory.newNnode = function (spec) - return node.nnode(spec) -end - -_deprecated_nodefactory.newUnshaped = function (spec) - return node.unshaped(spec) -end - -_deprecated_nodefactory.newDisc = function (spec) - return node.discretionary(spec) -end - -_deprecated_nodefactory.disc = function (spec) - return node.discretionary(spec) -end - -_deprecated_nodefactory.newAlternative = function (spec) - return node.alternative(spec) -end - -_deprecated_nodefactory.newGlue = function (spec) - return node.glue(spec) -end - -_deprecated_nodefactory.newKern = function (spec) - return node.kern(spec) -end - -_deprecated_nodefactory.newVglue = function (spec) - return node.vglue(spec) -end - -_deprecated_nodefactory.newVKern = function (spec) - return node.vkern(spec) -end - -_deprecated_nodefactory.newPenalty = function (spec) - return node.penalty(spec) -end - -_deprecated_nodefactory.newDiscretionary = function (spec) - return node.discretionary(spec) -end - -_deprecated_nodefactory.newVbox = function (spec) - return node.vbox(spec) -end - -_deprecated_nodefactory.newMigrating = function (spec) - return node.migrating(spec) -end - -_deprecated_nodefactory.zeroGlue = function () - return node.glue() -end - -_deprecated_nodefactory.hfillGlue = function () - return node.hfillglue() -end - -_deprecated_nodefactory.vfillGlue = function () - return node.vfillglue() -end - -_deprecated_nodefactory.hssGlue = function () - return node.hssglue() -end - -_deprecated_nodefactory.vssGlue = function () - return node.vssglue() -end - -_deprecated_nodefactory.zeroHbox = function () - return node.zerohbox() -end - -_deprecated_nodefactory.zeroVglue = function () - return node.zerovglue() -end +local _deprecated_nodefactory = { + newHbox = true, + newNnode = true, + newUnshaped = true, + newDisc = true, + disc = true, + newAlternative = true, + newGlue = true, + newKern = true, + newVglue = true, + newVKern = true, + newPenalty = true, + newDiscretionary = true, + newVbox = true, + newMigrating = true, + zeroGlue = true, + hfillGlue = true, + vfillGlue = true, + hssGlue = true, + vssGlue = true, + zeroHbox = true, + zeroVglue = true, +} setmetatable(nodetypes, { __index = function (_, prop) if _deprecated_nodefactory[prop] then SU.deprecated("SILE.types.node." .. prop, "SILE.types.node." .. prop:match("n?e?w?(.*)"):lower(), "0.10.0", "0.14.0") elseif type(prop) == "number" then -- luacheck: ignore 542 - -- Likely at attempt to iterate (or dump) the table, sort of safe to ignore + -- Likely an attempt to iterate, inspect, or dump the table, sort of safe to ignore else SU.error("Attempt to access non-existent SILE.types.node." .. prop) end From 75abdefffb27aa07973c83e05fd4ba63b479d85d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 4 Feb 2024 12:22:23 +0300 Subject: [PATCH 305/357] chore(core): Remove compatability shim leaving just deprecation notice --- core/deprecations.lua | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/core/deprecations.lua b/core/deprecations.lua index f5154110a..5875bb627 100644 --- a/core/deprecations.lua +++ b/core/deprecations.lua @@ -27,16 +27,8 @@ local fluentglobal = function () fluent_once = true end SILE.fluent = setmetatable({}, { - __call = function (_, ...) - fluentglobal() - SILE.fluent = fluent - return fluent(pl.utils.unpack({...}, 1, select("#", ...))) - end, - __index = function (_, key) - fluentglobal() - SILE.fluent = fluent - return fluent[key] - end + __call = fluentglobal, + __index = fluentglobal, }) local nobaseclass = function () From 2ade33ce98cc9bb3410732095a6c207febcc67e5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 7 Feb 2024 16:15:46 +0300 Subject: [PATCH 306/357] refactor(utilities): Move debug rounder into utilities --- core/utilities/init.lua | 14 ++++++++++++++ outputters/debug.lua | 14 +------------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 0d31bb30f..35cbd8ca1 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -259,6 +259,20 @@ utilities.min = function (...) return min end +-- LuaJIT 2.1 betas (and inheritors such as OpenResty and Moonjit) are biased +-- towards rounding 0.5 up to 1, all other Lua interpreters are biased +-- towards rounding such floating point numbers down. This hack shaves off +-- just enough to fix the bias so our test suite works across interpreters. +-- Note that even a true rounding function here will fail because the bias is +-- inherent to the floating point type. Also note we are erroring in favor of +-- the *less* common option because the LuaJIT VMS are hopelessly broken +-- whereas normal LUA VMs can be cooerced. +utilities.debug_round = function (input) + if input > 0 then input = input + .00000000000001 end + if input < 0 then input = input - .00000000000001 end + return string.format("%.4f", input) +end + utilities.compress = function (items) local rv = {} local max = math.max(pl.utils.unpack(pl.tablex.keys(items))) diff --git a/outputters/debug.lua b/outputters/debug.lua index fa08e7152..6fc22b629 100644 --- a/outputters/debug.lua +++ b/outputters/debug.lua @@ -8,19 +8,7 @@ local started = false local lastFont local outfile -local function _round (input) - -- LuaJIT 2.1 betas (and inheritors such as OpenResty and Moonjit) are biased - -- towards rounding 0.5 up to 1, all other Lua interpreters are biased - -- towards rounding such floating point numbers down. This hack shaves off - -- just enough to fix the bias so our test suite works across interpreters. - -- Note that even a true rounding function here will fail because the bias is - -- inherent to the floating point type. Also note we are erroring in favor of - -- the *less* common option because the LuaJIT VMS are hopelessly broken - -- whereas normal LUA VMs can be cooerced. - if input > 0 then input = input + .00000000000001 end - if input < 0 then input = input - .00000000000001 end - return string.format("%.4f", input) -end +local _round = SU.debug_round local outputter = pl.class(base) outputter._name = "debug" From e1106a7ab92cc4e9ec34a532b4556e417a386881 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 7 Feb 2024 15:59:42 +0300 Subject: [PATCH 307/357] feat(types): Add __tostring to colors for easier debugging --- types/color.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/types/color.lua b/types/color.lua index 1e28c0f65..be30094be 100644 --- a/types/color.lua +++ b/types/color.lua @@ -170,6 +170,16 @@ function color:_init (input) return self end +function color:__tostring() + local p = {} + for _, k in pairs({"r", "g", "b", "c", "m", "y", "k", "l"}) do + if self[k] then + table.insert(p, k .. SU.debug_round(self[k])) + end + end + return ("C<%s>"):format(pl.pretty.write(p, ""):gsub('[{}"]', "")) +end + function color.parse (_, input) local r, g, b, c, m, y, k, l if not input or type(input) ~= "string" then From 14320ec6fbee939ef523a403b0c3d30137f30391 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 7 Feb 2024 16:06:53 +0300 Subject: [PATCH 308/357] test(types): Use internal debug output for colors --- outputters/debug.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/outputters/debug.lua b/outputters/debug.lua index 6fc22b629..dc9df6b59 100644 --- a/outputters/debug.lua +++ b/outputters/debug.lua @@ -69,21 +69,21 @@ end function outputter:setColor (color) if color.r then - self:_writeline("Set color", _round(color.r), _round(color.g), _round(color.b)) + self:_writeline("Set color", tostring(color)) elseif color.c then - self:_writeline("Set color", _round(color.c), _round(color.m), _round(color.y), _round(color.k)) + self:_writeline("Set color", tostring(color)) elseif color.l then - self:_writeline("Set color", _round(color.l)) + self:_writeline("Set color", tostring(color)) end end function outputter:pushColor (color) if color.r then - self:_writeline("Push color", _round(color.r), _round(color.g), _round(color.b)) + self:_writeline("Push color", tostring(color)) elseif color.c then - self:_writeline("Push color (CMYK)", _round(color.c), _round(color.m), _round(color.y), _round(color.k)) + self:_writeline("Push color (CMYK)", tostring(color)) elseif color.l then - self:_writeline("Push color (grayscale)", _round(color.l)) + self:_writeline("Push color (grayscale)", tostring(color)) end end From e7fb6eb3ab0da700c4712d958c3b51b0c9796f5a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 7 Feb 2024 16:47:43 +0300 Subject: [PATCH 309/357] chore(types): Push actual color types, not just color values --- outputters/libtexpdf.lua | 4 ++-- packages/color-fonts/init.lua | 3 ++- packages/hanmenkyoshi/init.lua | 3 ++- tests/bug-liner-width.sil | 2 +- types/color.lua | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/outputters/libtexpdf.lua b/outputters/libtexpdf.lua index d7932cd94..a752cacb2 100644 --- a/outputters/libtexpdf.lua +++ b/outputters/libtexpdf.lua @@ -215,7 +215,7 @@ end function outputter:debugFrame (frame) self:_ensureInit() - self:pushColor({ r = 0.8, g = 0, b = 0 }) + self:pushColor(SILE.types.color({ r = 0.8, g = 0, b = 0 })) self:drawRule(frame:left()-_dl/2, frame:top()-_dl/2, frame:width()+_dl, _dl) self:drawRule(frame:left()-_dl/2, frame:top()-_dl/2, _dl, frame:height()+_dl) self:drawRule(frame:right()-_dl/2, frame:top()-_dl/2, _dl, frame:height()+_dl) @@ -237,7 +237,7 @@ end function outputter:debugHbox (hbox, scaledWidth) self:_ensureInit() - self:pushColor({ r = 0.8, g = 0.3, b = 0.3 }) + self:pushColor(SILE.types.color({ r = 0.8, g = 0.3, b = 0.3 })) local paperY = SILE.documentState.paperSize[2] local x, y = self:getCursor() y = paperY - y diff --git a/packages/color-fonts/init.lua b/packages/color-fonts/init.lua index d0ae4f63e..3484462e0 100644 --- a/packages/color-fonts/init.lua +++ b/packages/color-fonts/init.lua @@ -79,8 +79,9 @@ function package:_init () for i=1, #run do options = pl.tablex.deepcopy(options) if run[i].color then + local color = SILE.types.color(run[i].color) nodes[#nodes+1] = SILE.types.node.hbox({ - outputYourself = function () SILE.outputter:pushColor(run[i].color) end + outputYourself = function () SILE.outputter:pushColor(color) end }) end for node in nodeMaker(options):iterator(run[i].slice, run[i].chunk) do diff --git a/packages/hanmenkyoshi/init.lua b/packages/hanmenkyoshi/init.lua index 8feaa2dac..648fefa59 100644 --- a/packages/hanmenkyoshi/init.lua +++ b/packages/hanmenkyoshi/init.lua @@ -79,7 +79,8 @@ function package:registerCommands () if not frame.hanmen then SU.error("show-hanmen called on a frame with no hanmen") end - SILE.outputter:pushColor({r = 1, g= 0.9, b = 0.9 }) + local color = SILE.types.color({r = 1, g= 0.9, b = 0.9 }) + SILE.outputter:pushColor(color) if frame:writingDirection() == "TTB" then showHanmenTate(frame) else diff --git a/tests/bug-liner-width.sil b/tests/bug-liner-width.sil index 2dc8cb458..618d2ab3d 100644 --- a/tests/bug-liner-width.sil +++ b/tests/bug-liner-width.sil @@ -13,7 +13,7 @@ SILE.documentState.documentClass:registerCommand("advance-box-width", function ( local height = SU.max(box.height:tonumber(), (1 - bsratio) * bs) local depth = SU.max(box.depth:tonumber(), bsratio * bs) local cx, cy = typesetter.frame.state.cursorX, typesetter.frame.state.cursorY - SILE.outputter:pushColor(SILE.color("gray")) + SILE.outputter:pushColor(SILE.types.color("gray")) SILE.outputter:drawRule(cx, cy - height, outputWidth, height + depth) SILE.outputter:popColor() typesetter.frame:advanceWritingDirection(outputWidth) diff --git a/types/color.lua b/types/color.lua index be30094be..c6b112dba 100644 --- a/types/color.lua +++ b/types/color.lua @@ -163,7 +163,7 @@ local color = pl.class({ }) function color:_init (input) - local c = self:parse(input) + local c = type(input) == "string" and self:parse(input) or input for k, v in pairs(c) do self[k] = v end From 1ca2d574e3cd8673c61986958c1890d022f16762 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 7 Feb 2024 16:23:45 +0300 Subject: [PATCH 310/357] test(types): Update expected outputs --- tests/bug-1142.expected | 6 +++--- tests/bug-1171.expected | 14 +++++++------- tests/bug-1244-fallback-after-color.expected | 12 ++++++------ tests/bug-353.expected | 4 ++-- tests/bug-524.expected | 2 +- tests/bug-865.expected | 4 ++-- tests/bug-liner-width.expected | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/bug-1142.expected b/tests/bug-1142.expected index c276b649c..f37cbc8e3 100644 --- a/tests/bug-1142.expected +++ b/tests/bug-1142.expected @@ -4,14 +4,14 @@ Mx 14.8819 My 28.9764 Set font ;10;400;;normal;;;LTR;tests/TestCLR-Regular.ttf T 3 w=10.0000 (a) -Push color 1.0000 0.8784 0.5412 +Push color C<r1.0000,g0.8784,b0.5412> Mx 24.8819 T 7 a=10.0000 () Pop color -Push color 0.8980 0.6078 0.1451 +Push color C<r0.8980,g0.6078,b0.1451> T 8 a=10.0000 () Pop color -Push color 0.5176 0.2196 0.0510 +Push color C<r0.5176,g0.2196,b0.0510> T 9 w=10.0000 (☺) Pop color Mx 34.8819 diff --git a/tests/bug-1171.expected b/tests/bug-1171.expected index 7100a6dbf..0a30d6b1f 100644 --- a/tests/bug-1171.expected +++ b/tests/bug-1171.expected @@ -1,29 +1,29 @@ Set paper size 595.275597 841.8897729 Begin page -Push color 1.0000 0.8000 0.3020 +Push color C<r1.0000,g0.8000,b0.3020> Mx 542.4079 My 97.6592 Set font Twemoji Mozilla;10;400;;normal;;;TTB T 7876 a=10.0000 () Pop color -Push color 0.4000 0.2706 0.0000 +Push color C<r0.4000,g0.2706,b0.0000> T 7893 a=10.0000 () T 7894 w=10.0000 (😉) Pop color -Push color 1.0000 0.7961 0.2980 +Push color C<r1.0000,g0.7961,b0.2980> My 107.6592 T 9105 a=10.0000 () Pop color -Push color 0.3961 0.2784 0.1059 +Push color C<r0.3961,g0.2784,b0.1059> T 9106 a=10.0000 () Pop color -Push color 1.0000 1.0000 1.0000 +Push color C<r1.0000,g1.0000,b1.0000> T 9107 a=10.0000 () Pop color -Push color 0.3961 0.2784 0.1059 +Push color C<r0.3961,g0.2784,b0.1059> T 9108 a=10.0000 () Pop color -Push color 0.3922 0.6667 0.8667 +Push color C<r0.3922,g0.6667,b0.8667> T 9109 w=10.0000 (🤣) Pop color End page diff --git a/tests/bug-1244-fallback-after-color.expected b/tests/bug-1244-fallback-after-color.expected index 802612b9e..08180bdf5 100644 --- a/tests/bug-1244-fallback-after-color.expected +++ b/tests/bug-1244-fallback-after-color.expected @@ -7,16 +7,16 @@ T 1542 w=10.0000 (ん) Mx 24.8819 Set font Gentium Plus;10;400;;normal;;;LTR T 68 w=4.5898 (a) -Push color 1.0000 0.8784 0.5412 +Push color C<r1.0000,g0.8784,b0.5412> Mx 14.8819 My 40.6664 Set font ;10;400;;normal;;;LTR;tests/TestCLR-Regular.ttf T 7 a=10.0000 () Pop color -Push color 0.8980 0.6078 0.1451 +Push color C<r0.8980,g0.6078,b0.1451> T 8 a=10.0000 () Pop color -Push color 0.5176 0.2196 0.0510 +Push color C<r0.5176,g0.2196,b0.0510> T 9 w=10.0000 (☺) Pop color Mx 24.8819 @@ -28,16 +28,16 @@ T 1542 w=10.0000 (ん) Mx 24.8819 Set font Gentium Plus;10;400;;normal;;;LTR T 68 w=4.5898 (a) -Push color 1.0000 0.8784 0.5412 +Push color C<r1.0000,g0.8784,b0.5412> Mx 14.8819 My 64.6664 Set font ;10;400;;normal;;;LTR;tests/TestCLR-Regular.ttf T 7 a=10.0000 () Pop color -Push color 0.8980 0.6078 0.1451 +Push color C<r0.8980,g0.6078,b0.1451> T 8 a=10.0000 () Pop color -Push color 0.5176 0.2196 0.0510 +Push color C<r0.5176,g0.2196,b0.0510> T 9 w=10.0000 (☺) Pop color Mx 24.8819 diff --git a/tests/bug-353.expected b/tests/bug-353.expected index 47f50f2ca..9041381f9 100644 --- a/tests/bug-353.expected +++ b/tests/bug-353.expected @@ -1,9 +1,9 @@ Set paper size 419.5275636 595.275597 Begin page -Push color 0.9137 0.8471 0.7294 +Push color C<r0.9137,g0.8471,b0.7294> Draw line 0.0000 0.0000 419.5276 595.2756 Pop color -Push color 0.3529 0.2549 0.1608 +Push color C<r0.3529,g0.2549,b0.1608> Mx 40.9764 My 37.3321 Set font Gentium Plus;10;400;;normal;;;LTR diff --git a/tests/bug-524.expected b/tests/bug-524.expected index 81d11b92f..b329db328 100644 --- a/tests/bug-524.expected +++ b/tests/bug-524.expected @@ -1,6 +1,6 @@ Set paper size 595.275597 841.8897729 Begin page -Push color 1.0000 0.9000 0.9000 +Push color C<r1.0000,g0.9000,b0.9000> Draw line 49.4079 97.4092 500.0000 0.5000 Draw line 49.1579 107.4092 0.5000 -10.0000 Draw line 59.1579 107.4092 0.5000 -10.0000 diff --git a/tests/bug-865.expected b/tests/bug-865.expected index 016f0de20..ec70b85ed 100644 --- a/tests/bug-865.expected +++ b/tests/bug-865.expected @@ -27,7 +27,7 @@ Mx 38.0763 T 81 82 81 88 80 92 w=34.3262 (nonumy) Mx 75.0647 T 72 76 85 80 82 71 w=29.5508 (eirmod) -Push color 0.6000 0.6000 0.6000 +Push color C<r0.6000,g0.6000,b0.6000> Mx 14.8819 My 69.7847 Set font Libertinus Serif;30;400;;normal;;;LTR @@ -112,7 +112,7 @@ Mx 94.4649 T 81 82 81 88 80 92 w=34.3262 (nonumy) Mx 131.4336 T 72 76 85 80 82 71 w=29.5508 (eirmod) -Push color 0.6000 0.6000 0.6000 +Push color C<r0.6000,g0.6000,b0.6000> Mx 271.5059 My 125.4747 Set font Libertinus Serif;30;400;;normal;;;LTR diff --git a/tests/bug-liner-width.expected b/tests/bug-liner-width.expected index 9df478fab..6d21f07f1 100644 --- a/tests/bug-liner-width.expected +++ b/tests/bug-liner-width.expected @@ -1,12 +1,12 @@ Set paper size 209.7637818 297.6377985 Begin page -Push color 0.5020 0.5020 0.5020 +Push color C<r0.5020,g0.5020,b0.5020> Draw line 10.4882 14.8819 188.7874 34.5868 Pop color -Push color 0.5020 0.5020 0.5020 +Push color C<r0.5020,g0.5020,b0.5020> Draw line 10.4882 53.2819 188.7874 34.5868 Pop color -Push color 0.5020 0.5020 0.5020 +Push color C<r0.5020,g0.5020,b0.5020> Draw line 10.4882 91.6819 116.2969 34.5868 Pop color Mx 10.4882 From da80c56d6ac39e3961bab0ec8473356d54b7075d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 8 Feb 2024 16:41:32 +0300 Subject: [PATCH 311/357] feat(utilities): Automatically cast anything passed to SU.debug to a string --- core/utilities/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 35cbd8ca1..00163de63 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -119,7 +119,9 @@ utilities.debug = function (category, ...) for i, input in ipairs(inputs) do if type(input) == "function" then local status, output = pcall(input) - inputs[i] = status and output or SU.warn(("Output of %s debug function was an error: %s"):format(category, output)) + inputs[i] = status and tostring(output) or SU.warn(("Output of %s debug function was an error: %s"):format(category, output)) + elseif type(input) ~= "string" then + inputs[i] = tostring(input) end end local message = utilities.concat(inputs, " ") From 72965ada011b2fac942cfb08e09df2ff9b8a5ce5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 8 Feb 2024 16:48:31 +0300 Subject: [PATCH 312/357] perf(utilities): Leave tostring() casting to after debug invocations, not before --- classes/base.lua | 2 +- core/break.lua | 32 ++++++++++++++++---------------- core/settings.lua | 2 +- core/utilities/init.lua | 2 +- packages/math/base-elements.lua | 2 +- pagebuilders/grid.lua | 2 +- typesetters/firstfit.lua | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index b804b5a2f..38b97bd14 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -272,7 +272,7 @@ end function class:runHooks (category, options) for _, func in ipairs(self.hooks[category]) do - SU.debug("classhooks", "Running hook from", category, options and "with options " .. #options) + SU.debug("classhooks", "Running hook from", category, options and "with options #" .. #options) func(self, options) end end diff --git a/core/break.lua b/core/break.lua index 0894e6e6b..652f8d1c4 100644 --- a/core/break.lua +++ b/core/break.lua @@ -156,7 +156,7 @@ function lineBreak:tryBreak() -- 855 if not node then pi = ejectPenalty; breakType = "hyphenated" elseif node.is_discretionary then breakType = "hyphenated"; pi = param("hyphenPenalty") else breakType = "unhyphenated"; pi = node.penalty or 0 end - if debugging then SU.debug("break", "Trying a ", breakType, "break p =", pi) end + if debugging then SU.debug("break", "Trying a", breakType, "break p =", pi) end self.no_break_yet = true -- We have to store all this state crap in the object, or it's global variables all the way self.prev_prev_r = nil self.prev_r = self.activeListHead @@ -176,7 +176,7 @@ function lineBreak:tryBreak() -- 855 end -- 861 if self.r.lineNumber > self.old_l then - if debugging then SU.debug("break", "Minimum demerits = " .. self.minimumDemerits) end + if debugging then SU.debug("break", "Minimum demerits =", self.minimumDemerits) end if self.minimumDemerits < awful_bad and (self.old_l ~= self.easy_line or self.r == self.activeListHead) then self:createNewActiveNodes(breakType) end @@ -199,16 +199,16 @@ function lineBreak:tryBreak() -- 855 self.lineWidth = self.firstWidth end end - if debugging then SU.debug("break", "line width = " .. tostring(self.lineWidth)) end + if debugging then SU.debug("break", "line width =", self.lineWidth) end end if debugging then - SU.debug("break", " ---> (2) cuaw is " .. tostring(self.curActiveWidth)) - SU.debug("break", " ---> aw is " .. tostring(self.activeWidth)) + SU.debug("break", " ---> (2) cuaw is", self.curActiveWidth) + SU.debug("break", " ---> aw is", self.activeWidth) end self:considerDemerits(pi, breakType) if debugging then - SU.debug("break", " <--- cuaw is " .. tostring(self.curActiveWidth)) - SU.debug("break", " <--- aw is " .. tostring(self.activeWidth)) + SU.debug("break", " <--- cuaw is", self.curActiveWidth) + SU.debug("break", " <--- aw is ", self.activeWidth) end end end @@ -269,7 +269,7 @@ function lineBreak:tryAlternatives(from, to) local ss = shortfall - addWidth -- Warning, assumes abosolute local badness = SU.rateBadness(inf_bad, ss.length.amount, self.curActiveWidth[ss > 0 and "stretch" or "shrink"].length.amount) - if debugging then SU.debug("break", " badness of " .. ss .. " (" .. self.curActiveWidth .. ") is " .. badness) end + if debugging then SU.debug("break", " badness of", ss, "(", self.curActiveWidth, ") is", badness) end if badness < localMinimum then self.r.alternates = alternates self.r.altSelections = combination @@ -293,7 +293,7 @@ function lineBreak:considerDemerits(pi, breakType) -- 877 end shortfall = self.lineWidth - self.curActiveWidth self.badness, self.fitClass = fitclass(self, shortfall) - if debugging then SU.debug("break", self.badness .. " " .. self.fitClass) end + if debugging then SU.debug("break", self.badness, self.fitClass) end if (self.badness > inf_bad or pi == ejectPenalty) then if self.finalpass and self.minimumDemerits == awful_bad and self.r.next == self.activeListHead and self.prev_r == self.activeListHead then self.artificialDemerits = true @@ -382,11 +382,11 @@ function lineBreak:recordFeasible(pi, breakType) -- 881 local demerit = lineBreak:computeDemerits(pi, breakType) if debugging then if self.nodes[self.place] then - SU.debug("break", "@" .. self.nodes[self.place] .. " via @@" .. (self.r.serial or "0") .. " badness=" .. self.badness .. " demerit=".. demerit) -- 882 + SU.debug("break", "@", self.nodes[self.place], "via @@", (self.r.serial or "0"), "badness =", self.badness, "demerit =", demerit) -- 882 else SU.debug("break", "@ \\par via @@") end - SU.debug("break", " fit class = "..self.fitClass) + SU.debug("break", " fit class =", self.fitClass) end demerit = demerit + self.r.totalDemerits if demerit <= self.bestInClass[self.fitClass].minimalDemerits then @@ -422,7 +422,7 @@ function lineBreak:createNewActiveNodes(breakType) -- 862 end place = place + 1 end - if debugging then SU.debug("break", "Value of breakWidth = " .. tostring(self.breakWidth)) end + if debugging then SU.debug("break", "Value of breakWidth =", self.breakWidth) end end -- 869 (Add a new delta node) if self.prev_r.type == "delta" then @@ -432,7 +432,7 @@ function lineBreak:createNewActiveNodes(breakType) -- 862 self.activeWidth = SILE.types.length(self.breakWidth) else local newDelta = { next = self.r, type = "delta", width = self.breakWidth - self.curActiveWidth } - if debugging then SU.debug("break", "Added new delta node = " .. tostring(newDelta.width)) end + if debugging then SU.debug("break", "Added new delta node =", newDelta.width) end self.prev_r.next = newDelta self.prev_prev_r = self.prev_r self.prev_r = newDelta @@ -447,7 +447,7 @@ function lineBreak:createNewActiveNodes(breakType) -- 862 local class = classes[i] local best = self.bestInClass[class] local value = best.minimalDemerits - if debugging then SU.debug("break", "Class is "..class.." Best value here is " .. value) end + if debugging then SU.debug("break", "Class is", class, "Best value here is", value) end if value <= self.minimumDemerits then -- 871: this is what creates new active notes @@ -489,7 +489,7 @@ function lineBreak.dumpBreakNode(_, node) end function lineBreak:describeBreakNode(node) - --print("@@" .. b.serial .. ": line " .. (b.lineNumber -1) .. "." .. b.fitness .. " " .. b.type .. " t=".. b.totalDemerits .. " -> @@ " .. (b.prevBreak and b.prevBreak.serial or "0") ) + --SU.debug("break", "@@", b.serial, ": line", b.lineNumber - 1, ".", b.fitness, b.type, "t=", b.totalDemerits, "-> @@", b.prevBreak and b.prevBreak.serial or "0") if node.sentinel then return node.sentinel end if node.type == "delta" then return "delta "..node.width.."pt" end local before = self.nodes[node.curBreak-1] @@ -582,7 +582,7 @@ function lineBreak:doBreak (nodes, hsize, sideways) end -- 889 while 1 do - if debugging then SU.debug("break", "@" .. self.pass .. "pass") end + if debugging then SU.debug("break", "@", self.pass, "pass") end if self.threshold > inf_bad then self.threshold = inf_bad end if self.pass == "second" then self.nodes = SILE.hyphenate(self.nodes) diff --git a/core/settings.lua b/core/settings.lua index 5f39b0569..eae985a7a 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -124,7 +124,7 @@ function settings:declare (spec) SU.deprecated("'name' argument of SILE.settings:declare", "'parameter' argument of SILE.settings:declare", "0.10.10", "0.11.0") end if self.declarations[spec.parameter] then - SU.debug("settings", "Attempt to re-declare setting: " .. spec.parameter) + SU.debug("settings", "Attempt to re-declare setting:", spec.parameter) return end self.declarations[spec.parameter] = spec diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 00163de63..8e8d5a2e9 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -119,7 +119,7 @@ utilities.debug = function (category, ...) for i, input in ipairs(inputs) do if type(input) == "function" then local status, output = pcall(input) - inputs[i] = status and tostring(output) or SU.warn(("Output of %s debug function was an error: %s"):format(category, output)) + inputs[i] = status and output or SU.warn(("Output of %s debug function was an error: %s"):format(category, output)) elseif type(input) ~= "string" then inputs[i] = tostring(input) end diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 61a558235..fc0f517f7 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -955,7 +955,7 @@ function elements.text:stretchyReshape (depth, height) m = diff end end - SU.debug("math", "stretch: closestI =", tostring(closestI)) + SU.debug("math", "stretch: closestI =", closestI) if closest then -- Now we have to re-shape the glyph chain. We will assume there -- is only one glyph. diff --git a/pagebuilders/grid.lua b/pagebuilders/grid.lua index 1659761ec..89bbcf803 100644 --- a/pagebuilders/grid.lua +++ b/pagebuilders/grid.lua @@ -16,7 +16,7 @@ function pagebuilder.findBestBreak (_, options) SU.debug("pagebuilder", "Page builder for frame", SILE.typesetter.frame.id, "called with", #vboxlist, "nodes,", target) if SU.debugging("vboxes") then for j, box in ipairs(vboxlist) do - SU.debug("vboxes", (j == i and " >" or " ") .. j .. ": " .. box) + SU.debug("vboxes", function () return (j == i and " >" or " ") .. j .. ": " .. box end) end end while i < #vboxlist do diff --git a/typesetters/firstfit.lua b/typesetters/firstfit.lua index 8844f37cc..62fc7a382 100644 --- a/typesetters/firstfit.lua +++ b/typesetters/firstfit.lua @@ -8,16 +8,16 @@ function typesetter:breakIntoLines (nl, breakWidth) local length = SILE.types.length() for i = 1,#nl do local n = nl[i] if n.is_box then - SU.debug("break", n .. " " .. tostring(n:lineContribution())) + SU.debug("break", n, function () return n:lineContribution() end) length = length + n:lineContribution() - SU.debug("break", " Length now " .. tostring(length) .. " breakwidth ".. tostring(breakWidth)) + SU.debug("break", " Length now ", length, "breakwidth", breakWidth) end if not n.is_box or n.isHangable then SU.debug("break", n ) if n.is_glue then length = length + n.width:absolute() end - SU.debug("break", " Length now " .. tostring(length) .. " breakwidth " .. tostring(breakWidth)) + SU.debug("break", " Length now ", length, " breakwidth ", breakWidth) -- Can we break? if length:tonumber() >= breakWidth:tonumber() then SU.debug("break", "Breaking!") From 3995e1498745055a2b9e71a6c2b027e66fe7fc9e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 3 Feb 2024 18:24:48 +0300 Subject: [PATCH 313/357] feat(tooling): Add tooling to generate Lua API documentation from sources --- Makefile.am | 10 ++++++++-- build-aux/config.ld | 11 +++++++++++ configure.ac | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 build-aux/config.ld diff --git a/Makefile.am b/Makefile.am index 44377e867..f4df7e413 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,7 +70,7 @@ dist_pdf_DATA = $(_MANUAL) dist_license_DATA = LICENSE.md EXTRA_DIST = spec tests documentation sile-dev-1.rockspec fontconfig.conf EXTRA_DIST += Makefile-distfiles -EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh +EXTRA_DIST += build-aux/action-updater.js build-aux/cargo-updater.js build-aux/config.ld build-aux/decore-automake.sh build-aux/git-version-gen build-aux/list-dist-files.sh EXTRA_DIST += Dockerfile build-aux/docker-bootstrap.sh build-aux/docker-fontconfig.conf hooks/build EXTRA_DIST += default.nix flake.nix flake.lock shell.nix build-aux/pkg.nix EXTRA_DIST += package.json # imported by both Nix and Docker @@ -173,7 +173,13 @@ selfcheck: | $(bin_PROGRAMS) $(_BUILT_SUBDIRS) $(PDFINFO) $$output | $(GREP) "SILE v$(VERSION)" .PHONY: docs -docs: $(_MANUAL) +docs: $(_MANUAL) lua-api-docs + +.PHONY: lua-api-docs +lua-api-docs: lua-api-docs/index.html + +lua-api-docs/index.html: build-aux/config.ld + $(LDOC) -c build-aux/config.ld . .PHONY: docs-figures docs-figures: $(FIGURES) diff --git a/build-aux/config.ld b/build-aux/config.ld new file mode 100644 index 000000000..bce1eb056 --- /dev/null +++ b/build-aux/config.ld @@ -0,0 +1,11 @@ +project = "SILE" +description = "The SILE Typesetter" +dir = "../lua-api-docs" +format = "discount" +file = { + "../sile-lua", + "../core", + "../typesetters", +} +multimodule = true +merge = true diff --git a/configure.ac b/configure.ac index 5d221d056..e61906f5d 100644 --- a/configure.ac +++ b/configure.ac @@ -220,6 +220,7 @@ AM_COND_IF([DEPENDENCY_CHECKS], [ AX_PROGVAR([git]) AX_PROGVAR([grep]) AX_PROGVAR([head]) + AX_PROGVAR([ldoc]) AX_PROGVAR([luacheck]) AX_PROGVAR([luarocks]) AX_PROGVAR([nix]) From c0507d205f90bd018943f632943a7fceabe57b54 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 8 Feb 2024 18:45:54 +0300 Subject: [PATCH 314/357] chore(tooling): Add commit scope for API docs --- .commitlintrc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.commitlintrc.yml b/.commitlintrc.yml index 12a25a8fb..8285b630e 100644 --- a/.commitlintrc.yml +++ b/.commitlintrc.yml @@ -39,6 +39,7 @@ rules: - inputters - installation - languages + - api - manpage - manual - math From cf7e26a6a74e31d373a03704983e580e3fcf482f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 8 Feb 2024 18:45:15 +0300 Subject: [PATCH 315/357] docs(api): Start organizing modules and documenting interfaces --- core/settings.lua | 27 ++++++++++++++++++++++++--- core/sile.lua | 13 +++++++++++++ core/utilities/ast.lua | 4 +++- core/utilities/init.lua | 11 +++++++++++ core/utilities/numbers.lua | 9 +++++---- typesetters/base.lua | 14 +++++++------- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/core/settings.lua b/core/settings.lua index c63d5f411..0d9e03df6 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -1,7 +1,11 @@ +--- core settings instance +--- @module SILE.settings + local deprecator = function () SU.deprecated("SILE.settings.*", "SILE.settings:*", "0.13.0", "0.15.0") end +--- @type settings local settings = pl.class() function settings:_init() @@ -97,17 +101,21 @@ function settings:_init() end +--- Stash the current values of all settings in a stack to be returned to later function settings:pushState () if not self then return deprecator() end table.insert(self.stateQueue, self.state) self.state = pl.tablex.copy(self.state) end +--- Return the most recently pushed set of values in the setting stack function settings:popState () if not self then return deprecator() end self.state = table.remove(self.stateQueue) end +--- Declare a new setting +--- @param specs table: { parameter, ... } declaration specification function settings:declare (spec) if not spec then return deprecator() end if spec.name then @@ -130,8 +138,8 @@ function settings:reset () end --- Restore all settings to the value they had in the top-level state, --- that is at the head of the settings stack (normally the document --- level). +--- that is at the head of the settings stack (normally the document +--- level). function settings:toplevelState () if not self then return deprecator() end if #self.stateQueue ~= 0 then @@ -144,6 +152,8 @@ function settings:toplevelState () end end +--- Get the value of a setting +--- @param parameter The full name of the setting to fetch. function settings:get (parameter) -- HACK FIXME https://github.com/sile-typesetter/sile/issues/1699 -- See comment on set() below. @@ -161,6 +171,11 @@ function settings:get (parameter) end end +--- Set the value of a setting +--- @param parameter The full name of the setting to change. +--- @param value The new value to change it to. +--- @param makedefault boolean Whether to make this the new default value (default false). +--- @param reset Whether to reset the value to the current default value (default false). function settings:set (parameter, value, makedefault, reset) -- HACK FIXME https://github.com/sile-typesetter/sile/issues/1699 -- Anything dubbed current.xxx should likely NOT be a "setting" (subject @@ -204,6 +219,9 @@ function settings:set (parameter, value, makedefault, reset) end end +--- Isolate a block of processing so that setting changes made during the block don't last past the block. +--- (Under the hood this just uses `:pushState()`, the processes the function, then runs `:popState()`) +--- @param function A function wrapping the actions to take without affecting settings for future use. function settings:temporarily (func) if not func then return deprecator() end self:pushState() @@ -211,7 +229,10 @@ function settings:temporarily (func) self:popState() end -function settings:wrap () -- Returns a closure which applies the current state, later +--- Create a settings wrapper function that applies current settings to later content processing. +--- @return a closure fuction accepting one argument (content) to process using +--- typesetter settings as they are at the time of closure creation. +function settings:wrap () if not self then return deprecator() end local clSettings = pl.tablex.copy(self.state) return function(content) diff --git a/core/sile.lua b/core/sile.lua index 698a43340..d7a17eda9 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -1,7 +1,19 @@ +--- The core SILE library +--- @module SILE + -- Initialize SILE internals SILE = {} +--- Current version of SILE, prefixed with v SILE.version = require("core.version") + +--- Status information about what options SILE was compiled with +--- @field appkit boolean +--- @field font_variations boolean +--- @field fontconfig boolean +--- @field harfbuzz boolean +--- @field icu boolean +--- @table SILE.features SILE.features = require("core.features") -- Initialize Lua environment and global utilities @@ -113,6 +125,7 @@ local function runEvals (evals, arg) end end +--- initialize sile SILE.init = function () if not SILE.backend then SILE.backend = "libtexpdf" diff --git a/core/utilities/ast.lua b/core/utilities/ast.lua index b1c4e6d25..a2f0c9bb2 100644 --- a/core/utilities/ast.lua +++ b/core/utilities/ast.lua @@ -1,5 +1,7 @@ --- SILE AST utilities --- +--- @module SU.ast + +--- @type ast local ast = {} --- Find a command node in a SILE AST tree, diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 73ab0e299..bf8769648 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -1,11 +1,22 @@ +--- SILE.Utilities (aliased as SU) +--- @module SU +--- alias SU.utilities + local bitshim = require("bitshim") local luautf8 = require("lua-utf8") local semver = require("semver") +--- @type utilities local utilities = {} local epsilon = 1E-12 +--- Require that an option table contains a specific value, otherwise raise an error. +--- @param options Input table of options. +--- @param name Name of the required option. +--- @param context User friendly name of the function or calling context. +--- @param required_type The name of a data type that the option must sucessfully cast to. +-- SU.required utilities.required = function (options, name, context, required_type) if not options[name] then utilities.error(context.." needs a "..name.." parameter") end if required_type then diff --git a/core/utilities/numbers.lua b/core/utilities/numbers.lua index 6bb6dd024..b53cb2541 100644 --- a/core/utilities/numbers.lua +++ b/core/utilities/numbers.lua @@ -1,9 +1,10 @@ --- --- Number formatting utilities --- MIT License (c) 2022 SILE organization --- +--- Number formatting utilities +--- @submodule SU +--- submodule SU + local icu = require("justenoughicu") +--- @type formatNumber -- Language-specific number formatters add functions to this table, -- see e.g. languages/eo.lua local formatNumber = { diff --git a/typesetters/base.lua b/typesetters/base.lua index c92cb3116..ba2b7019c 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -1,12 +1,9 @@ ---- SILE typesetter (default/base) class. --- --- @copyright License: MIT --- @module typesetters.base --- - --- Typesetter base class +--- SILE typesetter base class. +--- @module SILE.typesetters.base +--- @type typesetter local typesetter = pl.class() + typesetter.type = "typesetter" typesetter._name = "base" @@ -46,6 +43,8 @@ function typesetter:init (frame) self:_init(frame) end +--- Constructor +-- @param frame A initial frame to attach the typesetter to. function typesetter:_init (frame) self:declareSettings() self.hooks = {} @@ -60,6 +59,7 @@ function typesetter:_init (frame) return self end +--- Declare new setting types function typesetter.declareSettings(_) -- Settings common to any typesetter instance. From 47fd2538867428c1d6421665c9c8b07398f7e046 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 10 Feb 2024 15:35:19 +0300 Subject: [PATCH 316/357] docs(api): Add doc-strings for some main SILE instance fields --- core/sile.lua | 179 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 163 insertions(+), 16 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index d7a17eda9..4ea859855 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -1,25 +1,42 @@ --- The core SILE library ---- @module SILE +-- @module SILE --- Initialize SILE internals +-- Placeholder for SILE internals SILE = {} ---- Current version of SILE, prefixed with v +--- Fields +-- @section fields + +--- Machine friendly short-form version. +-- Semver, prefixed with "v", possible postfixed with ".r" followed by VCS version information. +-- @string version SILE.version = require("core.version") ---- Status information about what options SILE was compiled with ---- @field appkit boolean ---- @field font_variations boolean ---- @field fontconfig boolean ---- @field harfbuzz boolean ---- @field icu boolean ---- @table SILE.features +--- Status information about what options SILE was compiled with. +-- @table SILE.features +-- @tfield boolean appkit +-- @tfield boolean font_variations +-- @tfield boolean fontconfig +-- @tfield boolean harfbuzz +-- @tfield boolean icu SILE.features = require("core.features") -- Initialize Lua environment and global utilities + +--- ABI version of Lua VM. +-- For example may be `"5.1"` or `"5.4"` or others. Note that the ABI version for most LuaJIT implementations is 5.1. +-- @string lua_version SILE.lua_version = _VERSION:sub(-3) + + +--- Whether or not Lua VM is a JIT compiler. +-- @boolean lua_isjit -- luacheck: ignore jit SILE.lua_isjit = type(jit) == "table" + +--- User friendly long-form version string. +-- For example may be "SILE v0.14.17 (Lua 5.4)". +-- @string full_version SILE.full_version = string.format("SILE %s (%s)", SILE.version, SILE.lua_isjit and jit.version or _VERSION) -- Backport of lots of Lua 5.3 features to Lua 5.[12] @@ -45,6 +62,10 @@ local lfs = require("lfs") -- Developer tooling profiler local ProFi +--- Modules +-- @section modules + +--- Utilities module, aliased as `SU`. SILE.utilities = require("core.utilities") SU = SILE.utilities -- regrettable global alias @@ -61,19 +82,70 @@ local core_loader = function (scope) }) end +--- Data tables +--- @section data + +--- Stash of all Lua functions used to power typesetter commands. +-- @table Commands SILE.Commands = {} + +--- Short usage messages corresponding to typesetter commands. +-- @table Help SILE.Help = {} + +--- List of currently enabled debug flags. +-- E.g. `{ typesetter = true, frames, true }`. +-- @table debugFlags SILE.debugFlags = {} + SILE.nodeMakers = {} SILE.tokenizers = {} SILE.status = {} + +--- The wild-west of stash stuff. +-- No rules, just right (or usually wrong). Everything in here *should* be somewhere else, but lots of early SILE code +-- relied on this as a global key/value store for various class, document, and package values. Since v0.14.0 with many +-- core SILE components being instances of classes –and especially with each package having it's own variable namespace– +-- there are almost always better places for things. This scratch space will eventually be completely deprecated, so +-- don't put anything new in here and only use things in it if there are no other current alternatives. +-- @table scratch SILE.scratch = {} + +--- Data storage for typesetter, frame, and class information. +-- Current document class instances, node queues, and other "hot" data can be found here. As with `SILE.scratch` +-- everything in here probably belongs elsewhere, but for now it is what it is. +-- @table documentState +-- @tfield table documentClass The instantiated document processing class. +-- @tfield table thisPageTemplate The frameset used for the current page. +-- @tfield table paperSize The current paper size. +-- @tfield table orgPaperSize The original paper size if the current one is modified via packages. SILE.documentState = {} + +--- Callback functions for handling types of raw content. +-- All registered handlers for raw content blocks have an entry in this table with the type as the key and the +-- processing function as the value. +-- @ table rawHandlers SILE.rawHandlers = {} +--- User input +-- @section input + +--- All user-provided input collected before beginning document processing. -- User input values, currently from CLI options, potentially all the inuts -- needed for a user to use a SILE-as-a-library version to produce documents -- programmatically. +-- @table input +-- @tfield table filenames Path names of file(s) intended for processing. Files are processed in the order provided. +-- File types may be mixed of any formaat for which SILE has an inputter module. +-- @tfield table evaluates List of strings to be evaluated as Lua code snippets *before* processing inputs. +-- @tfield table evaluteAfters List of strings to be evaluated as Lua code snippets *after* processing inputs. +-- @tfield table uses List of strings specifying module names (and optionally optionns) for modules to load *before* +-- processing inputs. For example this accomodates loading inputter modules before any input of that type is encountered. +-- Additionally it can be used to process a document using a document class *other than* the one specified in the +-- document itself. Document class modules loaded here are instantiated after load, meaning the document will not be +-- queried for a class at all. +-- @tfield table options Extra document class options to set or override in addition to ones found in the first input +-- document. SILE.input = { filenames = {}, evaluates = {}, @@ -125,7 +197,20 @@ local function runEvals (evals, arg) end end ---- initialize sile +--- Core functions +-- @section functions + +--- Initialize a SILE instance. +-- Presumes CLI args have already been processed and/or library inputs are set. +-- +-- 1. If no backend has been loaded already (e.g. via `--use`) then assumes *libtexpdf*. +-- 2. Loads and instantiates a shaper and outputter module appropriate for the chosen backend. +-- 3. Instantiates a pagebuilder. +-- 4. Starts a Lua profiler if the profile debug flag is set. +-- 5. Instantiates a dependency tracker if we've been asked to write make dependencies. +-- 6. Runs any code snippents passed with `--eval`. +-- +-- Does not move on to processing input document(s). SILE.init = function () if not SILE.backend then SILE.backend = "libtexpdf" @@ -187,6 +272,13 @@ local function suggest_luarocks (module) ) end +--- Multi-purpose loader to load and initialize modules. +-- This is used to load and intitialize core parts of SILE and also 3rd party modules. +-- Module types supported bay be an *inputter*, *outputer*, *shaper*, *typesetter*, *pagebuilder*, or *package*. +-- @tparam string|table module The module spec name to load (dot-separated, e.g. `"packages.lorem"`) or a table with +-- a module that has already been loaded. +-- @tparam[opt] table options Startup options as key/value pairs passed to the module when initialized. +-- @tparam[opt=false] boolean reload whether or not to reload a module that has been loaded and initialized before. SILE.use = function (module, options, reload) local status, pack if type(module) == "string" then @@ -233,6 +325,9 @@ SILE.use = function (module, options, reload) end end +-- --- Content loader like Lua's `require()` but whith special path handling for loading SILE resource files. +-- -- Used for example by commands that load data via a `src=file.name` option. +-- -- @tparam string dependency Lua spec SILE.require = function (dependency, pathprefix, deprecation_ack) if pathprefix and not deprecation_ack then local notice = string.format([[ @@ -276,6 +371,10 @@ SILE.require = function (dependency, pathprefix, deprecation_ack) return lib end +--- Process content. +-- This is the main 'action' SILE does. Once input files are parsed into an abstract syntax tree, then we recursively +-- iterate through the tree handling each item in the order encountered. +-- @tparam table ast SILE content in abstract syntax tree format (a table of strings, functions, or more AST trees). SILE.process = function (ast) if not ast then return end if SU.debugging("ast") then @@ -328,6 +427,12 @@ local function detectFormat (doc, filename) SU.error(("Unable to pick inputter to process input from '%s'"):format(filename)) end +--- Process an input string. +-- First converts the string to an AST, then runs `process` on it. +-- @tparam string doc Input string to be coverted to SILE content. +-- @tparam[opt] nil|string format The name of the formatter. If nil, defaults to using each intputter's auto detection. +-- @tparam[opt] nil|string filename Pseudo filename to identify the content with, useful for error messages stack traces. +-- @tparam[opt] nil|table options Options to pass to the inputter instance when instantiated. function SILE.processString (doc, format, filename, options) local cpf if not filename then @@ -359,6 +464,12 @@ function SILE.processString (doc, format, filename, options) if cpf then SILE.currentlyProcessingFile = cpf end end +--- Process an input file +-- Opens a file, converts the contents to an AST, then runs `process` on it. +-- Roughly equivalent to listing the file as an input, but easier to embed in code. +-- @tparam string filename Path of file to open string to be coverted to SILE content. +-- @tparam[opt] nil|string format The name of the formatter. If nil, defaults to using each intputter's auto detection. +-- @tparam[opt] nil|table options Options to pass to the inputter instance when instantiated. function SILE.processFile (filename, format, options) local doc if filename == "-" then @@ -415,7 +526,10 @@ SILE.typesetNaturally = function (frame, func) if SILE.typesetter.frame then SILE.typesetter.frame:enter(SILE.typesetter) end end --- Sort through possible places files could be +--- Resolve relative file paths to identify absolute resources locations. +-- Makes it possible to load resources from relative paths, relative to a document or project or SILE itself. +-- @tparam string filename Name of file to find using the same order of precidence logic in `require()`. +-- @tparam[opt] nil|string pathprefix Optional prefix in which to look for if the file isn't found otherwise. function SILE.resolveFile (filename, pathprefix) local candidates = {} -- Start with the raw file name as given prefixed with a path if requested @@ -443,6 +557,12 @@ function SILE.resolveFile (filename, pathprefix) return resolved end +--- Execute a registered SILE command. +-- Uses a function previously registered by any modules explicitly loaded by the user at runtime via `--use`, the SILE +-- core, the document class, or any loaded package. +-- @tparam string command Command name. +-- @tparam[opt={}] nil|table options Options to pass to the command. +-- @tparam[opt] nil|table content Any valid AST node to be processed by the command. function SILE.call (command, options, content) options = options or {} content = content or {} @@ -459,6 +579,17 @@ function SILE.call (command, options, content) return result end +--- (Deprecated) Register a function as a SILE command. +-- Takes any Lua function and registers it for use as a SILE command (which will in turn be used to process any content +-- nodes identified with the command name. +-- +-- Note that alternative versions of this action are available as methods on document classes and packages. Those +-- interfaces should be prefered to this global one. +-- @tparam string name Name of cammand to register. +-- @tparam function func Callback function to use as command handler. +-- @tparam[opt] nil|string help User friendly short usage string for use in error messages, documentation, etc. +-- @tparam[opt] nil|string pack Information identifying the module registering the command for use in error and usage +-- messages. Usually auto-detected. function SILE.registerCommand (name, func, help, pack, cheat) local class = SILE.documentState.documentClass if not cheat then @@ -472,16 +603,22 @@ function SILE.registerCommand (name, func, help, pack, cheat) return class:registerCommand(name, func, help, pack) end +--- Wrap an existing command with new default options. +-- Modifies an already registered SILE command with a new table of options to be used as default values any time it is +-- called. Calling options still take precidence. +-- @tparam string command Name of command to overwride. +-- @tparam table options Options to set as updated defaults. function SILE.setCommandDefaults (command, defaults) local oldCommand = SILE.Commands[command] - SILE.Commands[command] = function (options, content) - for k, v in pairs(defaults) do - options[k] = options[k] or v + SILE.Commands[command] = function (defaults, content) + for k, v in pairs(options) do + defaults[k] = defaults[k] or v end - return oldCommand(options, content) + return oldCommand(defaults, content) end end +-- TODO: Move to new table entry handler in types.unit function SILE.registerUnit (unit, spec) -- If a unit exists already, clear it first so we get fresh meta table entries, see #1607 if SILE.units[unit] then @@ -495,6 +632,16 @@ function SILE.paperSizeParser (size) return SILE.papersize(size) end +--- Finalize document processing +-- Signals that all the `SILE.process()` calls have been made and SILE should move on to finish up the output +-- +-- 1. Stops logging dependecies and writes them to a makedepends file if requested. +-- 2. Tells the document class to run its `:finish()` method. This method is typically responsible for calling the +-- `:finish()` method of the outputter module in the appropriate sequence. +-- 3. Closes out anything in active memory we don't need like font instances. +-- 4. Evaluate any snippets in SILE.input.evalAfter table. +-- 5. Close out the Lua profiler if it was running. +-- 6. Output version information if versions debug flag is set. function SILE.finish () if SILE.makeDeps then SILE.makeDeps:write() From c0d28b366786689b72977aabe6677aaeefadcd0d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 10 Feb 2024 15:35:19 +0300 Subject: [PATCH 317/357] style(core): Normalize Lua coding style for function definitions --- core/sile.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 4ea859855..3c3d2f2f6 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -71,7 +71,7 @@ SU = SILE.utilities -- regrettable global alias -- On demand loader, allows modules to be loaded into a specific scope but -- only when/if accessed. -local core_loader = function (scope) +local function core_loader (scope) return setmetatable({}, { __index = function (self, key) -- local var = rawget(self, key) @@ -211,7 +211,7 @@ end -- 6. Runs any code snippents passed with `--eval`. -- -- Does not move on to processing input document(s). -SILE.init = function () +function SILE.init () if not SILE.backend then SILE.backend = "libtexpdf" end @@ -279,7 +279,7 @@ end -- a module that has already been loaded. -- @tparam[opt] table options Startup options as key/value pairs passed to the module when initialized. -- @tparam[opt=false] boolean reload whether or not to reload a module that has been loaded and initialized before. -SILE.use = function (module, options, reload) +function SILE.use (module, options, reload) local status, pack if type(module) == "string" then status, pack = pcall(require, module) @@ -328,7 +328,7 @@ end -- --- Content loader like Lua's `require()` but whith special path handling for loading SILE resource files. -- -- Used for example by commands that load data via a `src=file.name` option. -- -- @tparam string dependency Lua spec -SILE.require = function (dependency, pathprefix, deprecation_ack) +local SILE.require (dependency, pathprefix, deprecation_ack) if pathprefix and not deprecation_ack then local notice = string.format([[ Please don't use the path prefix mechanism; it was intended to provide @@ -375,7 +375,7 @@ end -- This is the main 'action' SILE does. Once input files are parsed into an abstract syntax tree, then we recursively -- iterate through the tree handling each item in the order encountered. -- @tparam table ast SILE content in abstract syntax tree format (a table of strings, functions, or more AST trees). -SILE.process = function (ast) +function SILE.process (ast) if not ast then return end if SU.debugging("ast") then SU.debugAST(ast, 0) @@ -514,7 +514,7 @@ end -- TODO: this probably needs deprecating, moved here just to get out of the way so -- typesetters classing works as expected -SILE.typesetNaturally = function (frame, func) +function SILE.typesetNaturally (frame, func) local saveTypesetter = SILE.typesetter if SILE.typesetter.frame then SILE.typesetter.frame:leave(SILE.typesetter) end SILE.typesetter = SILE.typesetters.base(frame) @@ -608,7 +608,7 @@ end -- called. Calling options still take precidence. -- @tparam string command Name of command to overwride. -- @tparam table options Options to set as updated defaults. -function SILE.setCommandDefaults (command, defaults) +function SILE.setCommandDefaults (command, options) local oldCommand = SILE.Commands[command] SILE.Commands[command] = function (defaults, content) for k, v in pairs(options) do From f59670c95f31cb404ce6bfcd99e4ab750f5387ea Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 10 Feb 2024 22:50:59 +0300 Subject: [PATCH 318/357] fix(core): Output makedepends file after class finish and snippets Catches any new dependencies introduced in these late running code locations. --- core/sile.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 3c3d2f2f6..e868f740d 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -328,7 +328,7 @@ end -- --- Content loader like Lua's `require()` but whith special path handling for loading SILE resource files. -- -- Used for example by commands that load data via a `src=file.name` option. -- -- @tparam string dependency Lua spec -local SILE.require (dependency, pathprefix, deprecation_ack) +function SILE.require (dependency, pathprefix, deprecation_ack) if pathprefix and not deprecation_ack then local notice = string.format([[ Please don't use the path prefix mechanism; it was intended to provide @@ -635,20 +635,20 @@ end --- Finalize document processing -- Signals that all the `SILE.process()` calls have been made and SILE should move on to finish up the output -- --- 1. Stops logging dependecies and writes them to a makedepends file if requested. --- 2. Tells the document class to run its `:finish()` method. This method is typically responsible for calling the +-- 1. Tells the document class to run its `:finish()` method. This method is typically responsible for calling the -- `:finish()` method of the outputter module in the appropriate sequence. --- 3. Closes out anything in active memory we don't need like font instances. --- 4. Evaluate any snippets in SILE.input.evalAfter table. +-- 2. Closes out anything in active memory we don't need like font instances. +-- 3. Evaluate any snippets in SILE.input.evalAfter table. +-- 4. Stops logging dependecies and writes them to a makedepends file if requested. -- 5. Close out the Lua profiler if it was running. -- 6. Output version information if versions debug flag is set. function SILE.finish () - if SILE.makeDeps then - SILE.makeDeps:write() - end SILE.documentState.documentClass:finish() SILE.font.finish() runEvals(SILE.input.evaluateAfters, "evaluate-after") + if SILE.makeDeps then + SILE.makeDeps:write() + end if not SILE.quiet then io.stderr:write("\n") end From 01a0ef5f4400e8d41761acf9b8ab04517a141407 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 10 Feb 2024 23:36:19 +0300 Subject: [PATCH 319/357] chore(tooling): Setup Nix develop environment to build Lua API docs --- build-aux/config.ld | 1 - build-aux/pkg.nix | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build-aux/config.ld b/build-aux/config.ld index bce1eb056..ffa4c80f1 100644 --- a/build-aux/config.ld +++ b/build-aux/config.ld @@ -7,5 +7,4 @@ file = { "../core", "../typesetters", } -multimodule = true merge = true diff --git a/build-aux/pkg.nix b/build-aux/pkg.nix index 0be09f536..3046eb852 100644 --- a/build-aux/pkg.nix +++ b/build-aux/pkg.nix @@ -47,6 +47,8 @@ let # lua packages needed for testing busted luacheck + # packages needed for building api docs + ldoc # NOTE: Add lua packages here, to change the luaEnv also read by `flake.nix` ] ++ lib.optionals (lib.versionOlder lua.luaversion "5.2") [ bit32 From 96a5d3e490b1483497c4cf4c61e41cc8037b03da Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 11 Feb 2024 14:43:43 +0300 Subject: [PATCH 320/357] docs(api): Add all module directories we want to generate docs for --- build-aux/config.ld | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build-aux/config.ld b/build-aux/config.ld index ffa4c80f1..2907a3da4 100644 --- a/build-aux/config.ld +++ b/build-aux/config.ld @@ -4,7 +4,15 @@ dir = "../lua-api-docs" format = "discount" file = { "../sile-lua", - "../core", - "../typesetters", + "../core/", + "../classes/", + "../inputters/", + "../languages/", + "../outputters/", + "../packages/", + "../pagebuilders/", + "../shapers/", + "../types/", + "../typesetters/", } merge = true From ffb505b8f88b9431c1ccd24b56864eb02a84ee09 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 11 Feb 2024 15:36:57 +0300 Subject: [PATCH 321/357] docs(api): Add README to API docs --- build-aux/config.ld | 1 + 1 file changed, 1 insertion(+) diff --git a/build-aux/config.ld b/build-aux/config.ld index 2907a3da4..ce5c320ef 100644 --- a/build-aux/config.ld +++ b/build-aux/config.ld @@ -1,5 +1,6 @@ project = "SILE" description = "The SILE Typesetter" +readme = "../README.md" dir = "../lua-api-docs" format = "discount" file = { From dfc22835ab56879b8da3ce44c4040ee6e5b384e7 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 11 Feb 2024 16:05:00 +0300 Subject: [PATCH 322/357] docs(api): Work on navigation sanity in Lua docs --- classes/base.lua | 3 ++ core/languages.lua | 3 ++ core/sile.lua | 52 ++++++++++++++++++-------------- inputters/base.lua | 3 ++ outputters/base.lua | 3 ++ packages/base.lua | 3 ++ packages/bibtex/bibliography.lua | 14 ++++----- pagebuilders/base.lua | 3 ++ shapers/base.lua | 3 ++ types/color.lua | 3 ++ types/length.lua | 4 +++ types/measurement.lua | 4 +++ types/node.lua | 3 ++ types/unit.lua | 3 ++ typesetters/base.lua | 4 +-- 15 files changed, 76 insertions(+), 32 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index 38b97bd14..fc4ed7195 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -1,3 +1,6 @@ +--- SILE document class class. +-- @classmod SILE.classes + local class = pl.class() class.type = "class" class._name = "base" diff --git a/core/languages.lua b/core/languages.lua index 180ff7104..dca7e65ef 100644 --- a/core/languages.lua +++ b/core/languages.lua @@ -1,3 +1,6 @@ +--- SILE language class. +-- @classmod SILE.languages + local loadkit = require("loadkit") local cldr = require("cldr") diff --git a/core/sile.lua b/core/sile.lua index 5a3ce368e..22c9b8275 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -1,7 +1,30 @@ --- The core SILE library -- @module SILE --- Placeholder for SILE internals +--- Global library provisions. +-- @section globals +-- Loading SILE foo + +--- Penlight. +-- On-demand module loader, provided for SILE and document usage +pl = require("pl.import_into")() + +-- For developer testing only, usually in CI +if os.getenv("SILE_COVERAGE") then require("luacov") end + +--- UTF-8 String handler. +-- Lua 5.3+ has a UTF-8 safe string function module but it is somewhat +-- underwhelming. This module includes more functions and supports older Lua +-- versions. Docs: https://github.com/starwing/luautf8 +luautf8 = require("lua-utf8") + +--- Fluent localization library. +fluent = require("fluent")() + +-- Reserve global scope placeholder for profiler (developer tooling) +local ProFi + +-- Placeholder for SILE internals table SILE = {} --- Fields @@ -42,26 +65,6 @@ SILE.full_version = string.format("SILE %s (%s)", SILE.version, SILE.lua_isjit a -- Backport of lots of Lua 5.3 features to Lua 5.[12] if not SILE.lua_isjit and SILE.lua_version < "5.3" then require("compat53") end --- Penlight on-demand module loader, provided for SILE and document usage -pl = require("pl.import_into")() - --- For developer testing only, usually in CI -if os.getenv("SILE_COVERAGE") then require("luacov") end - --- Lua 5.3+ has a UTF-8 safe string function module but it is somewhat --- underwhelming. This module includes more functions and supports older Lua --- versions. Docs: https://github.com/starwing/luautf8 -luautf8 = require("lua-utf8") - --- Localization library, provided as global -fluent = require("fluent")() - --- Includes for _this_ scope -local lfs = require("lfs") - --- Developer tooling profiler -local ProFi - -- For warnings and shims scheduled for removal that are easier to keep track -- of when they are not spread across so many locations... -- Loaded early to make it easier to manage migrations in core code. @@ -157,8 +160,8 @@ SILE.input = { evaluateAfters = {}, uses = {}, options = {}, - preambles = {}, - postambles = {}, + preambles = {}, -- deprecated, undocumented + postambles = {}, -- deprecated, undocumented } -- Internal libraries that are idempotent and return classes that need instantiation @@ -469,6 +472,7 @@ end -- @tparam[opt] nil|string format The name of the formatter. If nil, defaults to using each intputter's auto detection. -- @tparam[opt] nil|table options Options to pass to the inputter instance when instantiated. function SILE.processFile (filename, format, options) + local lfs = require("lfs") local doc if filename == "-" then filename = "STDIN" @@ -588,6 +592,8 @@ end -- @tparam[opt] nil|string help User friendly short usage string for use in error messages, documentation, etc. -- @tparam[opt] nil|string pack Information identifying the module registering the command for use in error and usage -- messages. Usually auto-detected. +-- @see SILE.classes +-- @see SILE.packages function SILE.registerCommand (name, func, help, pack, cheat) local class = SILE.documentState.documentClass if not cheat then diff --git a/inputters/base.lua b/inputters/base.lua index 4674bdfde..9a476a00e 100644 --- a/inputters/base.lua +++ b/inputters/base.lua @@ -1,3 +1,6 @@ +--- SILE inputter class. +-- @classmod SILE.inputters + local _deprecated = [[ You appear to be using a document class '%s' programmed for SILE <= v0.12.5. This system was refactored in v0.13.0 and the shims trying to make it diff --git a/outputters/base.lua b/outputters/base.lua index 2d5042d8d..e337524fe 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -1,3 +1,6 @@ +--- SILE outputter class. +-- @classmod SILE.outputters + local outputter = pl.class() outputter.type = "outputter" outputter._name = "base" diff --git a/packages/base.lua b/packages/base.lua index 4b86d30cf..b55a1b2c6 100644 --- a/packages/base.lua +++ b/packages/base.lua @@ -1,3 +1,6 @@ +--- SILE package class. +-- @classmod SILE.packages + local package = pl.class() package.type = "package" package._name = "base" diff --git a/packages/bibtex/bibliography.lua b/packages/bibtex/bibliography.lua index b55104d63..0572390d1 100644 --- a/packages/bibtex/bibliography.lua +++ b/packages/bibtex/bibliography.lua @@ -9,18 +9,18 @@ local function find_outside_braces(str, pat, i) local j, k = string.find(str, pat, i) if not j then return j, k end local jb, kb = string.find(str, '%b{}', i) - while jb and jb < j do --- scan past braces - --- braces come first, so we search again after close brace + while jb and jb < j do -- scan past braces + -- braces come first, so we search again after close brace local i2 = kb + 1 j, k = string.find(str, pat, i2) if not j then return j, k end jb, kb = string.find(str, '%b{}', i2) end -- either pat precedes braces or there are no braces - return string.find(str, pat, j) --- 2nd call needed to get captures + return string.find(str, pat, j) -- 2nd call needed to get captures end -local function split(str, pat, find) --- return list of substrings separated by pat +local function split(str, pat, find) -- return list of substrings separated by pat find = find or string.find -- could be find_outside_braces -- @Omikhelia: I added this check here to avoid breaking on error, -- but probably in could have been done earlier... @@ -43,7 +43,7 @@ local function split(str, pat, find) --- return list of substrings separated by return t end -local function splitters(str, pat, find) --- return list of separators +local function splitters(str, pat, find) -- return list of separators find = find or string.find -- could be find_outside_braces local t = { } local insert = table.insert @@ -130,7 +130,7 @@ do trailers[i] = string.sub(trailer, 1, 1) end end - local commas = { } --- maps each comma to index of token the follows it + local commas = { } -- maps each comma to index of token the follows it for i, t in ipairs(trailers) do string.gsub(t, ',', function() table.insert(commas, i+1) end) end @@ -263,7 +263,7 @@ do end end ---- Thanks, Norman, for the above functions! +-- Thanks, Norman, for the above functions! local Bibliography Bibliography = { diff --git a/pagebuilders/base.lua b/pagebuilders/base.lua index 1c2da15c2..94063d337 100644 --- a/pagebuilders/base.lua +++ b/pagebuilders/base.lua @@ -1,3 +1,6 @@ +--- SILE pagebuilder class. +-- @classmod SILE.pagebuilders + local pagebuilder = pl.class() pagebuilder.type = "pagebuilder" pagebuilder._name = "base" diff --git a/shapers/base.lua b/shapers/base.lua index 6c67694f3..ed1e00448 100644 --- a/shapers/base.lua +++ b/shapers/base.lua @@ -1,3 +1,6 @@ +--- SILE shaper class. +-- @classmod SILE.shapers + -- local smallTokenSize = 20 -- Small words will be cached -- local shapeCache = {} -- local _key = function (options) diff --git a/types/color.lua b/types/color.lua index c6b112dba..a95ea6692 100644 --- a/types/color.lua +++ b/types/color.lua @@ -1,3 +1,6 @@ +--- SILE color type. +-- @classmod SILE.types.color + local colornames = { aliceblue = { 240, 248, 255 }, antiquewhite = { 250, 235, 215 }, diff --git a/types/length.lua b/types/length.lua index a1e6d21a0..8f5d7d6d7 100644 --- a/types/length.lua +++ b/types/length.lua @@ -1,3 +1,7 @@ +--- SILE length type. +-- @classmod SILE.types.length +-- @within Types + local function _error_if_not_number (a) if type(a) ~= "number" then SU.error("We tried to do impossible arithmetic on a " .. SU.type(a) .. ". (That's a bug)", true) diff --git a/types/measurement.lua b/types/measurement.lua index 36d1af0d0..c9cd56438 100644 --- a/types/measurement.lua +++ b/types/measurement.lua @@ -1,3 +1,7 @@ +--- SILE measurement type. +-- @classmod SILE.types.measurement +-- + local function _tonumber (amount) return SU.cast("number", amount) end diff --git a/types/node.lua b/types/node.lua index f34383b38..5592b2b8c 100644 --- a/types/node.lua +++ b/types/node.lua @@ -1,3 +1,6 @@ +--- SILE node type. +-- @classmod SILE.types.node + local nodetypes = {} -- This infinity needs to be smaller than an actual infinity but bigger than the infinite stretch diff --git a/types/unit.lua b/types/unit.lua index 452ecab9f..f99fc4878 100644 --- a/types/unit.lua +++ b/types/unit.lua @@ -1,3 +1,6 @@ +--- SILE unit type. +-- @classmod SILE.types.unit + local bits = require("core.parserbits") local unittypes = { diff --git a/typesetters/base.lua b/typesetters/base.lua index 75b41ddd1..0d7373cd0 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -1,5 +1,5 @@ ---- SILE typesetter base class. ---- @module SILE.typesetters.base +--- SILE typesetter class. +-- @classmod SILE.typesetters --- @type typesetter local typesetter = pl.class() From ba2e37a9959cebf1e0a334351a4041ee026bac4c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 12 Feb 2024 14:20:20 +0300 Subject: [PATCH 323/357] fix(utilities): Cast empty to default and only ever return a bool from SU.boolean() --- core/utilities/init.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index cf991daa2..5119f306b 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -36,9 +36,10 @@ utilities.boolean = function (value, default) if value == "true" then return true end if value == "no" then preferbool(); return false end if value == "yes" then preferbool(); return true end - if value == nil then return default end + if value == nil then return default == true end + if value == "" then return default == true end SU.error("Expecting a boolean value but got '" .. value .. "'") - return default + return default == true end local _skip_traceback_levels = 2 From ea38243abb42dfb5cd1173c4bd68e9c390d7aa73 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 12 Feb 2024 14:39:33 +0300 Subject: [PATCH 324/357] docs(api): Keep working on organizing and documenting, cleanup types --- core/font.lua | 2 + core/settings.lua | 32 +++++---- core/sile.lua | 3 +- core/utilities/ast.lua | 95 ++++++++++++------------ core/utilities/init.lua | 144 +++++++++++++++++++++++++++++++++---- core/utilities/numbers.lua | 5 +- core/utilities/sorting.lua | 7 +- languages/fr.lua | 3 +- typesetters/base.lua | 21 +++--- 9 files changed, 220 insertions(+), 92 deletions(-) diff --git a/core/font.lua b/core/font.lua index 9da62ba07..f7704fd07 100644 --- a/core/font.lua +++ b/core/font.lua @@ -1,3 +1,5 @@ +--- font +-- @module SILE.font local icu = require("justenoughicu") local lastshaper diff --git a/core/settings.lua b/core/settings.lua index 559aa44e8..7b1740535 100644 --- a/core/settings.lua +++ b/core/settings.lua @@ -125,7 +125,7 @@ function settings:popState () end --- Declare a new setting ---- @param specs table: { parameter, ... } declaration specification +--- @tparam table specs { parameter, type, default, help, hook, ... } declaration specification function settings:declare (spec) if not spec then return deprecator() end if spec.name then @@ -143,7 +143,7 @@ function settings:declare (spec) self:set(spec.parameter, spec.default, true) end ---- Reset all settings to their default value. +--- Reset all settings to their registered default values. function settings:reset () if not self then return deprecator() end for k,_ in pairs(self.state) do @@ -152,8 +152,7 @@ function settings:reset () end --- Restore all settings to the value they had in the top-level state, ---- that is at the head of the settings stack (normally the document ---- level). +-- that is at the tap of the settings stack (normally the document level). function settings:toplevelState () if not self then return deprecator() end if #self.stateQueue ~= 0 then @@ -167,7 +166,8 @@ function settings:toplevelState () end --- Get the value of a setting ---- @param parameter The full name of the setting to fetch. +-- @tparam string parameter The full name of the setting to fetch. +-- @return Value of setting function settings:get (parameter) -- HACK FIXME https://github.com/sile-typesetter/sile/issues/1699 -- See comment on set() below. @@ -186,10 +186,10 @@ function settings:get (parameter) end --- Set the value of a setting ---- @param parameter The full name of the setting to change. ---- @param value The new value to change it to. ---- @param makedefault boolean Whether to make this the new default value (default false). ---- @param reset Whether to reset the value to the current default value (default false). +-- @tparam string parameter The full name of the setting to change. +-- @param value The new value to change it to. +-- @tparam[opt=false] boolean makedefault Whether to make this the new default value. +-- @tparam[opt=false] boolean reset Whether to reset the value to the current default value. function settings:set (parameter, value, makedefault, reset) -- HACK FIXME https://github.com/sile-typesetter/sile/issues/1699 -- Anything dubbed current.xxx should likely NOT be a "setting" (subject @@ -234,10 +234,16 @@ function settings:set (parameter, value, makedefault, reset) self:runHooks(parameter, value) end +--- Register a callback hook to be run when a setting changes. +-- @tparam string parameter Name of the setting to add a hook to. +-- @tparam function func Callback function accepting one argument (the new value). function settings:registerHook (parameter, func) table.insert(self.hooks[parameter], func) end +--- Trigger execution of callback hooks for a given setting. +-- @tparam string parameter The name of the parameter changes. +-- @param value The new value of the setting, passed as the first argument to the hook function. function settings:runHooks (parameter, value) if self.hooks[parameter] then for _, func in ipairs(self.hooks[parameter]) do @@ -248,8 +254,8 @@ function settings:runHooks (parameter, value) end --- Isolate a block of processing so that setting changes made during the block don't last past the block. ---- (Under the hood this just uses `:pushState()`, the processes the function, then runs `:popState()`) ---- @param function A function wrapping the actions to take without affecting settings for future use. +-- (Under the hood this just uses `:pushState()`, the processes the function, then runs `:popState()`) +-- @tparam function func A function wrapping the actions to take without affecting settings for future use. function settings:temporarily (func) if not func then return deprecator() end self:pushState() @@ -258,8 +264,8 @@ function settings:temporarily (func) end --- Create a settings wrapper function that applies current settings to later content processing. ---- @return a closure fuction accepting one argument (content) to process using ---- typesetter settings as they are at the time of closure creation. +--- @treturn function a closure fuction accepting one argument (content) to process using +--- typesetter settings as they are at the time of closure creation. function settings:wrap () if not self then return deprecator() end local clSettings = pl.tablex.copy(self.state) diff --git a/core/sile.lua b/core/sile.lua index 22c9b8275..d54bcd736 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -73,7 +73,8 @@ require("core/deprecations") --- Modules -- @section modules ---- Utilities module, aliased as `SU`. +--- Utilities module, typically accessed via `SU` alias. +-- @see SU SILE.utilities = require("core.utilities") SU = SILE.utilities -- regrettable global alias diff --git a/core/utilities/ast.lua b/core/utilities/ast.lua index a2f0c9bb2..3e5b27c6f 100644 --- a/core/utilities/ast.lua +++ b/core/utilities/ast.lua @@ -1,15 +1,16 @@ ---- SILE AST utilities ---- @module SU.ast +--- AST utilities. +-- Functions for working with SILE's Abstract Syntax Trees. +-- @module SU.ast ---- @type ast +-- @type SU.ast local ast = {} --- Find a command node in a SILE AST tree, ---- looking only at the first level. ---- (We're not reimplementing XPath here.) ----@param tree table AST tree ----@param command string command name ----@return table|nil AST command node +-- looking only at the first level. +-- (We're not reimplementing XPath here.) +-- @tparam table tree AST tree +-- @tparam string command command name +-- @treturn table|nil AST command node function ast.findInTree (tree, command) for i=1, #tree do if type(tree[i]) == "table" and tree[i].command == command then @@ -19,10 +20,10 @@ function ast.findInTree (tree, command) end --- Find and extract (remove) a command node in a SILE AST tree, ---- looking only at the first level. ----@param tree table AST tree ----@param command string command name ----@return table|nil AST command node +-- looking only at the first level. +-- @tparam table tree AST tree +-- @tparam string command command name +-- @treturn table|nil AST command node function ast.removeFromTree (tree, command) for i=1, #tree do if type(tree[i]) == "table" and tree[i].command == command then @@ -32,12 +33,12 @@ function ast.removeFromTree (tree, command) end --- Create a command from a simple content tree. ---- It encapsulates the content in a command node. ----@param command string command name ----@param options table command options ----@param content table child AST tree ----@param position table position in source (or parent AST command node) ----@return table AST command node +-- It encapsulates the content in a command node. +-- @tparam string command command name +-- @tparam table options command options +-- @tparam table content child AST tree +-- @tparam table position position in source (or parent AST command node) +-- @treturn table AST command node function ast.createCommand (command, options, content, position) local result = { content } result.options = options or {} @@ -56,12 +57,12 @@ function ast.createCommand (command, options, content, position) end --- Create a command from a structured content tree. ---- The content is normally a table of an already prepared content list. ----@param command string command name ----@param options table command options ----@param content table child AST tree ----@param position table position in source (or parent AST command node) ----@return table AST command node +-- The content is normally a table of an already prepared content list. +-- @tparam string command command name +-- @tparam table options command options +-- @tparam table content child AST tree +-- @tparam table position position in source (or parent AST command node) +-- @treturn table AST command node function ast.createStructuredCommand (command, options, content, position) local result = type(content) == "table" and content or { content } result.options = options or {} @@ -80,9 +81,9 @@ function ast.createStructuredCommand (command, options, content, position) end --- Extract the sub-content tree from a (command) node, ---- that is the child nodes of the (command) node. ----@param content table AST tree ----@return table AST tree +-- that is the child nodes of the (command) node. +-- @tparam table content AST tree +-- @treturn table AST tree function ast.subContent (content) local out = {} for _, val in ipairs(content) do @@ -101,8 +102,8 @@ end --- Content tree trimming: remove leading and trailing spaces, but from --- a content tree i.e. possibly containing several elements. ----@param content table AST tree ----@return table AST tree +-- @tparam table content AST tree +-- @treturn table AST tree function ast.trimSubContent (content) if #content == 0 then return @@ -123,10 +124,10 @@ function ast.trimSubContent (content) end --- Process the AST walking through content nodes as a "structure": ---- Text nodes are ignored (e.g. usually just spaces due to indentation) ---- Command options are enriched with their "true" node position, so we can later ---- refer to it (as with an XPath pos()). ----@param content table AST tree +-- Text nodes are ignored (e.g. usually just spaces due to indentation) +-- Command options are enriched with their "true" node position, so we can later +-- refer to it (as with an XPath pos()). +-- @tparam table content AST tree function ast.processAsStructure (content) local iElem = 0 local nElem = 0 @@ -147,9 +148,9 @@ function ast.processAsStructure (content) end --- Call `action` on each content AST node, recursively, including `content` itself. ---- Not called on leaves, i.e. strings. ----@param content table AST tree ----@param action function function to call on each node +-- Not called on leaves, i.e. strings. +-- @tparam table content AST tree +-- @tparam function action A function to call on each node function ast.walkContent (content, action) if type(content) ~= "table" then return @@ -161,12 +162,12 @@ function ast.walkContent (content, action) end --- Strip position, line and column recursively from a content tree. ---- This can be used to remove position details where we do not want them, ---- e.g. in table of contents entries (referring to the original content, ---- regardless where it was exactly, for the purpose of checking whether ---- the table of contents changed.) ----@param content table AST tree ----@return table AST tree +-- This can be used to remove position details where we do not want them, +-- e.g. in table of contents entries (referring to the original content, +-- regardless where it was exactly, for the purpose of checking whether +-- the table of contents changed.) +-- @param table content AST tree +-- @treturn table AST tree function ast.stripContentPos (content) if type(content) ~= "table" then return content @@ -185,9 +186,9 @@ function ast.stripContentPos (content) end --- Flatten content trees into just the string components (allows passing ---- objects with complex structures to functions that need plain strings) ---- @param content table AST tree ---- @return string string representation of content +-- objects with complex structures to functions that need plain strings) +-- @tparam table content AST tree +-- @treturn string A string representation of content function ast.contentToString (content) local string = "" for i = 1, #content do @@ -206,8 +207,8 @@ function ast.contentToString (content) end --- Check whether a content AST tree is empty. ----@param content table AST tree ----@return boolean true if content is not empty +-- @tparam table content AST tree +-- @treturn boolean true if content is not empty function ast.hasContent (content) return type(content) == "function" or type(content) == "table" and #content > 0 end diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 5119f306b..af5948c1a 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -1,22 +1,23 @@ ---- SILE.Utilities (aliased as SU) ---- @module SU ---- alias SU.utilities +--- SILE.utilities (aliased as SU) +-- @module SU +-- @alias utilities local bitshim = require("bitshim") local luautf8 = require("lua-utf8") local semver = require("semver") ---- @type utilities local utilities = {} local epsilon = 1E-12 +--- Generic +-- @section generic + --- Require that an option table contains a specific value, otherwise raise an error. ---- @param options Input table of options. ---- @param name Name of the required option. ---- @param context User friendly name of the function or calling context. ---- @param required_type The name of a data type that the option must sucessfully cast to. --- SU.required +-- @param options Input table of options. +-- @param name Name of the required option. +-- @param context User friendly name of the function or calling context. +-- @param required_type The name of a data type that the option must sucessfully cast to. utilities.required = function (options, name, context, required_type) if not options[name] then utilities.error(context.." needs a "..name.." parameter") end if required_type then @@ -29,6 +30,13 @@ local function preferbool () utilities.warn("Please use boolean values or strings such as 'true' and 'false' instead of 'yes' and 'no'.") end +--- Cast user intput into a boolean type. +-- User input content such as options typed into documents will return string values such as "true" or "false rather +-- than true or false types. This evaluates those strings or other inputs ane returns a consistent boolean type in +-- return. +-- @tparam nil|bool|string value Input value such as a string to evaluate for thruthyness. +-- @tparam[opt=false] boolean default Whether to assume inputs that don't specifically evaluate to something should be true or false. +-- @treturn boolean utilities.boolean = function (value, default) if value == false then return false end if value == true then return true end @@ -44,6 +52,10 @@ end local _skip_traceback_levels = 2 +--- Raise an error and exit. +-- Outputs a warning message via `warn`, then finishes up anything it can without processing more content, then exits. +-- @tparam string message The error message to give. +-- @tparam boolean isbug Whether or not hitting this error is expected to be a code bug (as opposed to misakes in user input). utilities.error = function (message, isbug) _skip_traceback_levels = 3 utilities.warn(message, isbug) @@ -54,6 +66,10 @@ utilities.error = function (message, isbug) error("", 2) end +--- Output a warning. +-- Outputs a warning message including identifying where in the processing SILE is at when the warning is given. +-- @tparam string message The error message to give. +-- @tparam boolean isbug Whether or not hitting this warning is expected to be a code bug (as opposed to misakes in user input). utilities.warn = function (message, isbug) if SILE.quiet then return end io.stderr:write("\n! " .. message) @@ -68,22 +84,42 @@ utilities.warn = function (message, isbug) io.stderr:write("\n") end +--- Output an information message. +-- @tparam string message utilities.msg = function (message) if SILE.quiet then return end io.stderr:write("\n! " .. message .. "\n") end +--- Determine if a specific debug flag is set. +-- @tparam string category Name of the flag status to check, e.g. "frames". +-- @treturn boolean utilities.debugging = function (category) return SILE.debugFlags.all and category ~= "profile" or SILE.debugFlags[category] end -utilities.feq = function (lhs, rhs) -- Float point equal +--- Math +-- @section math + +--- Check equality of floating point values. +-- Comparing floating point numbers using math functions in Lua may give different and unexpected answers depending on +-- the Lua VM and other environmental factors. This normalizes them using our standard internal epsilon value and +-- compares the absolute intereger value to avoid floating point number wierdness. +-- @tparam float lhs +-- @tparam float rhs +-- @treturn boolean +utilities.feq = function (lhs, rhs) lhs = SU.cast("number", lhs) rhs = SU.cast("number", rhs) local abs = math.abs return abs(lhs - rhs) <= epsilon * (abs(lhs) + abs(rhs)) end +--- Iterate over a string split into tokens via a pattern. +-- @tparam string string Input string. +-- @tparam string pattern Pattern on which to split the input. +-- @treturn function An iterator function +-- @usage for str in SU.gtoke("foo-bar-baz", "-") do print(str) end utilities.gtoke = function (string, pattern) string = string and tostring(string) or '' pattern = pattern and tostring(pattern) or "%s+" @@ -106,6 +142,15 @@ utilities.gtoke = function (string, pattern) end) end +--- Warn about use of a deprecated feature. +-- Checks the current version and decides whether to warn or error, then oatputs a message with as much useful +-- information as possible to make it easy for end users to update their usage. +-- @tparam string old The name of the deprecated interface. +-- @tparam string new A name of a suggested replacement interface. +-- @tparam string warnat The first release where the interface is considered deprecated, at which point their might be +-- a shim. +-- @tparam string errorat The first release where the interface is no longer functional even with a shim. +-- @tparam string extra Longer-form help to include in output separate from the expected one-liner of warning messages. utilities.deprecated = function (old, new, warnat, errorat, extra) warnat, errorat = semver(warnat or 0), semver(errorat or 0) local current = SILE.version and semver(SILE.version:match("v([0-9]*.[0-9]*.[0-9]*)")) or warnat @@ -124,6 +169,17 @@ utilities.deprecated = function (old, new, warnat, errorat, extra) end end +--- Output a debug message only if debugging for a specific category is enabled. +-- Importantly passing siries of strings, functions, or tables is more effecient than trying to formulate a full message +-- using concatentation and tostring() methods in the original code because it doesn't have to even run if the relevant +-- debug flag is not enabled. +-- @tparam text category Category flag for which this message should be output. +-- @tparam string|function|table ... Each argument will be returned separated by spaces, strings directly, functions by +-- evaluating them and assuming the return value is a string, and tables by using their internal :__tostring() methods. +-- @usage +-- > glue = SILE.types.node.glue("6em") +-- > SU.debug("foo", "A glue node", glue) +-- [foo] A glue node G<6em> utilities.debug = function (category, ...) if SILE.quiet then return end if utilities.debugging(category) then @@ -141,6 +197,9 @@ utilities.debug = function (category, ...) end end +--- Output developer friendly debugging view of an AST. +-- @tparam table ast Abstract Syntax Tree. +-- @tparam integer level Starting level to review. utilities.debugAST = function (ast, level) if not ast then SU.error("debugAST called with nil", true) @@ -180,15 +239,24 @@ utilities.debugAST = function (ast, level) if level == 0 then SU.debug("ast", "]") end end +--- Dump the contents of a any Lua type. +-- For quick debugging, can be used on any number of any type of Lua value. Pretty-prints tables. +-- @tparam any ... Any number of values utilities.dump = function (...) local arg = { ... } -- Avoid things that Lua stuffs in arg like args to self() pl.pretty.dump(#arg == 1 and arg[1] or arg, "/dev/stderr") end +--- Concatenate values from a table using a given separator. +-- Differs from `table.concat` in that all values are explicitly cast to strings, allowing debugging of tables that +-- include functions, other tables, data types, etc. +-- @tparam table array Input. +-- @tparam[opt=" "] string separator Separator. utilities.concat = function (array, separator) return table.concat(utilities.map(tostring, array), separator) end +-- TODO: Unused, now deprecated? utilities.inherit = function (orig, spec) local new = pl.tablex.deepcopy(orig) if spec then @@ -198,6 +266,9 @@ utilities.inherit = function (orig, spec) return new end +--- Execute a callback function on each value in a table. +-- @tparam function func Function to run on each value. +-- @tparam table array Input list-like table. utilities.map = function (func, array) local new_array = {} local last = #array @@ -207,6 +278,11 @@ utilities.map = function (func, array) return new_array end +--- Iterate over key/value pairs in sequence of the sorted keys. +-- Table iteration order with `pairs` is non-deterministic. This function returns an iterator that can be used in plais +-- of `pairs` that will iterate through the values in the order of their *sorted* keys. +-- @tparam table input Input table. +-- @usage for val in SU.sortedpairs({ b: "runs second", a: "runs first" ) do print(val) end utilities.sortedpairs = function (input) local keys = {} for k, _ in pairs(input) do @@ -225,6 +301,12 @@ utilities.sortedpairs = function (input) end) end +--- Substitute a range of value(s) in one table with values from another. +-- @tparam table array Table to modify. +-- @tparam integer start First key to replace. +-- @tparam integer stop Last key to replace. +-- @tparam table replacement Table from which to pull key/values plairs to inject in array. +-- @treturn table array First input array modified with values from replacement. utilities.splice = function (array, start, stop, replacement) local ptr = start local room = stop - start + 1 @@ -245,6 +327,9 @@ utilities.splice = function (array, start, stop, replacement) return array end +--- Add up all the values in a table. +-- @tparam table array Input list-like table. +-- @treturn number Sum of all values. utilities.sum = function (array) local total = 0 local last = #array @@ -254,7 +339,9 @@ utilities.sum = function (array) return total end --- Lua <= 5.2 can't handle objects in math functions +--- Return maximum value of inputs. +-- `math.max`, but works on SILE types such as SILE.types.measurement. +-- Lua <= 5.2 can't handle math operators on objects. utilities.max = function (...) local input = pl.utils.pack(...) local max = table.remove(input, 1) @@ -264,6 +351,9 @@ utilities.max = function (...) return max end +--- Return minimum value of inputs. +-- `math.min`, but works on SILE types such as SILE.types.measurement. +-- Lua <= 5.2 can't handle math operators on objects. utilities.min = function (...) local input = pl.utils.pack(...) local min = input[1] @@ -273,6 +363,7 @@ utilities.min = function (...) return min end +--- Round and normalize a number for debugging. -- LuaJIT 2.1 betas (and inheritors such as OpenResty and Moonjit) are biased -- towards rounding 0.5 up to 1, all other Lua interpreters are biased -- towards rounding such floating point numbers down. This hack shaves off @@ -281,12 +372,19 @@ end -- inherent to the floating point type. Also note we are erroring in favor of -- the *less* common option because the LuaJIT VMS are hopelessly broken -- whereas normal LUA VMs can be cooerced. +-- @tparam number input Input value. +-- @treturn string Four-digit precision foating point. utilities.debug_round = function (input) if input > 0 then input = input + .00000000000001 end if input < 0 then input = input - .00000000000001 end return string.format("%.4f", input) end +--- Remove empty spaces from list-like tables +-- Iterating list-like tables is hard if some values have been removed. This converts { 1 = "a", 3 = "b" } into +-- { 1 = "a", 2 = "b" } which can be iterated using `ipairs()` without stopping after 1. +-- @tparam table items List-like table potentially with holes. +-- @treturn table List like table without holes. utilities.compress = function (items) local rv = {} local max = math.max(pl.utils.unpack(pl.tablex.keys(items))) @@ -294,6 +392,8 @@ utilities.compress = function (items) return rv end +--- Reverse the order of a list-like table. +-- @tparam table tbl Input list-like table. utilities.flip_in_place = function (tbl) local tmp, j for i = 1, math.floor(#tbl / 2) do @@ -304,6 +404,7 @@ utilities.flip_in_place = function (tbl) end end +-- TODO: Before documenting, consider whether this should be private to the one existing usage. utilities.allCombinations = function (options) local count = 1 for i=1,#options do count = count * options[i] end @@ -321,6 +422,11 @@ utilities.allCombinations = function (options) end) end +--- Return the type of an object +-- Like `type`, but also handles various SILE user data types. +-- @tparam any value Any input value. If a table is one of SILE's classes or types, report on it's internal type. +-- Otherwise use the output of `type`. +-- @treturn string utilities.type = function(value) if type(value) == "number" then return math.floor(value) == value and "integer" or "number" @@ -333,6 +439,12 @@ utilities.type = function(value) end end +--- Cast user intput to an expected type. +-- If possible, converts input from one type to another. Not all types can be cast. For example "four" can't be cast to +-- a number, but "4" or 4 can. Likewise "6pt" or 6 can be cast to a SILE.types.measurement, SILE.types.length, or even +-- a SILE.types.node.glue, but not a SILE.types.color. +-- @tparam string wantedType Expected type. +-- @return A value of the type wantedType. utilities.cast = function (wantedType, value) local actualType = SU.type(value) wantedType = string.lower(wantedType) @@ -386,12 +498,17 @@ utilities.rationWidth = function (target, width, ratio) return target end --- Unicode-related utilities +--- Unicode +-- @section utf8 + utilities.utf8char = function (c) utilities.deprecated("SU.utf8char", "luautf8.char", "0.11.0", "0.12.0") return luautf8.char(c) end +--- Convert a Unicode character to its corresponding codepoint. +-- @tparam string uchar A single inicode character. +-- @return number The Unicode code point where uchar is encoded. utilities.codepoint = function (uchar) local seq = 0 local val = -1 @@ -411,6 +528,9 @@ utilities.codepoint = function (uchar) return val end +--- Covert a code point to a Unicode character. +-- @tparam number|string codepoint Input code point value, either as a number or a string representing the decimal value "U+NNNN" or hex value "0xFFFF". +-- @treturn string The character replestened by a codepoint descriptions. utilities.utf8charfromcodepoint = function (codepoint) local val = codepoint local cp = val diff --git a/core/utilities/numbers.lua b/core/utilities/numbers.lua index b53cb2541..6bd6f3552 100644 --- a/core/utilities/numbers.lua +++ b/core/utilities/numbers.lua @@ -1,6 +1,5 @@ ---- Number formatting utilities ---- @submodule SU ---- submodule SU +--- Number formatting utilities. +--- @module SU.numbers local icu = require("justenoughicu") diff --git a/core/utilities/sorting.lua b/core/utilities/sorting.lua index 38a350e62..88a0402d2 100644 --- a/core/utilities/sorting.lua +++ b/core/utilities/sorting.lua @@ -1,7 +1,6 @@ --- --- Table sorting with language-dependent collation --- MIT License (c) 2022 SILE organization --- +--- Table sorting with language-dependent collation. +-- @module SU.sorting + local icu = require("justenoughicu") local collatedSort = { diff --git a/languages/fr.lua b/languages/fr.lua index f42e92a2d..919e75e7d 100644 --- a/languages/fr.lua +++ b/languages/fr.lua @@ -1,4 +1,5 @@ --- French language rules +--- French language rules +-- @submodule SILE.languages local computeSpaces = function() -- Computes: diff --git a/typesetters/base.lua b/typesetters/base.lua index 0d7373cd0..729038135 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -991,12 +991,11 @@ function linerBox:__tostring () return "*L[" .. self.name .. "]H<" .. tostring(self.width) .. ">^" .. tostring(self.height) .. "-" .. tostring(self.depth) .. "v" end ---- Any unclosed liner is reopened on the current line, so we clone and repeat --- it. +--- Any unclosed liner is reopened on the current line, so we clone and repeat it. -- An assumption is that the inserts are done after the current slice content, -- supposed to be just before meaningful (visible) content. ----@param slice table Current line nodes ----@return boolean Whether a liner was reopened +-- @tparam slice slice +-- @treturn boolean Whether a liner was reopened function typesetter:_repeatEnterLiners (slice) local m = self.state.liners if #m > 0 then @@ -1012,8 +1011,8 @@ end --- All pairs of liners are rebuilt as hboxes wrapping their content. -- Migrating content, however, must be kept outside the hboxes at top slice level. ----@param slice table Flat nodes from current line ----@return table New reboxed slice +-- @tparam table slice Flat nodes from current line +-- @treturn table New reboxed slice function typesetter._reboxLiners (_, slice) local outSlice = {} local migratingList = {} @@ -1061,8 +1060,8 @@ function typesetter._reboxLiners (_, slice) end --- Check if a node is a liner, and process it if so, in a stack. ----@param node any Current node ----@return boolean Whether a liner was opened +-- @tparam table node Current node (any type) +-- @treturn boolean Whether a liner was opened function typesetter:_processIfLiner(node) local entered = false if node.is_enter then @@ -1384,9 +1383,9 @@ end -- effects. -- If we are already in horizontal-restricted mode, the liner is processed -- immediately, since line breaking won't occur then. ----@param name string Name of the liner (usefull for debugging) ----@param content table SILE AST to process ----@param outputYourself function Output method for wrapped boxes +-- @tparam string name Name of the liner (usefull for debugging) +-- @tparam table content SILE AST to process +-- @tparam function outputYourself Output method for wrapped boxes function typesetter:liner (name, content, outputYourself) if self.state.hmodeOnly then SU.debug("typesetter.liner", "Applying liner in horizontal-restricted mode") From 79f6aad35d3f146e0c04716569ac772c03790c0c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 12 Feb 2024 16:31:22 +0300 Subject: [PATCH 325/357] chore(utilities): Move deprecated functions to deprecations file --- core/deprecations.lua | 8 ++++++++ core/sile.lua | 10 +++++----- core/utilities/init.lua | 10 ---------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/core/deprecations.lua b/core/deprecations.lua index 5875bb627..4bddc87ca 100644 --- a/core/deprecations.lua +++ b/core/deprecations.lua @@ -138,6 +138,14 @@ setmetatable(SILE.PackageManager, { __index = nopackagemanager }) +SU.utf8char = function () + SU.deprecated("SU.utf8char", "luautf8.char", "0.11.0", "0.12.0") +end + +SU.utf8codes = function () + SU.deprecated("SU.utf8codes", "luautf8.codes", "0.11.0", "0.12.0") +end + -- luacheck: ignore updatePackage -- luacheck: ignore installPackage updatePackage = nopackagemanager diff --git a/core/sile.lua b/core/sile.lua index d54bcd736..c41270f93 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -65,11 +65,6 @@ SILE.full_version = string.format("SILE %s (%s)", SILE.version, SILE.lua_isjit a -- Backport of lots of Lua 5.3 features to Lua 5.[12] if not SILE.lua_isjit and SILE.lua_version < "5.3" then require("compat53") end --- For warnings and shims scheduled for removal that are easier to keep track --- of when they are not spread across so many locations... --- Loaded early to make it easier to manage migrations in core code. -require("core/deprecations") - --- Modules -- @section modules @@ -78,6 +73,11 @@ require("core/deprecations") SILE.utilities = require("core.utilities") SU = SILE.utilities -- regrettable global alias +-- For warnings and shims scheduled for removal that are easier to keep track +-- of when they are not spread across so many locations... +-- Loaded early to make it easier to manage migrations in core code. +require("core/deprecations") + -- On demand loader, allows modules to be loaded into a specific scope but -- only when/if accessed. local function core_loader (scope) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index af5948c1a..3493ade09 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -501,11 +501,6 @@ end --- Unicode -- @section utf8 -utilities.utf8char = function (c) - utilities.deprecated("SU.utf8char", "luautf8.char", "0.11.0", "0.12.0") - return luautf8.char(c) -end - --- Convert a Unicode character to its corresponding codepoint. -- @tparam string uchar A single inicode character. -- @return number The Unicode code point where uchar is encoded. @@ -547,11 +542,6 @@ utilities.utf8charfromcodepoint = function (codepoint) return val end -utilities.utf8codes = function (ustr) - utilities.deprecated("SU.utf8codes", "luautf8.codes", "0.11.0", "0.12.0") - return luautf8.codes(ustr) -end - utilities.utf16codes = function (ustr, endian) local pos = 1 return function() From eea28def07b81d6de97673cf65a337e6261a8b3d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 12 Feb 2024 16:51:10 +0300 Subject: [PATCH 326/357] docs(api): Expand utilities docs and re-order for some sectioning --- core/utilities/init.lua | 551 ++++++++++++++++++++++------------------ 1 file changed, 306 insertions(+), 245 deletions(-) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 3493ade09..8dc00de0b 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -13,6 +13,27 @@ local epsilon = 1E-12 --- Generic -- @section generic +--- Concatenate values from a table using a given separator. +-- Differs from `table.concat` in that all values are explicitly cast to strings, allowing debugging of tables that +-- include functions, other tables, data types, etc. +-- @tparam table array Input. +-- @tparam[opt=" "] string separator Separator. +utilities.concat = function (array, separator) + return table.concat(utilities.map(tostring, array), separator) +end + +--- Execute a callback function on each value in a table. +-- @tparam function func Function to run on each value. +-- @tparam table array Input list-like table. +utilities.map = function (func, array) + local new_array = {} + local last = #array + for i = 1, last do + new_array[i] = func(array[i]) + end + return new_array +end + --- Require that an option table contains a specific value, otherwise raise an error. -- @param options Input table of options. -- @param name Name of the required option. @@ -26,6 +47,68 @@ utilities.required = function (options, name, context, required_type) return options[name] end +--- Iterate over key/value pairs in sequence of the sorted keys. +-- Table iteration order with `pairs` is non-deterministic. This function returns an iterator that can be used in plais +-- of `pairs` that will iterate through the values in the order of their *sorted* keys. +-- @tparam table input Input table. +-- @usage for val in SU.sortedpairs({ b: "runs second", a: "runs first" ) do print(val) end +utilities.sortedpairs = function (input) + local keys = {} + for k, _ in pairs(input) do + keys[#keys+1] = k + end + table.sort(keys, function(a, b) + if type(a) == type(b) then return a < b + elseif type(a) == "number" then return true + else return false + end + end) + return coroutine.wrap(function() + for i = 1, #keys do + coroutine.yield(keys[i], input[keys[i]]) + end + end) +end + +--- Substitute a range of value(s) in one table with values from another. +-- @tparam table array Table to modify. +-- @tparam integer start First key to replace. +-- @tparam integer stop Last key to replace. +-- @tparam table replacement Table from which to pull key/values plairs to inject in array. +-- @treturn table array First input array modified with values from replacement. +utilities.splice = function (array, start, stop, replacement) + local ptr = start + local room = stop - start + 1 + local last = replacement and #replacement or 0 + for i = 1, last do + if room > 0 then + room = room - 1 + array[ptr] = replacement[i] + else + table.insert(array, ptr, replacement[i]) + end + ptr = ptr + 1 + end + + for _ = 1, room do + table.remove(array, ptr) + end + return array +end + +-- TODO: Unused, now deprecated? +utilities.inherit = function (orig, spec) + local new = pl.tablex.deepcopy(orig) + if spec then + for k,v in pairs(spec) do new[k] = v end + end + if new.init then new:init() end + return new +end + +--- Type handling +-- @section types + local function preferbool () utilities.warn("Please use boolean values or strings such as 'true' and 'false' instead of 'yes' and 'no'.") end @@ -50,125 +133,70 @@ utilities.boolean = function (value, default) return default == true end -local _skip_traceback_levels = 2 - ---- Raise an error and exit. --- Outputs a warning message via `warn`, then finishes up anything it can without processing more content, then exits. --- @tparam string message The error message to give. --- @tparam boolean isbug Whether or not hitting this error is expected to be a code bug (as opposed to misakes in user input). -utilities.error = function (message, isbug) - _skip_traceback_levels = 3 - utilities.warn(message, isbug) - _skip_traceback_levels = 2 - io.stderr:flush() - SILE.outputter:finish() -- Only really useful from the REPL but no harm in trying - SILE.scratch.caughterror = true - error("", 2) -end - ---- Output a warning. --- Outputs a warning message including identifying where in the processing SILE is at when the warning is given. --- @tparam string message The error message to give. --- @tparam boolean isbug Whether or not hitting this warning is expected to be a code bug (as opposed to misakes in user input). -utilities.warn = function (message, isbug) - if SILE.quiet then return end - io.stderr:write("\n! " .. message) - if SILE.traceback or isbug then - io.stderr:write(" at:\n" .. SILE.traceStack:locationTrace()) - if _skip_traceback_levels == 2 then - io.stderr:write(debug.traceback("", _skip_traceback_levels) or "\t! debug.traceback() did not identify code location") +--- Cast user intput to an expected type. +-- If possible, converts input from one type to another. Not all types can be cast. For example "four" can't be cast to +-- a number, but "4" or 4 can. Likewise "6pt" or 6 can be cast to a SILE.types.measurement, SILE.types.length, or even +-- a SILE.types.node.glue, but not a SILE.types.color. +-- @tparam string wantedType Expected type. +-- @return A value of the type wantedType. +utilities.cast = function (wantedType, value) + local actualType = SU.type(value) + wantedType = string.lower(wantedType) + if wantedType:match(actualType) then return value + elseif actualType == "nil" and wantedType:match("nil") then return nil + elseif wantedType:match("length") then return SILE.types.length(value) + elseif wantedType:match("measurement") then return SILE.types.measurement(value) + elseif wantedType:match("vglue") then return SILE.types.node.vglue(value) + elseif wantedType:match("glue") then return SILE.types.node.glue(value) + elseif wantedType:match("kern") then return SILE.types.node.kern(value) + elseif actualType == "nil" then SU.error("Cannot cast nil to " .. wantedType) + elseif wantedType:match("boolean") then return SU.boolean(value) + elseif wantedType:match("string") then return tostring(value) + elseif wantedType:match("number") then + if type(value) == "table" and type(value.tonumber) == "function" then + return value:tonumber() end - else - io.stderr:write(" at " .. SILE.traceStack:locationHead()) + local num = tonumber(value) + if not num then SU.error("Cannot cast '" .. value .. "'' to " .. wantedType) end + return num + elseif wantedType:match("integer") then + local num + if type(value) == "table" and type(value.tonumber) == "function" then + num = value:tonumber() + else + num = tonumber(value) + end + if not num then SU.error("Cannot cast '" .. value .. "'' to " .. wantedType) end + if not wantedType:match("number") and num % 1 ~= 0 then + -- Could be an error but since it wasn't checked before, let's just warn: + -- Some packages might have wrongly typed settings, for instance. + SU.warn("Casting an integer but got a float number " .. num) + end + return num + else SU.error("Cannot cast to unrecognized type " .. wantedType) end - io.stderr:write("\n") end ---- Output an information message. --- @tparam string message -utilities.msg = function (message) - if SILE.quiet then return end - io.stderr:write("\n! " .. message .. "\n") -end - ---- Determine if a specific debug flag is set. --- @tparam string category Name of the flag status to check, e.g. "frames". --- @treturn boolean -utilities.debugging = function (category) - return SILE.debugFlags.all and category ~= "profile" or SILE.debugFlags[category] -end - ---- Math --- @section math - ---- Check equality of floating point values. --- Comparing floating point numbers using math functions in Lua may give different and unexpected answers depending on --- the Lua VM and other environmental factors. This normalizes them using our standard internal epsilon value and --- compares the absolute intereger value to avoid floating point number wierdness. --- @tparam float lhs --- @tparam float rhs --- @treturn boolean -utilities.feq = function (lhs, rhs) - lhs = SU.cast("number", lhs) - rhs = SU.cast("number", rhs) - local abs = math.abs - return abs(lhs - rhs) <= epsilon * (abs(lhs) + abs(rhs)) -end - ---- Iterate over a string split into tokens via a pattern. --- @tparam string string Input string. --- @tparam string pattern Pattern on which to split the input. --- @treturn function An iterator function --- @usage for str in SU.gtoke("foo-bar-baz", "-") do print(str) end -utilities.gtoke = function (string, pattern) - string = string and tostring(string) or '' - pattern = pattern and tostring(pattern) or "%s+" - local length = #string - return coroutine.wrap(function() - local index = 1 - repeat - local first, last = string:find(pattern, index) - if last then - if index < first then coroutine.yield({ string = string:sub(index, first - 1) }) end - coroutine.yield({ separator = string:sub(first, last) }) - index = last + 1 - else - if index <= length then - coroutine.yield({ string = string:sub(index) }) - end - break - end - until index > length - end) -end - ---- Warn about use of a deprecated feature. --- Checks the current version and decides whether to warn or error, then oatputs a message with as much useful --- information as possible to make it easy for end users to update their usage. --- @tparam string old The name of the deprecated interface. --- @tparam string new A name of a suggested replacement interface. --- @tparam string warnat The first release where the interface is considered deprecated, at which point their might be --- a shim. --- @tparam string errorat The first release where the interface is no longer functional even with a shim. --- @tparam string extra Longer-form help to include in output separate from the expected one-liner of warning messages. -utilities.deprecated = function (old, new, warnat, errorat, extra) - warnat, errorat = semver(warnat or 0), semver(errorat or 0) - local current = SILE.version and semver(SILE.version:match("v([0-9]*.[0-9]*.[0-9]*)")) or warnat - -- SILE.version is defined *after* most of SILE loads. It’s available at - -- runtime but not useful if we encounter deprecated code in core code. Users - -- will never encounter this failure, but as a developer it’s hard to test a - -- deprecation when core code refactoring is an all-or-nothing proposition. - -- Hence we fake it ‘till we make it, all deprecations internally are warnings. - local brackets = old:sub(1,1) == '\\' and "" or "()" - local _new = new and "Please use " .. (new .. brackets) .. " instead." or "Plase don't use it." - local msg = (old .. brackets) .. " was deprecated in SILE v" .. tostring(warnat) .. ". " .. _new .. (extra and ("\n\n" .. extra .. "\n") or "") - if errorat and current >= errorat then - SU.error(msg) - elseif warnat and current >= warnat then - SU.warn(msg) +--- Return the type of an object +-- Like Lua's `type`, but also handles various SILE user data types. +-- @tparam any value Any input value. If a table is one of SILE's classes or types, report on it's internal type. +-- Otherwise use the output of `type`. +-- @treturn string +utilities.type = function(value) + if type(value) == "number" then + return math.floor(value) == value and "integer" or "number" + elseif type(value) == "table" and value.prototype then + return value:prototype() + elseif type(value) == "table" and value.is_a then + return value.type + else + return type(value) end end +--- Errors and debugging +-- @section errors + --- Output a debug message only if debugging for a specific category is enabled. -- Importantly passing siries of strings, functions, or tables is more effecient than trying to formulate a full message -- using concatentation and tostring() methods in the original code because it doesn't have to even run if the relevant @@ -197,6 +225,13 @@ utilities.debug = function (category, ...) end end +--- Determine if a specific debug flag is set. +-- @tparam string category Name of the flag status to check, e.g. "frames". +-- @treturn boolean +utilities.debugging = function (category) + return SILE.debugFlags.all and category ~= "profile" or SILE.debugFlags[category] +end + --- Output developer friendly debugging view of an AST. -- @tparam table ast Abstract Syntax Tree. -- @tparam integer level Starting level to review. @@ -239,6 +274,33 @@ utilities.debugAST = function (ast, level) if level == 0 then SU.debug("ast", "]") end end +--- Warn about use of a deprecated feature. +-- Checks the current version and decides whether to warn or error, then oatputs a message with as much useful +-- information as possible to make it easy for end users to update their usage. +-- @tparam string old The name of the deprecated interface. +-- @tparam string new A name of a suggested replacement interface. +-- @tparam string warnat The first release where the interface is considered deprecated, at which point their might be +-- a shim. +-- @tparam string errorat The first release where the interface is no longer functional even with a shim. +-- @tparam string extra Longer-form help to include in output separate from the expected one-liner of warning messages. +utilities.deprecated = function (old, new, warnat, errorat, extra) + warnat, errorat = semver(warnat or 0), semver(errorat or 0) + local current = SILE.version and semver(SILE.version:match("v([0-9]*.[0-9]*.[0-9]*)")) or warnat + -- SILE.version is defined *after* most of SILE loads. It’s available at + -- runtime but not useful if we encounter deprecated code in core code. Users + -- will never encounter this failure, but as a developer it’s hard to test a + -- deprecation when core code refactoring is an all-or-nothing proposition. + -- Hence we fake it ‘till we make it, all deprecations internally are warnings. + local brackets = old:sub(1,1) == '\\' and "" or "()" + local _new = new and "Please use " .. (new .. brackets) .. " instead." or "Plase don't use it." + local msg = (old .. brackets) .. " was deprecated in SILE v" .. tostring(warnat) .. ". " .. _new .. (extra and ("\n\n" .. extra .. "\n") or "") + if errorat and current >= errorat then + SU.error(msg) + elseif warnat and current >= warnat then + SU.warn(msg) + end +end + --- Dump the contents of a any Lua type. -- For quick debugging, can be used on any number of any type of Lua value. Pretty-prints tables. -- @tparam any ... Any number of values @@ -247,84 +309,62 @@ utilities.dump = function (...) pl.pretty.dump(#arg == 1 and arg[1] or arg, "/dev/stderr") end ---- Concatenate values from a table using a given separator. --- Differs from `table.concat` in that all values are explicitly cast to strings, allowing debugging of tables that --- include functions, other tables, data types, etc. --- @tparam table array Input. --- @tparam[opt=" "] string separator Separator. -utilities.concat = function (array, separator) - return table.concat(utilities.map(tostring, array), separator) -end +local _skip_traceback_levels = 2 --- TODO: Unused, now deprecated? -utilities.inherit = function (orig, spec) - local new = pl.tablex.deepcopy(orig) - if spec then - for k,v in pairs(spec) do new[k] = v end - end - if new.init then new:init() end - return new +--- Raise an error and exit. +-- Outputs a warning message via `warn`, then finishes up anything it can without processing more content, then exits. +-- @tparam string message The error message to give. +-- @tparam boolean isbug Whether or not hitting this error is expected to be a code bug (as opposed to misakes in user input). +utilities.error = function (message, isbug) + _skip_traceback_levels = 3 + utilities.warn(message, isbug) + _skip_traceback_levels = 2 + io.stderr:flush() + SILE.outputter:finish() -- Only really useful from the REPL but no harm in trying + SILE.scratch.caughterror = true + error("", 2) end ---- Execute a callback function on each value in a table. --- @tparam function func Function to run on each value. --- @tparam table array Input list-like table. -utilities.map = function (func, array) - local new_array = {} - local last = #array - for i = 1, last do - new_array[i] = func(array[i]) - end - return new_array +--- Output an information message. +-- Basically like `warn`, except to source tracing information is added. +-- @tparam string message +utilities.msg = function (message) + if SILE.quiet then return end + io.stderr:write("\n! " .. message .. "\n") end ---- Iterate over key/value pairs in sequence of the sorted keys. --- Table iteration order with `pairs` is non-deterministic. This function returns an iterator that can be used in plais --- of `pairs` that will iterate through the values in the order of their *sorted* keys. --- @tparam table input Input table. --- @usage for val in SU.sortedpairs({ b: "runs second", a: "runs first" ) do print(val) end -utilities.sortedpairs = function (input) - local keys = {} - for k, _ in pairs(input) do - keys[#keys+1] = k - end - table.sort(keys, function(a, b) - if type(a) == type(b) then return a < b - elseif type(a) == "number" then return true - else return false - end - end) - return coroutine.wrap(function() - for i = 1, #keys do - coroutine.yield(keys[i], input[keys[i]]) +--- Output a warning. +-- Outputs a warning message including identifying where in the processing SILE is at when the warning is given. +-- @tparam string message The error message to give. +-- @tparam boolean isbug Whether or not hitting this warning is expected to be a code bug (as opposed to misakes in user input). +utilities.warn = function (message, isbug) + utilities.msg(message) + if SILE.traceback or isbug then + io.stderr:write(" at:\n" .. SILE.traceStack:locationTrace()) + if _skip_traceback_levels == 2 then + io.stderr:write(debug.traceback("", _skip_traceback_levels) or "\t! debug.traceback() did not identify code location") end - end) + else + io.stderr:write(" at " .. SILE.traceStack:locationHead()) + end + io.stderr:write("\n") end ---- Substitute a range of value(s) in one table with values from another. --- @tparam table array Table to modify. --- @tparam integer start First key to replace. --- @tparam integer stop Last key to replace. --- @tparam table replacement Table from which to pull key/values plairs to inject in array. --- @treturn table array First input array modified with values from replacement. -utilities.splice = function (array, start, stop, replacement) - local ptr = start - local room = stop - start + 1 - local last = replacement and #replacement or 0 - for i = 1, last do - if room > 0 then - room = room - 1 - array[ptr] = replacement[i] - else - table.insert(array, ptr, replacement[i]) - end - ptr = ptr + 1 - end +--- Math +-- @section math - for _ = 1, room do - table.remove(array, ptr) - end - return array +--- Check equality of floating point values. +-- Comparing floating point numbers using math functions in Lua may give different and unexpected answers depending on +-- the Lua VM and other environmental factors. This normalizes them using our standard internal epsilon value and +-- compares the absolute intereger value to avoid floating point number wierdness. +-- @tparam float lhs +-- @tparam float rhs +-- @treturn boolean +utilities.feq = function (lhs, rhs) + lhs = SU.cast("number", lhs) + rhs = SU.cast("number", rhs) + local abs = math.abs + return abs(lhs - rhs) <= epsilon * (abs(lhs) + abs(rhs)) end --- Add up all the values in a table. @@ -382,7 +422,7 @@ end --- Remove empty spaces from list-like tables -- Iterating list-like tables is hard if some values have been removed. This converts { 1 = "a", 3 = "b" } into --- { 1 = "a", 2 = "b" } which can be iterated using `ipairs()` without stopping after 1. +-- { 1 = "a", 2 = "b" } which can be iterated using `ipairs` without stopping after 1. -- @tparam table items List-like table potentially with holes. -- @treturn table List like table without holes. utilities.compress = function (items) @@ -422,66 +462,6 @@ utilities.allCombinations = function (options) end) end ---- Return the type of an object --- Like `type`, but also handles various SILE user data types. --- @tparam any value Any input value. If a table is one of SILE's classes or types, report on it's internal type. --- Otherwise use the output of `type`. --- @treturn string -utilities.type = function(value) - if type(value) == "number" then - return math.floor(value) == value and "integer" or "number" - elseif type(value) == "table" and value.prototype then - return value:prototype() - elseif type(value) == "table" and value.is_a then - return value.type - else - return type(value) - end -end - ---- Cast user intput to an expected type. --- If possible, converts input from one type to another. Not all types can be cast. For example "four" can't be cast to --- a number, but "4" or 4 can. Likewise "6pt" or 6 can be cast to a SILE.types.measurement, SILE.types.length, or even --- a SILE.types.node.glue, but not a SILE.types.color. --- @tparam string wantedType Expected type. --- @return A value of the type wantedType. -utilities.cast = function (wantedType, value) - local actualType = SU.type(value) - wantedType = string.lower(wantedType) - if wantedType:match(actualType) then return value - elseif actualType == "nil" and wantedType:match("nil") then return nil - elseif wantedType:match("length") then return SILE.types.length(value) - elseif wantedType:match("measurement") then return SILE.types.measurement(value) - elseif wantedType:match("vglue") then return SILE.types.node.vglue(value) - elseif wantedType:match("glue") then return SILE.types.node.glue(value) - elseif wantedType:match("kern") then return SILE.types.node.kern(value) - elseif actualType == "nil" then SU.error("Cannot cast nil to " .. wantedType) - elseif wantedType:match("boolean") then return SU.boolean(value) - elseif wantedType:match("string") then return tostring(value) - elseif wantedType:match("number") then - if type(value) == "table" and type(value.tonumber) == "function" then - return value:tonumber() - end - local num = tonumber(value) - if not num then SU.error("Cannot cast '" .. value .. "'' to " .. wantedType) end - return num - elseif wantedType:match("integer") then - local num - if type(value) == "table" and type(value.tonumber) == "function" then - num = value:tonumber() - else - num = tonumber(value) - end - if not num then SU.error("Cannot cast '" .. value .. "'' to " .. wantedType) end - if not wantedType:match("number") and num % 1 ~= 0 then - -- Could be an error but since it wasn't checked before, let's just warn: - -- Some packages might have wrongly typed settings, for instance. - SU.warn("Casting an integer but got a float number " .. num) - end - return num - else SU.error("Cannot cast to unrecognized type " .. wantedType) - end -end utilities.rateBadness = function(inf_bad, shortfall, spring) if spring == 0 then return inf_bad end @@ -498,8 +478,35 @@ utilities.rationWidth = function (target, width, ratio) return target end ---- Unicode --- @section utf8 +--- Text handling +-- @section text + +--- Iterate over a string split into tokens via a pattern. +-- @tparam string string Input string. +-- @tparam string pattern Pattern on which to split the input. +-- @treturn function An iterator function +-- @usage for str in SU.gtoke("foo-bar-baz", "-") do print(str) end +utilities.gtoke = function (string, pattern) + string = string and tostring(string) or '' + pattern = pattern and tostring(pattern) or "%s+" + local length = #string + return coroutine.wrap(function() + local index = 1 + repeat + local first, last = string:find(pattern, index) + if last then + if index < first then coroutine.yield({ string = string:sub(index, first - 1) }) end + coroutine.yield({ separator = string:sub(first, last) }) + index = last + 1 + else + if index <= length then + coroutine.yield({ string = string:sub(index) }) + end + break + end + until index > length + end) +end --- Convert a Unicode character to its corresponding codepoint. -- @tparam string uchar A single inicode character. @@ -542,6 +549,11 @@ utilities.utf8charfromcodepoint = function (codepoint) return val end +--- Convert a UTF-16 encoded string to a series of code points. +-- Like `luautf8.codes`, but for UTF-16 strings. +-- @tparam string ustr Input string. +-- @tparam string endian Either "le" or "be" depending on the enconding endedness. +-- @treturn string Serious of hex encoded code points. utilities.utf16codes = function (ustr, endian) local pos = 1 return function() @@ -575,7 +587,12 @@ utilities.utf16codes = function (ustr, endian) end end -utilities.splitUtf8 = function (str) -- Return an array of UTF8 strings each representing a Unicode char +--- Split a UTF-8 string into characters. +-- Lua's `string.split` will only explode a string by bytes. For text processing purposes it is usually more desirable +-- to split it into 1, 2, 3, or 4 byte grups matching the UTF-8 encoding. +-- @tparam string str Input UTF-8 encoded string. +-- @treturn table A list-like table of UTF8 strings each representing a Unicode char from the input string. +utilities.splitUtf8 = function (str) local rv = {} for _, cp in luautf8.next, str do table.insert(rv, luautf8.char(cp)) @@ -583,11 +600,21 @@ utilities.splitUtf8 = function (str) -- Return an array of UTF8 strings each rep return rv end +--- The last Unicode character in a UTF-8 encoded string. +-- Uses `SU.splitUtf8` to break an string into segments represtenting encoded characters, returns the last one. May be +-- more than one byte. +-- @tparam string str Input string. +-- @treturn string A single Unicode character. utilities.lastChar = function (str) local chars = utilities.splitUtf8(str) return chars[#chars] end +--- The first Unicode character in a UTF-8 encoded string. +-- Uses `SU.splitUtf8` to break an string into segments represtenting encoded characters, returns the first one. May be +-- more than one byte. +-- @tparam string str Input string. +-- @treturn string A single Unicode character. utilities.firstChar = function (str) local chars = utilities.splitUtf8(str) return chars[1] @@ -595,6 +622,12 @@ end local byte, floor, reverse = string.byte, math.floor, string.reverse +--- The Unicode character in a UTF-8 encoded string at a specifi position +-- Uses `SU.splitUtf8` to break an string into segments represtenting encoded characters, returns the Nth one. May be +-- more than one byte. +-- @tparam string str Input string. +-- @tparam number index Index of character to return. +-- @treturn string A single Unicode character. utilities.utf8charat = function (str, index) return str:sub(index):match("([%z\1-\127\194-\244][\128-\191]*)") end @@ -603,6 +636,9 @@ local utf16bom = function(endianness) return endianness == "be" and "\254\255" or endianness == "le" and "\255\254" or SU.error("Unrecognized endianness") end +--- Encode a string to a hexidecimal replesentation. +-- @tparam string str Input UTF-8 string +-- @treturn string Hexidecimal replesentation of str. utilities.hexencoded = function (str) local ustr = "" for i = 1, #str do @@ -611,6 +647,9 @@ utilities.hexencoded = function (str) return ustr end +--- Decode a hexidecimal replesentation into a string. +-- @tparam string str Input hexidecimal encoded string. +-- @treturn string UTF-8 string. utilities.hexdecoded = function (str) if #str % 2 == 1 then SU.error("Cannot decode hex string with odd len") end local ustr = "" @@ -640,9 +679,24 @@ local utf8_to_utf16 = function(str, endianness) return ustr end +--- Convert a UTF-8 string to big-endian UTF-16. +-- @tparam string str UTF-8 encoded string. +-- @treturn string Big-endian UTF-16 encoded string. utilities.utf8_to_utf16be = function (str) return utf8_to_utf16(str, "be") end + +--- Convert a UTF-8 string to little-endian UTF-16. +-- @tparam string str UTF-8 encoded string. +-- @treturn string Little-endian UTF-16 encoded string. utilities.utf8_to_utf16le = function (str) return utf8_to_utf16(str, "le") end + +--- Convert a UTF-8 string to big-endian UTF-16, then encode in hex. +-- @tparam string str UTF-8 encoded string. +-- @treturn string Hexidecimal representation of a big-endian UTF-16 encoded string. utilities.utf8_to_utf16be_hexencoded = function (str) return utilities.hexencoded(utilities.utf8_to_utf16be(str)) end + +--- Convert a UTF-8 string to little-endian UTF-16, then encode in hex. +-- @tparam string str UTF-8 encoded string. +-- @treturn string Hexidecimal representation of a little-endian UTF-16 encoded string. utilities.utf8_to_utf16le_hexencoded = function (str) return utilities.hexencoded(utilities.utf8_to_utf16le(str)) end local utf16_to_utf8 = function (str, endianness) @@ -656,7 +710,14 @@ local utf16_to_utf8 = function (str, endianness) return ustr end +--- Convert a big-endian UTF-16 string to UTF-8. +-- @tparam string str Big-endian UTF-16 encoded string. +-- @treturn string UTF-8 encoded string. utilities.utf16be_to_utf8 = function (str) return utf16_to_utf8(str, "be") end + +--- Convert a little-endian UTF-16 string to UTF-8. +-- @tparam string str Little-endian UTF-16 encoded string. +-- @treturn string UTF-8 encoded string. utilities.utf16le_to_utf8 = function (str) return utf16_to_utf8(str, "le") end utilities.breadcrumbs = function () From 78d90084c4cffbe9a7c06ae117f8b2f216c07430 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 12 Feb 2024 17:28:25 +0300 Subject: [PATCH 327/357] refactor(utilities): Move AST debug function into related module --- core/utilities/ast.lua | 42 ++++++++++++++++++++++++++++++++++++++++ core/utilities/init.lua | 43 +---------------------------------------- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/core/utilities/ast.lua b/core/utilities/ast.lua index 3e5b27c6f..650d3469c 100644 --- a/core/utilities/ast.lua +++ b/core/utilities/ast.lua @@ -5,6 +5,48 @@ -- @type SU.ast local ast = {} +--- Output developer friendly debugging view of an AST. +-- @tparam table tree Abstract Syntax Tree. +-- @tparam integer level Starting level to review. +function ast.debug (tree, level) + if not tree then + SU.error("debugAST called with nil", true) + end + local out = string.rep(" ", 1+level) + if level == 0 then + SU.debug("ast", function () + return "[" .. SILE.currentlyProcessingFile + end) + end + if type(tree) == "function" then + SU.debug("ast", function () + return out .. tostring(tree) + end) + elseif type(tree) == "table" then + for _, content in ipairs(tree) do + if type(content) == "string" then + SU.debug("ast", function () + return out .. "[" .. content .. "]" + end) + elseif type(content) == "table" then + if SILE.Commands[content.command] then + SU.debug("ast", function () + return out .. "\\" .. content.command .. " " .. pl.pretty.write(content.options, "") + end) + if (#content>=1) then ast.debug(content, level+1) end + elseif content.id == "content" or (not content.command and not content.id) then + ast.debug(content, level+1) + else + SU.debug("ast", function () + return out .. "?\\" .. (content.command or content.id) + end) + end + end + end + end + if level == 0 then SU.debug("ast", "]") end +end + --- Find a command node in a SILE AST tree, -- looking only at the first level. -- (We're not reimplementing XPath here.) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 8dc00de0b..72749c318 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -232,48 +232,6 @@ utilities.debugging = function (category) return SILE.debugFlags.all and category ~= "profile" or SILE.debugFlags[category] end ---- Output developer friendly debugging view of an AST. --- @tparam table ast Abstract Syntax Tree. --- @tparam integer level Starting level to review. -utilities.debugAST = function (ast, level) - if not ast then - SU.error("debugAST called with nil", true) - end - local out = string.rep(" ", 1+level) - if level == 0 then - SU.debug("ast", function () - return "[" .. SILE.currentlyProcessingFile - end) - end - if type(ast) == "function" then - SU.debug("ast", function () - return out .. tostring(ast) - end) - elseif type(ast) == "table" then - for _, content in ipairs(ast) do - if type(content) == "string" then - SU.debug("ast", function () - return out .. "[" .. content .. "]" - end) - elseif type(content) == "table" then - if SILE.Commands[content.command] then - SU.debug("ast", function () - return out .. "\\" .. content.command .. " " .. pl.pretty.write(content.options, "") - end) - if (#content>=1) then utilities.debugAST(content, level+1) end - elseif content.id == "content" or (not content.command and not content.id) then - utilities.debugAST(content, level+1) - else - SU.debug("ast", function () - return out .. "?\\" .. (content.command or content.id) - end) - end - end - end - end - if level == 0 then SU.debug("ast", "]") end -end - --- Warn about use of a deprecated feature. -- Checks the current version and decides whether to warn or error, then oatputs a message with as much useful -- information as possible to make it easy for end users to update their usage. @@ -760,6 +718,7 @@ utilities.formatNumber = require("core.utilities.numbers") utilities.collatedSort = require("core.utilities.sorting") utilities.ast = require("core.utilities.ast") +utilities.debugAST = utilities.ast.debug utilities.subContent = function (content) SU.deprecated("SU.subContent", "SU.ast.subContent", "0.15.0", "0.17.0", [[ From d2701154a5ae711242878bda39a88bf1113a1c6b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 12 Feb 2024 18:01:48 +0300 Subject: [PATCH 328/357] style(utilities): Normalize coding style of function definitions --- core/utilities/init.lua | 96 ++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/core/utilities/init.lua b/core/utilities/init.lua index 72749c318..eb274cc47 100644 --- a/core/utilities/init.lua +++ b/core/utilities/init.lua @@ -18,14 +18,14 @@ local epsilon = 1E-12 -- include functions, other tables, data types, etc. -- @tparam table array Input. -- @tparam[opt=" "] string separator Separator. -utilities.concat = function (array, separator) +function utilities.concat (array, separator) return table.concat(utilities.map(tostring, array), separator) end --- Execute a callback function on each value in a table. -- @tparam function func Function to run on each value. -- @tparam table array Input list-like table. -utilities.map = function (func, array) +function utilities.map (func, array) local new_array = {} local last = #array for i = 1, last do @@ -39,7 +39,7 @@ end -- @param name Name of the required option. -- @param context User friendly name of the function or calling context. -- @param required_type The name of a data type that the option must sucessfully cast to. -utilities.required = function (options, name, context, required_type) +function utilities.required (options, name, context, required_type) if not options[name] then utilities.error(context.." needs a "..name.." parameter") end if required_type then return utilities.cast(required_type, options[name]) @@ -52,7 +52,7 @@ end -- of `pairs` that will iterate through the values in the order of their *sorted* keys. -- @tparam table input Input table. -- @usage for val in SU.sortedpairs({ b: "runs second", a: "runs first" ) do print(val) end -utilities.sortedpairs = function (input) +function utilities.sortedpairs (input) local keys = {} for k, _ in pairs(input) do keys[#keys+1] = k @@ -76,7 +76,7 @@ end -- @tparam integer stop Last key to replace. -- @tparam table replacement Table from which to pull key/values plairs to inject in array. -- @treturn table array First input array modified with values from replacement. -utilities.splice = function (array, start, stop, replacement) +function utilities.splice (array, start, stop, replacement) local ptr = start local room = stop - start + 1 local last = replacement and #replacement or 0 @@ -97,7 +97,7 @@ utilities.splice = function (array, start, stop, replacement) end -- TODO: Unused, now deprecated? -utilities.inherit = function (orig, spec) +function utilities.inherit (orig, spec) local new = pl.tablex.deepcopy(orig) if spec then for k,v in pairs(spec) do new[k] = v end @@ -120,7 +120,7 @@ end -- @tparam nil|bool|string value Input value such as a string to evaluate for thruthyness. -- @tparam[opt=false] boolean default Whether to assume inputs that don't specifically evaluate to something should be true or false. -- @treturn boolean -utilities.boolean = function (value, default) +function utilities.boolean (value, default) if value == false then return false end if value == true then return true end if value == "false" then return false end @@ -139,7 +139,7 @@ end -- a SILE.types.node.glue, but not a SILE.types.color. -- @tparam string wantedType Expected type. -- @return A value of the type wantedType. -utilities.cast = function (wantedType, value) +function utilities.cast (wantedType, value) local actualType = SU.type(value) wantedType = string.lower(wantedType) if wantedType:match(actualType) then return value @@ -182,7 +182,7 @@ end -- @tparam any value Any input value. If a table is one of SILE's classes or types, report on it's internal type. -- Otherwise use the output of `type`. -- @treturn string -utilities.type = function(value) +function utilities.type (value) if type(value) == "number" then return math.floor(value) == value and "integer" or "number" elseif type(value) == "table" and value.prototype then @@ -208,7 +208,7 @@ end -- > glue = SILE.types.node.glue("6em") -- > SU.debug("foo", "A glue node", glue) -- [foo] A glue node G<6em> -utilities.debug = function (category, ...) +function utilities.debug (category, ...) if SILE.quiet then return end if utilities.debugging(category) then local inputs = pl.utils.pack(...) @@ -228,7 +228,7 @@ end --- Determine if a specific debug flag is set. -- @tparam string category Name of the flag status to check, e.g. "frames". -- @treturn boolean -utilities.debugging = function (category) +function utilities.debugging (category) return SILE.debugFlags.all and category ~= "profile" or SILE.debugFlags[category] end @@ -241,7 +241,7 @@ end -- a shim. -- @tparam string errorat The first release where the interface is no longer functional even with a shim. -- @tparam string extra Longer-form help to include in output separate from the expected one-liner of warning messages. -utilities.deprecated = function (old, new, warnat, errorat, extra) +function utilities.deprecated (old, new, warnat, errorat, extra) warnat, errorat = semver(warnat or 0), semver(errorat or 0) local current = SILE.version and semver(SILE.version:match("v([0-9]*.[0-9]*.[0-9]*)")) or warnat -- SILE.version is defined *after* most of SILE loads. It’s available at @@ -262,7 +262,7 @@ end --- Dump the contents of a any Lua type. -- For quick debugging, can be used on any number of any type of Lua value. Pretty-prints tables. -- @tparam any ... Any number of values -utilities.dump = function (...) +function utilities.dump (...) local arg = { ... } -- Avoid things that Lua stuffs in arg like args to self() pl.pretty.dump(#arg == 1 and arg[1] or arg, "/dev/stderr") end @@ -273,7 +273,7 @@ local _skip_traceback_levels = 2 -- Outputs a warning message via `warn`, then finishes up anything it can without processing more content, then exits. -- @tparam string message The error message to give. -- @tparam boolean isbug Whether or not hitting this error is expected to be a code bug (as opposed to misakes in user input). -utilities.error = function (message, isbug) +function utilities.error (message, isbug) _skip_traceback_levels = 3 utilities.warn(message, isbug) _skip_traceback_levels = 2 @@ -286,7 +286,7 @@ end --- Output an information message. -- Basically like `warn`, except to source tracing information is added. -- @tparam string message -utilities.msg = function (message) +function utilities.msg (message) if SILE.quiet then return end io.stderr:write("\n! " .. message .. "\n") end @@ -295,7 +295,7 @@ end -- Outputs a warning message including identifying where in the processing SILE is at when the warning is given. -- @tparam string message The error message to give. -- @tparam boolean isbug Whether or not hitting this warning is expected to be a code bug (as opposed to misakes in user input). -utilities.warn = function (message, isbug) +function utilities.warn (message, isbug) utilities.msg(message) if SILE.traceback or isbug then io.stderr:write(" at:\n" .. SILE.traceStack:locationTrace()) @@ -318,7 +318,7 @@ end -- @tparam float lhs -- @tparam float rhs -- @treturn boolean -utilities.feq = function (lhs, rhs) +function utilities.feq (lhs, rhs) lhs = SU.cast("number", lhs) rhs = SU.cast("number", rhs) local abs = math.abs @@ -328,7 +328,7 @@ end --- Add up all the values in a table. -- @tparam table array Input list-like table. -- @treturn number Sum of all values. -utilities.sum = function (array) +function utilities.sum (array) local total = 0 local last = #array for i = 1, last do @@ -340,7 +340,7 @@ end --- Return maximum value of inputs. -- `math.max`, but works on SILE types such as SILE.types.measurement. -- Lua <= 5.2 can't handle math operators on objects. -utilities.max = function (...) +function utilities.max (...) local input = pl.utils.pack(...) local max = table.remove(input, 1) for _, val in ipairs(input) do @@ -352,7 +352,7 @@ end --- Return minimum value of inputs. -- `math.min`, but works on SILE types such as SILE.types.measurement. -- Lua <= 5.2 can't handle math operators on objects. -utilities.min = function (...) +function utilities.min (...) local input = pl.utils.pack(...) local min = input[1] for _, val in ipairs(input) do @@ -372,7 +372,7 @@ end -- whereas normal LUA VMs can be cooerced. -- @tparam number input Input value. -- @treturn string Four-digit precision foating point. -utilities.debug_round = function (input) +function utilities.debug_round (input) if input > 0 then input = input + .00000000000001 end if input < 0 then input = input - .00000000000001 end return string.format("%.4f", input) @@ -383,7 +383,7 @@ end -- { 1 = "a", 2 = "b" } which can be iterated using `ipairs` without stopping after 1. -- @tparam table items List-like table potentially with holes. -- @treturn table List like table without holes. -utilities.compress = function (items) +function utilities.compress (items) local rv = {} local max = math.max(pl.utils.unpack(pl.tablex.keys(items))) for i = 1, max do if items[i] then rv[#rv+1] = items[i] end end @@ -392,7 +392,7 @@ end --- Reverse the order of a list-like table. -- @tparam table tbl Input list-like table. -utilities.flip_in_place = function (tbl) +function utilities.flip_in_place (tbl) local tmp, j for i = 1, math.floor(#tbl / 2) do tmp = tbl[i] @@ -403,7 +403,7 @@ utilities.flip_in_place = function (tbl) end -- TODO: Before documenting, consider whether this should be private to the one existing usage. -utilities.allCombinations = function (options) +function utilities.allCombinations (options) local count = 1 for i=1,#options do count = count * options[i] end return coroutine.wrap(function() @@ -421,13 +421,13 @@ utilities.allCombinations = function (options) end -utilities.rateBadness = function(inf_bad, shortfall, spring) +function utilities.rateBadness (inf_bad, shortfall, spring) if spring == 0 then return inf_bad end local bad = math.floor(100 * math.abs(shortfall / spring) ^ 3) return math.min(inf_bad, bad) end -utilities.rationWidth = function (target, width, ratio) +function utilities.rationWidth (target, width, ratio) if ratio < 0 and width.shrink:tonumber() > 0 then target:___add(width.shrink:tonumber() * ratio) elseif ratio > 0 and width.stretch:tonumber() > 0 then @@ -444,7 +444,7 @@ end -- @tparam string pattern Pattern on which to split the input. -- @treturn function An iterator function -- @usage for str in SU.gtoke("foo-bar-baz", "-") do print(str) end -utilities.gtoke = function (string, pattern) +function utilities.gtoke (string, pattern) string = string and tostring(string) or '' pattern = pattern and tostring(pattern) or "%s+" local length = #string @@ -469,7 +469,7 @@ end --- Convert a Unicode character to its corresponding codepoint. -- @tparam string uchar A single inicode character. -- @return number The Unicode code point where uchar is encoded. -utilities.codepoint = function (uchar) +function utilities.codepoint (uchar) local seq = 0 local val = -1 for i = 1, #uchar do @@ -491,7 +491,7 @@ end --- Covert a code point to a Unicode character. -- @tparam number|string codepoint Input code point value, either as a number or a string representing the decimal value "U+NNNN" or hex value "0xFFFF". -- @treturn string The character replestened by a codepoint descriptions. -utilities.utf8charfromcodepoint = function (codepoint) +function utilities.utf8charfromcodepoint (codepoint) local val = codepoint local cp = val local hex = (cp:match("[Uu]%+(%x+)") or cp:match("0[xX](%x+)")) @@ -512,7 +512,7 @@ end -- @tparam string ustr Input string. -- @tparam string endian Either "le" or "be" depending on the enconding endedness. -- @treturn string Serious of hex encoded code points. -utilities.utf16codes = function (ustr, endian) +function utilities.utf16codes (ustr, endian) local pos = 1 return function() if pos > #ustr then @@ -550,7 +550,7 @@ end -- to split it into 1, 2, 3, or 4 byte grups matching the UTF-8 encoding. -- @tparam string str Input UTF-8 encoded string. -- @treturn table A list-like table of UTF8 strings each representing a Unicode char from the input string. -utilities.splitUtf8 = function (str) +function utilities.splitUtf8 (str) local rv = {} for _, cp in luautf8.next, str do table.insert(rv, luautf8.char(cp)) @@ -563,7 +563,7 @@ end -- more than one byte. -- @tparam string str Input string. -- @treturn string A single Unicode character. -utilities.lastChar = function (str) +function utilities.lastChar (str) local chars = utilities.splitUtf8(str) return chars[#chars] end @@ -573,7 +573,7 @@ end -- more than one byte. -- @tparam string str Input string. -- @treturn string A single Unicode character. -utilities.firstChar = function (str) +function utilities.firstChar (str) local chars = utilities.splitUtf8(str) return chars[1] end @@ -586,7 +586,7 @@ local byte, floor, reverse = string.byte, math.floor, string.reverse -- @tparam string str Input string. -- @tparam number index Index of character to return. -- @treturn string A single Unicode character. -utilities.utf8charat = function (str, index) +function utilities.utf8charat (str, index) return str:sub(index):match("([%z\1-\127\194-\244][\128-\191]*)") end @@ -597,7 +597,7 @@ end --- Encode a string to a hexidecimal replesentation. -- @tparam string str Input UTF-8 string -- @treturn string Hexidecimal replesentation of str. -utilities.hexencoded = function (str) +function utilities.hexencoded (str) local ustr = "" for i = 1, #str do ustr = ustr..string.format("%02x", byte(str, i, i+1)) @@ -608,7 +608,7 @@ end --- Decode a hexidecimal replesentation into a string. -- @tparam string str Input hexidecimal encoded string. -- @treturn string UTF-8 string. -utilities.hexdecoded = function (str) +function utilities.hexdecoded (str) if #str % 2 == 1 then SU.error("Cannot decode hex string with odd len") end local ustr = "" for i = 1, #str, 2 do @@ -640,22 +640,22 @@ end --- Convert a UTF-8 string to big-endian UTF-16. -- @tparam string str UTF-8 encoded string. -- @treturn string Big-endian UTF-16 encoded string. -utilities.utf8_to_utf16be = function (str) return utf8_to_utf16(str, "be") end +function utilities.utf8_to_utf16be (str) return utf8_to_utf16(str, "be") end --- Convert a UTF-8 string to little-endian UTF-16. -- @tparam string str UTF-8 encoded string. -- @treturn string Little-endian UTF-16 encoded string. -utilities.utf8_to_utf16le = function (str) return utf8_to_utf16(str, "le") end +function utilities.utf8_to_utf16le (str) return utf8_to_utf16(str, "le") end --- Convert a UTF-8 string to big-endian UTF-16, then encode in hex. -- @tparam string str UTF-8 encoded string. -- @treturn string Hexidecimal representation of a big-endian UTF-16 encoded string. -utilities.utf8_to_utf16be_hexencoded = function (str) return utilities.hexencoded(utilities.utf8_to_utf16be(str)) end +function utilities.utf8_to_utf16be_hexencoded (str) return utilities.hexencoded(utilities.utf8_to_utf16be(str)) end --- Convert a UTF-8 string to little-endian UTF-16, then encode in hex. -- @tparam string str UTF-8 encoded string. -- @treturn string Hexidecimal representation of a little-endian UTF-16 encoded string. -utilities.utf8_to_utf16le_hexencoded = function (str) return utilities.hexencoded(utilities.utf8_to_utf16le(str)) end +function utilities.utf8_to_utf16le_hexencoded (str) return utilities.hexencoded(utilities.utf8_to_utf16le(str)) end local utf16_to_utf8 = function (str, endianness) local bom = utf16bom(endianness) @@ -671,14 +671,14 @@ end --- Convert a big-endian UTF-16 string to UTF-8. -- @tparam string str Big-endian UTF-16 encoded string. -- @treturn string UTF-8 encoded string. -utilities.utf16be_to_utf8 = function (str) return utf16_to_utf8(str, "be") end +function utilities.utf16be_to_utf8 (str) return utf16_to_utf8(str, "be") end --- Convert a little-endian UTF-16 string to UTF-8. -- @tparam string str Little-endian UTF-16 encoded string. -- @treturn string UTF-8 encoded string. -utilities.utf16le_to_utf8 = function (str) return utf16_to_utf8(str, "le") end +function utilities.utf16le_to_utf8 (str) return utf16_to_utf8(str, "le") end -utilities.breadcrumbs = function () +function utilities.breadcrumbs () local breadcrumbs = {} setmetatable (breadcrumbs, { @@ -720,28 +720,28 @@ utilities.collatedSort = require("core.utilities.sorting") utilities.ast = require("core.utilities.ast") utilities.debugAST = utilities.ast.debug -utilities.subContent = function (content) +function utilities.subContent (content) SU.deprecated("SU.subContent", "SU.ast.subContent", "0.15.0", "0.17.0", [[ Note that the new implementation no longer introduces an id="stuff" key.]]) return utilities.ast.subContent(content) end -utilities.hasContent = function(content) +function utilities.hasContent (content) SU.deprecated("SU.hasContent", "SU.ast.hasContent", "0.15.0", "0.17.0") return SU.ast.hasContent(content) end -utilities.contentToString = function (content) +function utilities.contentToString (content) SU.deprecated("SU.contentToString", "SU.ast.contentToString", "0.15.0", "0.17.0") return SU.ast.contentToString(content) end -utilities.walkContent = function (content, action) +function utilities.walkContent (content, action) SU.deprecated("SU.walkContent", "SU.ast.walkContent", "0.15.0", "0.17.0") SU.ast.walkContent(content, action) end -utilities.stripContentPos = function (content) +function utilities.stripContentPos (content) SU.deprecated("SU.stripContentPos", "SU.ast.stripContentPos", "0.15.0", "0.17.0") return SU.ast.stripContentPos(content) end From 8ec9c0316c8e85587cd561daa3843cfa6794c026 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 13 Feb 2024 21:08:38 +0300 Subject: [PATCH 329/357] ci(tooling): Avoid needing API doc tooling for testing runs --- .cirrus.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index c50746cdc..f9d02041e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -42,7 +42,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false NPM=false DOCKER=false \ + --enable-developer LDOC=false LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false NPM=false DOCKER=false \ --disable-font-variations \ --with-system-lua-sources \ --with-system-luarocks \ diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 4aa41a092..975828a86 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -60,7 +60,7 @@ jobs: run: | ./bootstrap.sh ./configure \ - --enable-developer LUACHECK=false NIX=false DELTA=cat \ + --enable-developer LDOC=false LUACHECK=false NIX=false DELTA=cat \ --disable-font-variations \ --without-manual - name: Make diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d3e7f9de..abad02550 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: ./bootstrap.sh ./configure \ ${{ matrix.luaVersion[1] }} \ - --enable-developer LUACHECK=false NIX=false DELTA=cat \ + --enable-developer LDOC=false LUACHECK=false NIX=false DELTA=cat \ --disable-font-variations \ --with${{ !startsWith(matrix.luaVersion[0], 'luajit') && 'out' || '' }}-luajit \ --without-system-luarocks \ From e8ec8628617dca68c2f10f47edf926ad41fd0ed8 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 13 Feb 2024 22:11:16 +0300 Subject: [PATCH 330/357] refactor(core): Move global library handling to its own module --- core/globals.lua | 19 +++++++++++++++++++ core/sile.lua | 23 +++-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) create mode 100644 core/globals.lua diff --git a/core/globals.lua b/core/globals.lua new file mode 100644 index 000000000..d202b039b --- /dev/null +++ b/core/globals.lua @@ -0,0 +1,19 @@ +--- Global library provisions. +-- @module globals +-- @alias _G + +--- Penlight. +-- On-demand module loader, provided for SILE and document usage +_G.pl = require("pl.import_into")() + +--- UTF-8 String handler. +-- Lua 5.3+ has a UTF-8 safe string function module but it is somewhat +-- underwhelming. This module includes more functions and supports older Lua +-- versions. Docs: https://github.com/starwing/luautf8 +_G.luautf8 = require("lua-utf8") + +--- Fluent localization library. +_G.fluent = require("fluent")() + +-- For developer testing only, usually in CI +if os.getenv("SILE_COVERAGE") then require("luacov") end diff --git a/core/sile.lua b/core/sile.lua index c41270f93..d42d40177 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -1,27 +1,10 @@ --- The core SILE library -- @module SILE ---- Global library provisions. --- @section globals --- Loading SILE foo +-- Placeholder for 3rd party Lua libraries SILE always provides as globals +require("core.globals") ---- Penlight. --- On-demand module loader, provided for SILE and document usage -pl = require("pl.import_into")() - --- For developer testing only, usually in CI -if os.getenv("SILE_COVERAGE") then require("luacov") end - ---- UTF-8 String handler. --- Lua 5.3+ has a UTF-8 safe string function module but it is somewhat --- underwhelming. This module includes more functions and supports older Lua --- versions. Docs: https://github.com/starwing/luautf8 -luautf8 = require("lua-utf8") - ---- Fluent localization library. -fluent = require("fluent")() - --- Reserve global scope placeholder for profiler (developer tooling) +-- Reserve scope placeholder for profiler (developer tooling) local ProFi -- Placeholder for SILE internals table From 296b808ecbd71292a03c3638e74b9653fbcd89b9 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 13 Feb 2024 22:11:39 +0300 Subject: [PATCH 331/357] docs(api): Expand API docs, cover globals and some class and package stuff --- classes/base.lua | 12 ++++++++++++ core/globals.lua | 19 +++++++++++++------ core/sile.lua | 4 ++-- packages/base.lua | 12 ++++++++++++ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index fc4ed7195..05be90033 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -280,6 +280,18 @@ function class:runHooks (category, options) end end +--- Register a function as a SILE command. +-- Takes any Lua function and registers it for use as a SILE command (which will in turn be used to process any content +-- nodes identified with the command name. +-- +-- Note that this should only be used to register commands supplied directly by a document class. A similar method is +-- available for packages, `packages:registerCommand`. +-- @tparam string name Name of cammand to register. +-- @tparam function func Callback function to use as command handler. +-- @tparam[opt] nil|string help User friendly short usage string for use in error messages, documentation, etc. +-- @tparam[opt] nil|string pack Information identifying the module registering the command for use in error and usage +-- messages. Usually auto-detected. +-- @see SILE.packages:registerCommand function class.registerCommand (_, name, func, help, pack) SILE.Commands[name] = func if not pack then diff --git a/core/globals.lua b/core/globals.lua index d202b039b..041de291b 100644 --- a/core/globals.lua +++ b/core/globals.lua @@ -2,17 +2,24 @@ -- @module globals -- @alias _G ---- Penlight. --- On-demand module loader, provided for SILE and document usage +--- Penlight od-demand loader. +-- The Lua language adopts a "no batteries included" philosophy by providing a minimal standard library. Penlight is +-- a widely used set libraries for making it easier to work with common tasks. Loading SILE implies that the PEnlight +-- on-demand module loader is available, allowing any Penlight functions to be accessed using the `pl` prefix. Consult +-- the [Penlight documentation](https://lunarmodules.github.io/Penlight/) for specifics of the utilities available. _G.pl = require("pl.import_into")() ---- UTF-8 String handler. --- Lua 5.3+ has a UTF-8 safe string function module but it is somewhat --- underwhelming. This module includes more functions and supports older Lua --- versions. Docs: https://github.com/starwing/luautf8 +--- UTF-8 string library. +-- LuaJIT 5.1 and 5.2's `string` module only handle strings as bytes. Lua 5.3+ has a UTF-8 safe `string` module, but its +-- feature set is somewhat underwhelming. This module includes more functions and levels the playing field no matter +-- which Lua VM is being used. See [luautf8 docs](https://github.com/starwing/luautf8) for more details. _G.luautf8 = require("lua-utf8") --- Fluent localization library. +-- For handling messages in various languages SILE provides an implementation of [Project +-- Fluent](https://projectfluent.org/)'s localization system (originally developed by Mozilla for use in Firefox). This +-- global is an instantiated interface to [fluent-lua](https://github.com/alerque/fluent-lua) pre-loaded with resources +-- for all the langugaes and regions SILE has support for. _G.fluent = require("fluent")() -- For developer testing only, usually in CI diff --git a/core/sile.lua b/core/sile.lua index d42d40177..431ce3396 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -576,8 +576,8 @@ end -- @tparam[opt] nil|string help User friendly short usage string for use in error messages, documentation, etc. -- @tparam[opt] nil|string pack Information identifying the module registering the command for use in error and usage -- messages. Usually auto-detected. --- @see SILE.classes --- @see SILE.packages +-- @see SILE.classes:registerCommand +-- @see SILE.packages:registerCommand function SILE.registerCommand (name, func, help, pack, cheat) local class = SILE.documentState.documentClass if not cheat then diff --git a/packages/base.lua b/packages/base.lua index b55a1b2c6..6fae09fec 100644 --- a/packages/base.lua +++ b/packages/base.lua @@ -65,6 +65,18 @@ function package.registerCommands (_) end -- This gives us a hook to match commands with the packages that registered -- them as opposed to core commands or class-provided commands + +--- Register a function as a SILE command. +-- Takes any Lua function and registers it for use as a SILE command (which will in turn be used to process any content +-- nodes identified with the command name. +-- +-- A similar method is available for classes, `classes:registerCommand`. +-- @tparam string name Name of cammand to register. +-- @tparam function func Callback function to use as command handler. +-- @tparam[opt] nil|string help User friendly short usage string for use in error messages, documentation, etc. +-- @tparam[opt] nil|string pack Information identifying the module registering the command for use in error and usage +-- messages. Usually auto-detected. +-- @see SILE.classes:registerCommand function package:registerCommand (name, func, help, pack) self.class:registerCommand(name, func, help, pack) end From ba879807d1986f83633c3df73819fe9ef0e69b2e Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 13 Feb 2024 23:23:19 +0300 Subject: [PATCH 332/357] docs(api): Introduce new top level types to LDoc to organize stuff --- .editorconfig | 2 +- build-aux/config.ld | 26 +++++++++++++++----------- classes/base.lua | 2 +- core/languages.lua | 2 +- inputters/base.lua | 2 +- languages/fr.lua | 2 +- outputters/base.lua | 2 +- packages/base.lua | 2 +- pagebuilders/base.lua | 2 +- shapers/base.lua | 2 +- types/color.lua | 2 +- types/length.lua | 3 +-- types/measurement.lua | 3 +-- types/node.lua | 2 +- types/unit.lua | 2 +- typesetters/base.lua | 2 +- 16 files changed, 30 insertions(+), 28 deletions(-) diff --git a/.editorconfig b/.editorconfig index c8de8f6b5..b877137e0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,7 +17,7 @@ indent_size = 8 [*.md] trim_trailing_whitespace = false -[{*.lua,*.lua.in,sile.in,*rockspec,.busted,.luacheckrc}] +[{*.lua,*.lua.in,sile.in,*rockspec,.busted,.luacheckrc,config.ld}] indent_style = space indent_size = 3 max_line_length = 120 diff --git a/build-aux/config.ld b/build-aux/config.ld index ce5c320ef..e1d4634e0 100644 --- a/build-aux/config.ld +++ b/build-aux/config.ld @@ -4,16 +4,20 @@ readme = "../README.md" dir = "../lua-api-docs" format = "discount" file = { - "../sile-lua", - "../core/", - "../classes/", - "../inputters/", - "../languages/", - "../outputters/", - "../packages/", - "../pagebuilders/", - "../shapers/", - "../types/", - "../typesetters/", + "../sile-lua", + "../core/", + "../classes/", + "../inputters/", + "../languages/", + "../outputters/", + "../packages/", + "../pagebuilders/", + "../shapers/", + "../types/", + "../typesetters/", } merge = true +no_space_before_args = true +sort_modules = true +new_type("interfaces", "Interfaces", true) +new_type("types", "Types", true) diff --git a/classes/base.lua b/classes/base.lua index 05be90033..6462b3cd6 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -1,5 +1,5 @@ --- SILE document class class. --- @classmod SILE.classes +-- @interfaces classes local class = pl.class() class.type = "class" diff --git a/core/languages.lua b/core/languages.lua index dca7e65ef..67c93471e 100644 --- a/core/languages.lua +++ b/core/languages.lua @@ -1,5 +1,5 @@ --- SILE language class. --- @classmod SILE.languages +-- @interfaces languages local loadkit = require("loadkit") local cldr = require("cldr") diff --git a/inputters/base.lua b/inputters/base.lua index 9a476a00e..cd609669c 100644 --- a/inputters/base.lua +++ b/inputters/base.lua @@ -1,5 +1,5 @@ --- SILE inputter class. --- @classmod SILE.inputters +-- @interfaces inputters local _deprecated = [[ You appear to be using a document class '%s' programmed for SILE <= v0.12.5. diff --git a/languages/fr.lua b/languages/fr.lua index 919e75e7d..f9df5e967 100644 --- a/languages/fr.lua +++ b/languages/fr.lua @@ -1,5 +1,5 @@ --- French language rules --- @submodule SILE.languages +-- @submodule languages local computeSpaces = function() -- Computes: diff --git a/outputters/base.lua b/outputters/base.lua index e337524fe..51cc36e59 100644 --- a/outputters/base.lua +++ b/outputters/base.lua @@ -1,5 +1,5 @@ --- SILE outputter class. --- @classmod SILE.outputters +-- @interfaces outputters local outputter = pl.class() outputter.type = "outputter" diff --git a/packages/base.lua b/packages/base.lua index 6fae09fec..26754d8f1 100644 --- a/packages/base.lua +++ b/packages/base.lua @@ -1,5 +1,5 @@ --- SILE package class. --- @classmod SILE.packages +-- @interfaces packages local package = pl.class() package.type = "package" diff --git a/pagebuilders/base.lua b/pagebuilders/base.lua index 94063d337..2eef602f5 100644 --- a/pagebuilders/base.lua +++ b/pagebuilders/base.lua @@ -1,5 +1,5 @@ --- SILE pagebuilder class. --- @classmod SILE.pagebuilders +-- @interfaces pagebuilders local pagebuilder = pl.class() pagebuilder.type = "pagebuilder" diff --git a/shapers/base.lua b/shapers/base.lua index ed1e00448..ec4ddfb36 100644 --- a/shapers/base.lua +++ b/shapers/base.lua @@ -1,5 +1,5 @@ --- SILE shaper class. --- @classmod SILE.shapers +-- @interfaces shapers -- local smallTokenSize = 20 -- Small words will be cached -- local shapeCache = {} diff --git a/types/color.lua b/types/color.lua index a95ea6692..e436915b6 100644 --- a/types/color.lua +++ b/types/color.lua @@ -1,5 +1,5 @@ --- SILE color type. --- @classmod SILE.types.color +-- @types color local colornames = { aliceblue = { 240, 248, 255 }, diff --git a/types/length.lua b/types/length.lua index 8f5d7d6d7..3de74b519 100644 --- a/types/length.lua +++ b/types/length.lua @@ -1,6 +1,5 @@ --- SILE length type. --- @classmod SILE.types.length --- @within Types +-- @types length local function _error_if_not_number (a) if type(a) ~= "number" then diff --git a/types/measurement.lua b/types/measurement.lua index c9cd56438..5a44d2ab8 100644 --- a/types/measurement.lua +++ b/types/measurement.lua @@ -1,6 +1,5 @@ --- SILE measurement type. --- @classmod SILE.types.measurement --- +-- @types measurement local function _tonumber (amount) return SU.cast("number", amount) diff --git a/types/node.lua b/types/node.lua index 5592b2b8c..c8ddeadd7 100644 --- a/types/node.lua +++ b/types/node.lua @@ -1,5 +1,5 @@ --- SILE node type. --- @classmod SILE.types.node +-- @types node local nodetypes = {} diff --git a/types/unit.lua b/types/unit.lua index f99fc4878..d5d43c255 100644 --- a/types/unit.lua +++ b/types/unit.lua @@ -1,5 +1,5 @@ --- SILE unit type. --- @classmod SILE.types.unit +-- @types unit local bits = require("core.parserbits") diff --git a/typesetters/base.lua b/typesetters/base.lua index 729038135..6572ca4f0 100644 --- a/typesetters/base.lua +++ b/typesetters/base.lua @@ -1,5 +1,5 @@ --- SILE typesetter class. --- @classmod SILE.typesetters +-- @interfaces typesetters --- @type typesetter local typesetter = pl.class() From 9ada9c83a7ff0ddb64f5c11d418b1f4c1dc413ba Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 00:28:21 +0300 Subject: [PATCH 333/357] chore(tooling): Bump Nix flake dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Includes ldoc 1.4.x → 1.5.x which we need now. --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 0dca04683..41825bac4 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", "owner": "numtide", "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", "type": "github" }, "original": { @@ -41,11 +41,11 @@ ] }, "locked": { - "lastModified": 1694102001, - "narHash": "sha256-vky6VPK1n1od6vXbqzOXnekrQpTL4hbPAwUhT5J9c9E=", + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "9e21c80adf67ebcb077d75bd5e7d724d21eeafd6", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", "type": "github" }, "original": { @@ -72,11 +72,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1696577711, - "narHash": "sha256-94VRjvClIKDym1QRqPkX5LTQoAwZ1E6QE/3dWtOXSIQ=", + "lastModified": 1707743206, + "narHash": "sha256-AehgH64b28yKobC/DAWYZWkJBxL/vP83vkY+ag2Hhy4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "a2eb207f45e4a14a1e3019d9e3863d1e208e2295", + "rev": "2d627a2a704708673e56346fcb13d25344b8eaf3", "type": "github" }, "original": { From 6ab6978b69cce3a24302686e5e47286af5c22551 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 01:34:10 +0300 Subject: [PATCH 334/357] docs(api): Add API docs for measurements --- core/sile.lua | 5 +- types/measurement.lua | 316 +++++++++++++++++++++++------------------- 2 files changed, 177 insertions(+), 144 deletions(-) diff --git a/core/sile.lua b/core/sile.lua index 431ce3396..5d2a8e889 100644 --- a/core/sile.lua +++ b/core/sile.lua @@ -1,4 +1,7 @@ ---- The core SILE library +--- The core SILE library. +-- Depending on how SILE was loaded, everything in here will probably be available under a top level `SILE` global. Note +-- that an additional global `SU` is typically available as an alias to `SILE.utilities`. Also some 3rd party Lua +-- libraries are always made available in the global scope, see `globals`. -- @module SILE -- Placeholder for 3rd party Lua libraries SILE always provides as globals diff --git a/types/measurement.lua b/types/measurement.lua index 5a44d2ab8..4a80d58e5 100644 --- a/types/measurement.lua +++ b/types/measurement.lua @@ -1,4 +1,7 @@ --- SILE measurement type. +-- Measurements consist of an amount and a unit. Any registered `types.unit` may be used. Some units are relative and +-- their value may depend on the context where they are evaluated. Others are absolute. Unlike `types.length` +-- measurements have no stretch or shrink parameters. -- @types measurement local function _tonumber (amount) @@ -45,148 +48,175 @@ local function _error_if_relative (a, b) end end -local measurement = pl.class({ - type = "measurement", - amount = 0, - unit = "pt", - relative = false, - _mutable = false, - - _init = function (self, amount, unit) - if unit then self.unit = unit end - if SU.type(amount) == "length" then - self.amount = amount.length.amount - self.unit = amount.length.unit - elseif type(amount) == "table" then - self.amount = amount.amount - self.unit = amount.unit - elseif type(tonumber(amount)) == "number" then - self.amount = tonumber(amount) - elseif type(amount) == "string" then - local parsed = SILE.parserBits.measurement:match(amount) - if not parsed then SU.error("Could not parse measurement '"..amount.."'") end - self.amount, self.unit = parsed.amount, parsed.unit - end - local _su = SILE.types.unit[self.unit] - if not _su then SU.error("Unknown unit: " .. unit) end - self.relative = _su.relative - if self.unit == "pt" then self._mutable = true end - end, - - absolute = function (self) - return SILE.types.measurement(self:tonumber()) - end, - - tostring = function (self) - return self:__tostring() - end, - - tonumber = function (self) - local def = SILE.types.unit[self.unit] - local amount = def.converter and def.converter(self.amount) or (self.amount * def.value) - return amount - end, - - __tostring = function (self) - return self.amount .. self.unit - end, - - __concat = function (a, b) - return tostring(a) .. tostring(b) - end, - - __add = function (self, other) - if _similarunit(self, other) then - return SILE.types.measurement(_amount(self) + _amount(other), _unit(self, other)) - else - _error_if_relative(self, other) - return SILE.types.measurement(_tonumber(self) + _tonumber(other)) - end - end, - - -- Note all private math (_ + __func()) functions: - -- * Are much faster than regular math operations - -- * Are **not** intended for use outside of the most performance sensitive loops - -- * Modify the lhs input in-place, never instantiating new objects - -- * Always assume absolute lhs input and absolutize the rhs values at runtime - -- * Assmue the inputs are sane with much less error checking than regular math funcs - -- * Are not composable using chained methods since they return nil for safety - ___add = function (self, other) - _error_if_immutable(self) - self.amount = self.amount + _pt_amount(other) - return nil - end, - - __sub = function (self, other) - if _similarunit(self, other) then - return SILE.types.measurement(_amount(self) - _amount(other), _unit(self, other)) - else - _error_if_relative(self, other) - return SILE.types.measurement(_tonumber(self) - _tonumber(other)) - end - end, - - -- See usage comments on SILE.types.measurement:___add() - ___sub = function (self, other) - _error_if_immutable(self) - self.amount = self.amount - _pt_amount(other) - return nil - end, - - __mul = function (self, other) - if _hardnumber(self, other) then - return SILE.types.measurement(_amount(self) * _amount(other), _unit(self, other)) - else - _error_if_relative(self, other) - return SILE.types.measurement(_tonumber(self) * _tonumber(other)) - end - end, - - __pow = function (self, other) - if _hardnumber(self, other) then - return SILE.types.measurement(_amount(self) ^ _amount(other), self.unit) - else - _error_if_relative(self, other) - return SILE.types.measurement(_tonumber(self) ^ _tonumber(other)) - end - end, - - __div = function (self, other) - if _hardnumber(self, other) then - return SILE.types.measurement(_amount(self) / _amount(other), self.unit) - else - _error_if_relative(self, other) - return SILE.types.measurement(_tonumber(self) / _tonumber(other)) - end - end, - - __mod = function (self, other) - if _hardnumber(self, other) then - return SILE.types.measurement(_amount(self) % _amount(other), self.unit) - else - _error_if_relative(self, other) - return SILE.types.measurement(_tonumber(self) % _tonumber(other)) - end - end, - - __unm = function (self) - local ret = SILE.types.measurement(self) - ret.amount = self.amount * -1 - return ret - end, - - __eq = function (self, other) - return _tonumber(self) == _tonumber(other) - end, - - __lt = function (self, other) - return _tonumber(self) < _tonumber(other) - end, - - __le = function (self, other) - return _tonumber(self) <= _tonumber(other) - end - - }) +--- @type measurement +local measurement = pl.class() +measurement.type = "measurement" + +measurement.amount = 0 +measurement.unit = "pt" +measurement.relative = false +measurement._mutable = false + +--- Constructor. +-- @tparam number|length|measurement|string amount Amount of units or a string with the amount and unit. +-- @tparam[opt=pt] string unit Name of unit. +-- @usage +-- SILE.types.measurement(3, "em") +-- SILE.types.measurement("2%fw") +-- SILE.types.measurement(6) +function measurement:_init (amount, unit) + if unit then self.unit = unit end + if SU.type(amount) == "length" then + self.amount = amount.length.amount + self.unit = amount.length.unit + elseif type(amount) == "table" then + self.amount = amount.amount + self.unit = amount.unit + elseif type(tonumber(amount)) == "number" then + self.amount = tonumber(amount) + elseif type(amount) == "string" then + local parsed = SILE.parserBits.measurement:match(amount) + if not parsed then SU.error("Could not parse measurement '"..amount.."'") end + self.amount, self.unit = parsed.amount, parsed.unit + end + local _su = SILE.types.unit[self.unit] + if not _su then SU.error("Unknown unit: " .. unit) end + self.relative = _su.relative + if self.unit == "pt" then self._mutable = true end +end + +--- Convert relative measurements to absolute values and return a measurement. +-- Resolves relative measurements (like em relevant to the currrent font size) into absolute measurements. +-- @treturn measurement A new measurement in pt with any relative values resolved. +-- @usage +-- > a = SILE.types.measurement("1.2em") +-- > print(a:absolute()) +-- 12pt +function measurement:absolute () + return SILE.types.measurement(self:tonumber()) +end + +function measurement:tostring () + return self:__tostring() +end + +--- Convert relative measurements to absolute values and return a number. +-- Similar to `measurement:absolute` but returns a number instead of a new measurement type. +-- @treturn number A number (corresponding to pts) for the amount with any relative values resolved. +function measurement:tonumber () + local def = SILE.types.unit[self.unit] + local amount = def.converter and def.converter(self.amount) or (self.amount * def.value) + return amount +end + +function measurement:__tostring () + return self.amount .. self.unit +end + +function measurement:__concat (other) + return tostring(self) .. tostring(other) +end + +--- Addition meta-method. +-- Assuming matching relative units or absolute units, allows two measurements to be combined into one. +-- @tparam measurement other +-- @treturn measuremnet A new measurement of the same unit type as `self` with the value of `other` added. +-- @usage +-- > a = SILE.types.measurement(6, "em") +-- > b = SILE.types.measurement("2em") +-- > c = a + b +-- > print(c) +-- 8em +function measurement:__add (other) + if _similarunit(self, other) then + return SILE.types.measurement(_amount(self) + _amount(other), _unit(self, other)) + else + _error_if_relative(self, other) + return SILE.types.measurement(_tonumber(self) + _tonumber(other)) + end +end + +-- Note all private math (_ + __func()) functions: +-- * Are much faster than regular math operations +-- * Are **not** intended for use outside of the most performance sensitive loops +-- * Modify the lhs input in-place, never instantiating new objects +-- * Always assume absolute lhs input and absolutize the rhs values at runtime +-- * Assmue the inputs are sane with much less error checking than regular math funcs +-- * Are not composable using chained methods since they return nil for safety +function measurement:___add (other) + _error_if_immutable(self) + self.amount = self.amount + _pt_amount(other) + return nil +end + +function measurement:__sub (other) + if _similarunit(self, other) then + return SILE.types.measurement(_amount(self) - _amount(other), _unit(self, other)) + else + _error_if_relative(self, other) + return SILE.types.measurement(_tonumber(self) - _tonumber(other)) + end +end + +-- See usage comments on SILE.types.measurement:___add() +function measurement:___sub (other) + _error_if_immutable(self) + self.amount = self.amount - _pt_amount(other) + return nil +end + +function measurement:__mul (other) + if _hardnumber(self, other) then + return SILE.types.measurement(_amount(self) * _amount(other), _unit(self, other)) + else + _error_if_relative(self, other) + return SILE.types.measurement(_tonumber(self) * _tonumber(other)) + end +end + +function measurement:__pow (other) + if _hardnumber(self, other) then + return SILE.types.measurement(_amount(self) ^ _amount(other), self.unit) + else + _error_if_relative(self, other) + return SILE.types.measurement(_tonumber(self) ^ _tonumber(other)) + end +end + +function measurement:__div (other) + if _hardnumber(self, other) then + return SILE.types.measurement(_amount(self) / _amount(other), self.unit) + else + _error_if_relative(self, other) + return SILE.types.measurement(_tonumber(self) / _tonumber(other)) + end +end + +function measurement:__mod (other) + if _hardnumber(self, other) then + return SILE.types.measurement(_amount(self) % _amount(other), self.unit) + else + _error_if_relative(self, other) + return SILE.types.measurement(_tonumber(self) % _tonumber(other)) + end +end + +function measurement:__unm () + local ret = SILE.types.measurement(self) + ret.amount = self.amount * -1 + return ret +end + +function measurement:__eq (other) + return _tonumber(self) == _tonumber(other) +end + +function measurement:__lt (other) + return _tonumber(self) < _tonumber(other) +end + +function measurement:__le (other) + return _tonumber(self) <= _tonumber(other) +end return measurement From 386ac58e84ce98c40d410b2b3fbe1ccf676b745a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 02:04:57 +0300 Subject: [PATCH 335/357] docs(api): Begin API docs for lengths --- types/length.lua | 334 ++++++++++++++++++++++-------------------- types/measurement.lua | 3 +- 2 files changed, 176 insertions(+), 161 deletions(-) diff --git a/types/length.lua b/types/length.lua index 3de74b519..62e147ddc 100644 --- a/types/length.lua +++ b/types/length.lua @@ -1,4 +1,7 @@ --- SILE length type. +-- Lengths are composed of 3 `measurement`s: a length, a stretch, and a shrink. Each part internally is just +-- a measurement, but combined describe a flexible length that is allowed to grow up to the amout defined by stretch or +-- compress up to the amount defined by shrink. -- @types length local function _error_if_not_number (a) @@ -7,165 +10,176 @@ local function _error_if_not_number (a) end end -return pl.class({ - type = "length", - length = nil, - stretch = nil, - shrink = nil, - - _init = function (self, spec, stretch, shrink) - if stretch or shrink then - self.length = SILE.types.measurement(spec or 0) - self.stretch = SILE.types.measurement(stretch or 0) - self.shrink = SILE.types.measurement(shrink or 0) - elseif type(spec) == "number" then - self.length = SILE.types.measurement(spec) - elseif SU.type(spec) == "measurement" then - self.length = spec - elseif SU.type(spec) == "glue" then - self.length = SILE.types.measurement(spec.width.length or 0) - self.stretch = SILE.types.measurement(spec.width.stretch or 0) - self.shrink = SILE.types.measurement(spec.width.shrink or 0) - elseif type(spec) == "table" then - self.length = SILE.types.measurement(spec.length or 0) - self.stretch = SILE.types.measurement(spec.stretch or 0) - self.shrink = SILE.types.measurement(spec.shrink or 0) - elseif type(spec) == "string" then - local amount = tonumber(spec) - if type(amount) == "number" then - self:_init(amount) - else - local parsed = SILE.parserBits.length:match(spec) - if not parsed then SU.error("Could not parse length '"..spec.."'") end - self:_init(parsed) - end - end - if not self.length then self.length = SILE.types.measurement() end - if not self.stretch then self.stretch = SILE.types.measurement() end - if not self.shrink then self.shrink = SILE.types.measurement() end - end, - - absolute = function (self) - return SILE.types.length(self.length:tonumber(), self.stretch:tonumber(), self.shrink:tonumber()) - end, - - negate = function (self) - return self:__unm() - end, - - tostring = function (self) - return self:__tostring() - end, - - tonumber = function (self) - return self.length:tonumber() - end, - - new = function (_) - SU.deprecated("SILE.length.new", "SILE.types.length", "0.10.0") - end, - - make = function (_) - SU.deprecated("SILE.length.make", "SILE.types.length", "0.10.0") - end, - - parse = function (_) - SU.deprecated("SILE.length.parse", "SILE.types.length", "0.10.0") - end, - - fromLengthOrNumber = function (_, _) - SU.deprecated("SILE.length.fromLengthOrNumber", "SILE.types.length", "0.10.0") - end, - - __index = function (_, key) - SU.deprecated("SILE.length." .. key, "SILE.types.length", "0.10.0") - end, - - __tostring = function (self) - local str = tostring(self.length) - if self.stretch.amount ~= 0 then str = str .. " plus " .. tostring(self.stretch) end - if self.shrink.amount ~= 0 then str = str .. " minus " .. tostring(self.shrink) end - return str - end, - - __add = function (self, other) - if type(self) == "number" then self, other = other, self end - other = SU.cast("length", other) - return SILE.types.length(self.length + other.length, - self.stretch + other.stretch, - self.shrink + other.shrink) - end, - - -- See usage comments on SILE.types.measurement:___add() - ___add = function (self, other) - if SU.type(other) ~= "length" then - self.length:___add(other) - else - self.length:___add(other.length) - self.stretch:___add(other.stretch) - self.shrink:___add(other.shrink) - end - return nil - end, - - __sub = function (self, other) - local result = SILE.types.length(self) - other = SU.cast("length", other) - result.length = result.length - other.length - result.stretch = result.stretch - other.stretch - result.shrink = result.shrink - other.shrink - return result - end, - - -- See usage comments on SILE.types.measurement:___add() - ___sub = function (self, other) - self.length:___sub(other.length) - self.stretch:___sub(other.stretch) - self.shrink:___sub(other.shrink) - return nil - end, - - __mul = function (self, other) - if type(self) == "number" then self, other = other, self end - _error_if_not_number(other) - local result = SILE.types.length(self) - result.length = result.length * other - result.stretch = result.stretch * other - result.shrink = result.shrink * other - return result - end, - - __div = function (self, other) - local result = SILE.types.length(self) - _error_if_not_number(other) - result.length = result.length / other - result.stretch = result.stretch / other - result.shrink = result.shrink / other - return result - end, - - __unm = function (self) - local result = SILE.types.length(self) - result.length = result.length:__unm() - return result - end, - - __lt = function (self, other) - local a = SU.cast("number", self) - local b = SU.cast("number", other) - return a - b < 0 - end, - - __le = function (self, other) - local a = SU.cast("number", self) - local b = SU.cast("number", other) - return a - b <= 0 - end, - - __eq = function (self, other) - local a = SU.cast("length", self) - local b = SU.cast("length", other) - return a.length == b.length and a.stretch == b.stretch and a.shrink == b.shrink +--- @type length +local length = pl.class() +length.type = "length" + +length.length = nil +length.stretch = nil +length.shrink = nil + +--- Constructor. +-- @tparam measurement spec A measurement or value that can be cast to a measurement. +-- @tparam[opt=0] measurement stretch A measurement describing how much the length is allowed to grow. +-- @tparam[opt=0] measurement shrink A measurement describing how much the length is allowed to grow. +-- @treturn length +-- @usage +-- SILE.types.length("6em", "4pt", "2pt") +-- SILE.types.length("6em plus 4pt minus 2pt") +-- SILE.types.length(30, 4, 2) +function length:_init (spec, stretch, shrink) + if stretch or shrink then + self.length = SILE.types.measurement(spec or 0) + self.stretch = SILE.types.measurement(stretch or 0) + self.shrink = SILE.types.measurement(shrink or 0) + elseif type(spec) == "number" then + self.length = SILE.types.measurement(spec) + elseif SU.type(spec) == "measurement" then + self.length = spec + elseif SU.type(spec) == "glue" then + self.length = SILE.types.measurement(spec.width.length or 0) + self.stretch = SILE.types.measurement(spec.width.stretch or 0) + self.shrink = SILE.types.measurement(spec.width.shrink or 0) + elseif type(spec) == "table" then + self.length = SILE.types.measurement(spec.length or 0) + self.stretch = SILE.types.measurement(spec.stretch or 0) + self.shrink = SILE.types.measurement(spec.shrink or 0) + elseif type(spec) == "string" then + local amount = tonumber(spec) + if type(amount) == "number" then + self:_init(amount) + else + local parsed = SILE.parserBits.length:match(spec) + if not parsed then SU.error("Could not parse length '"..spec.."'") end + self:_init(parsed) end + end + if not self.length then self.length = SILE.types.measurement() end + if not self.stretch then self.stretch = SILE.types.measurement() end + if not self.shrink then self.shrink = SILE.types.measurement() end +end + +function length:absolute () + return SILE.types.length(self.length:tonumber(), self.stretch:tonumber(), self.shrink:tonumber()) +end + +function length:negate () + return self:__unm() +end + +function length:tostring () + return self:__tostring() +end + +function length:tonumber () + return self.length:tonumber() +end + +function length.new (_) + SU.deprecated("SILE.length.new", "SILE.types.length", "0.10.0") +end + +function length.make (_) + SU.deprecated("SILE.length.make", "SILE.types.length", "0.10.0") +end + +function length.parse (_) + SU.deprecated("SILE.length.parse", "SILE.types.length", "0.10.0") +end + +function length.fromLengthOrNumber (_, _) + SU.deprecated("SILE.length.fromLengthOrNumber", "SILE.types.length", "0.10.0") +end + +function length.__index (_, key) + SU.deprecated("SILE.length." .. key, "SILE.types.length", "0.10.0") +end + +function length:__tostring () + local str = tostring(self.length) + if self.stretch.amount ~= 0 then str = str .. " plus " .. tostring(self.stretch) end + if self.shrink.amount ~= 0 then str = str .. " minus " .. tostring(self.shrink) end + return str +end + +function length:__add (other) + if type(self) == "number" then self, other = other, self end + other = SU.cast("length", other) + return SILE.types.length(self.length + other.length, + self.stretch + other.stretch, + self.shrink + other.shrink) +end + +-- See usage comments on SILE.types.measurement:___add() +function length:___add (other) + if SU.type(other) ~= "length" then + self.length:___add(other) + else + self.length:___add(other.length) + self.stretch:___add(other.stretch) + self.shrink:___add(other.shrink) + end + return nil +end + +function length:__sub (other) + local result = SILE.types.length(self) + other = SU.cast("length", other) + result.length = result.length - other.length + result.stretch = result.stretch - other.stretch + result.shrink = result.shrink - other.shrink + return result +end + +-- See usage comments on SILE.types.measurement:___add() +function length:___sub (other) + self.length:___sub(other.length) + self.stretch:___sub(other.stretch) + self.shrink:___sub(other.shrink) + return nil +end + +function length:__mul (other) + if type(self) == "number" then self, other = other, self end + _error_if_not_number(other) + local result = SILE.types.length(self) + result.length = result.length * other + result.stretch = result.stretch * other + result.shrink = result.shrink * other + return result +end + +function length:__div (other) + local result = SILE.types.length(self) + _error_if_not_number(other) + result.length = result.length / other + result.stretch = result.stretch / other + result.shrink = result.shrink / other + return result +end + +function length:__unm () + local result = SILE.types.length(self) + result.length = result.length:__unm() + return result +end + +function length:__lt (other) + local a = SU.cast("number", self) + local b = SU.cast("number", other) + return a - b < 0 +end + +function length:__le (other) + local a = SU.cast("number", self) + local b = SU.cast("number", other) + return a - b <= 0 +end + +function length:__eq (other) + local a = SU.cast("length", self) + local b = SU.cast("length", other) + return a.length == b.length and a.stretch == b.stretch and a.shrink == b.shrink +end - }) +return length diff --git a/types/measurement.lua b/types/measurement.lua index 4a80d58e5..05134ac63 100644 --- a/types/measurement.lua +++ b/types/measurement.lua @@ -60,6 +60,7 @@ measurement._mutable = false --- Constructor. -- @tparam number|length|measurement|string amount Amount of units or a string with the amount and unit. -- @tparam[opt=pt] string unit Name of unit. +-- @treturn measurement -- @usage -- SILE.types.measurement(3, "em") -- SILE.types.measurement("2%fw") @@ -86,7 +87,7 @@ function measurement:_init (amount, unit) end --- Convert relative measurements to absolute values and return a measurement. --- Resolves relative measurements (like em relevant to the currrent font size) into absolute measurements. +-- Resolves relative measurements (like em relevant to the current font size) into absolute measurements. -- @treturn measurement A new measurement in pt with any relative values resolved. -- @usage -- > a = SILE.types.measurement("1.2em") From 5daec29c0e877ac551b7af5dbf27102c13702d7b Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 02:13:28 +0300 Subject: [PATCH 336/357] chore(types): Drop deprecation errors for >= 5 version old deprecations --- types/length.lua | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/types/length.lua b/types/length.lua index 62e147ddc..3a091b0d4 100644 --- a/types/length.lua +++ b/types/length.lua @@ -75,26 +75,6 @@ function length:tonumber () return self.length:tonumber() end -function length.new (_) - SU.deprecated("SILE.length.new", "SILE.types.length", "0.10.0") -end - -function length.make (_) - SU.deprecated("SILE.length.make", "SILE.types.length", "0.10.0") -end - -function length.parse (_) - SU.deprecated("SILE.length.parse", "SILE.types.length", "0.10.0") -end - -function length.fromLengthOrNumber (_, _) - SU.deprecated("SILE.length.fromLengthOrNumber", "SILE.types.length", "0.10.0") -end - -function length.__index (_, key) - SU.deprecated("SILE.length." .. key, "SILE.types.length", "0.10.0") -end - function length:__tostring () local str = tostring(self.length) if self.stretch.amount ~= 0 then str = str .. " plus " .. tostring(self.stretch) end From db57837d5786c0fb880d3433a34bf197650b43d4 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 14:31:10 +0300 Subject: [PATCH 337/357] docs(api): Start organizing how to document individual modules --- build-aux/config.ld | 3 +++ classes/base.lua | 2 +- classes/bible.lua | 3 +++ classes/book.lua | 3 +++ classes/diglot.lua | 3 +++ classes/docbook.lua | 3 +++ classes/jbook.lua | 3 +++ classes/jplain.lua | 3 +++ classes/letter.lua | 3 +++ classes/pecha.lua | 3 +++ classes/plain.lua | 3 +++ classes/tbook.lua | 3 +++ classes/tplain.lua | 3 +++ classes/triglot.lua | 3 +++ packages/pdf/init.lua | 4 +++- 15 files changed, 43 insertions(+), 2 deletions(-) diff --git a/build-aux/config.ld b/build-aux/config.ld index e1d4634e0..2c2f41be2 100644 --- a/build-aux/config.ld +++ b/build-aux/config.ld @@ -19,5 +19,8 @@ file = { merge = true no_space_before_args = true sort_modules = true +kind_names = { module = "Library" } new_type("interfaces", "Interfaces", true) new_type("types", "Types", true) +new_type("use", "Modules", true) +-- vim: ft=lua diff --git a/classes/base.lua b/classes/base.lua index 6462b3cd6..f6e3783ba 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -1,4 +1,4 @@ ---- SILE document class class. +--- SILE document class interface. -- @interfaces classes local class = pl.class() diff --git a/classes/bible.lua b/classes/bible.lua index cdbd54226..82ec301da 100644 --- a/classes/bible.lua +++ b/classes/bible.lua @@ -1,3 +1,6 @@ +--- bible document class. +-- @use classes.bible + local plain = require("classes.plain") local class = pl.class(plain) diff --git a/classes/book.lua b/classes/book.lua index 0d623bd0c..286d479d2 100644 --- a/classes/book.lua +++ b/classes/book.lua @@ -1,3 +1,6 @@ +--- book document class. +-- @use classes.book + local plain = require("classes.plain") local class = pl.class(plain) diff --git a/classes/diglot.lua b/classes/diglot.lua index 402679a4b..acfc6f9b6 100644 --- a/classes/diglot.lua +++ b/classes/diglot.lua @@ -1,3 +1,6 @@ +--- diglot document class. +-- @use classes.diglot + local plain = require("classes.plain") local class = pl.class(plain) diff --git a/classes/docbook.lua b/classes/docbook.lua index c3b635c45..6081a5c1a 100644 --- a/classes/docbook.lua +++ b/classes/docbook.lua @@ -1,3 +1,6 @@ +--- docbook document class. +-- @use classes.docbook + local plain = require("classes.plain") local class = pl.class(plain) diff --git a/classes/jbook.lua b/classes/jbook.lua index 7cd2e5f53..6c98fa16f 100644 --- a/classes/jbook.lua +++ b/classes/jbook.lua @@ -1,3 +1,6 @@ +--- jbook document class. +-- @use classes.jbook + local tbook = require("classes.tbook") local class = pl.class(tbook) diff --git a/classes/jplain.lua b/classes/jplain.lua index b5350ef60..2ddd37a0b 100644 --- a/classes/jplain.lua +++ b/classes/jplain.lua @@ -1,3 +1,6 @@ +--- jplain document class. +-- @use classes.jplain + -- Basic! Transitional! In development! Not very good! Don't use it! local tplain = require("classes.tplain") diff --git a/classes/letter.lua b/classes/letter.lua index a5904e004..5a95f5bd4 100644 --- a/classes/letter.lua +++ b/classes/letter.lua @@ -1,3 +1,6 @@ +--- letter document class. +-- @use classes.letter + local plain = require("classes.plain") local class = pl.class(plain) diff --git a/classes/pecha.lua b/classes/pecha.lua index 0b23b6eea..9e7a08832 100644 --- a/classes/pecha.lua +++ b/classes/pecha.lua @@ -1,3 +1,6 @@ +--- tbook document class. +-- @use classes.tbook + local plain = require("classes.plain") local class = pl.class(plain) diff --git a/classes/plain.lua b/classes/plain.lua index 6bf7c8ca5..cd5b18b84 100644 --- a/classes/plain.lua +++ b/classes/plain.lua @@ -1,3 +1,6 @@ +--- plain document class. +-- @use classes.plain + local base = require("classes.base") local class = pl.class(base) diff --git a/classes/tbook.lua b/classes/tbook.lua index 11c2e8721..aad8c1620 100644 --- a/classes/tbook.lua +++ b/classes/tbook.lua @@ -1,3 +1,6 @@ +--- tbook document class. +-- @use classes.tbook + local book = require("classes.book") local tplain = require("classes.tplain") diff --git a/classes/tplain.lua b/classes/tplain.lua index 6a6db9f0a..9981044f9 100644 --- a/classes/tplain.lua +++ b/classes/tplain.lua @@ -1,3 +1,6 @@ +--- tplain document class. +-- @use classes.tplain + -- Basic! Transitional! In development! Not very good! Don't use it! local plain = require("classes.plain") diff --git a/classes/triglot.lua b/classes/triglot.lua index 8590406c4..4af034b86 100644 --- a/classes/triglot.lua +++ b/classes/triglot.lua @@ -1,3 +1,6 @@ +--- triglot document class. +-- @use classes.triglot + local book = require("classes.book") local class = pl.class(book) diff --git a/packages/pdf/init.lua b/packages/pdf/init.lua index d8af25e96..93b92f845 100644 --- a/packages/pdf/init.lua +++ b/packages/pdf/init.lua @@ -1,4 +1,6 @@ --- +--- pdf package +--- @use packages.pdf + -- This package and its commands are perhaps ill-named: -- Exception made of the pdf:literal command below, the concepts of links -- (anchor, target), bookmarks, and metadata are not specific to PDF. From 414ba29478c8bb11db306ba13cc55040f0311295 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 17:25:41 +0300 Subject: [PATCH 338/357] chore(tooling): Ignore some directories LuaLS chokes on --- .luarc.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.luarc.json b/.luarc.json index 3fd760fee..776a3289c 100644 --- a/.luarc.json +++ b/.luarc.json @@ -10,6 +10,12 @@ "executablePath", "extendSilePath" ], + "Lua.workspace.ignoreDir": [ + "languages", + "lua-libraries", + "spec", + "tests" + ], "Lua.workspace.preloadFileSize": 5120, "Lua.workspace.checkThirdParty": false } From 338d2661e3a55ededf87439b78d7bd5a4b8987e5 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Wed, 14 Feb 2024 11:07:36 +0300 Subject: [PATCH 339/357] refactor(core): Address issues raised by sumneko Lua lints --- classes/base.lua | 2 +- core/break.lua | 2 +- packages/background/init.lua | 2 +- packages/counters/init.lua | 2 +- packages/math/init.lua | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/classes/base.lua b/classes/base.lua index f6e3783ba..2403d9cac 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -20,7 +20,7 @@ class.options = setmetatable({}, { elseif type(value) == "function" then opts[key] = value elseif type(key) == "number" then - return nil + return else SU.error("Attempted to set an undeclared class option '" .. key .. "'") end diff --git a/core/break.lua b/core/break.lua index 652f8d1c4..13d98a6d6 100644 --- a/core/break.lua +++ b/core/break.lua @@ -289,7 +289,7 @@ function lineBreak:considerDemerits(pi, breakType) -- 877 -- self:dumpActiveRing() local shortfall = self.lineWidth - self.curActiveWidth if self.seenAlternatives then - self:tryAlternatives(self.r.prevBreak and self.r.prevBreak.curBreak or 1, self.r.curBreak and self.r.curBreak or 1, shortfall) + self:tryAlternatives(self.r.prevBreak and self.r.prevBreak.curBreak or 1, self.r.curBreak and self.r.curBreak or 1) end shortfall = self.lineWidth - self.curActiveWidth self.badness, self.fitClass = fitclass(self, shortfall) diff --git a/packages/background/init.lua b/packages/background/init.lua index 41661cb5c..d601b5376 100644 --- a/packages/background/init.lua +++ b/packages/background/init.lua @@ -49,7 +49,7 @@ function package:registerCommands () else SU.error("background requires a color or an image src parameter") end - outputBackground(SILE.scratch.background) + outputBackground() end, "Output a solid background color <color> or an image <src> on pages after initialization.") end diff --git a/packages/counters/init.lua b/packages/counters/init.lua index be390896c..a01a518d5 100644 --- a/packages/counters/init.lua +++ b/packages/counters/init.lua @@ -49,7 +49,7 @@ function package:formatMultilevelCounter (counter, options) options = options or {} local maxlevel = options.level and SU.min(SU.cast("integer", options.level), #counter.value) or #counter.value -- Option minlevel is undocumented and should perhaps be deprecated: is there a real use case for it? - local minlevel = options.minlevel and SU.min(SU.cast("integer", options.minlevel, #counter.value)) or 1 + local minlevel = options.minlevel and SU.min(SU.cast("integer", options.minlevel), #counter.value) or 1 local out = {} if SU.boolean(options.noleadingzeros, false) then while counter.value[minlevel] == 0 do minlevel = minlevel + 1 end -- skip leading zeros diff --git a/packages/math/init.lua b/packages/math/init.lua index 761cc3ea5..3509dcd97 100644 --- a/packages/math/init.lua +++ b/packages/math/init.lua @@ -65,7 +65,7 @@ function package:registerCommands () local mode = (options and options.mode) and options.mode or 'text' local mbox xpcall(function() - mbox = self:ConvertMathML(content, mbox) + mbox = self:ConvertMathML(content) end, function(err) print(err); print(debug.traceback()) end) self:handleMath(mbox, mode) end) From a67bc6489ce1666a3eeda8871a3506ae4706d0f6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 15 Feb 2024 01:36:42 +0300 Subject: [PATCH 340/357] refactor(core): Address issues raised by Luacheck lints --- core/break.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/break.lua b/core/break.lua index 13d98a6d6..35b9afb8e 100644 --- a/core/break.lua +++ b/core/break.lua @@ -287,11 +287,10 @@ function lineBreak:considerDemerits(pi, breakType) -- 877 self.artificialDemerits = false local nodeStaysActive = false -- self:dumpActiveRing() - local shortfall = self.lineWidth - self.curActiveWidth if self.seenAlternatives then self:tryAlternatives(self.r.prevBreak and self.r.prevBreak.curBreak or 1, self.r.curBreak and self.r.curBreak or 1) end - shortfall = self.lineWidth - self.curActiveWidth + local shortfall = self.lineWidth - self.curActiveWidth self.badness, self.fitClass = fitclass(self, shortfall) if debugging then SU.debug("break", self.badness, self.fitClass) end if (self.badness > inf_bad or pi == ejectPenalty) then From c11f610551821651a1bdbc79cc5814b236832a68 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 1 Mar 2024 13:55:28 +0300 Subject: [PATCH 341/357] chore(deps): Bump pinned versions of patch level crate updates --- Cargo.lock | 526 ++++++++++++++++++++++++++++------------------------- 1 file changed, 279 insertions(+), 247 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84b6bad55..7e711da16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arc-swap" @@ -91,9 +91,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block-buffer" @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "regex-automata", @@ -125,14 +125,43 @@ dependencies = [ ] [[package]] -name = "cc" -version = "1.0.83" +name = "camino" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ - "libc", + "serde", ] +[[package]] +name = "cargo-platform" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" + [[package]] name = "cfg-if" version = "1.0.0" @@ -141,9 +170,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.14" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -151,9 +180,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.14" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", @@ -164,36 +193,36 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.6" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" +checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "clap_mangen" -version = "0.2.16" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b5db60b3310cdb376fbeb8826e875a38080d0c61bdec0a91a3da8338948736" +checksum = "e1dd95b5ebb5c1c54581dd6346f3ed6a79a3eef95dd372fc2ac13d535535300e" dependencies = [ "clap", "roff", @@ -205,15 +234,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.0" @@ -283,9 +303,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -327,9 +347,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "errno" @@ -404,9 +424,9 @@ dependencies = [ [[package]] name = "freetype" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +checksum = "efc8599a3078adf8edeb86c71e9f8fa7d88af5ca31e806a867756081f90f5d83" dependencies = [ "freetype-sys", "libc", @@ -414,11 +434,11 @@ dependencies = [ [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "66ee28c39a43d89fbed8b4798fb4ba56722cfd2b5af81f9326c27614ba88ecd5" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -435,9 +455,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.55.2" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002667cd1ebb789313d0d0afe3d23b2821cf3b0e91605095f0e6d8751f0ceeea" +checksum = "6dd025382892c7b500a9ce1582cd803f9c2ebfe44aff52e9c7f86feee7ced75e" dependencies = [ "gix-actor", "gix-commitgraph", @@ -478,9 +498,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.28.1" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadca029ef716b4378f7afb19f7ee101fde9e58ba1f1445971315ac866db417" +checksum = "da27b5ab4ab5c75ff891dccd48409f8cc53c28a79480f1efdd33184b2dc1d958" dependencies = [ "bstr", "btoi", @@ -510,23 +530,23 @@ dependencies = [ [[package]] name = "gix-commitgraph" -version = "0.22.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a7007ba021f059803afaf6f8a48872422abc20550ac12ede6ddea2936cec36" +checksum = "7e8dcbf434951fa477063e05fea59722615af70dc2567377e58c2f7853b010fc" dependencies = [ "bstr", "gix-chunk", "gix-features", "gix-hash", - "memmap2 0.9.3", + "memmap2", "thiserror", ] [[package]] name = "gix-config" -version = "0.31.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cae98c6b4c66c09379bc35274b172587d6b0ac369a416c39128ad8c6454f9bb" +checksum = "367304855b369cadcac4ee5fb5a3a20da9378dd7905106141070b79f85241079" dependencies = [ "bstr", "gix-config-value", @@ -545,11 +565,11 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e0be46f4cf1f8f9e88d0e3eb7b29718aff23889563249f379119bd1ab6910e" +checksum = "74ab5d22bc21840f4be0ba2e78df947ba14d8ba6999ea798f86b5bdb999edd0c" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "bstr", "gix-path", "libc", @@ -558,9 +578,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7f3dfb72bebe3449b5e642be64e3c6ccbe9821c8b8f19f487cf5bfbbf4067e" +checksum = "17077f0870ac12b55d2eed9cb3f56549e40def514c8a783a0a79177a8a76b7c5" dependencies = [ "bstr", "itoa", @@ -570,10 +590,11 @@ dependencies = [ [[package]] name = "gix-diff" -version = "0.37.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931394f69fb8c9ed6afc0aae3487bd869e936339bcc13ed8884472af072e0554" +checksum = "fd6a0454f8c42d686f17e7f084057c717c082b7dbb8209729e4e8f26749eb93a" dependencies = [ + "bstr", "gix-hash", "gix-object", "thiserror", @@ -581,9 +602,9 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.26.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45d5cf0321178883e38705ab2b098f625d609a7d4c391b33ac952eff2c490f2" +checksum = "b8d7b2896edc3d899d28a646ccc6df729827a6600e546570b2783466404a42d6" dependencies = [ "bstr", "dunce", @@ -596,9 +617,9 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.36.1" +version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d46a4a5c6bb5bebec9c0d18b65ada20e6517dbd7cf855b87dd4bbdce3a771b2" +checksum = "d50270e8dcc665f30ba0735b17984b9535bdf1e646c76e638e007846164d57af" dependencies = [ "crc32fast", "flate2", @@ -614,20 +635,20 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e86eb040f5776a5ade092282e51cdcad398adb77d948b88d17583c2ae4e107" +checksum = "7555c23a005537434bbfcb8939694e18cad42602961d0de617f8477cc2adecdd" dependencies = [ "gix-features", ] [[package]] name = "gix-glob" -version = "0.14.1" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db19298c5eeea2961e5b3bf190767a2d1f09b8802aeb5f258e42276350aff19" +checksum = "ae6232f18b262770e343dcdd461c0011c9b9ae27f0c805e115012aa2b902c1b8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "bstr", "gix-features", "gix-path", @@ -635,9 +656,9 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8cf8c2266f63e582b7eb206799b63aa5fa68ee510ad349f637dfe2d0653de0" +checksum = "b0ed89cdc1dce26685c80271c4287077901de3c3dd90234d5fa47c22b2268653" dependencies = [ "faster-hex", "thiserror", @@ -645,9 +666,9 @@ dependencies = [ [[package]] name = "gix-hashtable" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb61880816d7ec4f0b20606b498147d480860ddd9133ba542628df2f548d3ca" +checksum = "ebe47d8c0887f82355e2e9e16b6cecaa4d5e5346a7a474ca78ff94de1db35a5b" dependencies = [ "gix-hash", "hashbrown", @@ -656,11 +677,11 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.26.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83a4fcc121b2f2e109088f677f89f85e7a8ebf39e8e6659c0ae54d4283b1650" +checksum = "9e50e63df6c8d4137f7fb882f27643b3a9756c468a1a2cdbe1ce443010ca8778" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "bstr", "btoi", "filetime", @@ -672,16 +693,18 @@ dependencies = [ "gix-object", "gix-traverse", "itoa", - "memmap2 0.7.1", + "libc", + "memmap2", + "rustix", "smallvec", "thiserror", ] [[package]] name = "gix-lock" -version = "11.0.1" +version = "12.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5c65e6a29830a435664891ced3f3c1af010f14900226019590ee0971a22f37" +checksum = "f40a439397f1e230b54cf85d52af87e5ea44cc1e7748379785d3f6d03d802b00" dependencies = [ "gix-tempfile", "gix-utils", @@ -696,14 +719,14 @@ checksum = "d75e7ab728059f595f6ddc1ad8771b8d6a231971ae493d9d5948ecad366ee8bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "gix-object" -version = "0.38.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740f2a44267f58770a1cb3a3d01d14e67b089c7136c48d4bddbb3cfd2bf86a51" +checksum = "0c89402e8faa41b49fde348665a8f38589e461036475af43b6b70615a6a313a2" dependencies = [ "bstr", "btoi", @@ -720,9 +743,9 @@ dependencies = [ [[package]] name = "gix-odb" -version = "0.54.0" +version = "0.56.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8630b56cb80d8fa684d383dad006a66401ee8314e12fbf0e566ddad8c115143b" +checksum = "46ae6da873de41c6c2b73570e82c571b69df5154dcd8f46dfafc6687767c33b1" dependencies = [ "arc-swap", "gix-date", @@ -739,9 +762,9 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.44.0" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1431ba2e30deff1405920693d54ab231c88d7c240dd6ccc936ee223d8f8697c3" +checksum = "782b4d42790a14072d5c400deda9851f5765f50fe72bca6dece0da1cd6f05a9a" dependencies = [ "clru", "gix-chunk", @@ -751,7 +774,7 @@ dependencies = [ "gix-object", "gix-path", "gix-tempfile", - "memmap2 0.7.1", + "memmap2", "parking_lot", "smallvec", "thiserror", @@ -759,9 +782,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dd0998ab245f33d40ca2267e58d542fe54185ebd1dc41923346cf28d179fb6" +checksum = "69e0b521a5c345b7cd6a81e3e6f634407360a038c8b74ba14c621124304251b8" dependencies = [ "bstr", "gix-trace", @@ -772,20 +795,20 @@ dependencies = [ [[package]] name = "gix-quote" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7dc10303d73a960d10fb82f81188b036ac3e6b11b5795b20b1a60b51d1321f" +checksum = "4d1b102957d975c6eb56c2b7ad9ac7f26d117299b910812b2e9bf086ec43496d" dependencies = [ "bstr", - "btoi", + "gix-utils", "thiserror", ] [[package]] name = "gix-ref" -version = "0.38.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec2f6d07ac88d2fb8007ee3fa3e801856fb9d82e7366ec0ca332eb2c9d74a52" +checksum = "64d9bd1984638d8f3511a2fcbe84fcedb8a5b5d64df677353620572383f42649" dependencies = [ "gix-actor", "gix-date", @@ -797,16 +820,16 @@ dependencies = [ "gix-path", "gix-tempfile", "gix-validate", - "memmap2 0.7.1", + "memmap2", "thiserror", "winnow", ] [[package]] name = "gix-refspec" -version = "0.19.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb0974cc41dbdb43a180c7f67aa481e1c1e160fcfa8f4a55291fd1126c1a6e7" +checksum = "be219df5092c1735abb2a53eccdf775e945eea6986ee1b6e7a5896dccc0be704" dependencies = [ "bstr", "gix-hash", @@ -818,9 +841,9 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.23.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ca97ac73459a7f3766aa4a5638a6e37d56d4c7962bc1986fbaf4883d0772588" +checksum = "aa78e1df3633bc937d4db15f8dca2abdb1300ca971c0fabcf9fa97e38cf4cd9f" dependencies = [ "bstr", "gix-date", @@ -834,9 +857,9 @@ dependencies = [ [[package]] name = "gix-revwalk" -version = "0.9.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16d8c892e4cd676d86f0265bf9d40cefd73d8d94f86b213b8b77d50e77efae0" +checksum = "702de5fe5c2bbdde80219f3a8b9723eb927466e7ecd187cfd1b45d986408e45f" dependencies = [ "gix-commitgraph", "gix-date", @@ -849,21 +872,21 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f6dce0c6683e2219e8169aac4b1c29e89540a8262fef7056b31d80d969408c" +checksum = "022592a0334bdf77c18c06e12a7c0eaff28845c37e73c51a3e37d56dd495fb35" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "gix-path", "libc", - "windows", + "windows-sys 0.52.0", ] [[package]] name = "gix-tempfile" -version = "11.0.1" +version = "12.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388dd29114a86ec69b28d1e26d6d63a662300ecf61ab3f4cc578f7d7dc9e7e23" +checksum = "a8ef376d718b1f5f119b458e21b00fbf576bc9d4e26f8f383d29f5ffe3ba3eaa" dependencies = [ "gix-fs", "libc", @@ -876,15 +899,15 @@ dependencies = [ [[package]] name = "gix-trace" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e1127ede0475b58f4fe9c0aaa0d9bb0bad2af90bbd93ccd307c8632b863d89" +checksum = "02b202d766a7fefc596e2cc6a89cda8ad8ad733aed82da635ac120691112a9b1" [[package]] name = "gix-traverse" -version = "0.34.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d050ec7d4e1bb76abf0636cf4104fb915b70e54e3ced9a4427c999100ff38a" +checksum = "65109e445ba7a409b48f34f570a4d7db72eade1dc1bcff81990a490e86c07161" dependencies = [ "gix-commitgraph", "gix-date", @@ -898,9 +921,9 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.25.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c427a1a11ccfa53a4a2da47d9442c2241deee63a154bc15cc14b8312fbc4005" +checksum = "8f0f17cceb7552a231d1fec690bc2740c346554e3be6f5d2c41dfa809594dc44" dependencies = [ "bstr", "gix-features", @@ -912,11 +935,12 @@ dependencies = [ [[package]] name = "gix-utils" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de6225e2de30b6e9bca2d9f1cc4731640fcef0fb3cabddceee366e7e85d3e94f" +checksum = "60157a15b9f14b11af1c6817ad7a93b10b50b4e5136d98a127c46a37ff16eeb6" dependencies = [ "fastrand", + "unicode-normalization", ] [[package]] @@ -989,9 +1013,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -1004,15 +1028,15 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1026,9 +1050,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lua-src" @@ -1041,9 +1065,9 @@ dependencies = [ [[package]] name = "luajit-src" -version = "210.5.4+c525bcb" +version = "210.5.6+9cc2e42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a10ab4ed12d22cb50ef43ece4f6c5ca594b2d2480019e87facfd422225a9908" +checksum = "23b365d859c9ffc187f48bb3e25ec80c3b40cf3f68f53544f4adeaee70554157" dependencies = [ "cc", "which", @@ -1057,36 +1081,27 @@ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" -dependencies = [ - "libc", -] - -[[package]] -name = "memmap2" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mlua" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aba10897af47c8e85283db95529b0c6a2d8f3c7b9733c0d2f206d9ee8fc51a3" +checksum = "868d02cb5eb97761bbf6bd6922c1c7a88b8ea252bbf43bd8350a0bf8497a1fc0" dependencies = [ "bstr", "mlua-sys", @@ -1098,9 +1113,9 @@ dependencies = [ [[package]] name = "mlua-sys" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4655631a02e3739d014951291ecfa08db49c4da3f7f8c6f3931ed236af5dd78e" +checksum = "2847b42764435201d8cbee1f517edb79c4cca4181877b90047587c89e1b7bce4" dependencies = [ "cc", "cfg-if", @@ -1111,9 +1126,9 @@ dependencies = [ [[package]] name = "mlua_derive" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f359220f24e6452dd82a3f50d7242d4aab822b5594798048e953d7a9e0314c6" +checksum = "aaade5f94e5829db58791664ba98f35fea6a3ffebc783becb51dc97c7a21abee" dependencies = [ "itertools", "once_cell", @@ -1121,23 +1136,29 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.48", + "syn 2.0.52", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] @@ -1179,9 +1200,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "powerfmt" @@ -1215,18 +1236,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "prodash" -version = "26.2.2" +version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf" +checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" [[package]] name = "quote" @@ -1248,9 +1269,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -1260,9 +1281,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -1283,9 +1304,9 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rust-embed" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f" +checksum = "fb78f46d0066053d16d4ca7b898e9343bc3530f71c61d5ad84cd404ada068745" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1294,22 +1315,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16" +checksum = "b91ac2a3c6c0520a3fb3dd89321177c3c692937c4eb21893378219da10c44fc8" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.48", + "syn 2.0.52", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.2.0" +version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" +checksum = "86f69089032567ffff4eada41c573fc43ff466c7db7c5688b2e7969584345581" dependencies = [ "globset", "sha2", @@ -1324,11 +1345,11 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", @@ -1341,6 +1362,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + [[package]] name = "same-file" version = "1.0.6" @@ -1356,24 +1383,44 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +dependencies = [ + "serde", +] + [[package]] name = "serde" -version = "1.0.195" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", ] [[package]] @@ -1428,15 +1475,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "syn" @@ -1450,9 +1497,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1461,13 +1508,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] @@ -1484,33 +1530,34 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "time" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", "libc", + "num-conv", "num_threads", "powerfmt", "serde", @@ -1526,10 +1573,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -1556,9 +1604,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-bom" @@ -1574,9 +1622,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1600,12 +1648,15 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "vergen" -version = "8.2.6" +version = "8.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1290fd64cc4e7d3c9b07d7f333ce0ce0007253e32870e632624835cc80b83939" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" dependencies = [ "anyhow", + "cargo_metadata", + "cfg-if", "gix", + "regex", "rustversion", "time", ] @@ -1628,15 +1679,15 @@ dependencies = [ [[package]] name = "which" -version = "5.0.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" +checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" dependencies = [ "either", "home", "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1670,25 +1721,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core", - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.0", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -1704,7 +1736,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -1724,17 +1756,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -1745,9 +1777,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -1757,9 +1789,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -1769,9 +1801,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -1781,9 +1813,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -1793,9 +1825,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -1805,9 +1837,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -1817,15 +1849,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.5.33" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] From d931849f93c50a2722e07411579f891708b53fc6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 12 Mar 2024 11:49:14 +0300 Subject: [PATCH 342/357] fix(build): Correct configure flag so debug builds are not release mode --- build-aux/ax_rust_boilerplate.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 index 12ccecde4..3dae605b3 100644 --- a/build-aux/ax_rust_boilerplate.m4 +++ b/build-aux/ax_rust_boilerplate.m4 @@ -6,7 +6,7 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Build Rust code with debugging information])) - AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"]) + AM_CONDITIONAL([DEBUG_RELEASE], [test "x$enable_debug" = "xyes"]) AC_ARG_ENABLE([dependency-checks], AS_HELP_STRING([--disable-dependency-checks], From b48aecc7f2b5500ec33a7d644a419d372a6f0885 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 12 Mar 2024 11:57:03 +0300 Subject: [PATCH 343/357] chore(build): Remove duplicated configure flag setup --- configure.ac | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure.ac b/configure.ac index e61906f5d..d4c46dee8 100644 --- a/configure.ac +++ b/configure.ac @@ -31,11 +31,6 @@ AC_ARG_ENABLE([dependency-checks], [Disable dependency checks])) AM_CONDITIONAL([DEPENDENCY_CHECKS], [test "x$enable_dependency_checks" != "xno"]) -AC_ARG_ENABLE([developer], - AS_HELP_STRING([--enable-developer], - [Check for and enable tooling required only for developers])) -AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) - AM_CONDITIONAL([SHARED], [test "x$enable_shared" = "xyes"]) AM_CONDITIONAL([STATIC], [test "x$enable_static" = "xyes"]) From d3a7eecf0a28c120f73d406be6579bc6ae1021be Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 12 Mar 2024 12:01:11 +0300 Subject: [PATCH 344/357] chore(build): Enable debug profile automatically in developer mode --- build-aux/ax_rust_boilerplate.m4 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 index 3dae605b3..8becdec68 100644 --- a/build-aux/ax_rust_boilerplate.m4 +++ b/build-aux/ax_rust_boilerplate.m4 @@ -3,6 +3,13 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ AX_TRANSFORM_PACKAGE_NAME AX_SHELL_COMPLETION_DIRS + AC_ARG_ENABLE([developer], + AS_HELP_STRING([--enable-developer], + [Check for and enable tooling required only for developers. Also enables debugging profile.])) + AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) + + AM_COND_IF([DEVELOPER], [enable_debug=yes ]) + AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Build Rust code with debugging information])) @@ -13,11 +20,6 @@ AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ [Disable build tooling dependency checks])) AM_CONDITIONAL([DEPENDENCY_CHECKS], [test "x$enable_dependency_checks" != "xno"]) - AC_ARG_ENABLE([developer], - AS_HELP_STRING([--enable-developer], - [Check for and enable tooling required only for developers])) - AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) - AC_MSG_NOTICE([checking for tools used by automake to build Rust projects]) AC_PROG_INSTALL AX_PROGVAR([cargo]) From b0e931e75ba506627c59aaf26f8fb43c71b1cc11 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 14 Mar 2024 22:57:04 +0300 Subject: [PATCH 345/357] chore(classes): Guard against attempts to load invalid package names --- classes/base.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/classes/base.lua b/classes/base.lua index 2403d9cac..f834aa3b1 100644 --- a/classes/base.lua +++ b/classes/base.lua @@ -189,6 +189,8 @@ function class:loadPackage (packname, options, reload) -- Allow loading by injecting whole packages as-is, otherwise try to load it with the usual packages path. if type(packname) == "table" then pack, packname = packname, packname._name + elseif type(packname) == "nil" or packname == "nil" or pl.stringx.strip(packname) == "" then + SU.error(("Attempted to load package with an invalid packname '%s'"):format(packname)) else pack = require(("packages.%s"):format(packname)) if pack._name ~= packname then From d0378fb1c817c46b3153abd04ce1bd68be1a6bea Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 15 Mar 2024 00:39:06 +0300 Subject: [PATCH 346/357] chore(core): Fixup ec6ed657 which didn't shim old pack styles properly --- inputters/base.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inputters/base.lua b/inputters/base.lua index cd609669c..fd8ec3854 100644 --- a/inputters/base.lua +++ b/inputters/base.lua @@ -69,7 +69,7 @@ local function process_ambles (ambles) if amble.pack then amble, options = amble.pack, amble.options end if amble.type == "package" then local class = SILE.documentState.documentClass - class:loadPackage(amble.pack, options) + class:loadPackage(amble, options) else SILE.documentState.documentClass:initPackage(amble, options) end From 6bfb6e66b4cf7d00f8aa17cdbd8c40927ecf7a06 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Thu, 28 Mar 2024 15:06:03 +0300 Subject: [PATCH 347/357] chore(cli): Make sure configured data directory is considered when user adds paths from env --- src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 28ae63b11..f0c33b456 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,9 +29,10 @@ pub fn inject_paths(lua: &Lua) { lua.load(r#"require("core.pathsetup")"#).exec().unwrap(); #[cfg(not(feature = "static"))] { + let datadir = env!("CONFIGURE_DATADIR").to_string(); let sile_path = match env::var("SILE_PATH") { - Ok(val) => val, - Err(_) => env!("CONFIGURE_DATADIR").to_string(), + Ok(val) => format!("{datadir};{val}"), + Err(_) => datadir, }; let sile_path: LuaString = lua.create_string(&sile_path).unwrap(); lua.load(chunk! { From 44ff649029c99b80994ef340b3d3e6c9c33c243c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sat, 30 Mar 2024 01:59:05 +0300 Subject: [PATCH 348/357] =?UTF-8?q?chore(tooling):=20Fix=20spelling=20of?= =?UTF-8?q?=20embeded=E2=86=92embedded=20in=20configure=20option?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 4 ++-- Makefile.am | 16 ++++++++-------- configure.ac | 6 +++--- src/embed.rs.in | 20 ++++++++++---------- src/lib.rs | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 334be762b..d6f9f0f84 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,8 +14,8 @@ jobs: configuration: - [ 'dynamic', '' ] - [ 'system', '--with-system-lua-sources' ] - - [ 'embeded', '--enable-embeded-resources' ] - - [ 'static', '--enable-embeded-resources --disable-shared --enable-static' ] + - [ 'embedded', '--enable-embedded-resources' ] + - [ 'static', '--enable-embedded-resources --disable-shared --enable-static' ] runs-on: ubuntu-22.04 name: Build Ubuntu ${{ matrix.configuration[0] }} steps: diff --git a/Makefile.am b/Makefile.am index f4df7e413..43352c7a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,7 +61,7 @@ bin_SCRIPTS = sile-lua dist_man_MANS = sile-lua.1 sile_SOURCES = src/bin/sile.rs src/lib.rs src/cli.rs EXTRA_sile_SOURCES = -if !EMBEDED_RESOURCES +if !EMBEDDED_RESOURCES nobase_dist_pkgdata_DATA = $(SILEDATA) $(LUALIBRARIES) nobase_nodist_pkgdata_DATA = $(BUILT_LUA_SOURCES) $(LUAMODULES) endif @@ -87,11 +87,11 @@ include $(top_srcdir)/build-aux/rust_boilerplate.mk Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ -if EMBEDED_RESOURCES -_EMBEDED_SOURCES = src/embed.rs src/embed-includes.rs -nodist_sile_SOURCES = $(_EMBEDED_SOURCES) -BUILT_SOURCES += $(_EMBEDED_SOURCES) -CLEANFILES += $(_EMBEDED_SOURCES) +if EMBEDDED_RESOURCES +_EMBEDDED_SOURCES = src/embed.rs src/embed-includes.rs +nodist_sile_SOURCES = $(_EMBEDDED_SOURCES) +BUILT_SOURCES += $(_EMBEDDED_SOURCES) +CLEANFILES += $(_EMBEDDED_SOURCES) $(CARGO_BIN): justenough/.libs/fontmetrics.a $(CARGO_BIN): justenough/.libs/justenoughfontconfig.a $(CARGO_BIN): justenough/.libs/justenoughharfbuzz.a @@ -115,7 +115,7 @@ src/embed.rs: src/embed.rs.in src/embed-includes.rs -e '/@INCLUDE_EMDED_INCLUDES@/r $(word 2,$^)' \ -e '/@INCLUDE_EMDED_INCLUDES@/d' \ $< > $@ -endif EMBEDED_RESOURCES +endif EMBEDDED_RESOURCES if LUAJIT MLUAVER = luajit @@ -128,7 +128,7 @@ if !SYSTEM_LUA_SOURCES CARGO_FEATURE_ARGS += --features vendored endif -if EMBEDED_RESOURCES +if EMBEDDED_RESOURCES CARGO_FEATURE_ARGS += --features static endif diff --git a/configure.ac b/configure.ac index d4c46dee8..34b95a707 100644 --- a/configure.ac +++ b/configure.ac @@ -34,10 +34,10 @@ AM_CONDITIONAL([DEPENDENCY_CHECKS], [test "x$enable_dependency_checks" != "xno"] AM_CONDITIONAL([SHARED], [test "x$enable_shared" = "xyes"]) AM_CONDITIONAL([STATIC], [test "x$enable_static" = "xyes"]) -AC_ARG_ENABLE([embeded], - AS_HELP_STRING([--enable-embeded-resources], +AC_ARG_ENABLE([embedded], + AS_HELP_STRING([--enable-embedded-resources], [Compile resources such as Lua module files directly into the Rust CLI binary])) -AM_CONDITIONAL([EMBEDED_RESOURCES], [test "x$enable_embeded_resources" = "xyes"]) +AM_CONDITIONAL([EMBEDDED_RESOURCES], [test "x$enable_embedded_resources" = "xyes"]) AC_ARG_ENABLE([font-variations], AS_HELP_STRING([--disable-font-variations], diff --git a/src/embed.rs.in b/src/embed.rs.in index f787d7347..f9b26cdbf 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -40,14 +40,14 @@ extern "C-unwind" { } /// Register a Lua function in the loaders/searchers table to return C modules linked into the CLI -/// binary and another to return embeded Lua resources as Lua modules. See discussion in mlua: +/// binary and another to return embedded Lua resources as Lua modules. See discussion in mlua: /// https://github.com/khvzak/mlua/discussions/322 -pub fn inject_embeded_loader(lua: &Lua) { +pub fn inject_embedded_loader(lua: &Lua) { let package: LuaTable = lua.globals().get("package").unwrap(); let loaders: LuaTable = match package.get("loaders").unwrap() { LuaValue::Table(loaders) => loaders, LuaValue::Nil => package.get("searchers").unwrap(), - _ => panic!("Unable to find approprate interface to inject embeded loader"), + _ => panic!("Unable to find approprate interface to inject embedded loader"), }; loaders .push(LuaFunction::wrap(|lua, module: String| unsafe { @@ -94,9 +94,9 @@ pub fn inject_embeded_loader(lua: &Lua) { let mut resource_option: Option<EmbeddedFile> = None; for pattern in &package_epath { let path = pattern.replace('?', &module_path); - let embeded = SileModules::get(&path); - if embeded.is_some() { - resource_option = embeded; + let embedded = SileModules::get(&path); + if embedded.is_some() { + resource_option = embedded; break; } } @@ -104,12 +104,12 @@ pub fn inject_embeded_loader(lua: &Lua) { Some(module) => { return LuaFunction::wrap(move |lua, ()| { let data = str::from_utf8(module.data.as_ref()) - .expect("Embeded content is not valid UTF-8"); + .expect("Embedded content is not valid UTF-8"); lua.load(data).call::<_, LuaValue>(()) }) .into_lua(lua) } - None => format!("Module '{module}' is not embeded in Rust binary").into_lua(lua), + None => format!("Module '{module}' is not embedded in Rust binary").into_lua(lua), } })) .unwrap(); @@ -121,14 +121,14 @@ pub fn inject_embeded_loader(lua: &Lua) { match SileModules::get(&path) { Some(module) => LuaFunction::wrap(move |lua, ()| { let data = str::from_utf8(module.data.as_ref()) - .expect("Embeded content is not valid UTF-8"); + .expect("Embedded content is not valid UTF-8"); lua.load(chunk! { return assert(fluent:add_messages($data)) }) .call::<_, LuaValue>(()) }) .into_lua(lua), - None => format!("FTL resource '{module_path}' is not embeded in Rust binary") + None => format!("FTL resource '{module_path}' is not embedded in Rust binary") .into_lua(lua), } })) diff --git a/src/lib.rs b/src/lib.rs index f0c33b456..ae6a911ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,7 @@ pub type Result<T> = anyhow::Result<T>; pub fn start_luavm() -> crate::Result<Lua> { let lua = unsafe { Lua::unsafe_new() }; #[cfg(feature = "static")] - crate::embed::inject_embeded_loader(&lua); + crate::embed::inject_embedded_loader(&lua); inject_paths(&lua); load_sile(&lua); inject_version(&lua); From 1ad9ad5f187c22a58c6b07a8d8a39f287a657a2c Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 14 Apr 2024 01:38:02 +0300 Subject: [PATCH 349/357] chore(build): Vendor all used autoconf-archive macros --- build-aux/ax_add_am_macro.m4 | 29 ++++++++++++++++++++++ build-aux/ax_am_macros.m4 | 44 ++++++++++++++++++++++++++++++++++ build-aux/ax_append_to_file.m4 | 27 +++++++++++++++++++++ build-aux/ax_file_escapes.m4 | 30 +++++++++++++++++++++++ build-aux/ax_print_to_file.m4 | 27 +++++++++++++++++++++ 5 files changed, 157 insertions(+) create mode 100644 build-aux/ax_add_am_macro.m4 create mode 100644 build-aux/ax_am_macros.m4 create mode 100644 build-aux/ax_append_to_file.m4 create mode 100644 build-aux/ax_file_escapes.m4 create mode 100644 build-aux/ax_print_to_file.m4 diff --git a/build-aux/ax_add_am_macro.m4 b/build-aux/ax_add_am_macro.m4 new file mode 100644 index 000000000..3962002bf --- /dev/null +++ b/build-aux/ax_add_am_macro.m4 @@ -0,0 +1,29 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_add_am_macro.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_ADD_AM_MACRO([RULE]) +# +# DESCRIPTION +# +# Adds the specified rule to $AMINCLUDE. This macro will only work +# properly with implementations of Make which allow include statements. +# See also AX_ADD_AM_MACRO_STATIC. +# +# LICENSE +# +# Copyright (c) 2009 Tom Howard <tomhoward@users.sf.net> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AC_DEFUN([AX_ADD_AM_MACRO],[ + AC_REQUIRE([AX_AM_MACROS]) + AX_APPEND_TO_FILE([$AMINCLUDE],[$1]) +]) diff --git a/build-aux/ax_am_macros.m4 b/build-aux/ax_am_macros.m4 new file mode 100644 index 000000000..36c3ab6a2 --- /dev/null +++ b/build-aux/ax_am_macros.m4 @@ -0,0 +1,44 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_am_macros.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_AM_MACROS +# +# DESCRIPTION +# +# Adds support for macros that create Make rules. You must manually add +# the following line +# +# @INC_AMINCLUDE@ +# +# to your Makefile.in (or Makefile.am if you use Automake) files. +# +# LICENSE +# +# Copyright (c) 2009 Tom Howard <tomhoward@users.sf.net> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 11 + +AC_DEFUN([AX_AM_MACROS], +[ +AC_MSG_NOTICE([adding automake macro support]) +AMINCLUDE="aminclude.am" +AC_SUBST(AMINCLUDE) +AC_MSG_NOTICE([creating $AMINCLUDE]) +AMINCLUDE_TIME=`LC_ALL=C date` +AX_PRINT_TO_FILE([$AMINCLUDE],[[ +# generated automatically by configure from AX_AUTOMAKE_MACROS +# on $AMINCLUDE_TIME + +]]) + +INC_AMINCLUDE="include \$(top_builddir)/$AMINCLUDE" +AC_SUBST(INC_AMINCLUDE) +]) diff --git a/build-aux/ax_append_to_file.m4 b/build-aux/ax_append_to_file.m4 new file mode 100644 index 000000000..fca570837 --- /dev/null +++ b/build-aux/ax_append_to_file.m4 @@ -0,0 +1,27 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_append_to_file.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_TO_FILE([FILE],[DATA]) +# +# DESCRIPTION +# +# Appends the specified data to the specified file. +# +# LICENSE +# +# Copyright (c) 2008 Tom Howard <tomhoward@users.sf.net> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 9 + +AC_DEFUN([AX_APPEND_TO_FILE],[ +AC_REQUIRE([AX_FILE_ESCAPES]) +printf "%s" "$2" >> "$1" +]) diff --git a/build-aux/ax_file_escapes.m4 b/build-aux/ax_file_escapes.m4 new file mode 100644 index 000000000..a86fdc326 --- /dev/null +++ b/build-aux/ax_file_escapes.m4 @@ -0,0 +1,30 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_FILE_ESCAPES +# +# DESCRIPTION +# +# Writes the specified data to the specified file. +# +# LICENSE +# +# Copyright (c) 2008 Tom Howard <tomhoward@users.sf.net> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AC_DEFUN([AX_FILE_ESCAPES],[ +AX_DOLLAR="\$" +AX_SRB="\\135" +AX_SLB="\\133" +AX_BS="\\\\" +AX_DQ="\"" +]) diff --git a/build-aux/ax_print_to_file.m4 b/build-aux/ax_print_to_file.m4 new file mode 100644 index 000000000..8aa71120d --- /dev/null +++ b/build-aux/ax_print_to_file.m4 @@ -0,0 +1,27 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_print_to_file.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PRINT_TO_FILE([FILE],[DATA]) +# +# DESCRIPTION +# +# Writes the specified data to the specified file. +# +# LICENSE +# +# Copyright (c) 2008 Tom Howard <tomhoward@users.sf.net> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AC_DEFUN([AX_PRINT_TO_FILE],[ +AC_REQUIRE([AX_FILE_ESCAPES]) +printf "$2" > "$1" +]) From ad0178de140534f4d8e34474bbca5b4a2347736a Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Sun, 14 Apr 2024 01:44:36 +0300 Subject: [PATCH 350/357] chore(tooling): Ignore new automated intermediate artifact --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 674cc4563..47a5e18a6 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ Makefile.in /autom4te.cache /config.status /configure +/aminclude.am build-aux/compile build-aux/config.guess build-aux/config.sub From 4a3c3c8ff9634f7b5097b893ff89b06945f80dc7 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Fri, 12 Apr 2024 16:02:48 +0300 Subject: [PATCH 351/357] refactor(build): Use more standardized macros from my other projects --- .cirrus.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/deploy.yml | 10 +- .github/workflows/test.yml | 2 +- Makefile.am | 40 +-- README.md | 4 +- bootstrap.sh | 13 +- build-aux/ax_git_version.m4 | 9 - build-aux/ax_rust_boilerplate.m4 | 49 ---- build-aux/ax_transform_package_name.m4 | 18 -- build-aux/pkg.nix | 8 +- build-aux/que_developer_mode.m4 | 19 ++ build-aux/que_dist_checksums.am | 21 ++ build-aux/que_dist_checksums.m4 | 20 ++ build-aux/que_docker_boilerplate.am | 28 ++ build-aux/que_docker_boilerplate.m4 | 18 ++ .../{git_version.mk => que_git_version.am} | 4 +- build-aux/que_git_version.m4 | 26 ++ ...lerplate.mk.in => que_rust_boilerplate.am} | 24 +- build-aux/que_rust_boilerplate.m4 | 42 +++ ...n_dirs.mk => que_shell_completion_dirs.am} | 0 ...n_dirs.m4 => que_shell_completion_dirs.m4} | 11 +- configure.ac | 260 +++++++++--------- documentation/c02-gettingstarted.sil | 2 +- flake.nix | 2 +- 25 files changed, 365 insertions(+), 269 deletions(-) delete mode 100644 build-aux/ax_git_version.m4 delete mode 100644 build-aux/ax_rust_boilerplate.m4 delete mode 100644 build-aux/ax_transform_package_name.m4 create mode 100644 build-aux/que_developer_mode.m4 create mode 100644 build-aux/que_dist_checksums.am create mode 100644 build-aux/que_dist_checksums.m4 create mode 100644 build-aux/que_docker_boilerplate.am create mode 100644 build-aux/que_docker_boilerplate.m4 rename build-aux/{git_version.mk => que_git_version.am} (91%) create mode 100644 build-aux/que_git_version.m4 rename build-aux/{rust_boilerplate.mk.in => que_rust_boilerplate.am} (84%) create mode 100644 build-aux/que_rust_boilerplate.m4 rename build-aux/{shell_completion_dirs.mk => que_shell_completion_dirs.am} (100%) rename build-aux/{ax_shell_completion_dirs.m4 => que_shell_completion_dirs.m4} (90%) diff --git a/.cirrus.yml b/.cirrus.yml index f9d02041e..9e1502455 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -42,7 +42,7 @@ task: - ./bootstrap.sh configure_script: | ./configure MAKE=gmake \ - --enable-developer LDOC=false LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false NPM=false DOCKER=false \ + --enable-developer-mode LDOC=false LUAROCKS=false LUACHECK=false BUSTED=false DELTA=cat PDFINFO=false NIX=false NPM=false DOCKER=false \ --disable-font-variations \ --with-system-lua-sources \ --with-system-luarocks \ diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 975828a86..94c52599d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -60,7 +60,7 @@ jobs: run: | ./bootstrap.sh ./configure \ - --enable-developer LDOC=false LUACHECK=false NIX=false DELTA=cat \ + --enable-developer-mode LDOC=false LUACHECK=false NIX=false DELTA=cat \ --disable-font-variations \ --without-manual - name: Make diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ddd17a16e..5744aa20d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,7 +25,15 @@ jobs: run: | echo "REF=${GITHUB_REF##refs/*/}" >> $GITHUB_ENV ./bootstrap.sh - ./configure --disable-dependency-checks --enable-developer DOCKER=docker + ./configure \ + --enable-developer-mode \ + FCMATCH=true \ + LDOC=false \ + LUACHECK=false \ + BUSTED=false \ + DELTA=false \ + NIX=false \ + PDFINFO=false - name: Publish Docker Image to GH Container Registry run: | make docker-build-push diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index abad02550..28b9d1cd4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: ./bootstrap.sh ./configure \ ${{ matrix.luaVersion[1] }} \ - --enable-developer LDOC=false LUACHECK=false NIX=false DELTA=cat \ + --enable-developer-mode LDOC=false LUACHECK=false NIX=false DELTA=cat \ --disable-font-variations \ --with${{ !startsWith(matrix.luaVersion[0], 'luajit') && 'out' || '' }}-luajit \ --without-system-luarocks \ diff --git a/Makefile.am b/Makefile.am index 43352c7a4..3f82a98ad 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,5 @@ ACLOCAL_AMFLAGS = -I build-aux +AM_DISTCHECK_CONFIGURE_FLAGS = --enable-developer-mode .ONESHELL: .SECONDARY: @@ -82,7 +83,16 @@ BUILT_SOURCES = $(BUILT_LUA_SOURCES) Makefile-distfiles CLEANFILES = $(MANUAL) -include $(top_srcdir)/build-aux/rust_boilerplate.mk +DISTCLEANFILES = @AMINCLUDE@ + +# A classical use of the autoconf-archive include macro would expand +# INC_AMINCLUDE here, but the perl script that inlines include statements +# runs before the automake that organizes logic and performs substitution. +# Consequentially with a substitution here it becomes impossible to use +# automake conditionals and substitutions in the included Makefile fragments. +# By entering the expanded value directly we are ready in time for the inlining +# functionality and hence can use conditionals in included makefile fragments. +include $(top_srcdir)/aminclude.am Makefile-distfiles: $(wildcard .version .tarball-version) | $(LUAMODLOCK) $(SHELL) build-aux/list-dist-files.sh > $@ @@ -257,13 +267,13 @@ patterndeps = $(_FORCED) $(_TEST_DEPS) $(_DOCS_DEPS) | $(bin_PROGRAMS) $(DEPDIRS .PHONY: force force: ; -PHONY_DEVELOPER_TARGETS = busted compare coverage docker docker-build-push \ +PHONY_DEVELOPER_TARGETS = busted compare coverage \ docker-dep-check docker-ghcr-to-hub gource.webm lint luacheck luarocks-lint \ prerelease regression_previews regressions release release-preview tagrelease \ test update_expecteds update_libtexpdf .PHONY: $(PHONY_DEVELOPER_TARGETS) -if DEVELOPER +if DEVELOPER_MODE RELTYPE ?= @@ -382,9 +392,6 @@ export DOCKER_REGISTRY ?= docker.io export DOCKER_REPO ?= siletypesetter/$(TRANSFORMED_PACKAGE_NAME) export DOCKER_TAG ?= HEAD -docker: Dockerfile hooks/build .version - ./hooks/build $(VERSION) - docker-dep-check: .docker_deps .aur_deps $(DIFF) -u $^ @@ -403,28 +410,11 @@ CLEANFILES += .docker_deps CLEANFILES += .aur_deps -define docker_push = - test -z "$(DOCKER_PAT)" || \ - $(DOCKER) login https://$(DOCKER_REGISTRY) -u $(DOCKER_USERNAME) -p $(DOCKER_PAT) - $(DOCKER) push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) - if [[ "$(DOCKER_TAG)" == v*.*.* ]]; then \ - tag=$(DOCKER_TAG) ; \ - $(DOCKER) tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ - $(DOCKER) tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ - $(DOCKER) push $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ - $(DOCKER) push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ - fi -endef - docker-ghcr-to-hub: $(DOCKER) pull $(GHCR_REGISTRY)/$(GHCR_REPO):$(DOCKER_TAG) $(DOCKER) tag $(GHCR_REGISTRY)/$(GHCR_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) $(docker_push) -docker-build-push: docker - $(DOCKER) tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) - $(docker_push) - gource.webm: $(MKDIR_P) /tmp/gravatars magick documentation/sile-logo.pdf[0] -density 300 -colorspace RGB -negate -resize 50% /tmp/sile-logo.jpg @@ -437,9 +427,9 @@ gource.webm: gource -a 0.2 -s 0.2 -i 0 --logo /tmp/sile-logo.jpg -b 000000 --max-file-lag 5 --hide filenames --date-format '%Y-%m-%d' --user-image-dir /tmp/gravatars --user-filter simoncozens --key -1920x1080 -o - | \ ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i - -vcodec libvpx -b 10000K $@ -else !DEVELOPER +else !DEVELOPER_MODE $(PHONY_DEVELOPER_TARGETS): @: $(error "Please reconfigure using --enable-developer to use developer tooling") -endif !DEVELOPER +endif !DEVELOPER_MODE diff --git a/README.md b/README.md index 40abe9b95..e25401e5b 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,7 @@ $ ./bootstrap.sh If you just plan on installing and using SILE, the default configure options (plus any Lua related options discussed above) should be fine. If you plan on developing SILE itself (whether to just tinker with it for your own use or contribute upstream) there is one particularly useful configuration option. -You can add `--enable-developer` will set the 'installed data' directory to the source location which will enable the compiled binary to run directly from the source directory without being installed at all. +You can add `--enable-developer-mode` will set the 'installed data' directory to the source location which will enable the compiled binary to run directly from the source directory without being installed at all. Additionally it will enable checks for tooling we expect SILE contributors to have such as tools used for testing. Using this options also enables a number of targets that wouldn’t normally be needed by end users such as `make regressions`. @@ -245,7 +245,7 @@ $ ./configure $ make ``` -If you just want to mess with SILE locally you can stop here (especially if you used `--enable-developer`). +If you just want to mess with SILE locally you can stop here (especially if you used `--enable-developer-mode`). However to actually install, you will need to run the installation command with system permissions. ```console diff --git a/bootstrap.sh b/bootstrap.sh index 07eaf4c6a..dc49b2827 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -36,11 +36,14 @@ else fi # Autoreconf uses a perl script to inline includes from Makefile.am into -# Makefile.in before ./configure is even run ... which is where we're going to -# use AC_SUBST to setup project specific build options. We need to pre-seed -# a file to avoid a file not found error on first run. The configure process -# will rebuild this and also re-include it into the final Makefile. -touch build-aux/rust_boilerplate.mk +# Makefile.in before ./configure is ever run even once ... which typically means +# AX_AUTOMAKE_MACROS forfeit access to substitutions or conditional logic +# because they enter the picture after those steps. We're intentially using the +# expanded value of @INC_AMINCLUDE@ directly so the include will be inlined. To +# bootstrap we must pre-seed an empty file to avoid a 'file not found' error on +# first run. Subsequently running ./configure will generate the correct content +# based on the configuration flags and also get re-inlined into Makefile.in. +touch aminclude.am autoreconf --install diff --git a/build-aux/ax_git_version.m4 b/build-aux/ax_git_version.m4 deleted file mode 100644 index 4b1029e0d..000000000 --- a/build-aux/ax_git_version.m4 +++ /dev/null @@ -1,9 +0,0 @@ -AC_DEFUN([AX_GIT_VERSION], [ - - AC_PROG_AWK - AC_PROG_GREP - QUE_PROGVAR([cmp]) - - AX_TRANSFORM_PACKAGE_NAME - -]) diff --git a/build-aux/ax_rust_boilerplate.m4 b/build-aux/ax_rust_boilerplate.m4 deleted file mode 100644 index 73eb9913f..000000000 --- a/build-aux/ax_rust_boilerplate.m4 +++ /dev/null @@ -1,49 +0,0 @@ -AC_DEFUN_ONCE([AX_RUST_BOILERPLATE], [ - - AX_TRANSFORM_PACKAGE_NAME - AX_SHELL_COMPLETION_DIRS - - AC_ARG_ENABLE([developer], - AS_HELP_STRING([--enable-developer], - [Check for and enable tooling required only for developers. Also enables debugging profile.])) - AM_CONDITIONAL([DEVELOPER], [test "x$enable_developer" = "xyes"]) - - AM_COND_IF([DEVELOPER], [enable_debug=yes ]) - - AC_ARG_ENABLE(debug, - AS_HELP_STRING([--enable-debug], - [Build Rust code with debugging information])) - AM_CONDITIONAL([DEBUG_RELEASE], [test "x$enable_debug" = "xyes"]) - - AC_ARG_ENABLE([dependency-checks], - AS_HELP_STRING([--disable-dependency-checks], - [Disable build tooling dependency checks])) - AM_CONDITIONAL([DEPENDENCY_CHECKS], [test "x$enable_dependency_checks" != "xno"]) - - AC_MSG_NOTICE([checking for tools used by automake to build Rust projects]) - AC_PROG_INSTALL - QUE_PROGVAR([cargo]) - QUE_PROGVAR([jq]) - QUE_PROGVAR([rustc]) - QUE_PROGVAR([cmp]) - QUE_PROGVAR([xargs]) - AM_COND_IF([DEPENDENCY_CHECKS], [ - AM_COND_IF([DEVELOPER], [ - QUE_PROGVAR([git]) - QUE_PROGVAR([rustfmt]) - ]) - ]) - - AC_MSG_CHECKING([whether to build Rust code with debugging information]) - AM_COND_IF([DEBUG_RELEASE], [ - AC_MSG_RESULT(yes) - RUST_TARGET_SUBDIR=debug - ], [ - AC_MSG_RESULT(no) - RUST_TARGET_SUBDIR=release - ]) - AC_SUBST([RUST_TARGET_SUBDIR]) - - AC_CONFIG_FILES([build-aux/rust_boilerplate.mk]) - -]) diff --git a/build-aux/ax_transform_package_name.m4 b/build-aux/ax_transform_package_name.m4 deleted file mode 100644 index 0ff3298ca..000000000 --- a/build-aux/ax_transform_package_name.m4 +++ /dev/null @@ -1,18 +0,0 @@ -# The autotools supplied AC_ARG_PROGAM enables renaming operations, but it -# supplies them as a sed operation that can be applied to multiple binaries. -# This isn't convenient to use if we're just renaming the top level package, so -# we go ahead and *do* the transformation and save for use as a substitution. - -AC_DEFUN_ONCE([AX_TRANSFORM_PACKAGE_NAME], [ - - AC_PROG_SED - - TRANSFORMED_PACKAGE_NAME="$(printf "$PACKAGE_NAME" | $SED -e "$(printf "$program_transform_name" | $SED -e 's/\$\$/\$/')")" - AC_SUBST([TRANSFORMED_PACKAGE_NAME]) - - PACKAGE_VAR="$(printf "$PACKAGE_NAME" | $SED -e "s/-/_/g")" - AC_SUBST([PACKAGE_VAR]) - - AC_ARG_PROGRAM - -]) diff --git a/build-aux/pkg.nix b/build-aux/pkg.nix index 3046eb852..ee993b7a9 100644 --- a/build-aux/pkg.nix +++ b/build-aux/pkg.nix @@ -132,12 +132,10 @@ in stdenv.mkDerivation (finalAttrs: { enableParallelBuilding = true; - # Autoconf wants to check that Makefile imports are valid files even before - # it potentially generates said files from substitution templates. The - # upstream project uses a bootstrap.sh to create this. Since we skip that, we - # have to fix this race condition ourselves. + # See commentary in bootstrap.sh; we're getting AMINCCLUDE stuff inlined + # instead of included but need to avoid a file not found error on first run. postUnpack = '' - touch source/build-aux/rust_boilerplate.mk + touch source/aminclude.am ''; passthru = { diff --git a/build-aux/que_developer_mode.m4 b/build-aux/que_developer_mode.m4 new file mode 100644 index 000000000..18bd29fe8 --- /dev/null +++ b/build-aux/que_developer_mode.m4 @@ -0,0 +1,19 @@ +# Like AM_MAINTAINER_MODE, but doesn't touch automake internals and so +# can be used freely to control access to project specific developer +# tooling without breaking autotools if disabled. +AC_DEFUN([QUE_DEVELOPER_MODE], [ + m4_case(m4_default([$1], [disable]), + [enable], [m4_define([_que_developer_def], [disable])], + [disable], [m4_define([_que_developer_def], [enable])], + [m4_define([_que_developer_def], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_DEVELOPER_MODE: $1])]) + AC_MSG_CHECKING([whether to enable developer-specific portions of Makefiles]) + AC_ARG_ENABLE([developer-mode], + [AS_HELP_STRING([--]_que_developer_def[-developer-mode], + _que_developer_def[ dependencies and make targets only useful for developers])], + [USE_DEVELOPER_MODE=$enableval], + [USE_DEVELOPER_MODE=]m4_if(_que_developer_def, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_DEVELOPER_MODE]) + AM_CONDITIONAL([DEVELOPER_MODE], [test $USE_DEVELOPER_MODE = yes]) + +]) diff --git a/build-aux/que_dist_checksums.am b/build-aux/que_dist_checksums.am new file mode 100644 index 000000000..ffaecc669 --- /dev/null +++ b/build-aux/que_dist_checksums.am @@ -0,0 +1,21 @@ +# Output both a file that can be attatched to releases and also write STDOUT +# for the sake of CI build logs so they can be audited as matching what is +# eventually posted. The list of files checksummed is a glob (even though we +# know an exact pattern) to avoid errors for formats not generated. +checksum_dist = \ + shopt -s nullglob ; \ + $(SHA256SUM) $(distdir)*.{tar.{gz,bz2,lz,xz,zst},zip} |\ + $(TEE) $(distdir).sha256.txt + +# Since the checksums file isn't an artifact produced by the default source dist +# creation process, we have to clean it up ourselves so distcheck can see that +# everything round-tripped cleanly. +distclean-local: distclean-local-checksums + +distclean-local-checksums: + rm -f $(distdir).sha256.txt + +# Append checksum operation to function that runs after compressing dist archives +am__post_remove_distdir = $(am__remove_distdir); $(checksum_dist) + +# vim: ft=automake diff --git a/build-aux/que_dist_checksums.m4 b/build-aux/que_dist_checksums.m4 new file mode 100644 index 000000000..7ace93afd --- /dev/null +++ b/build-aux/que_dist_checksums.m4 @@ -0,0 +1,20 @@ +AC_DEFUN_ONCE([QUE_DIST_CHECKSUMS], [ + + QUE_TRANSFORM_PACKAGE_NAME + + AC_REQUIRE([AX_AM_MACROS]) + AX_ADD_AM_MACRO([dnl +EXTRA_DIST += build-aux/que_dist_checksums.am +])dnl + + AM_COND_IF([DEVELOPER_MODE], [ + + QUE_PROGVAR([sha256sum]) + QUE_PROGVAR([tee]) + + AX_ADD_AM_MACRO([dnl +$(cat build-aux/que_dist_checksums.am) +])dnl + + ]) +]) diff --git a/build-aux/que_docker_boilerplate.am b/build-aux/que_docker_boilerplate.am new file mode 100644 index 000000000..cec6ca3e1 --- /dev/null +++ b/build-aux/que_docker_boilerplate.am @@ -0,0 +1,28 @@ +export VERSION_FROM_AUTOTOOLS = v$(VERSION) + +DOCKER_DEVELOPER_TARGETS = docker +.PHONY: $(DOCKER_DEVELOPER_TARGETS) + +export DOCKER_REGISTRY ?= ghcr.io +export DOCKER_REPO ?= alerque/$(TRANSFORMED_PACKAGE_NAME) +export DOCKER_TAG ?= HEAD + +docker: Dockerfile hooks/build .version + ./hooks/build $(VERSION) + +docker-build-push: docker + docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) + $(docker_push) + +define docker_push = + test -z "$(DOCKER_PAT)" || \ + docker login https://$(DOCKER_REGISTRY) -u $(DOCKER_USERNAME) -p $(DOCKER_PAT) + docker push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$(DOCKER_TAG) + if [[ "$(DOCKER_TAG)" == v*.*.* ]]; then \ + tag=$(DOCKER_TAG) ; \ + docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ + docker tag $(DOCKER_REPO):$(DOCKER_TAG) $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ + docker push $(DOCKER_REGISTRY)/$(DOCKER_REPO):latest ; \ + docker push $(DOCKER_REGISTRY)/$(DOCKER_REPO):$${tag//.*} ; \ + fi +endef diff --git a/build-aux/que_docker_boilerplate.m4 b/build-aux/que_docker_boilerplate.m4 new file mode 100644 index 000000000..066bf3e13 --- /dev/null +++ b/build-aux/que_docker_boilerplate.m4 @@ -0,0 +1,18 @@ +AC_DEFUN_ONCE([QUE_DOCKER_BOILERPLATE], [ + + QUE_TRANSFORM_PACKAGE_NAME + + AC_MSG_NOTICE([checking for tools used by automake to build Docker projects]) + AC_PROG_INSTALL + AM_COND_IF([DEVELOPER_MODE], [ + QUE_PROGVAR([docker]) + ]) + + AC_REQUIRE([AX_AM_MACROS]) + AX_ADD_AM_MACRO([dnl +EXTRA_DIST += build-aux/que_docker_boilerplate.am + +$($SED -E "s/@PACKAGE_VAR@/$PACKAGE_VAR/g" build-aux/que_docker_boilerplate.am) +])dnl + +]) diff --git a/build-aux/git_version.mk b/build-aux/que_git_version.am similarity index 91% rename from build-aux/git_version.mk rename to build-aux/que_git_version.am index 97a35ad8b..6b9e8098c 100644 --- a/build-aux/git_version.mk +++ b/build-aux/que_git_version.am @@ -1,6 +1,5 @@ .SECONDEXPANSION: -# EXTRA_@PACKAGE_VAR@_SOURCES += .version EXTRA_DIST += build-aux/git-version-gen BUILT_SOURCES += .version CLEANFILES += .version .version-prev @@ -25,6 +24,9 @@ check-git-version: $(PACKAGE_NAME)$(EXEEXT) | .version $(GREP) -Fx '$(VERSION)' $| ./$< --version | $(GREP) -Ff $| +installcheck-local-version: + ./$(TRANSFORMED_PACKAGE_NAME)$(EXEEXT) --version + dist-hook: dist-tarball-version .PHONY: dist-tarball-version diff --git a/build-aux/que_git_version.m4 b/build-aux/que_git_version.m4 new file mode 100644 index 000000000..f91ca11b2 --- /dev/null +++ b/build-aux/que_git_version.m4 @@ -0,0 +1,26 @@ +AC_DEFUN_ONCE([QUE_GIT_VERSION], [ + + AM_CONDITIONAL([SOURCE_IS_GIT], + [test -d .git]) + + AM_CONDITIONAL([SOURCE_IS_DIST], + [test -f .tarball-version]) + + AM_CONDITIONAL([SOURCE_IS_ARCHIVE], + [test ! -d .git -a ! -f .tarball-version]) + + AC_PROG_AWK + AC_PROG_GREP + + QUE_TRANSFORM_PACKAGE_NAME + + AM_COND_IF([SOURCE_IS_DIST], [], [QUE_PROGVAR([cmp])]) + + AC_REQUIRE([AX_AM_MACROS]) + AX_ADD_AM_MACRO([dnl +EXTRA_DIST += build-aux/que_git_version.am + +$(cat build-aux/que_git_version.am) +])dnl + +]) diff --git a/build-aux/rust_boilerplate.mk.in b/build-aux/que_rust_boilerplate.am similarity index 84% rename from build-aux/rust_boilerplate.mk.in rename to build-aux/que_rust_boilerplate.am index fd139b466..2f7b2dd48 100644 --- a/build-aux/rust_boilerplate.mk.in +++ b/build-aux/que_rust_boilerplate.am @@ -11,12 +11,14 @@ if !DEBUG_RELEASE CARGO_RELEASE_ARGS += --release --locked endif -CARGO_ENV = CARGO_TARGET_DIR=@abs_top_builddir@/target -CARGO_BIN = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) -_RUST_OUT = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir +CARGO_ENV = CARGO_TARGET_DIR=@builddir@/target +CARGO_BIN = @builddir@/target/@RUST_TARGET_SUBDIR@/$(PACKAGE_NAME) +_RUST_OUT = @builddir@/target/@RUST_TARGET_SUBDIR@/.cargo_out_dir -include $(top_srcdir)/build-aux/git_version.mk -include $(top_srcdir)/build-aux/shell_completion_dirs.mk +distclean-local: distclean-local-rust + +distclean-local-rust: + -rm -rf @builddir@/target @PACKAGE_NAME@$(EXEEXT): $(CARGO_BIN) $(INSTALL) $< $@ @@ -53,7 +55,6 @@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): $(CARGO_BIN) | $(COMPLETION $(INSTALL) -m755 $$(cat $(_RUST_OUT))/$(COMPLETIONS_OUT_DIR)/_$(PACKAGE_NAME) $@ $(_RUST_OUT) $(CARGO_BIN): $(@PACKAGE_VAR@_SOURCES) $(EXTRA_@PACKAGE_VAR@_SOURCES) - cd $(top_srcdir) set -e export AUTOTOOLS_DEPENDENCIES="$^" $(CARGO_ENV) $(CARGO) build $(CARGO_VERBOSE) $(CARGO_FEATURE_ARGS) $(CARGO_RELEASE_ARGS) @@ -63,7 +64,7 @@ $(_RUST_OUT) $(CARGO_BIN): $(@PACKAGE_VAR@_SOURCES) $(EXTRA_@PACKAGE_VAR@_SOURCE RUST_DEVELOPER_TARGETS = cargo-test clippy rustfmt .PHONY: $(RUST_DEVELOPER_TARGETS) -if DEVELOPER +if DEVELOPER_MODE test: cargo-test lint: rustfmt clippy @@ -74,22 +75,19 @@ rustfmt: $(GIT) ls-files '*.rs' '*.rs.in' | $(XARGS) $(RUSTFMT) --check --config skip_children=true clippy: - cd $(srcdir) $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clippy $(CARGO_FEATURE_ARGS) -- -D warnings clean-cargo: - cd $(top_srcdir) $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) clean cargo-test: $(PACKAGE_NAME)$(EXEEXT) - cd $(srcdir) $(CARGO_ENV) $(CARGO) $(CARGO_VERBOSE) test $(CARGO_FEATURE_ARGS) --locked -else !DEVELOPER +else !DEVELOPER_MODE $(RUST_DEVELOPER_TARGETS): - @: $(error "Please reconfigure using --enable-developer to use developer tooling") + @: $(error "Please reconfigure using --enable-developer-mode to use developer tooling") -endif !DEVELOPER +endif !DEVELOPER_MODE # vim: ft=automake diff --git a/build-aux/que_rust_boilerplate.m4 b/build-aux/que_rust_boilerplate.m4 new file mode 100644 index 000000000..36fa0923d --- /dev/null +++ b/build-aux/que_rust_boilerplate.m4 @@ -0,0 +1,42 @@ +AC_DEFUN_ONCE([QUE_RUST_BOILERPLATE], [ + + QUE_TRANSFORM_PACKAGE_NAME + QUE_DEVELOPER_MODE + QUE_SHELL_COMPLETION_DIRS + + AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], + [Build Rust code with debugging information])) + AM_CONDITIONAL([DEBUG_RELEASE], [test "x$debug_release" = "xyes"]) + + AC_MSG_NOTICE([checking for tools used by automake to build Rust projects]) + AC_PROG_INSTALL + AC_PROG_SED + QUE_PROGVAR([cargo]) + QUE_PROGVAR([jq]) + QUE_PROGVAR([rustc]) + QUE_PROGVAR([cmp]) + QUE_PROGVAR([xargs]) + AM_COND_IF([DEVELOPER_MODE], [ + QUE_PROGVAR([git]) + QUE_PROGVAR([rustfmt]) + ]) + + AC_MSG_CHECKING([whether to build Rust code with debugging information]) + AM_COND_IF([DEBUG_RELEASE], [ + AC_MSG_RESULT(yes) + RUST_TARGET_SUBDIR=debug + ], [ + AC_MSG_RESULT(no) + RUST_TARGET_SUBDIR=release + ]) + AC_SUBST([RUST_TARGET_SUBDIR]) + + AC_REQUIRE([AX_AM_MACROS]) + AX_ADD_AM_MACRO([dnl +EXTRA_DIST += build-aux/que_rust_boilerplate.am + +$($SED -E "s/@PACKAGE_VAR@/$PACKAGE_VAR/g;s/@PACKAGE_NAME@/$PACKAGE_NAME/g" build-aux/que_rust_boilerplate.am) +])dnl + +]) diff --git a/build-aux/shell_completion_dirs.mk b/build-aux/que_shell_completion_dirs.am similarity index 100% rename from build-aux/shell_completion_dirs.mk rename to build-aux/que_shell_completion_dirs.am diff --git a/build-aux/ax_shell_completion_dirs.m4 b/build-aux/que_shell_completion_dirs.m4 similarity index 90% rename from build-aux/ax_shell_completion_dirs.m4 rename to build-aux/que_shell_completion_dirs.m4 index 1545cfd94..380ff53d4 100644 --- a/build-aux/ax_shell_completion_dirs.m4 +++ b/build-aux/que_shell_completion_dirs.m4 @@ -1,6 +1,6 @@ -AC_DEFUN_ONCE([AX_SHELL_COMPLETION_DIRS], [ +AC_DEFUN_ONCE([QUE_SHELL_COMPLETION_DIRS], [ - AX_TRANSFORM_PACKAGE_NAME + QUE_TRANSFORM_PACKAGE_NAME AC_ARG_WITH([bash-completion-dir], AS_HELP_STRING([--with-bash-completion-dir[=PATH]], @@ -44,4 +44,11 @@ AC_DEFUN_ONCE([AX_SHELL_COMPLETION_DIRS], [ [ZSH_COMPLETION_DIR="$with_zsh_completion_dir"]) AC_SUBST([ZSH_COMPLETION_DIR]) + AC_REQUIRE([AX_AM_MACROS]) + AX_ADD_AM_MACRO([dnl +EXTRA_DIST += build-aux/que_shell_completion_dirs.am + +$(cat build-aux/que_shell_completion_dirs.am) +])dnl + ]) diff --git a/configure.ac b/configure.ac index 998e5dc87..d920668c4 100644 --- a/configure.ac +++ b/configure.ac @@ -5,10 +5,10 @@ AC_CONFIG_MACRO_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign tar-pax dist-zstd dist-zip no-dist-gzip color-tests subdir-objects]) AM_SILENT_RULES([yes]) -AX_GIT_VERSION +QUE_GIT_VERSION QUE_TRANSFORM_PACKAGE_NAME - -AM_CONDITIONAL([IS_SDIST], [test ! -e .gitignore]) +QUE_DEVELOPER_MODE +QUE_DIST_CHECKSUMS # Checks for programs. AC_PROG_CC @@ -27,12 +27,8 @@ LT_INIT([dlopen]) AC_CANONICAL_HOST -AX_RUST_BOILERPLATE - -AC_ARG_ENABLE([dependency-checks], - AS_HELP_STRING([--disable-dependency-checks], - [Disable dependency checks])) -AM_CONDITIONAL([DEPENDENCY_CHECKS], [test "x$enable_dependency_checks" != "xno"]) +QUE_RUST_BOILERPLATE +QUE_DOCKER_BOILERPLATE AM_CONDITIONAL([SHARED], [test "x$enable_shared" = "xyes"]) AM_CONDITIONAL([STATIC], [test "x$enable_static" = "xyes"]) @@ -90,144 +86,140 @@ AC_ARG_WITH([manual], [Rebuild manual and install to system’s PDF documentation directory])) AM_CONDITIONAL([MANUAL], [test "x$with_manual" = "xyes"]) -AM_CONDITIONAL([FONT_DOWNLOAD_TOOLS], [test -z ${DEVELOPER_TRUE} || (test -z ${MANUAL_TRUE} && test -z ${IS_SDIST_FALSE})]) +AM_CONDITIONAL([FONT_DOWNLOAD_TOOLS], [test -z ${DEVELOPER_MODE_TRUE} || (test -z ${MANUAL_TRUE} && test -z ${SOURCE_IS_DIST_FALSE})]) AC_SUBST([FONT_DOWNLOAD_TOOLS]) -AM_COND_IF([DEPENDENCY_CHECKS], [ - AC_MSG_NOTICE([checking for SILE specific build dependencies]) +AC_MSG_NOTICE([checking for SILE specific build dependencies]) - QUE_FONT(Gentium Plus) +QUE_FONT(Gentium Plus) - QUE_PROGVAR([pdfinfo]) - QUE_PROGVAR([jq]) - QUE_PROGVAR([xargs]) - AM_COND_IF([MANUAL], [ - QUE_PROGVAR([dot]) - QUE_PROGVAR([gs]) - ]) +QUE_PROGVAR([pdfinfo]) +QUE_PROGVAR([jq]) +QUE_PROGVAR([xargs]) +AM_COND_IF([MANUAL], [ + QUE_PROGVAR([dot]) + QUE_PROGVAR([gs]) + ]) - AC_MSG_CHECKING([for OS X]) - have_appkit=no - case $host_os in - darwin*) +AC_MSG_CHECKING([for OS X]) +have_appkit=no +case $host_os in + darwin*) + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([for AppKit works]) + save_LIBS="$LIBS" + LIBS="$LIBS -framework AppKit -fmodules" + AC_LANG_PUSH([Objective C]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[@import AppKit;]],[[]])], + [ + have_appkit=yes AC_MSG_RESULT([yes]) - AC_MSG_CHECKING([for AppKit works]) - save_LIBS="$LIBS" - LIBS="$LIBS -framework AppKit -fmodules" - AC_LANG_PUSH([Objective C]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[@import AppKit;]],[[]])], - [ - have_appkit=yes - AC_MSG_RESULT([yes]) - ], [ - have_appkit=no - AC_MSG_RESULT([no]) - ]) - AC_LANG_POP([Objective C]) - LIBS="$save_LIBS" - ;; - *) + ], [ + have_appkit=no AC_MSG_RESULT([no]) - ;; - esac - - AM_COND_IF([FONTCONFIG], - [PKG_CHECK_MODULES(FONTCONFIG, [fontconfig], - [], - [AC_MSG_FAILURE([Fontconfig package not found])])]) - - AM_COND_IF([HARFBUZZ], - [PKG_CHECK_MODULES(HARFBUZZ, [harfbuzz >= 2.7.4], - [], - [AC_MSG_FAILURE([--with-harfbuzz was given, but harfbuzz not found])]) ]) - - AM_COND_IF([FONT_VARIATIONS], - [PKG_CHECK_MODULES(HARFBUZZ_SUBSET, [harfbuzz-subset >= 6.0.0], - [AC_DEFINE(HAVE_HARFBUZZ_SUBSET, [1], [Have harfbuzz-subset library])], - [AC_MSG_FAILURE([--enable-font-variations was given, but harfbuzz version not new enough to include required subset library functions])])]) - - AM_COND_IF([SYSTEM_LIBTEXPDF], - [AC_CHECK_LIB([texpdf], [texpdf_doc_set_verbose], - [], - [AC_MSG_FAILURE([--with-system-libtexpdf was given, but test for libtexpdf failed])])], - [AC_CONFIG_SUBDIRS([libtexpdf])]) - - PKG_CHECK_MODULES(ICU, icu-uc icu-io, [ + ]) + AC_LANG_POP([Objective C]) + LIBS="$save_LIBS" + ;; + *) + AC_MSG_RESULT([no]) + ;; +esac + +AM_COND_IF([FONTCONFIG], + [PKG_CHECK_MODULES(FONTCONFIG, [fontconfig], + [], + [AC_MSG_FAILURE([Fontconfig package not found])])]) + +AM_COND_IF([HARFBUZZ], + [PKG_CHECK_MODULES(HARFBUZZ, [harfbuzz >= 2.7.4], + [], + [AC_MSG_FAILURE([--with-harfbuzz was given, but harfbuzz not found])]) ]) + +AM_COND_IF([FONT_VARIATIONS], + [PKG_CHECK_MODULES(HARFBUZZ_SUBSET, [harfbuzz-subset >= 6.0.0], + [AC_DEFINE(HAVE_HARFBUZZ_SUBSET, [1], [Have harfbuzz-subset library])], + [AC_MSG_FAILURE([--enable-font-variations was given, but harfbuzz version not new enough to include required subset library functions])])]) + +AM_COND_IF([SYSTEM_LIBTEXPDF], + [AC_CHECK_LIB([texpdf], [texpdf_doc_set_verbose], + [], + [AC_MSG_FAILURE([--with-system-libtexpdf was given, but test for libtexpdf failed])])], + [AC_CONFIG_SUBDIRS([libtexpdf])]) + +PKG_CHECK_MODULES(ICU, icu-uc icu-io, [ + with_icu=yes +],[ + AC_CHECK_TOOL(ICU_CONFIG, icu-config, no) + AC_MSG_CHECKING([for ICU by using icu-config fallback]) + if test "$ICU_CONFIG" != "no" && "$ICU_CONFIG" --version >/dev/null; then + ICU_LIBS=`icu-config --ldflags-libsonly --ldflags-icuio` + ICU_CFLAGS=`icu-config --cppflags` with_icu=yes - ],[ - AC_CHECK_TOOL(ICU_CONFIG, icu-config, no) - AC_MSG_CHECKING([for ICU by using icu-config fallback]) - if test "$ICU_CONFIG" != "no" && "$ICU_CONFIG" --version >/dev/null; then - ICU_LIBS=`icu-config --ldflags-libsonly --ldflags-icuio` - ICU_CFLAGS=`icu-config --cppflags` - with_icu=yes - AC_MSG_RESULT([yes]) - else - AC_MSG_FAILURE([Required ICU library not found]) - fi - ]) + AC_MSG_RESULT([yes]) + else + AC_MSG_FAILURE([Required ICU library not found]) + fi +]) - AX_PROG_LUA([5.1]) - AX_LUA_HEADERS - AX_LUA_LIBS +AX_PROG_LUA([5.1]) +AX_LUA_HEADERS +AX_LUA_LIBS - AM_COND_IF([SYSTEM_LUAROCKS], [ - AS_IF([test "$LUA_SHORT_VERSION" -lt 52], [ - AM_COND_IF([LUAJIT], [], [ - AX_LUA_MODULE([bit32], [bit32]) - ]) +AM_COND_IF([SYSTEM_LUAROCKS], [ + AS_IF([test "$LUA_SHORT_VERSION" -lt 52], [ + AM_COND_IF([LUAJIT], [], [ + AX_LUA_MODULE([bit32], [bit32]) ]) - AX_LUA_MODULE([cassowary], [cassowary]) - AS_IF([test "$LUA_SHORT_VERSION" -lt 53], - AX_LUA_MODULE([compat53], [compat53]) - ) - AX_LUA_MODULE([cldr], [cldr]) - AX_LUA_MODULE([fluent], [fluent]) - AX_LUA_MODULE([linenoise], [linenoise]) - AX_LUA_MODULE([loadkit], [loadkit]) - AX_LUA_MODULE([lpeg], [lpeg]) - AX_LUA_MODULE([zlib], [lua-zlib]) - AX_LUA_MODULE([cliargs], [lua_cliargs]) - AX_LUA_MODULE([epnf], [luaepnf]) - AX_LUA_MODULE([lxp], [luaexpat]) - AX_LUA_MODULE([lfs], [luafilesystem]) - AX_LUA_MODULE([repl], [luarepl]) - AX_LUA_MODULE([ssl], [luasec]) - AX_LUA_MODULE([socket], [luasocket]) - AX_LUA_MODULE([lua-utf8], [luautf8]) - AX_LUA_MODULE([pl], [penlight]) - AX_LUA_MODULE([vstruct], [vstruct]) - ], [ - QUE_PROGVAR([luarocks]) - ]) - - # Required for downloading fonts for the manual and for tests - # Since the source tarball includes a prebuilt manual we only need this for Git source builds - AM_COND_IF([FONT_DOWNLOAD_TOOLS], [ - QUE_PROGVAR([curl]) - QUE_PROGVAR([bsdtar]) ]) + AX_LUA_MODULE([cassowary], [cassowary]) + AS_IF([test "$LUA_SHORT_VERSION" -lt 53], + AX_LUA_MODULE([compat53], [compat53]) + ) + AX_LUA_MODULE([cldr], [cldr]) + AX_LUA_MODULE([fluent], [fluent]) + AX_LUA_MODULE([linenoise], [linenoise]) + AX_LUA_MODULE([loadkit], [loadkit]) + AX_LUA_MODULE([lpeg], [lpeg]) + AX_LUA_MODULE([zlib], [lua-zlib]) + AX_LUA_MODULE([cliargs], [lua_cliargs]) + AX_LUA_MODULE([epnf], [luaepnf]) + AX_LUA_MODULE([lxp], [luaexpat]) + AX_LUA_MODULE([lfs], [luafilesystem]) + AX_LUA_MODULE([repl], [luarepl]) + AX_LUA_MODULE([ssl], [luasec]) + AX_LUA_MODULE([socket], [luasocket]) + AX_LUA_MODULE([lua-utf8], [luautf8]) + AX_LUA_MODULE([pl], [penlight]) + AX_LUA_MODULE([vstruct], [vstruct]) +], [ + QUE_PROGVAR([luarocks]) +]) - AM_COND_IF([DEVELOPER], [ - QUE_PROGVAR([busted]) - QUE_PROGVAR([cmp]) - QUE_PROGVAR([curl]) - QUE_PROGVAR([delta]) - QUE_PROGVAR([diff]) - QUE_PROGVAR([docker]) - QUE_PROGVAR([git]) - QUE_PROGVAR([grep]) - QUE_PROGVAR([head]) - QUE_PROGVAR([ldoc]) - QUE_PROGVAR([luacheck]) - QUE_PROGVAR([luarocks]) - QUE_PROGVAR([nix]) - QUE_PROGVAR([npm]) - QUE_PROGVAR([perl]) - QUE_PROGVAR([sort]) - QUE_PROGVAR([tr]) - ]) +# Required for downloading fonts for the manual and for tests +# Since the source tarball includes a prebuilt manual we only need this for Git source builds +AM_COND_IF([FONT_DOWNLOAD_TOOLS], [ + QUE_PROGVAR([curl]) + QUE_PROGVAR([bsdtar]) +]) +AM_COND_IF([DEVELOPER_MODE], [ + QUE_PROGVAR([busted]) + QUE_PROGVAR([cmp]) + QUE_PROGVAR([curl]) + QUE_PROGVAR([delta]) + QUE_PROGVAR([diff]) + QUE_PROGVAR([git]) + QUE_PROGVAR([grep]) + QUE_PROGVAR([head]) + QUE_PROGVAR([ldoc]) + QUE_PROGVAR([luacheck]) + QUE_PROGVAR([luarocks]) + QUE_PROGVAR([nix]) + QUE_PROGVAR([npm]) + QUE_PROGVAR([perl]) + QUE_PROGVAR([sort]) + QUE_PROGVAR([tr]) ]) AM_CONDITIONAL([APPKIT], [test "x$have_appkit" = "xyes"]) @@ -262,7 +254,7 @@ AC_SUBST([LUAROCKSARGS]) # Avoid need for `--datarootdir=$(cd ..; pwd)` hack to run locally for # tests/manual build when developer mode is enabled -AM_COND_IF([DEVELOPER], [ +AM_COND_IF([DEVELOPER_MODE], [ adl_RECURSIVE_EVAL(["$(pwd)"], [SILE_PATH]) datarootdir="$(cd ..; pwd)" ],[ diff --git a/documentation/c02-gettingstarted.sil b/documentation/c02-gettingstarted.sil index 255c7d436..699754d3d 100644 --- a/documentation/c02-gettingstarted.sil +++ b/documentation/c02-gettingstarted.sil @@ -228,7 +228,7 @@ Otherwise to go with default of bundling them, just run: \begin{autodoc:note} If you plan on developing SILE itself (whether just to hack on it for your own use or contribute upstream) there are two particularly useful configuration options. First, you can add \code{--datarootdir=$(cd ..;pwd)} which will enable the compiled binary to run directly from the source directory without being installed at all. -Second, you can add \code{--enable-developer} to also check for tooling we expect SILE developers to have, such as tools used for testing. +Second, you can add \code{--enable-developer-mode} to also check for tooling we expect SILE developers to have, such as tools used for testing. Using this option also enables a number of targets that wouldn't normally be needed by end-users, such as \code{make regressions}. \end{autodoc:note} diff --git a/flake.nix b/flake.nix index fe1ceaf0c..43120b416 100644 --- a/flake.nix +++ b/flake.nix @@ -77,7 +77,7 @@ nativeCheckInputs FONTCONFIG_FILE ; - configureFlags = sile.configureFlags ++ [ "--enable-developer" ]; + configureFlags = sile.configureFlags ++ [ "--enable-developer-mode" ]; nativeBuildInputs = sile.nativeBuildInputs ++ [ pkgs.luarocks # For regression test diff highlighting From 812a6354974544c1590a06011241554874599a2d Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 16 Apr 2024 00:49:52 +0300 Subject: [PATCH 352/357] chore(build): Add checksums to things not known to dist checksum macro --- .github/workflows/build.yml | 2 ++ build-aux/sile_dist_checksums.m4 | 15 +++++++++++++++ configure.ac | 1 + 3 files changed, 18 insertions(+) create mode 100644 build-aux/sile_dist_checksums.m4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b5785834..4db2ef85a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,7 @@ jobs: if: ${{ matrix.configuration[0] == 'static' }} run: | cp sile sile-${{ env.CARCH }} + sha256sum sile-${{ env.CARCH }} | tee -a sile-${{ env.VERSION }}.sha256.txt - name: Upload static binary artifact if: ${{ matrix.configuration[0] == 'static' && !contains(github.ref, 'refs/tags/v') }} uses: actions/upload-artifact@v4 @@ -86,6 +87,7 @@ jobs: sile-${{ env.VERSION }}.zip sile-${{ env.VERSION }}.tar.zst sile-${{ env.CARCH }} + sile-${{ env.VERSION }}.sha256.txt build-nix: runs-on: ubuntu-22.04 diff --git a/build-aux/sile_dist_checksums.m4 b/build-aux/sile_dist_checksums.m4 new file mode 100644 index 000000000..79d890644 --- /dev/null +++ b/build-aux/sile_dist_checksums.m4 @@ -0,0 +1,15 @@ +AC_DEFUN_ONCE([SILE_DIST_CHECKSUMS], [ + + QUE_DIST_CHECKSUMS + + AM_COND_IF([DEVELOPER_MODE], [ + + AX_ADD_AM_MACRO([dnl +checksum_dist += \ + ; \$(SHA256SUM) sile-\$(VERSION).pdf |\ + \$(TEE) -a \$(distdir).sha256.txt +])dnl + + ]) +]) + diff --git a/configure.ac b/configure.ac index d920668c4..73ae209ac 100644 --- a/configure.ac +++ b/configure.ac @@ -9,6 +9,7 @@ QUE_GIT_VERSION QUE_TRANSFORM_PACKAGE_NAME QUE_DEVELOPER_MODE QUE_DIST_CHECKSUMS +SILE_DIST_CHECKSUMS # Checks for programs. AC_PROG_CC From 8349f0c5e6e72ad7cd71ea2960baa5399fdd8114 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Tue, 16 Apr 2024 00:49:52 +0300 Subject: [PATCH 353/357] ci(actions): Fixup Nix and Docker build dependencies --- .github/workflows/build.yml | 2 ++ .github/workflows/deploy.yml | 12 ++++++++++-- configure.ac | 5 +---- flake.nix | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4db2ef85a..075c78d42 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,8 @@ jobs: run: | ./bootstrap.sh ./configure \ + --enable-developer-mode \ + BUSTED=false DELTA=false LDOC=false LUACHECK=false NIX=false \ --disable-font-variations \ --with-manual \ ${{ matrix.configuration[1] }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5744aa20d..5e0f0d8c2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -21,17 +21,25 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install libluajit-5.1-dev luajit luarocks - name: Configure run: | echo "REF=${GITHUB_REF##refs/*/}" >> $GITHUB_ENV ./bootstrap.sh ./configure \ --enable-developer-mode \ + --without-harfbuzz \ + --disable-font-variations \ + BSDTAR=false \ + BUSTED=false \ + DELTA=false \ FCMATCH=true \ LDOC=false \ LUACHECK=false \ - BUSTED=false \ - DELTA=false \ + LUAROCKS=false \ NIX=false \ PDFINFO=false - name: Publish Docker Image to GH Container Registry diff --git a/configure.ac b/configure.ac index 73ae209ac..a7da9b54c 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ AC_ARG_WITH([manual], [Rebuild manual and install to system’s PDF documentation directory])) AM_CONDITIONAL([MANUAL], [test "x$with_manual" = "xyes"]) -AM_CONDITIONAL([FONT_DOWNLOAD_TOOLS], [test -z ${DEVELOPER_MODE_TRUE} || (test -z ${MANUAL_TRUE} && test -z ${SOURCE_IS_DIST_FALSE})]) +AM_CONDITIONAL([FONT_DOWNLOAD_TOOLS], [test -z ${DEVELOPER_MODE_TRUE} || (test -z ${SOURCE_IS_DIST_TRUE} && test -z ${MANUAL_TRUE})]) AC_SUBST([FONT_DOWNLOAD_TOOLS]) AC_MSG_NOTICE([checking for SILE specific build dependencies]) @@ -206,12 +206,9 @@ AM_COND_IF([FONT_DOWNLOAD_TOOLS], [ AM_COND_IF([DEVELOPER_MODE], [ QUE_PROGVAR([busted]) - QUE_PROGVAR([cmp]) QUE_PROGVAR([curl]) QUE_PROGVAR([delta]) QUE_PROGVAR([diff]) - QUE_PROGVAR([git]) - QUE_PROGVAR([grep]) QUE_PROGVAR([head]) QUE_PROGVAR([ldoc]) QUE_PROGVAR([luacheck]) diff --git a/flake.nix b/flake.nix index 43120b416..202f2ce62 100644 --- a/flake.nix +++ b/flake.nix @@ -77,7 +77,7 @@ nativeCheckInputs FONTCONFIG_FILE ; - configureFlags = sile.configureFlags ++ [ "--enable-developer-mode" ]; + configureFlags = sile.configureFlags ++ [ "--enable-developer-mode" "--with-manual" ]; nativeBuildInputs = sile.nativeBuildInputs ++ [ pkgs.luarocks # For regression test diff highlighting From 0727652858e431e5f60a71433544fcf781d11395 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan <caleb@alerque.com> Date: Mon, 20 May 2024 23:44:48 +0300 Subject: [PATCH 354/357] chore(cli): Fix typo in variable name with a better name --- Makefile.am | 4 ++-- src/embed.rs.in | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3f82a98ad..d970f8d43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -122,8 +122,8 @@ src/embed-includes.rs: Makefile-distfiles src/embed.rs: src/embed.rs.in src/embed-includes.rs $(SED) \ - -e '/@INCLUDE_EMDED_INCLUDES@/r $(word 2,$^)' \ - -e '/@INCLUDE_EMDED_INCLUDES@/d' \ + -e '/@EMBEDED_INCLUDE_LIST@/r $(word 2,$^)' \ + -e '/@EMBEDED_INCLUDE_LIST@/d' \ $< > $@ endif EMBEDDED_RESOURCES diff --git a/src/embed.rs.in b/src/embed.rs.in index f9b26cdbf..9d35d32da 100644 --- a/src/embed.rs.in +++ b/src/embed.rs.in @@ -25,7 +25,7 @@ use std::str; #[exclude = "src/*"] #[exclude = "target/*"] #[exclude = "tests/*"] -// @INCLUDE_EMDED_INCLUDES@ -- this marker line gets replaced by a list of includes +// @EMBEDED_INCLUDE_LIST@ -- this marker line gets replaced by a list of includes pub struct SileModules; // Link Lua loader functions from C modules that Lua would otherwise be loading externally that From 5e5aba1674452f8b5beedbc30f0b7b4b5778026c Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 28 May 2024 13:44:44 +0200 Subject: [PATCH 355/357] docs(manual): Reorganize chapters c02-c03 more consistently (#2029) --- documentation/c02-gettingstarted.sil | 111 ++++++++++++--------------- documentation/c03-input.sil | 83 ++++++++++++-------- 2 files changed, 100 insertions(+), 94 deletions(-) diff --git a/documentation/c02-gettingstarted.sil b/documentation/c02-gettingstarted.sil index 699754d3d..c66604b5b 100644 --- a/documentation/c02-gettingstarted.sil +++ b/documentation/c02-gettingstarted.sil @@ -1,67 +1,26 @@ \begin{document} \chapter{Getting Started} -Now that we understand some of what SILE is about and what it seeks to do, let’s dive into SILE itself. - -Before we show you how to use SILE, let’s have a quick look at an example SILE document. -This is the input that we’re going to feed to SILE, which it is going to process and turn into a PDF file. -Each of the examples can be saved as a text file and then use them as input to SILE. - -\section{Selecting a text editor} - -A SILE document is just a \em{plain text} file. -When you create your own SILE files, you will need to create them in a plain text editor. -Trying to create these files in a word processor such as Word will not work, as they will be saved with the word processor’s formatting codes rather than as plain text. - -Lots of good text editors exist (many of them for free) and any of them will work for SILE documents so which one you use is entirely a matter of preference. -You can get started with even the most basic text editors built into your desktop environment such as Notepad on Windows, \nohyphenation{TextEdit} on macOS, \nohyphenation{Gedit} on Gnome, Kate on KDE, etc. -However more advanced text editors (sometimes categorized as \em{code editors)} can offer a lot of features that make the editing process more robust. -Editors are typically either graphical (GUI) or terminal (TUI) oriented and range from relatively simple to extremely complex integrated development environments (IDE). -Examples of popular cross-platform GUI oriented editors include VS Code, Sublime Text, and Atom\footnote{Still relatively popular, but was discontinued in late 2022.}. -Examples of popular terminal based editors include VIM\footnote{VIM & NeoVIM users can benefit from syntax highlighting and other features via the \code{vim-sile} plugin at \url{https://github.com/sile-typesetter/vim-sile}.}, Emacs, and GNU Nano. -Depending on your operating system there may be platform-specific editors to consider such as Notepad++ on Windows or TextMate on macOS. -Many more niche options abound: Lapce, Lite XL, Micro, Geany, BBEdit, UltraEdit, Eclipse, JetBrains IDE(s), Netbrains, Bluefish, CudaText, Leafpad, etc. - -For comparisons of editors see \url{https://alternativeto.net/category/developer-tools/code-editor/} and select your platform. - -\section{A basic SILE document} - -Once you have an editor, it’s time to consider a SILE input file. -There are several different input formats that could be used including SIL and XML. -For the purpose of this documentation we'll mostly use the SIL input format, but all examples translate 1-to-1 to XML. -To begin with, here’s the most basic SILE file of all: - -\begin[type=autodoc:codeblock]{raw} -\begin{document} -Hello SILE! -\end{document} -\end{raw} - -We’ll pick apart this document in the next chapter, but for now take it for granted -that this is what a SILE document looks like. - -This is going to produce an A4-sized PDF -document, with the text \autodoc:example{Hello SILE} at the top left, and the page -number (1) centered at the bottom. How are we going to get to that PDF? +To begin harnessing the power of SILE, now that we have covered some of its key aspects and objectives, let’s dive into installing it on your computer, and set up everything you need to start typesetting documents. \section{Installing SILE} -First of all, we need to get SILE running on our computer. -Ready to use packages are available for macOS and many Linux distributions. +Ready-to-use packages are available for macOS and many Linux distributions. Details for those we know about are listed in the sections below. -Many other Linux distributions without native packages can also take advantage of either Linuxbrew or Nix packaging. -For all other systems you will need to follow the steps to download and compile the source yourself. -Alternatively, Docker containers are also available for use on any system that can run them. +If your Linux distribution doesn’t have native packages, fear not! +You can also use either Linuxbrew or Nix packaging. + +For other operating systems, you will need to download and compile the source code yourself, following the steps outlined below. +Alternatively, Docker containers are available for use on any compatible system. \subsection{macOS} -For macOS, the recommended way to install SILE is through the Homebrew package manager. -Once you have Homebrew running (see \url{http://brew.sh}), installing SILE is as easy as running: +For macOS users, the recommended method for installing SILE is through the Homebrew package manager. +Once Homebrew is up and running (see \url{http://brew.sh}), you can install SILE effortlessly by running: \terminal{$ brew install sile} -The formula also has an option that can compile SILE from the current Git HEAD version. -To test the latest unreleased code you can install using: +Additionally, you have the option to compile SILE from the latest (unreleased) source code: \terminal{$ brew install sile --HEAD} @@ -121,6 +80,7 @@ $ pkgin install sile \subsection{NixOS or under Nix on any platform} In addition to NixOS, the \code{nix} package manager is available as a standalone package manager on many platforms including most Linux and BSD distributions, macOS, and even for Windows via WSL, and so presents an alternative way to run SILE on most systems. + The \code{sile} package is available in both the stable and unstable channels, the unstable channel having the latest stable SILE releases and the stable channel being frozen on NixOS releases. You can use all the usual Nix tricks, including adding SILE into a \code{nix shell} environment or executing it directly with \code{nix run}. @@ -229,7 +189,7 @@ Otherwise to go with default of bundling them, just run: If you plan on developing SILE itself (whether just to hack on it for your own use or contribute upstream) there are two particularly useful configuration options. First, you can add \code{--datarootdir=$(cd ..;pwd)} which will enable the compiled binary to run directly from the source directory without being installed at all. Second, you can add \code{--enable-developer-mode} to also check for tooling we expect SILE developers to have, such as tools used for testing. -Using this option also enables a number of targets that wouldn't normally be needed by end-users, such as \code{make regressions}. +Using this option also enables a number of targets that wouldn’t normally be needed by end-users, such as \code{make regressions}. \end{autodoc:note} \begin{autodoc:note} @@ -285,18 +245,49 @@ According to the rumors, SILE may be built on Windows using CMake and Visual Stu Additionally some Windows executables are supposed to be generated using Azure for every commit. You may download these executables by selecting the latest build from \url{https://simoncozens-github.visualstudio.com/sile/_build} and downloading the “sile” artifact from the Artifacts drop down. +\section{Selecting a text editor} + +A SILE document is just a \em{plain text} file. +When you create your own SILE files, you will need to create them in a plain text editor. +Trying to create these files in a word processor such as Word will not work, as they will be saved with the word processor’s formatting codes rather than as plain text. + +Lots of good text editors exist (many of them for free) and any of them will work for SILE documents so which one you use is entirely a matter of preference. +You can get started with even the most basic text editors built into your desktop environment such as Notepad on Windows, \nohyphenation{TextEdit} on macOS, \nohyphenation{Gedit} on Gnome, Kate on KDE, etc. +However more advanced text editors (sometimes categorized as \em{code editors}) can offer a lot of features that make the editing process more robust. +Editors are typically either graphical (GUI) or terminal (TUI) oriented and range from relatively simple to extremely complex integrated development environments (IDE). +Examples of popular cross-platform GUI oriented editors include VS Code, Sublime Text, and Atom\footnote{Still relatively popular, but was discontinued in late 2022.}. +Examples of popular terminal based editors include VIM\footnote{VIM & NeoVIM users can benefit from syntax highlighting and other features via the \code{vim-sile} plugin at \url{https://github.com/sile-typesetter/vim-sile}.}, Emacs, and GNU Nano. +Depending on your operating system there may be platform-specific editors to consider such as Notepad++ on Windows or TextMate on macOS. +Many more niche options abound: Lapce, Lite XL, Micro, Geany, BBEdit, UltraEdit, Eclipse, JetBrains IDE(s), Netbrains, Bluefish, CudaText, Leafpad, etc. + +For comparisons of editors see \url{https://alternativeto.net/category/developer-tools/code-editor/} and select your platform. + \section{Running SILE} -Let’s move to a new directory, and in a text editor, create the file \code{hello.sil}. -Copy in the content above and save the file. +Once you have set up an editor, it’s time to consider a SILE input file. + +\subsection{A basic document} + +Let’s move to a new directory, and in a text editor, create a file \code{hello.sil}. +Copy in the following content and save the file. + +\begin[type=autodoc:codeblock]{raw} +\begin{document} +Hello SILE! +\end{document} +\end{raw} + +It is a the most basic document file of all, in “TeX-like” SIL syntax (more on that later). + Then, at your command line type: \terminal{$ sile hello.sil} -Once again, this should produce an output file \code{hello.pdf}. +This produces an A4-sized PDF document \code{hello.pdf}, with the text \autodoc:example{Hello SILE} at the top left, and the page number (1) centered at the bottom. + Congratulations—you have just typeset your first document with SILE! -All the available CLI options are documented both in the help output (\code{sile --help}) and in the man page (\code{man sile}). +All the available command-line options are documented both in the help output (\code{sile --help}) and in the man page (\code{man sile}). This manual will only mention a few in passing as they come up in other other topics. \begin{autodoc:note} @@ -306,7 +297,7 @@ If you want to write to a different filename altogether, use the \code{--output You can use \code{--output -} to write the output directly to the system IO stream—useful if you wish to use SILE as part of a pipeline. \end{autodoc:note} -\section{Let’s do something cool} +\subsection{Let’s do something cool} In \url{https://sile-typesetter.org/examples/docbook.xml}, you will find a typical DocBook 5.0 article. Normally turning DocBook to print involves a complicated dance of XSLT processors, format object processors, and/or strange LaTeX packages. @@ -326,13 +317,13 @@ The \autodoc:class{docbook} class will provide the commands necessary to process In Chapter 9, we’ll look at how the \autodoc:class{docbook} class works, and how you can define processing expectations for other XML formats. -\section{Running SILE remotely as a CI job} +\subsection{Running SILE remotely as a CI job} It may be useful for some work flows to run SILE remotely on a CI server as part of a job that renders documents automatically from sources. This comes with the caveats mentioned in the section \em{Running via Docker} above, but if you plan ahead and arrange your projects properly it can be quite useful. There are actually many ways to run SILE remotely as part of a CI work flow. -Because packages are available for many platforms, one way would be to just use your platform's native package installation system to pull them into whatever CI-runner environment you already use. +Because packages are available for many platforms, one way would be to just use your platform’s native package installation system to pull them into whatever CI-runner environment you already use. Another way is to pull in the prebuilt Docker container and run that. As a case study, here is how a workflow could be setup in GitHub Actions: @@ -384,7 +375,7 @@ First you make add \code{--tree ./} to install them in the current directory. In this case, assuming this is the same directory as your document, SILE will automatically find such plugins. Additionally you may install them to your user profile by adding \code{--local} when installing. In this case you will also need to modify your user environment to check for plugins in that path since Lua does not do so by default. -This can be done by running \code{eval $(luarocks path)} before running SILE (or from your shell's initialization script). +This can be done by running \code{eval $(luarocks path)} before running SILE (or from your shell’s initialization script). \subsection{Finding Lua version in use for running SILE} diff --git a/documentation/c03-input.sil b/documentation/c03-input.sil index 525a74c2c..7bb1d4451 100644 --- a/documentation/c03-input.sil +++ b/documentation/c03-input.sil @@ -1,41 +1,57 @@ \begin{document} \chapter{SILE’s Input} -First, we need to clear some air. -In our own earlier documentation we gave the impression the primary way to feed content into SILE was a propriatry language. -This was \em{never} really true since XML was always fully supported as an alternative. -It is even less true now that 3rd party plugins can add their own input formats. - -Hence this chanpter has been renamed. -The original chapter title was "SILE’s Input Language", as if there was only one. -The truth is there \em{is} an input syntax we call "SIL", but even that is perhaps best thought of as a structured data syntax rather than a unique language. -The input strings \code{\\em\{foo\}} in SIL input syntax is 100\% equivalent to \code{<em>foo</em>} in XML input syntax. -The SIL input syntax is provided as an easier to type alternative than XML which can be a bit verbose and tedious to work with by hand. -On the other hand if you're handling data written by some other program, XML might be a much better solution. - -3rd party packages can also add their own input formats. -The stipulation is that an inputter parses some content and returns an AST with content tags and options recognized by SILE. -Markdown, Djot, and others have packages available that provide inputters, allowing them to be first class input candidates. -Many others like Dockbook and TEI are just XML with a special tag schema. -SILE can be extended to cover any tag schema. - -With that in mind, lets go back and reconsider the first SILE file we saw that was in SIL input syntax. +As mentioned earlier, a SILE document is essentially a plain text file. +However, you will need some markup to guide SILE in formatting the text. +Such markup allows you to emphasize some words, start a new paragraph, introduce a chapter, and so forth. + +\section{Concerning input formats} + +The default SILE distribution includes support for a proprietary input language known as SIL, which comes in two different “flavors,” right out of the box: + +\begin{itemize} +\item{A “TeX-like” SIL syntax, loosely inspired by LaTeX but with notable deviations and different design choices. +It looks like this: \autodoc:command{\em{content}}, producing \autodoc:example{\em{content}}.} +\item{An “XML flavor” which is equivalent to the TeX-like syntax but (quite obviously) presented in XML form. +The previous example, in XML format, look like this: \code{<em>content</em>}.} +\end{itemize} + +For the purpose of this documentation, we will mostly use the SIL TeX-like input format. +The SIL input syntax offers a more convenient and user-friendly alternative to XML, which can often be verbose and tedious to work with by hand. +On the other hand, if you are handling data written by some other program, XML might be a much better solution. + +But before moving forward, it is essential to note that SILE can actually accept other input markup languages. +Third-party packages can also add their own input formats. +Thus, SILE is quite versatile and not tied to the default SIL syntax, whether in its TeX-like or XML flavor. + +Arbitrary XML schemas may be processed, with appropriate package support.\footnote{It sounds easy when put in those terms, and it is quite true. +But of course, most XML-based document formats are fairly large and complex specifications. +Thus, implementing support for them may not be as straightforward as it initially appears.} +The SILE distribution ships with support for (a subset of) the DocBook specification. +There are also existing 3rd-party packages providing support for other XML schemas; such as the TEI (Tex Initiative Encoding) specifications, USX (Unified Scripture XML), and others. + +SILE is flexible and can be extended to support other markup languages, beyond XML. +For instance, there are 3rd-party collections of modules for the lightweight markup languages Markdown and Djot, and others. + +The stipulation is that an “inputter” component parses the content and produces an AST (Abstract Syntax Tree) recognized by SILE. +With the right inputter, any markup language could potentially be supported and elevated to the status of a first-class input candidate within SILE. + +With that being acknowledged, let’s get back to the SIL syntax. \section{The SIL flavor} -In the Getting Started chapter we looked at this document: +The first SILE file we saw in the Getting Started chapter was in SIL TeX-like input syntax (which we will just refer to as “SIL” from now on). +Let’s take reconsider it: -\begin[type=autodoc:codeblock]{raw} \begin{document} Hello SILE! \end{document} -\end{raw} - -\section{Defining the paper size} A document starts with a \code{\\begin\{document\}} command and ends with \code{\\end\{document\}}. In between, SILE documents are made up of two elements: text to be typeset on the page, such as “Hello SILE!” in our example, and commands. +\subsection{Defining the paper size} + The default paper size is A4, although each class may override this value. To manually change the paper size, an optional argument may be added to the document declaration: @@ -63,7 +79,7 @@ In Chapter 4 we will meet more of these relative units, and in Chapter 7 we will \subsection{Setting orientation as landscape} -The orientation of the page is defined as "portrait" by default, but if you want to set it as landscape there is an option for that: +The orientation of the page is defined as “portrait” by default, but if you want to set it as landscape there is an option for that: \begin[type=autodoc:codeblock]{raw} \begin[landscape=true]{document} @@ -90,7 +106,7 @@ Finally, there is also the case when the actual paper sheets available to you ar For instance, \code{papersize=6in x 9in, sheetsize=a4} produces an A4-dimensioned document, but with you content formatted as a 6 per 9 inches US trade book. You may, obviously, combine these options and also specify a bleed area. -\section{Ordinary text} +\subsection{Ordinary text} On the whole, ordinary text isn’t particularly interesting—it’s just typeset. @@ -173,7 +189,7 @@ If you specifically want to break up the ligatures, insert empty groups (using t \code{af\{\}f\{\}luent f\{\}ishing}: ‘\autodoc:example{af{}f{}luent f{}ishing}’. See the section on the \autodoc:package{features} package for more information on how to control the display of ligatures and other font features. -\section{Commands} +\subsection{Commands} Typically (and we’ll unpack that statement later), SILE commands are made up of a backslash followed by a command name, and a document starts with a \code{\\begin\{document\}} command and ends with \code{\\end\{document\}}. @@ -210,7 +226,7 @@ Here are a few more examples of SILE commands: \font[family=Times,size=10pt]{Hi there!} % Parameters and argument \end{raw}% -\section{Environments} +\subsection{Environments} Commands like \autodoc:command{\chapter} (to start a chapter) and \autodoc:command{\em} (to emphasise text) are normally used to enclose a relatively small piece of text—a few lines at most. Where you want to enclose a larger piece of the document, you can use an \em{environment}. @@ -230,19 +246,18 @@ Hi there! However, in some cases the environment form of the command will be easier to read and will help you to be clearer on where the command begins and ends. -\section{SIL flavor grammar specifications} +\subsection{SIL grammar specifications} -The official grammar for the SIL flavor is the LPEG reference implementation. +The official grammar for the SIL syntax is the LPEG reference implementation. That being said the reference implementation has some idiosyncrasies and is not the easiest to read. For convenience an ABNF grammar is also provided in the source tree, see \code{sil.abnf}. This grammar does not completely express the language as it cannot express the way SIL can embed other syntaxes, but it is a decent approximation. -The intent behind many of the syntax choices is to make it easy to have parity with XML flavors. +The intent behind many of the syntax choices is to make it easy to have parity with SXML flavors. This means limiting commands to valid XML identifiers (e.g. starting with an ASCII letter, not a digit or special character), requiring a single top level command as the document, and so forth. -\section{The XML flavor} +\section{The XML syntax} -As mentioned at the start of the chapter, SILE can actually process its input in a completely different file format. What we’ve seen so far has been SILE’s “TeX-like” SIL syntax flavor, but it can also directly read and process XML files. (If it isn’t well-formed XML, then SILE will get very upset.) @@ -264,7 +279,7 @@ The example above, in XML flavor, would look like this: <font family="Times" size="10pt">Hi there!</font> \end{raw} -We don’t expect humans to write their documents in SILE’s XML flavor—the TeX-like SIL flavor is much better for that—but having an XML flavor allows for computers to deal with SILE a lot more easily. +We don’t expect humans to write their documents in SILE’s XML flavor—the SIL flavor is much better for that—but having an XML flavor allows for computers to deal with SILE a lot more easily. One could create graphical user interfaces to edit SILE documents, or convert other XML formats to SILE. However, there is an even smarter way of processing XML with SILE. From 9deee2f83396e844938a273920f04fce60c1a335 Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 28 May 2024 13:46:31 +0200 Subject: [PATCH 356/357] docs(manual): Bump url and rules to high status (#2030) --- documentation/c05-packages.sil | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/c05-packages.sil b/documentation/c05-packages.sil index df4c4037c..c8fba70a7 100644 --- a/documentation/c05-packages.sil +++ b/documentation/c05-packages.sil @@ -117,7 +117,7 @@ This section covers a range of different topics from initial capitals to text tr \package-documentation{unichar} \subsection{url} -\status:medium +\status:high \package-documentation{url} \subsection{gutenberg} @@ -146,7 +146,7 @@ Line-filling patterns or rules, rectangular blobs of inks... What else to say? \package-documentation{leaders} \subsection{rules} -\status:medium +\status:high \package-documentation{rules} \section{Boxes & Effects} From b5fac49d399ebced18d623f2ee934500604f3bda Mon Sep 17 00:00:00 2001 From: Omikhleia <didier.willis@gmail.com> Date: Tue, 28 May 2024 14:15:10 +0200 Subject: [PATCH 357/357] docs(manual): Explain raw handlers and reserved SIL keywords (#2031) --- documentation/c04-useful.sil | 37 ++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/documentation/c04-useful.sil b/documentation/c04-useful.sil index b30472661..4ed41fa92 100644 --- a/documentation/c04-useful.sil +++ b/documentation/c04-useful.sil @@ -86,7 +86,7 @@ It’s quite fiddly to be always changing font specifications manually; SILE’s \autodoc:class{plain} class notably provides the \autodoc:command{\strong{…}} command as a a shortcut for \autodoc:command{\font[weight=700]{…}}, and the \autodoc:command{\em{…}} to emphasize text (switching between italic or regular style as needed). Note for parameters that accept multiple values, values may be separated with commas. -Be sure to wrap the value in quotes so the commas don't get parsed as new parameters. +Be sure to wrap the value in quotes so the commas don’t get parsed as new parameters. For example \autodoc:command{\font[features="+calt,+ss01"]} will enable OpenType feature flags for both contextual alternatives and alternative style set 1. Similarly values that are themselves key=value pairs the quotation marks will keep them separate from other parameters. For example \autodoc:command{\font[variations="wght=150,wdth=122"]} can be used to set both the weight and width axis values. @@ -282,7 +282,7 @@ This command has three modes: Another former use case or \code{\\script[src=…]} was to load SILE packages. This use case has been deprecated in favor of the more robust loader \code{\\use[module=…]}. Be sure to use a module spec with period delimiters not a path with slashes (e.g. \code{packages.math} not \code{packages/math}). - This will ensure cross-platform compatibility as well as make sure packages don't get loaded multiple times. + This will ensure cross-platform compatibility as well as make sure packages don’t get loaded multiple times. \end{autodoc:note} Doing anything interesting inline requires knowledge of the internals of SILE, (thankfully the code is not that hard to read) but to get you started, the Lua function \code{SILE.typesetter:typeset(…)} will add text to a page, \code{SILE.call("…")} will call a SILE command, and \code{SILE.typesetter:leaveHmode()} ends the current paragraph and outputs the text. @@ -317,4 +317,37 @@ This means that for the environment block version (\code{\\begin\{lua\}}) there The first instance of such an end tag terminates the block, and there is currently no way to escape it. For the inline command form (\code{\\lua}) an exact matching number of open and closing braces may appear in the Lua code—the next closing brace at the same level as the opening brace will close the tag, even if it happens to be inside some quoted string in the Lua code. Including any number of nested opening and closing braces is possible as long as they are balanced. + +\section{Including raw inline content} + +When parsing a SIL file, SILE invokes an “inputter” module, which implements the SIL language grammar and constructs an abstract syntax tree (AST) for processing. +This implies that the content of any command or environment is in SIL syntax. + +However, there are cases when you may need to pass raw content that should remain unparsed — or, more properly, later parsed by a \em{different} grammar. +While you could escape all special characters in your content with backslashes to prevent them from being interpreted as SIL constructs, this approach is tedious and cumbersome. + +This issue already arises in several scenarios. +For instance, the \code{\\lua} command (and the legacy \code{\\script} command) described above fall into this category. +In these cases, one expects to use Lua code without the need for escaping it. + +Similarly, the content of the \code{\\math} command (for the \autodoc:package{math} package) falls outside the scope of the SIL language syntax and requires a different grammar. +After all, its content follows the TeX math syntax, with commands with multiple arguments, special use of brackets, and so on. +Therefore, we need to instruct the SIL parser that this content should not be interpreted,but rather extracted as a raw string. +Later, it will be fed to another dedicated inputter for parsing.\footnote{In the case of math, it is currently a \em{pseudo}-inputter, but that is an implementation detail.} + +The SIL inputter reserves a few special keywords: \code{\\lua}, \code{\\script}; but also \code{\\ftl}, \code{\\math}, \code{\\sil}, \code{\\use}, \code{\\xml}; and finally \code{\\raw}, which we will discuss here. + +It is obvious that we can’t reserve too many keywords in advance. +However, they must be known \em{before} parsing a file, which means they can’t be dynamic. +The reserved keywords can’t be overridden or redefined after document parsing has begun. +So, how can we achieve extensibility? + +SILE provides a mechanism to address this: \em{raw handlers}. +Through the Lua interface, packages and classes can register a function that gets called when a raw command is encountered in the input stream. +From within a SIL file, the \code{\\raw[type=…]} command can then be used to invoke that handler, passing the raw content.\footnote{In a certain sense, all things equal, raw handlers are similar to the concept of “CDATA sections” in XML.} + +Raw handlers are identified by the \autodoc:parameter{type} parameter. +By default, SILE comes with a \code{text} raw handler, which simply typesets its content“verbatim” (as a string) without interpreting it. +Packages and classes can register their own additional raw handlers to fulfill specific needs. + \end{document}