texlive[63642] Master/texmf-dist: lua-widow-control (18jun22)

commits+karl at tug.org commits+karl at tug.org
Sat Jun 18 22:06:28 CEST 2022


Revision: 63642
          http://tug.org/svn/texlive?view=revision&revision=63642
Author:   karl
Date:     2022-06-18 22:06:28 +0200 (Sat, 18 Jun 2022)
Log Message:
-----------
lua-widow-control (18jun22)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/luatex/lua-widow-control/README.md
    trunk/Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdf
    trunk/Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdf
    trunk/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex
    trunk/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx
    trunk/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl
    trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty
    trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty
    trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua
    trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex
    trunk/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm

Added Paths:
-----------
    trunk/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md

Modified: trunk/Master/texmf-dist/doc/luatex/lua-widow-control/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lua-widow-control/README.md	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/doc/luatex/lua-widow-control/README.md	2022-06-18 20:06:28 UTC (rev 63642)
@@ -48,4 +48,4 @@
 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.
 
 ---
-_v2.1.2 (2022-05-26)_ <!--%%version %%dashdate-->
+_v2.2.0 (2022-06-17)_ <!--%%version %%dashdate-->

Modified: trunk/Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdf
===================================================================
(Binary files differ)

Added: trunk/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md	                        (rev 0)
+++ trunk/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md	2022-06-18 20:06:28 UTC (rev 63642)
@@ -0,0 +1,153 @@
+<!-- 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: 2022 Max Chernoff
+-->
+
+Changelog
+=========
+
+All notable changes to lua-widow-control will be listed here, in reverse chronological order. **Changes listed in bold** are important changes: they either remove options or commands, or may change the location of page breaks.
+
+## v2.2.0 (2022-06-17)
+
+- Fix paragraphs not being properly saved for potential expansion. **May affect page breaks.**
+- Add a new `draft` option ([#36](https://github.com/gucci-on-fleek/lua-widow-control/issues/36)).
+- Fix a node memory leak ([#29](https://github.com/gucci-on-fleek/lua-widow-control/issues/29)). You should now be able to use lua-widow-control on documents with > 10 000 pages.
+- Use `\lua_load_module:n` when available.
+- Add additional metadata to the documentation.
+
+
+## [v2.1.2 (2022-05-27)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-3744f3e78bdf02fc63d508a0f80595260191607c)
+
+- Fully-support footnotes/inserts: lua-widow-control now moves the "footnote text" with the "footnote mark" when it moves a line to the next page.
+- No longer attempt to expand paragraphs in `\vbox`es
+- Minor documentation updates
+
+
+## [v2.1.1 (2022-05-20)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-980f24ac64816bd0d453754f8f1af676f0f7ee99)
+
+- Prevent spurious `under/overfull \vbox` warnings when widows/orphans are removed
+- Add TUGboat article to the distributed documentation
+- Rewrite many portions of the manual
+- Add support for `luahbtex` and `mmoptex` ([#35](https://github.com/gucci-on-fleek/lua-widow-control/pull/35) [@vlasakm](https://github.com/vlasakm))
+- Fix the (undocumented) `microtype` LaTeX option
+
+
+## [v2.1.0 (2022-05-14)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-82563aa0396805008059e3a96c2bf30b59c58026)
+
+- Fully support grid snapping in ConTeXt
+- New warnings when a new widow/orphan is inadvertently created
+- Significant internal rewrites
+- Add Plain and OpTeX interfaces to `\nobreak` behaviour and debug mode
+
+
+## [v2.0.6 (2022-04-23)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-2aa9269b33a03f66d2ece634c3dcba6b258fddf0)
+
+- Emergency fix for renamed LMTX engine Lua functions
+- Internal LaTeX refactoring
+
+
+## [v2.0.5 (2022-04-13)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-e3234ac7dfb31118d08fcb5ed0fe03f394df2b57)
+
+- Support nested `\lwcdisablecmd` macros
+- Fix `\lwcdisablecmd` in Plain TeX
+- Support command patching in OpTeX
+- Patch memoir to prevent spurious asterisks at broken two-line paragraphs ([#32](https://github.com/gucci-on-fleek/lua-widow-control/issues/32))
+
+
+## [v2.0.4 (2022-04-07)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-8a0e97e448976280a38d41f92c2781320b1a91f0)
+
+- Don't expand paragraphs typeset during output routines ([#31](https://github.com/gucci-on-fleek/lua-widow-control/issues/31))
+
+
+## [v2.0.3 (2022-03-28)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-d6622dd9fd04a4bc7678ff18420c1b4bdf077844)
+
+- Automatically patch section commands provided by memoir, KOMA-Script, and titlesec.
+
+
+## [v2.0.2 (2022-03-20)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-7e79189406a2318c33dcaceb85d9d1021b357a3f)
+
+_Final release present in TeX Live 2021_
+
+- Add `balanced` mode preset.
+
+
+## [v2.0.1 (2022-03-18)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-f3048dbcbfaf4d7d6f6a57e236cdb9684ff5d18d)
+
+- Documentation updates ([#25](https://github.com/gucci-on-fleek/lua-widow-control/issues/25))
+- Bug fixes ([#28](https://github.com/gucci-on-fleek/lua-widow-control/issues/28))
+
+
+## [v2.0.0 (2022-03-07)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-cea06ddad8dfcf15fa9ba2a86c6640648b9df523)
+
+- **Page breaks may be slightly different**
+- **Removed `\lwcemergencystretch` and `\lwcdisablecmd` in LaTeX. Please use the new key–value interface**
+- Use expl3 for the LaTeX files ([#20](https://github.com/gucci-on-fleek/lua-widow-control/pull/20))
+- Use a key–value interface for configuration with LaTeX ([#11](https://github.com/gucci-on-fleek/lua-widow-control/issues/11))
+- Silence some extraneous `luatexbase` info messages
+- Add a "debug mode" to print extra information ([#12](https://github.com/gucci-on-fleek/lua-widow-control/issues/12))
+- Fix error message line wrapping
+- Don't reset `\interlinepenalty` and `\brokenpenalty`
+- Set and analyze `\displaywidowpenalty`
+- Keep section headings with moved orphans ([#17](https://github.com/gucci-on-fleek/lua-widow-control/issues/17))
+- Add the ability to configure the maximum paragraph cost ([#22](https://github.com/gucci-on-fleek/lua-widow-control/issues/22))
+- Add a "strict" mode
+- Use an improved cost function to select the best paragraph to lengthen ([#23](https://github.com/gucci-on-fleek/lua-widow-control/issues/23))
+- Dozens of bug fixes
+- Miscellaneous documentation updates
+
+
+## [v1.1.6 (2022-02-22)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-2c7201854d89535ef7c02f6c38486205677f1aa1)
+
+- Add support for the OpTeX format/macro package.
+- Add support for the LuaTeX/MKIV version of ConTeXt.
+- Ensure compatibility with the new `linebreaker` package.
+- Fix a small bug with `\lwcdisablecmd`.
+- Test the `\outputpenalty` for the specific values that indicate a widow or orphan.
+
+
+## [v1.1.5 (2022-02-15)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-5cc95212c8141006ae3a600d26a4e0cd63b368c0)
+
+- Improve the appearance of the demo table in the documentation ([#4](https://github.com/gucci-on-fleek/lua-widow-control/issues/4))
+- Improve compatibility with microtype
+- Block loading the package without LuaTeX
+- Improve logging
+- Bug fix to prevent crashing
+
+
+## [v1.1.4 (2022-02-04)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-a8caba8e689ce5c743a88dcf1dcd8e4a0db67fb2)
+
+- Enable protrusion/expansion in the demo table in the documentation ([#3](https://github.com/gucci-on-fleek/lua-widow-control/issues/3))
+- Fix `\prevdepth` bug
+
+
+## [v1.1.3 (2022-01-30)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-8d1228bf1697e2720062b0c2a40f306005da72e8)
+
+- Fix bug when used with the LaTeX `calc` package. ([#2](https://github.com/gucci-on-fleek/lua-widow-control/issues/2))
+
+
+## [v1.1.2 (2021-12-14)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-61a684d92f1a38ecf0ff53c6da22b2a973fae530)
+
+- Fix crash under ConTeXt LMTX
+
+
+## [v1.1.1 (2021-11-26)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/v1.1.1)
+
+- Minor documentation updates
+
+
+## [v1.1.0 (2021-11-08)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-8c958011bb4bd7f6e4ad843321c0d2643645a08f)
+
+- Extensive documentation updates
+- Clarify that lua-widow-control *does* in fact support columns
+- Add `\lwcdisablecmd` macro to disable lua-widow-control for certain commands
+- Automatically disable lua-widow-control inside section headings (uses `\lwcdisablecmd`)
+- Add automated tests to prevent regressions
+- Fix a rare issue that would cause indefinite hangs
+
+
+
+## [v1.0.0 (2021-10-09)](https://github.com/gucci-on-fleek/lua-widow-control/releases/tag/release-bae44a6858432e095597521bf1ef7df2104b6b9c)
+
+Initial release


Property changes on: trunk/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex
===================================================================
--- trunk/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex	2022-06-18 20:06:28 UTC (rev 63642)
@@ -39,10 +39,32 @@
 
 \input lwc-manual-samples
 
+\definecolor[expanded][r=0.00, g=0.70, b=0.25]
+\definecolor[failure] [r=0.90, g=0.00, b=0.25]
+\definecolor[moved]   [r=0.25, g=0.25, b=1.00]
+
+\usemodule[markdown]
+\define[4]\markdownRendererLinkPrototype{\goto{#1}[url(#3)]}
+\def\markdownOptionHtml{true}
+\def\markdownOptionShiftHeadings{1}
+\startluacode
+    interfaces.implement {
+        name = "markdownRendererHeadingThreePrototype",
+        public = true,
+        arguments = { "string" },
+        actions = function (str)
+            context.subsection {
+                title = str,
+                list = str:match "v%d+%.%d+%.%d+"
+            }
+        end
+    }
+\stopluacode
+
 \startdocument[
     title=lua-widow-control,
     author=Max Chernoff,
-    version=2.1.2, %%version
+    version=2.2.0, %%version
     github=https://github.com/gucci-on-fleek/lua-widow-control,
     ctan=https://www.ctan.org/pkg/lua-widow-control,
 ]
@@ -501,9 +523,27 @@
     C = \frac{d}{\sqrt{l}}
 \stopformula where $d$ is the total demerits of the paragraph, and $l$ is the number of lines in the paragraph; however, advanced users may also set a custom cost function by redefining the \inlineLUA{lwc.paragraph_cost(demerits, lines)} function.
 
+\subsection{Draft Mode}
+
+You can use the draft mode to visualize how \lwc/ processes pages. Any \color[failure]{remaining widows and orphans will be coloured red}, any \color[expanded]{expanded paragraphs will be coloured green}, and any \color[moved]{lines moved to the next page will be coloured blue}. In addition, the cost of each paragraph is shown in the right margin.
+
+\startTABLE[setups=commandtable]
+    \NC \plainop/
+    \NC\inlineTEX{\lwcdraft 1}
+    \NC\NR
+    \NC \LaTeX{}
+    \NC\inlineTEX{\lwcsetup{draft}}
+    \NC\NR
+    \NC \ConTeXt{}
+    \NC\inlineTEX{\setuplwc[draft = start]}
+    \NC\NR
+\stopTABLE
+
+Advanced users may also customize the colours used by modifying the \inlineLUA{lwc.colours} table. The table keys are currently \type{expanded}, \type{failure}, and \type{moved}. The table values are \acronym{RGB} 3-tuples, where each element is a float between zero and one.
+
 \subsection{Debug Mode}
 
-\Lwc/ offers a \q{debug} mode that prints extra information in the log files. This may be helpful to understand how \lwc/ is processing paragraphs and pages. If you are reporting an issue with \lwc/ make sure to compile your document with debug mode enabled!
+\Lwc/ offers a \q{debug} mode that prints extra information in the log files. This may be helpful to understand how \lwc/ is processing paragraphs and pages, although the information is likely inscrutable unless you are the package's author. If you are reporting an issue with \lwc/ make sure to compile your document with debug mode enabled!
 
 \startTABLE[setups=commandtable]
     \NC \plainop/
@@ -712,6 +752,8 @@
     system remove widows or orphans that \lwc/ cannot.
 
     \item \Lwc/ does not move footnotes in \mkxl/ due to limitations with the \LuaMetaTeX{} engine.
+
+    \item Draft mode does not colour any text in \mkxl/. Draft mode will not colour the first line of a page in \mkiv/ and \OpTeX{}.
 \stopitemize
 
 \section{Contributions}
@@ -729,6 +771,16 @@
 \placelistofpublications
 
 \page
+
+\setuphead[subsection][
+    alternative=normal,
+    style=\ssitb,
+    after={\blank[disable, penalty:10000]}
+]
+\markdownInput{../../CHANGELOG.md}
+
+\page
+
 \setuplayout[
     width=middle,
     backspace=1in,
@@ -745,8 +797,6 @@
 \usemodule[scite]
 \setupbodyfont[10pt]
 \setuphead[subsection][
-    alternative=normal,
-    style=\ssita,
     page=yes,
     continue=yes,
 ]

Modified: trunk/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx
===================================================================
--- trunk/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx	2022-06-18 20:06:28 UTC (rev 63642)
@@ -13,6 +13,7 @@
 %     journal={TUGboat},
 %     volume={43},
 %     number={1},
+%     pages={28--39},
 %     year={2022},
 %     month=may,
 %     DOI={10.47397/tb/43-1/tb133chernoff-widows},
@@ -156,9 +157,26 @@
     }}%
 }
 
-\let\nameref=\undefined % latex3/hyperref#234
 \usepackage[hidelinks,pdfa]{hyperref}
 
+\usepackage{hyperxmp}
+\hypersetup{
+    pdfdisplaydoctitle=true,
+    pdftitle={Automatically removing widows and orphans with lua-widow-control},
+    pdfauthor={Max Chernoff},
+    pdflang={en},
+    pdfcontacturl={https://github.com/gucci-on-fleek/lua-widow-control},
+    pdfcopyright={SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+},
+    pdflicenseurl={https://creativecommons.org/licenses/by-sa/4.0/},
+    pdfdoi={10.47397/tb/43-1/tb133chernoff-widows},
+    pdfpublication={TUGboat},
+    pdfpubtype={journal},
+    pdfvolumenum={43},
+    pdfissuenum={1},
+    pdfpagerange={28-39},
+    pdfdate={2022-05}
+}
+
 \begin{document}
     \maketitle
 

Modified: trunk/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl
===================================================================
--- trunk/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl	2022-06-18 20:06:28 UTC (rev 63642)
@@ -1,10 +1,10 @@
 %D \module
 %D   [     file=t-lua-widow-control,
-%D      version=2.1.2, %%version
+%D      version=2.2.0, %%version
 %D        title=lua-widow-control,
 %D     subtitle=\ConTeXt module for lua-widow-control,
 %D       author=Max Chernoff,
-%D         date=2022-05-26, %%dashdate
+%D         date=2022-06-17, %%dashdate
 %D    copyright=Max Chernoff,
 %D      license=MPL-2.0+,
 %D          url=https://github.com/gucci-on-fleek/lua-widow-control]
@@ -28,6 +28,8 @@
 
     \lwc_debug{\lwcparameter{debug}}
 
+    \lwc_draft{\lwcparameter{draft}}
+
     \lwc_nobreak{\lwcparameter{nobreak}}
 
     \lwc_max_cost=\lwcparameter{maxcost}
@@ -61,6 +63,7 @@
     emergencystretch=3em,
     \c!state=\v!start,
     debug=\v!stop,
+    draft=\v!stop,
     orphanpenalty=1,
     widowpenalty=1,
     brokenpenalty=1,

Modified: trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty	2022-06-18 20:06:28 UTC (rev 63642)
@@ -12,8 +12,8 @@
 % report a real version number here for debugging.
 \PackageInfo{lua-widow-control}{%
     Real version:
-    2022/05/26 %%slashdate
-    v2.1.2 %%version
+    2022/06/17 %%slashdate
+    v2.2.0 %%version
 }
 
 \PackageWarning{lua-widow-control}{%

Modified: trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty	2022-06-18 20:06:28 UTC (rev 63642)
@@ -13,7 +13,7 @@
 
 \DeclareRelease{}{0000-00-00}{lua-widow-control-2022-02-22.sty}
 \DeclareRelease{v1.1.6}{2022-02-22}{lua-widow-control-2022-02-22.sty}
-\DeclareCurrentRelease{v2.1.2}{2022-05-26} %%version %%dashdate
+\DeclareCurrentRelease{v2.2.0}{2022-06-17} %%version %%dashdate
 
 % If this version of LaTeX doesn't support command hooks, then we load
 % the last v1.1.X version of the package.
@@ -23,8 +23,8 @@
 
 \ProvidesExplPackage
     {lua-widow-control}
-    {2022/05/26} %%slashdate
-    {v2.1.2} %%version
+    {2022/06/17} %%slashdate
+    {v2.2.0} %%version
     {Use Lua to remove widows and orphans}
 
 % Unconditional Package Loads
@@ -116,7 +116,11 @@
 }
 
 % Load the Lua code
-\lua_now:n { require "lua-widow-control" }
+\cs_if_exist:NTF \lua_load_module:n {
+    \lua_load_module:n { lua-widow-control }
+} {
+    \lua_now:n { require "lua-widow-control" }
+}
 
 % Here, we enable font expansion/contraction. It isn't strictly necessary for
 % \lwc/'s functionality; however, it is required for the
@@ -220,9 +224,17 @@
     disable .value_forbidden:n = true,
 
     debug .choice:,
-    debug / true  .code:n = \__lwc_debug:n { true  },
-    debug / false .code:n = \__lwc_debug:n { false },
+    debug / true  .code:n     = \__lwc_debug:n { true  },
+    debug / false .code:n     = \__lwc_debug:n { false },
+    debug .default:n          = true,
+    debug .value_required:n   = false,
 
+    draft .choice:,
+    draft / true  .code:n     = \__lwc_draft:n { true  },
+    draft / false .code:n     = \__lwc_draft:n { false },
+    draft .default:n          = true,
+    draft .value_required:n   = false,
+
     nobreak .code:n           = \__lwc_nobreak:n { #1 },
     nobreak .value_required:n = true,
     nobreak .initial:n        = keep,

Modified: trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua	2022-06-18 20:06:28 UTC (rev 63642)
@@ -118,10 +118,17 @@
 local INFINITY = 10000
 local INSERT_CLASS_MULTIPLE = 1000 * 1000
 local INSERT_FIRST_MULTIPLE = 1000
+local llap_offset = math.max(tex.dimen.parindent, tex.sp("12pt"))
 local min_col_width = tex.sp("250pt")
 local PAGE_MULTIPLE = 100
 local SINGLE_LINE = 50
 
+lwc.colours = {
+    expanded = {0.00, 0.70, 0.25},
+    failure  = {0.90, 0.00, 0.25},
+    moved    = {0.25, 0.25, 1.00},
+}
+
 --[[ Package/module initialization.
 
      Here, we replace any format/engine-specific variables/functions with some
@@ -135,6 +142,7 @@
       max_cost,
       pagenum,
       paragraph_attribute,
+      shrink_order,
       stretch_order,
       warning
 
@@ -142,9 +150,11 @@
     -- LMTX has removed underscores from most of the Lua parts
     debug("LMTX")
     contrib_head = "contributehead"
+    shrink_order = "shrinkorder"
     stretch_order = "stretchorder"
 else
     contrib_head = "contrib_head"
+    shrink_order = "shrink_order"
     stretch_order = "stretch_order"
 end
 
@@ -184,8 +194,8 @@
         debug("Plain/LaTeX")
         luatexbase.provides_module {
             name = lwc.name,
-            date = "2022/05/26", --%%slashdate
-            version = "2.1.2", --%%version
+            date = "2022/06/17", --%%slashdate
+            version = "2.2.0", --%%version
             description = [[
 
 This module provides a LuaTeX-based solution to prevent
@@ -211,6 +221,23 @@
 Please use LaTeX, Plain TeX, ConTeXt or OpTeX.]]
 end
 
+--[[ Select the fonts
+
+     We want to use cmr7 for the draft mode cost displays, and the easiest
+     way to do so is to just hardcode the font id's. This relies on some
+     implementation details; however, it is very unlikely to ever be an issue
+  ]]
+local SMALL_FONT
+if plain then
+    SMALL_FONT = 4
+elseif latex then
+    SMALL_FONT = 7
+elseif optex then
+    SMALL_FONT = 7
+elseif context then
+    SMALL_FONT = 3
+end
+
 --[[ Table to hold the alternate paragraph versions.
 
      This is global(ish) mutable state, which isn't ideal, but any other way of
@@ -219,8 +246,7 @@
 local paragraphs = {}
 local inserts = {}
 
---[[
-    Function definitions
+--[[ Function definitions
   ]]
 
 --- Gets the current paragraph and page locations
@@ -268,6 +294,7 @@
 
 
 --- Checks if the ConTeXt "grid snapping" is active
+---
 --- @return boolean
 local function grid_mode_enabled()
     -- Compare the token "mode" to see if `\\ifgridsnapping` is `\\iftrue`
@@ -371,6 +398,91 @@
 end
 
 
+lwc.draft_mode = false
+--- Changes the text colour in a node list if draft mode is active
+---
+--- @param head node The first node to colour
+--- @param colour table<number> A 3-tuple of RGB values
+--- @return node head The coloured node
+local function colour_list(head, colour)
+    if not lwc.draft_mode then
+        return head
+    end
+
+    -- Adapted from https://tex.stackexchange.com/a/372437
+    -- \\pdfextension colorstack is ignored in LMTX
+    local start_colour = new_node("whatsit", "pdf_colorstack")
+    start_colour.stack = 0
+    start_colour.command = 1
+    start_colour.data = string.format("%.2f %.2f %.2f rg", table.unpack(colour))
+
+    local end_colour = new_node("whatsit", "pdf_colorstack")
+    end_colour.stack = 0
+    end_colour.command = 2
+
+    start_colour.next = head
+    last(head).next = end_colour
+
+    return start_colour
+end
+
+
+--- Generate an \\llap'ed box containing the provided string
+---
+--- @param str string The string to typeset
+--- @return node head The box node
+local function llap_string(str)
+    local first = new_node("glue")
+    first.width = llap_offset
+
+    local m = first
+    for letter in str:gmatch(".")  do
+        local n = new_node("glyph")
+        n.font = SMALL_FONT
+        n.char = string.byte(letter)
+
+        m.next = n
+        m = n
+    end
+
+    local hss = new_node("glue")
+    hss.stretch = 1
+    hss[stretch_order] = 1
+    hss.shrink = 1
+    hss[shrink_order] = 1
+    m.next = hss
+
+    return node.hpack(first, 0, "exactly")
+end
+
+
+--- Typesets the cost of a paragraph beside it in draft mode
+---
+--- @param paragraph node
+--- @param cost number
+--- @return nil
+local function show_cost(paragraph, cost)
+    if not lwc.draft_mode then
+        return
+    end
+
+    local last_hlist_end = last(next_of_type(
+        last(paragraph),
+        hlist_id,
+        { subtype = line_subid, reverse = true }
+    ).list)
+
+    local cost_str
+    if cost < math.maxinteger then
+        cost_str = string.format("%.0f", cost)
+    else
+        cost_str = "infinite"
+    end
+
+    last_hlist_end.next = llap_string(cost_str)
+end
+
+
 --- Saves each paragraph, but lengthened by 1 line
 ---
 --- Called by the `pre_linebreak_filter` callback
@@ -411,15 +523,27 @@
 
     local long_cost = lwc.paragraph_cost(long_info.demerits, long_info.prevgraf)
 
-    if long_info.prevgraf == natural_info.prevgraf + 1 and
-       long_cost > 10 -- Any paragraph that is "free" to expand is suspicious
+    if long_info.prevgraf ~= natural_info.prevgraf + 1 or
+       long_cost < 10 -- Any paragraph that is "free" to expand is suspicious
     then
-        table.insert(paragraphs, {
-            cost = long_cost,
-            node = next_of_type(long_node, hlist_id, { subtype = line_subid })
-        })
+        -- This paragraph is infinitely bad
+        long_cost = math.maxinteger
     end
 
+    local saved_node = next_of_type(long_node, hlist_id, { subtype = line_subid })
+
+    show_cost(saved_node, long_cost)
+    for n in traverse_id(hlist_id, saved_node) do
+        n.list = colour_list(n.list, lwc.colours.expanded)
+    end
+
+    table.insert(paragraphs, {
+        cost = long_cost,
+        node = copy_list(saved_node)
+    })
+
+    free_list(long_node)
+
     -- Print some debugging information
     get_chars(head)
     debug(get_location(), "nat  lines    " .. natural_info.prevgraf)
@@ -452,21 +576,21 @@
     -- Tag the paragraphs
     if not status.output_active then -- Don't run during the output routine
         -- Get the start and end of the paragraph
-        local top_para = next_of_type(head, hlist_id, { subtype = line_subid })
-        local bottom_para = last(head)
+        local top = next_of_type(head, hlist_id, { subtype = line_subid })
+        local bottom = last(head)
 
-        while bottom_para.id == insert_id do
-            bottom_para = bottom_para.prev
+        while bottom.id == insert_id do
+            bottom = bottom.prev
         end
 
-        if top_para ~= bottom_para then
+        if top ~= bottom then
             set_attribute(
-                top_para,
+                top,
                 paragraph_attribute,
                 #paragraphs + (PAGE_MULTIPLE * pagenum())
             )
             set_attribute(
-                bottom_para,
+                bottom,
                 paragraph_attribute,
                 -1 * (#paragraphs + (PAGE_MULTIPLE * pagenum()))
             )
@@ -474,11 +598,15 @@
             -- We need a special tag for a 1-line paragraph since the node can only
             -- have a single attribute value
             set_attribute(
-                top_para,
+                top,
                 paragraph_attribute,
                 #paragraphs + (PAGE_MULTIPLE * pagenum()) + SINGLE_LINE
             )
         end
+
+        if #paragraphs > 0 then
+            show_cost(head, paragraphs[#paragraphs].cost)
+        end
     end
 end
 
@@ -582,12 +710,14 @@
 ---
 --- @return nil
 local function reset_state()
+    for _, paragraph in ipairs(paragraphs) do
+        free_list(paragraph.node)
+    end
     paragraphs = {}
 
     for _, insert in ipairs(inserts) do
         free(insert)
     end
-
     inserts = {}
 end
 
@@ -597,6 +727,25 @@
 --- @return nil
 local function remove_widows_fail()
     warning("Widow/Orphan/broken hyphen NOT removed on page " .. pagenum())
+
+    local last_line = next_of_type(
+        last(tex_lists.page_head),
+        hlist_id,
+        { subtype = line_subid, reverse = true }
+    )
+    if last_line then
+        last_line.list = colour_list(last_line.list, lwc.colours.failure)
+    end
+
+    local next_first_line = next_of_type(
+        tex_lists[contrib_head],
+        hlist_id,
+        { subtype = line_subid }
+    )
+    if next_first_line then
+        next_first_line.list = colour_list(next_first_line.list, lwc.colours.failure)
+    end
+
     reset_state()
 end
 
@@ -625,18 +774,24 @@
 
     -- Find the first paragraph on the page, from the top
     local first_val, first_head = find_attribute(head, paragraph_attribute)
-    if first_val // PAGE_MULTIPLE == pagenum() - 1 then
+    while abs(first_val) // PAGE_MULTIPLE == pagenum() - 1 do
         --[[ If the first complete paragraph on the page was initially broken on the
              previous page, then we can't expand it here so we need to skip it.
           ]]
-        first_index = find_attribute(
+        first_val, first_head = find_attribute(
             first_head.next,
             paragraph_attribute
-        ) % PAGE_MULTIPLE
-    else
-        first_index = first_val % PAGE_MULTIPLE
+        )
     end
 
+    first_index = first_val % PAGE_MULTIPLE
+
+    if first_index >= SINGLE_LINE then
+        first_index = first_index - SINGLE_LINE
+    end
+
+    debug("first/last", first_index .. "/" .. last_index)
+
     return first_index, last_index
 end
 
@@ -653,21 +808,13 @@
     local best_index = 1
     local best_cost = paragraphs[best_index].cost
 
-    -- We find the current "best" replacement, then free the unused ones
+    -- We find the current "best" replacement
     for index, paragraph in pairs(paragraphs) do
         if paragraph.cost < best_cost and
            index <  last_paragraph_index and
            index >= first_paragraph_index
         then
-            -- Free the old best paragraph
-            free_list(paragraphs[best_index].node)
-            paragraphs[best_index].node = nil
-            -- Set the new best paragraph
             best_index, best_cost = index, paragraph.cost
-        elseif index > 1 then
-            -- Not sure why `i > 1` is required?
-            free_list(paragraph.node)
-            paragraph.node = nil
         end
     end
 
@@ -677,7 +824,8 @@
     )
 
     if best_cost  >  tex_count[max_cost] or
-       best_index == last_paragraph_index
+       best_index == last_paragraph_index or
+       best_cost  == math.maxinteger
     then
         return nil
     else
@@ -737,9 +885,11 @@
                 if box_value > 0 then
                     selected_inserts[#selected_inserts + 1] = copy(inserts[box_value])
                 end
+
+                m = free(m)
+            else
+                m = m.next
             end
-
-            m = m.next
         end
 
         if not insert_box.list then
@@ -811,10 +961,19 @@
        is_matching_penalty(potential_penalty.penalty)
     then
         warning("Making a new widow/orphan/broken hyphen on page " .. pagenum())
+
+        local second_last_line = next_of_type(
+            potential_penalty,
+            hlist_id,
+            { subtype = line_subid, reverse = true }
+        )
+        second_last_line.list = colour_list(second_last_line.list, lwc.colours.failure)
     end
 
     last_line = copy_list(n)
 
+    last_line.list = colour_list(last_line.list, lwc.colours.moved)
+
     -- Reinsert any inserts originally present in this moved line
     local selected_inserts = get_inserts(last_line)
     for _, insert in ipairs(selected_inserts) do
@@ -824,10 +983,11 @@
     -- Add back in the content from the next page
     last(last_line).next = copy_list(tex_lists[contrib_head])
 
+    free_list(n.prev.prev.next)
     n.prev.prev.next = nil
 
     -- Set the content of the next page
-    last(last_line)
+    free_list(tex_lists[contrib_head])
     tex_lists[contrib_head] = last_line
 
     return true
@@ -842,11 +1002,11 @@
 --- @param head node
 --- @param paragraph_index number
 local function replace_paragraph(head, paragraph_index)
-    local target_node = paragraphs[paragraph_index].node
-    local free_next_nodes = false
+    local target_node = copy_list(paragraphs[paragraph_index].node)
 
     local start_found = false
     local end_found = false
+    local free_nodes_begin
 
     -- Loop through all of the nodes on the page with the lwc attribute
     local n = head
@@ -884,7 +1044,7 @@
             end
 
             n.prev.next = target_node
-            free_next_nodes = true
+            free_nodes_begin = n
         end
 
         -- Insert the end of the replacement paragraph
@@ -907,17 +1067,17 @@
                 target_node_last.next = n.next
             end
 
+            n.next = nil
+
             break
         end
 
-        if free_next_nodes then
-            n = free(n)
-        else
-            n = n.next
-        end
+        n = n.next
     end
 
-    if not (start_found and end_found) then
+    if start_found and end_found then
+        free_list(free_nodes_begin)
+    else
         warning("Paragraph NOT expanded on page " .. pagenum())
     end
 end
@@ -946,6 +1106,7 @@
 
     -- Nothing that we can do if there aren't any paragraphs available to expand
     if #paragraphs == 0 then
+        debug("failure", "no paragraphs to expand")
         remove_widows_fail()
         return head
     end
@@ -952,12 +1113,16 @@
 
     -- Check the original height of \\box255
     local vsize = tex_dimen.vsize
-    local orig_height_diff = vpack(head).height - vsize
+    local orig_vpack = vpack(head)
+    local orig_height_diff = orig_vpack.height - vsize
+    orig_vpack.list = nil
+    free(orig_vpack)
 
     -- Find the paragraph to expand
     local paragraph_index = best_paragraph(head)
 
     if not paragraph_index then
+        debug("failure", "no good paragraph")
         remove_widows_fail()
         return head
     end
@@ -964,6 +1129,7 @@
 
     -- Move the last line of the page to the next page
     if not move_last_line(head) then
+        debug("failure", "can't move last line")
         remove_widows_fail()
         return head
     end
@@ -975,13 +1141,19 @@
          over/underfull box warnings, so we correct any discrepancies
          here.
       ]]
-    local new_height_diff = vpack(head).height - vsize
+    local new_vpack = vpack(head)
+    local new_height_diff = new_vpack.height - vsize
+    new_vpack.list = nil
+    free(new_vpack)
     -- We need the original height discrepancy in case there are \\vfill's
     local net_height_diff = orig_height_diff - new_height_diff
+    local bls = tex.skip.baselineskip
+    local bls_width = bls.width
+    free(bls)
 
     if abs(net_height_diff) > 0 and
        -- A difference larger than 0.25\\baselineskip is probably not from \lwc/
-       abs(net_height_diff) < tex.skip.baselineskip.width / 4
+       abs(net_height_diff) < bls_width / 4
     then
         local bottom_glue = new_node("glue")
         bottom_glue.width = net_height_diff
@@ -1214,6 +1386,13 @@
     end,
     { "string" }
 )
+register_tex_cmd(
+    "draft",
+    function(str)
+        lwc.draft_mode = str ~= "0" and str ~= "false" and str ~= "stop"
+    end,
+    { "string" }
+)
 
 --- Silence the luatexbase "Enabling/Removing <callback>" info messages
 ---

Modified: trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex	2022-06-18 20:06:28 UTC (rev 63642)
@@ -3,7 +3,7 @@
 % SPDX-License-Identifier: MPL-2.0+
 % SPDX-FileCopyrightText: 2022 Max Chernoff
 
-\wlog{lua-widow-control v2.1.2} %%version
+\wlog{lua-widow-control v2.2.0} %%version
 
 \ifx\directlua\undefined
     \errmessage{%
@@ -88,6 +88,7 @@
 \let\lwcenable=\lwc at enable
 \let\lwcdisable=\lwc at disable
 \let\lwcdebug=\lwc at debug
+\let\lwcdraft=\lwc at draft
 \let\iflwc=\lwc at if@enabled
 \let\lwcnobreak=\lwc at nobreak
 

Modified: trunk/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm
===================================================================
--- trunk/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm	2022-06-18 20:05:56 UTC (rev 63641)
+++ trunk/Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm	2022-06-18 20:06:28 UTC (rev 63642)
@@ -3,7 +3,7 @@
 % SPDX-License-Identifier: MPL-2.0+
 % SPDX-FileCopyrightText: 2022 Max Chernoff
 
-\_codedecl\lwcenable{lua-widow-control <v2.1.2>} %%version
+\_codedecl\lwcenable{lua-widow-control <v2.2.0>} %%version
 \_namespace{lwc}
 
 \_clubpenalty=1
@@ -72,6 +72,7 @@
 \_let\lwcdisable=\.disable
 \_let\lwcdisablecmd=\.disable_cmd
 \_let\lwcdebug=\.debug
+\_let\lwcdraft=\.draft
 \_let\iflwc=\.if_enabled
 \_let\lwcnobreak=\.nobreak
 



More information about the tex-live-commits mailing list.