diff options
author | Karl Berry <karl@freefriends.org> | 2022-02-22 21:11:36 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-02-22 21:11:36 +0000 |
commit | b58ee08a4c930684f420d4f7cf5fca4b804f7744 (patch) | |
tree | 135720e6b67d62f2a76f7bf49f0a2b75ae3c3b3f /Master | |
parent | 16e52a84e2d3fced8748b0a0c772c7772aaff173 (diff) |
lua-widow-control (22feb22)
git-svn-id: svn://tug.org/texlive/trunk@62144 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
12 files changed, 304 insertions, 131 deletions
diff --git a/Master/texmf-dist/doc/luatex/lua-widow-control/README.md b/Master/texmf-dist/doc/luatex/lua-widow-control/README.md index 1f328f56a4d..d9ccf7b4549 100644 --- a/Master/texmf-dist/doc/luatex/lua-widow-control/README.md +++ b/Master/texmf-dist/doc/luatex/lua-widow-control/README.md @@ -1,13 +1,13 @@ <!-- lua-widow-control https://github.com/gucci-on-fleek/lua-widow-control SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+ - SPDX-FileCopyrightText: 2021 Max Chernoff + SPDX-FileCopyrightText: 2022 Max Chernoff --> lua-widow-control ================= -Lua-widow-control is a Plain TeX/LaTeX/ConTeXt package that removes widows and orphans without any user intervention. Using the power of LuaTeX, it does so _without_ stretching any glue or shortening any pages or columns. Instead, lua-widow-control automatically lengthens a paragraph on a page or column where a widow or orphan would otherwise occur. +Lua-widow-control is a Plain TeX/LaTeX/ConTeXt/OpTeX package that removes widows and orphans without any user intervention. Using the power of LuaTeX, it does so _without_ stretching any glue or shortening any pages or columns. Instead, lua-widow-control automatically lengthens a paragraph on a page or column where a widow or orphan would otherwise occur. Please see the [**full documentation**](https://github.com/gucci-on-fleek/lua-widow-control/releases/latest/download/lua-widow-control.pdf) for more. @@ -32,6 +32,7 @@ To load the package, add the relevant line to your preamble: |LaTeX |`\usepackage{lua-widow-control}`| |ConTeXt |`\usemodule[lua-widow-control]` | |Plain TeX |`\input lua-widow-control` | +|OpTeX |`\load[lua-widow-control]` | Licence @@ -42,4 +43,4 @@ Lua-widow-control is licensed under the [_Mozilla Public License_, version 2.0]( Please note that a compiled document is absolutely **not** considered to be an "Executable Form" as defined by the MPL. The use of lua-widow-control in a document does not place **any** obligations on the document's author or distributors. The MPL and CC-BY-SA licenses **only** apply to you if you distribute the lua-widow-control source code or documentation. --- -_v1.1.5 (2022-02-15)_ <!--%%version %%date--> +_v1.1.6 (2022-02-22)_ <!--%%version %%date--> diff --git a/Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdf b/Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdf Binary files differindex ecb0ae15e98..4560ff7c560 100644 --- a/Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdf +++ b/Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdf diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.bib b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.bib index 009c0e5cfa5..c705e871b41 100644 --- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.bib +++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.bib @@ -1,7 +1,7 @@ % lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+ -% SPDX-FileCopyrightText: 2021 Max Chernoff +% SPDX-FileCopyrightText: 2022 Max Chernoff @book{texbook, author = {Donald E. Knuth}, diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.mkxl b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.mkxl index a4489b2e705..0256bdd56a2 100644 --- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.mkxl +++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.mkxl @@ -1,7 +1,7 @@ % lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ -% SPDX-FileCopyrightText: 2021 Max Chernoff +% SPDX-FileCopyrightText: 2022 Max Chernoff \startenvironment[lwc-documentation] \unprotect diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.tex b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.tex index 564f51618a5..bbee53cee14 100644 --- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.tex +++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-documentation.tex @@ -3,7 +3,7 @@ % lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+ -% SPDX-FileCopyrightText: 2021 Max Chernoff +% SPDX-FileCopyrightText: 2022 Max Chernoff % Warning: Compiles slowly @@ -37,12 +37,12 @@ \startdocument[ title=lua-widow-control, author=Max Chernoff, - version=1.1.5, %%version + version=1.1.6, %%version github=https://github.com/gucci-on-fleek/lua-widow-control, ctan=https://www.ctan.org/pkg/lua-widow-control, ] -\Lwc/ is a Plain~\TeX/\LaTeX/\ConTeXt{} package that removes \waos/ without any user intervention. Using the power of \LuaTeX{}, it does so \emph{without} stretching any glue or shortening any pages or columns. Instead, \lwc/ automatically lengthens a paragraph on a page or column where a \woo/ would otherwise occur. +\Lwc/ is a Plain~\TeX/\LaTeX/\ConTeXt{}/Op\TeX{} package that removes \waos/ without any user intervention. Using the power of \LuaTeX{}, it does so \emph{without} stretching any glue or shortening any pages or columns. Instead, \lwc/ automatically lengthens a paragraph on a page or column where a \woo/ would otherwise occur. \section{Quick Start} Ensure that your \TeX~Live/Mik\TeX{} distribution is up-to-date. Then, \LaTeX{} users just need to place \inlineTEX{\usepackage{lua-widow-control}} in the preamble of your document. For more details, see the \goto{Installation and Usage sections}[sec:install]. @@ -166,6 +166,9 @@ Run \type{tlmgr install lua-widow-control} in a terminal, or install using the \ \subsection{Mik\TeX} Run \type{mpm --install=lua-widow-control} in a terminal, or install using the \q{Mik\TeX{} Maintenance} \acronym{GUI}. +\subsection{\ConTeXt{} \acronym{MKIV} Standalone} +Run \type{first-setup.sh --modules="lua-widow-control"} in a terminal or install manually. + \subsection{Manual} Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install the package. Most other users will be better served by using the \lwc/ supplied by \TeX~Live and Mik\TeX{}; however, all users may manually install the package if desired. The procedure should be fairly similar regardless of your \acronym{OS}, \TeX{} distribution, or format. @@ -190,7 +193,10 @@ Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install \Lwc/ requires \LuaTeX{} ($\ge$ 0.85), \LaTeX{} ($\ge$ 2015/01/01), \sans{microtype} (any version), and \sans{etoolbox} (any version). Any version of \TeX~Live $\ge$ 2016 will meet these requirements. \subsection{\ConTeXt{}} -\Lwc/ requires \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}). +\Lwc/ supports both \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) and \ConTeXt{} \acronym{MKIV} (\LuaTeX{}). + +\subsection{Op\TeX{}} +\Lwc/ works with any version of Op\TeX{} and has no dependencies. \section{Loading the Package} @@ -207,6 +213,10 @@ Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install \inlineTEX{\usemodule[lua-widow-control]} +\subsection{Op\TeX{}} + +\inlineTEX{\load[lua-widow-control]} + \section{Columns} Since \TeX{} implements column breaking and page breaking through the same internal mechanisms, \lwc/ should remove \waos/ between columns just as well as it does with \waos/ between pages. This has been tested with the standard \LaTeX{} class option \type{twocolumn} and the two-column output routine from Chapter~23 of \cite[title][texbook].\cite[texbook] \Lwc/ should presumably work with any other multi-column implementation; however, due to the diversity and complexity of output~routines, this cannot be guaranteed. @@ -242,6 +252,14 @@ Since \TeX{} implements column breaking and page breaking through the same inter \NC \NC \inlineTEX{\prependtoks\lwc@patch@post\to\everyafterfoo} \NC\NR \stopTABLE +\subsection{Op\TeX{}} +\startTABLE +\NC Enable (default) \NC \inlineTEX{\lwcenable} \NC\NR +\NC Disable \NC \inlineTEX{\lwcdisable} \NC\NR +\NC \estretch/ \NC \inlineTEX{\lwcemergencystretch=3em} \NC\NR +\NC Selectively Disable \NC \emph{Not Implemented} \NC\NR +\stopTABLE + \subsection{\estretch/} You can configure the \estretch/ used when stretching a paragraph. The default value is 3~em. @@ -256,6 +274,9 @@ You could just disable then reenable \lwc/ every time that you use the command; \Lwc/ automatically patches the default \LaTeX{}, \ConTeXt{}, and Plain~\TeX{} section commands, so you shouldn't need to patch these yourself; however, \lwc/ does \bold{not} patch the non-standard section commands provided by \sans{memoir}, \sans{\acronym{KOMA}-script}, \sans{titlesec}, and others. You'll need to patch these yourself. Under \ConTeXt{}, you need to use a different method to selectively disable \lwc/. Instead of using \tex{lwcdisablecmd}, you should use one of the preexisting \tex{everyfoo} hooks as shown in the table above since patching commands is rarely advisable in \ConTeXt{} + +No commands are provided for selectively disabling \lwc/ with Op\TeX{}. Users must implement this functionality themselves. + \section[sec:issues]{Known Issues} \startitemize \item \Lwc/ will not expand the first paragraph of a document. @@ -336,6 +357,14 @@ Please note that a compiled document is \bold{not} considered to be an \q{Execut \typeTEXfile{../source/t-lua-widow-control.mkxl} +\subsection{t-lua-widow-control.mkiv} + +\typeTEXfile{../source/t-lua-widow-control.mkiv} + +\subsection{lua-widow-control.opm} + +\typeTEXfile{../source/lua-widow-control.opm} + \subsection{Demo from \in{Table}[tab:demo]} \typeTEXfile{lwc-documentation-demo-text.tmp} diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex index 143f3cbc8c7..0ba9f17f76b 100644 --- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex +++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex @@ -1,7 +1,7 @@ % lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+ -% SPDX-FileCopyrightText: 2021 Max Chernoff +% SPDX-FileCopyrightText: 2022 Max Chernoff \startbuffer[demo-text] \definepapersize[smallpaper][ diff --git a/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkiv b/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkiv new file mode 100644 index 00000000000..6eff5c9b00c --- /dev/null +++ b/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkiv @@ -0,0 +1,77 @@ +%D \module +%D [ file=t-lua-widow-control, +%D version=1.1.6, %%version +%D title=lua-widow-control, +%D subtitle=\ConTeXt module for lua-widow-control, +%D author=Max Chernoff, +%D date=2022-02-22, %%date +%D copyright=Max Chernoff, +%D license=MPL-2.0+, +%D url=https://github.com/gucci-on-fleek/lua-widow-control] +\startmodule[lua-widow-control] +\unprotect + +\installnamespace{lwc} + +\installcommandhandler \????lwc {lwc} \????lwc + +\newdimen\lwcemergencystretch +\appendtoks + \lwcemergencystretch=\lwcparameter{emergencystretch} +\to\everysetuplwc + +\appendtoks + \doifelse{\lwcparameter{\c!state}}\v!start{ + \ctxlua{lwc.enable_callbacks()} + }{ + \ctxlua{lwc.disable_callbacks()} + } +\to\everysetuplwc + +\define\iflwc{\ctxlua{lwc.if_lwc_enabled()}} + +\ctxloadluafile{lua-widow-control} + +\setuplwc[emergencystretch=3em, \c!state=\v!start] + +% We can't just set the penalties because they will be reset automatically +% at \\starttext. +\startsetups[*default] + \clubpenalty=1 + \widowpenalty=1 + \displaywidowpenalty=0 + \interlinepenalty=0 + \brokenpenalty=0 +\stopsetups + +\setups[*default] + +% Here, we enable font expansion/contraction. It isn't strictly necessary for +% \lwc/'s functionality; however, it is required for the +% lengthened paragraphs to not have terrible spacing. +\definefontfeature[default][default][expansion=quality] +\setupalign[hz] + +% Expansion of some parts of the document, such as section headings, is quite +% undesirable, so we'll disable \lwc/ for certain commands. +% We should only reenable \lwc/ at the end if it was already enabled. +\newif\iflwc@should@reenable + +\define\lwc@patch@pre{% + \iflwc% + \lwc@should@reenabletrue% + \setuplwc[state=stop]% + \else% + \lwc@should@reenablefalse + \fi% +} + +\define\lwc@patch@post{\iflwc@should@reenable% + \setuplwc[state=start]% +\fi} + +\prependtoks\lwc@patch@pre\to\everybeforesectionheadhandle % Sectioning +\prependtoks\lwc@patch@post\to\everyaftersectionheadhandle + +\protect +\stopmodule diff --git a/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl b/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl index b38d6eda018..6eff5c9b00c 100644 --- a/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl +++ b/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl @@ -1,10 +1,10 @@ %D \module %D [ file=t-lua-widow-control, -%D version=1.1.5, %%version +%D version=1.1.6, %%version %D title=lua-widow-control, %D subtitle=\ConTeXt module for lua-widow-control, %D author=Max Chernoff, -%D date=2022-02-15, %%date +%D date=2022-02-22, %%date %D copyright=Max Chernoff, %D license=MPL-2.0+, %D url=https://github.com/gucci-on-fleek/lua-widow-control] @@ -57,10 +57,14 @@ % We should only reenable \lwc/ at the end if it was already enabled. \newif\iflwc@should@reenable -\define\lwc@patch@pre{\iflwc% - \lwc@should@reenabletrue% - \setuplwc[state=stop]% -\fi} +\define\lwc@patch@pre{% + \iflwc% + \lwc@should@reenabletrue% + \setuplwc[state=stop]% + \else% + \lwc@should@reenablefalse + \fi% +} \define\lwc@patch@post{\iflwc@should@reenable% \setuplwc[state=start]% diff --git a/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty b/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty index 1be00709bc8..9ef5a76de56 100644 --- a/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty +++ b/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty @@ -1,11 +1,11 @@ % lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ -% SPDX-FileCopyrightText: 2021 Max Chernoff +% SPDX-FileCopyrightText: 2022 Max Chernoff \NeedsTeXFormat{LaTeX2e}[2015/01/01] % Formats built after 2015 include \LuaTeX{}Base \ProvidesPackage{lua-widow-control}% - [2022/02/15 v1.1.5] %%version %%date + [2022/02/22 v1.1.6] %%version %%date \ifdefined\directlua\else \PackageError{lua-widow-control}{% @@ -56,14 +56,20 @@ % We should only reenable \lwc/ at the end if it was already enabled. \newif\iflwc@should@reenable -\newcommand{\lwc@patch@pre}{\iflwc% - \lwc@should@reenabletrue% - \lwcdisable% -\fi} +\newcommand{\lwc@patch@pre}{% + \iflwc% + \lwc@should@reenabletrue% + \lwcdisable% + \else% + \lwc@should@reenablefalse% + \fi% +} -\newcommand{\lwc@patch@post}{\iflwc@should@reenable% - \lwcenable% -\fi} +\newcommand{\lwc@patch@post}{% + \iflwc@should@reenable% + \lwcenable% + \fi% +} \newcommand{\lwcdisablecmd}[1]{% \ifdefined#1 diff --git a/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua b/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua index 9304bf9a4d1..f1ecb54c65f 100644 --- a/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua +++ b/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua @@ -2,7 +2,7 @@ lua-widow-control https://github.com/gucci-on-fleek/lua-widow-control SPDX-License-Identifier: MPL-2.0+ - SPDX-FileCopyrightText: 2021 Max Chernoff + SPDX-FileCopyrightText: 2022 Max Chernoff ]] lwc = {} @@ -14,13 +14,19 @@ lwc.name = "lua-widow-control" detect the format name then set some flags for later processing. ]] local format = tex.formatname +local context, latex, plain, optex, lmtx if format:find('cont') then -- cont-en, cont-fr, cont-nl, ... - lwc.context = true + context = true + if status.luatex_engine == "luametatex" then + lmtx = true + end elseif format:find('latex') then -- lualatex, lualatex-dev, ... - lwc.latex = true + latex = true elseif format == 'luatex' then -- Plain - lwc.plain = true + plain = true +elseif format == 'optex' then -- OpTeX + optex = true end --[[ @@ -29,7 +35,7 @@ end ]] local last = node.slide local copy = node.copy_list -local par_id = node.id("par") +local par_id = node.id("par") or node.id("local_par") local glue_id = node.id("glue") local set_attribute = node.set_attribute local has_attribute = node.has_attribute @@ -39,36 +45,29 @@ local min_col_width = tex.sp("25em") local maxdimen = 1073741823 -- \\maxdimen in sp --[[ - This error is raised in the following circumstances: - - When the user manually loads the Lua module without loading Lua\TeX{}Base - - When the package is used with an unsupported format - Both of these are pretty unlikely, but it can't hurt to check. - ]] -assert(lwc.context or luatexbase, [[ - - This module requires a supported callback library. Please - follow the following format-dependant instructions: - - LaTeX: Use a version built after 2015-01-01, or include - `\usepackage{luatexbase}' before loading this module. - - Plain: Include `\input ltluatex' before loading this module. - - ConTeXt: Use the LMTX version. -]]) - ---[[ Package/module initialization ]] -if lwc.context then - lwc.warning = logs.reporter("module", lwc.name) - lwc.info = logs.reporter("module", lwc.name) - lwc.attribute = attributes.public(lwc.name) - lwc.contrib_head = 'contributehead' -- For \LuaMetaTeX{} - lwc.stretch_order = "stretchorder" - lwc.pagenum = function () return tex.count["realpageno"] end -elseif lwc.plain or lwc.latex then +local warning, info, attribute, contrib_head, stretch_order, pagenum + +if context and lmtx then + warning = logs.reporter("module", lwc.name) + info = logs.reporter("module", lwc.name) + attribute = attributes.public(lwc.name) + contrib_head = 'contributehead' -- For \LuaMetaTeX{} + stretch_order = "stretchorder" + pagenum = function() return tex.count["realpageno"] end +elseif context and not lmtx then + warning = logs.reporter("module", lwc.name) + info = logs.reporter("module", lwc.name) + attribute = attributes.public(lwc.name) + contrib_head = 'contrib_head' + stretch_order = "stretch_order" + pagenum = function() return tex.count["realpageno"] end +elseif plain or latex then luatexbase.provides_module { name = lwc.name, - date = "2022/02/15", --%%date - version = "1.1.5", --%%version + date = "2022/02/22", --%%date + version = "1.1.6", --%%version description = [[ This module provides a LuaTeX-based solution to prevent @@ -77,29 +76,30 @@ elseif lwc.plain or lwc.latex then paragraphs. ]], } - lwc.warning = function(str) luatexbase.module_warning(lwc.name, str) end - lwc.info = function(str) luatexbase.module_info(lwc.name, str) end - lwc.attribute = luatexbase.new_attribute(lwc.name) - lwc.contrib_head = 'contrib_head' -- For \LuaTeX{} - lwc.stretch_order = "stretch_order" - lwc.pagenum = function () return tex.count[0] end + warning = function(str) luatexbase.module_warning(lwc.name, str) end + info = function(str) luatexbase.module_info(lwc.name, str) end + attribute = luatexbase.new_attribute(lwc.name) + contrib_head = 'contrib_head' -- For \LuaTeX{} + stretch_order = "stretch_order" + pagenum = function() return tex.count[0] end +elseif optex then + local write_nl = texio.write_nl + warning = function(str) write_nl(lwc.name .. " Warning: " .. str) end + info = function(str) write_nl("log", lwc.name .. " Info: " .. str) end + attribute = alloc.new_attribute(lwc.name) + contrib_head = 'contrib_head' + stretch_order = "stretch_order" + pagenum = function() return tex.count[0] end else -- uh oh error [[ Unsupported format. - Please use (Lua)LaTeX, Plain (Lua)TeX, or ConTeXt (MKXL/LMTX) + Please use (Lua)LaTeX, Plain (Lua)TeX, ConTeXt (MKXL/LMTX), + or OpTeX. ]] end -lwc.paragraphs = {} -- List to hold the alternate paragraph versions - -if tex.interlinepenalty ~= 0 then - lwc.warning [[ -\interlinepenalty is set to a non-zero value. -This may prevent lua-widow-control from -properly functioning. -]] -end +local paragraphs = {} -- List to hold the alternate paragraph versions --[[ @@ -118,8 +118,8 @@ end --- @return table t Enablers/Disablers for the callback --- enable: function = Enable the callback --- disable: function = Disable the callback -function lwc.register_callback(t) - if lwc.plain or lwc.latex then -- Both use \LuaTeX{}Base for callbacks +local function register_callback(t) + if plain or latex then -- Both use \LuaTeX{}Base for callbacks return { enable = function() luatexbase.add_to_callback(t.callback, t.func, t.name) @@ -128,19 +128,19 @@ function lwc.register_callback(t) luatexbase.remove_from_callback(t.callback, t.name) end, } - elseif lwc.context and not t.lowlevel then + elseif context and not t.lowlevel then return { -- Register the callback when the table is created, -- but activate it when `enable()` is called. enable = nodes.tasks.appendaction(t.category, t.position, "lwc." .. t.name) - or function() + or function() nodes.tasks.enableaction(t.category, "lwc." .. t.name) - end, + end, disable = function() nodes.tasks.disableaction(t.category, "lwc." .. t.name) end, } - elseif lwc.context and t.lowlevel then + elseif context and t.lowlevel then --[[ Some of the callbacks in \ConTeXt{} have no associated "actions". Unlike with \LuaTeX{}base, \ConTeXt{} leaves some \LuaTeX{} callbacks unregistered @@ -153,17 +153,31 @@ function lwc.register_callback(t) enable = function() callback.register(t.callback, t.func) end, disable = function() callback.register(t.callback, nil) end, } + elseif optex then + return { + enable = function() + callback.add_to_callback(t.callback, t.func, t.name) + end, + disable = function() + callback.remove_from_callback(t.callback, t.name) + end, + } end end - --- Saves each paragraph, but lengthened by 1 line function lwc.save_paragraphs(head) -- Prevent the "underfull hbox" warnings when we store a potential paragraph - lwc.callbacks.disable_box_warnings.enable() + local renable_box_warnings + if (latex or plain) and + #luatexbase.callback_descriptions("hpack_quality") == 0 + then -- See #18 and michal-h21/linebreaker#3 + renable_box_warnings = true + lwc.callbacks.disable_box_warnings.enable() + end -- Ensure that we were actually given a par (only under \ConTeXt{} for some reason) - if head.id ~= par_id and lwc.context then + if head.id ~= par_id and context then return head end @@ -173,8 +187,8 @@ function lwc.save_paragraphs(head) -- Prevent ultra-short last lines (\TeX{}Book p. 104), except with narrow columns local parfillskip = last(new_head) if parfillskip.id == glue_id and tex.hsize > min_col_width then - parfillskip[lwc.stretch_order] = 0 - parfillskip.stretch = 0.8 * tex.hsize -- Last line must be at least 20% long + parfillskip[stretch_order] = 0 + parfillskip.stretch = 0.8 * tex.hsize -- Last line must be at least 20% long end -- Break the paragraph 1 line longer than natural @@ -187,7 +201,9 @@ function lwc.save_paragraphs(head) local natural_node, natural_info = tex.linebreak(copy(head)) flush_list(natural_node) - lwc.callbacks.disable_box_warnings.disable() + if renable_box_warnings then + lwc.callbacks.disable_box_warnings.disable() + end -- If we can't lengthen the paragraph, assign a \emph{very} large demerit value local long_demerits @@ -202,26 +218,24 @@ function lwc.save_paragraphs(head) prevdepth.width = natural_info.prevdepth - long_info.prevdepth last(long_node).next = prevdepth - table.insert(lwc.paragraphs, {demerits = long_demerits, node = long_node}) + table.insert(paragraphs, { demerits = long_demerits, node = long_node }) -- \LuaMetaTeX{} crashes if we return `true` return head end - --- Tags the beginning and the end of each paragraph as it is added to the page. --- --- We add an attribute to the first and last node of each paragraph. The ID is --- some arbitrary number for \lwc/, and the value corresponds to the --- paragraphs index, which is negated for the end of the paragraph. function lwc.mark_paragraphs(head) - set_attribute(head, lwc.attribute, #lwc.paragraphs) - set_attribute(last(head), lwc.attribute, -1 * #lwc.paragraphs) + set_attribute(head, attribute, #paragraphs) + set_attribute(last(head), attribute, -1 * #paragraphs) return head end - --- A "safe" version of the last/slide function. --- --- Sometimes the node list can form a loop. Since there is no last element @@ -236,7 +250,7 @@ local function safe_last(head) local id = node.is_node(head) -- Returns the internal node id if ids[id] then - lwc.warning [[Circular node list detected! + warning [[Circular node list detected! This should never happen. I'll try and recover, but your output may be corrupted. As a workaround, disable lua-widow-control for the affected paragraph or change the page breaks in your document.]] @@ -254,7 +268,6 @@ affected paragraph or change the page breaks in your document.]] return head end - --- Remove the widows and orphans from the page, just after the output routine. --- --- This function holds the "meat" of the module. It is called just after the @@ -263,21 +276,36 @@ end --- replace one paragraph with the same paragraph, but lengthened by one line. --- Then, we can push the bottom line of the page to the next page. function lwc.remove_widows(head) - local penalty = tex.outputpenalty - local paragraphs = lwc.paragraphs + local penalty = tex.outputpenalty - tex.interlinepenalty + local widowpenalty = tex.widowpenalty + local clubpenalty = tex.clubpenalty + local displaywidowpenalty = tex.displaywidowpenalty + local brokenpenalty = tex.brokenpenalty --[[ We only need to process pages that have orphans or widows. If `paragraphs` is empty, then there is nothing that we can do. + + The list of penalties is from: + https://tug.org/TUGboat/tb39-3/tb123mitt-widows-code.pdf#subsection.0.2.1 ]] - if penalty >= 10000 or - penalty <= -10000 or - penalty == 0 or - #paragraphs == 0 then - return head + if (penalty == widowpenalty or + penalty == displaywidowpenalty or + penalty == clubpenalty or + penalty == clubpenalty + widowpenalty or + penalty == clubpenalty + displaywidowpenalty or + penalty == brokenpenalty or + penalty == brokenpenalty + widowpenalty or + penalty == brokenpenalty + displaywidowpenalty or + penalty == brokenpenalty + clubpenalty or + penalty == brokenpenalty + clubpenalty + widowpenalty or + penalty == brokenpenalty + clubpenalty + displaywidowpenalty) and + #paragraphs >= 1 then + else + return head end - lwc.info("Widow/orphan detected. Attempting to remove.") + info("Widow/orphan detected. Attempting to remove.") local head_save = head -- Save the start of the `head` linked-list @@ -309,7 +337,7 @@ function lwc.remove_widows(head) -- Loop through all of the nodes on the page while head do -- Insert the start of the replacement paragraph - if has_attribute(head, lwc.attribute, paragraph_index) then + if has_attribute(head, attribute, paragraph_index) then safe_last(target_node) -- Remove any loops head.prev.next = target_node @@ -317,25 +345,25 @@ function lwc.remove_widows(head) end -- Insert the end of the replacement paragraph - if has_attribute(head, lwc.attribute, -1 * paragraph_index) then + if has_attribute(head, attribute, -1 * paragraph_index) then safe_last(target_node).next = head.next clear_flag = false end -- Start of final paragraph - if has_attribute(head, lwc.attribute, #paragraphs) then + if has_attribute(head, attribute, #paragraphs) then local last_line = copy(last(head)) - last(last_line).next = copy(tex.lists[lwc.contrib_head]) + last(last_line).next = copy(tex.lists[contrib_head]) last(head).prev.prev.next = nil -- Move the last line to the next page - tex.lists[lwc.contrib_head] = last_line - lwc.info( - "Widow/orphan successfully removed at paragraph " + tex.lists[contrib_head] = last_line + info( + "Widow/orphan successfully removed at paragraph " .. paragraph_index .. " on page " - .. lwc.pagenum() + .. pagenum() .. "." ) end @@ -347,37 +375,36 @@ function lwc.remove_widows(head) end end - lwc.paragraphs = {} -- Clear paragraphs array at the end of the page + paragraphs = {} -- Clear paragraphs array at the end of the page return head_save end - -- Add all of the callbacks lwc.callbacks = { - disable_box_warnings = lwc.register_callback({ + disable_box_warnings = register_callback({ callback = "hpack_quality", - func = function() end, - name = "disable_box_warnings", + func = function() end, + name = "disable_box_warnings", lowlevel = true, }), - remove_widows = lwc.register_callback({ + remove_widows = register_callback({ callback = "pre_output_filter", - func = lwc.remove_widows, - name = "remove_widows", + func = lwc.remove_widows, + name = "remove_widows", lowlevel = true, }), - save_paragraphs = lwc.register_callback({ + save_paragraphs = register_callback({ callback = "pre_linebreak_filter", - func = lwc.save_paragraphs, - name = "save_paragraphs", + func = lwc.save_paragraphs, + name = "save_paragraphs", category = "processors", position = "after", }), - mark_paragraphs = lwc.register_callback({ + mark_paragraphs = register_callback({ callback = "post_linebreak_filter", - func = lwc.mark_paragraphs, - name = "mark_paragraphs", + func = lwc.mark_paragraphs, + name = "mark_paragraphs", category = "finalizers", position = "after", }), @@ -393,11 +420,10 @@ function lwc.enable_callbacks() enabled = true else - lwc.warning("Already enabled") + warning("Already enabled") end end - function lwc.disable_callbacks() if enabled then lwc.callbacks.save_paragraphs.disable() @@ -410,7 +436,7 @@ function lwc.disable_callbacks() enabled = false else - lwc.warning("Already disabled") + warning("Already disabled") end end @@ -422,5 +448,4 @@ function lwc.if_lwc_enabled() end end - return lwc diff --git a/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex b/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex index efab23b8b4b..d83e6114f4f 100644 --- a/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex +++ b/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex @@ -1,9 +1,9 @@ % lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ -% SPDX-FileCopyrightText: 2021 Max Chernoff +% SPDX-FileCopyrightText: 2022 Max Chernoff -\wlog{lua-widow-control v1.1.5} %%version +\wlog{lua-widow-control v1.1.6} %%version \ifx\directlua\undefined \errmessage{% @@ -46,10 +46,14 @@ % We should only reenable \lwc/ at the end if it was already enabled. \newif\iflwc@should@reenable -\def\lwc@patch@pre{\iflwc% - \lwc@should@reenabletrue% - \lwcdisable% -\fi} +\def\lwc@patch@pre{% + \iflwc% + \lwc@should@reenabletrue% + \lwcdisable% + \else% + \lwc@should@reenablefalse% + \fi% +} \def\lwc@patch@post{\iflwc@should@reenable% \lwcenable% diff --git a/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm b/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm new file mode 100644 index 00000000000..4b8837cfec9 --- /dev/null +++ b/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm @@ -0,0 +1,27 @@ +% lua-widow-control +% https://github.com/gucci-on-fleek/lua-widow-control +% SPDX-License-Identifier: MPL-2.0+ +% SPDX-FileCopyrightText: 2022 Max Chernoff + +\_codedecl\lwcenable{lua-widow-control <v1.1.6>} %%version + +\_clubpenalty=1 +\_widowpenalty=1 +\_displaywidowpenalty=0 +\_interlinepenalty=0 +\_brokenpenalty=0 + +\_newdimen\lwcemergencystretch +\lwcemergencystretch=3em + +\_directlua{require "lua-widow-control"} + +% Define \TeX{} wrappers for Lua functions +\_def\lwcenable{\_directlua{lwc.enable_callbacks()}} +\_def\lwcdisable{\_directlua{lwc.disable_callbacks()}} +\_def\iflwc{\_directlua{lwc.if_lwc_enabled()}} + +% Enable \lwc/ by default when the package is loaded. +\lwcenable + +\_endcode |