summaryrefslogtreecommitdiff
path: root/Master/texmf-dist
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2022-06-18 20:06:28 +0000
committerKarl Berry <karl@freefriends.org>2022-06-18 20:06:28 +0000
commit6aef67d9f5fa3aa0eff4adc1196a7cf4e36c81a9 (patch)
treef96c841c384afd9888443815fff064c92cedea40 /Master/texmf-dist
parentebf61fc815a3b70fb28f94ecffbcc7243dcf833c (diff)
lua-widow-control (18jun22)
git-svn-id: svn://tug.org/texlive/trunk@63642 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r--Master/texmf-dist/doc/luatex/lua-widow-control/README.md2
-rw-r--r--Master/texmf-dist/doc/luatex/lua-widow-control/lua-widow-control.pdfbin459643 -> 509126 bytes
-rw-r--r--Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdfbin333173 -> 391529 bytes
-rw-r--r--Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md153
-rw-r--r--Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex58
-rw-r--r--Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx20
-rw-r--r--Master/texmf-dist/tex/context/third/lua-widow-control/t-lua-widow-control.mkxl7
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty4
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control.sty24
-rw-r--r--Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.lua277
-rw-r--r--Master/texmf-dist/tex/luatex/lua-widow-control/lua-widow-control.tex3
-rw-r--r--Master/texmf-dist/tex/optex/lua-widow-control/lua-widow-control.opm3
12 files changed, 484 insertions, 67 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 c1ce5258f09..61e62cb59ad 100644
--- a/Master/texmf-dist/doc/luatex/lua-widow-control/README.md
+++ b/Master/texmf-dist/doc/luatex/lua-widow-control/README.md
@@ -48,4 +48,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.
---
-_v2.1.2 (2022-05-26)_ <!--%%version %%dashdate-->
+_v2.2.0 (2022-06-17)_ <!--%%version %%dashdate-->
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
index f2d8337ee81..36b8db29084 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
Binary files differ
diff --git a/Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdf b/Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdf
index 9c9de8bd020..b5061094963 100644
--- a/Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdf
+++ b/Master/texmf-dist/doc/luatex/lua-widow-control/tb133chernoff-widows.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md b/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md
new file mode 100644
index 00000000000..0314b88e6bc
--- /dev/null
+++ b/Master/texmf-dist/source/luatex/lua-widow-control/CHANGELOG.md
@@ -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
diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex
index d2eb12c82ea..c8902383714 100644
--- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex
+++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.tex
@@ -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 @@ sets the values to~5\,000 and 10\,000 respectively.
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 @@ ultra-short~lines.
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 @@ Please note that a compiled document is \bold{not} considered to be an \q{Execut
\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 @@ If want to offer any improvements to the code below, please open an issue or a \
\usemodule[scite]
\setupbodyfont[10pt]
\setuphead[subsection][
- alternative=normal,
- style=\ssita,
page=yes,
continue=yes,
]
diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx b/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx
index af35ab0f4d3..7cd18ab68cc 100644
--- a/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx
+++ b/Master/texmf-dist/source/luatex/lua-widow-control/tb133chernoff-widows.ltx
@@ -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
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 682e8d23c5d..59825332020 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=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,
diff --git a/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty b/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty
index b7b2ab44c04..74645635600 100644
--- a/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty
+++ b/Master/texmf-dist/tex/lualatex/lua-widow-control/lua-widow-control-2022-02-22.sty
@@ -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}{%
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 89f417a4576..7d1be850b91 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
@@ -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,8 +224,16 @@
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,
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 4bd109e4839..800faf56242 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
@@ -118,10 +118,17 @@ local iftrue = token.create("iftrue")
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 @@ local contrib_head,
max_cost,
pagenum,
paragraph_attribute,
+ shrink_order,
stretch_order,
warning
@@ -142,9 +150,11 @@ if lmtx then
-- 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 @@ elseif plain or latex or optex then
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 @@ else -- This shouldn't ever happen
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 @@ end
local paragraphs = {}
local inserts = {}
---[[
- Function definitions
+--[[ Function definitions
]]
--- Gets the current paragraph and page locations
@@ -268,6 +294,7 @@ end
--- 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 @@ local function natural_paragraph(head)
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 @@ function lwc.save_paragraphs(head)
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 @@ local function mark_paragraphs(head)
-- 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 @@ local function mark_paragraphs(head)
-- 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 @@ end
---
--- @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 @@ end
--- @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 @@ local function first_last_paragraphs(head)
-- 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 function best_paragraph(head)
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 @@ local function best_paragraph(head)
)
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 @@ local function get_inserts(last_line)
if box_value > 0 then
selected_inserts[#selected_inserts + 1] = copy(inserts[box_value])
end
- end
- m = m.next
+ m = free(m)
+ else
+ m = m.next
+ end
end
if not insert_box.list then
@@ -811,10 +961,19 @@ local function move_last_line(head)
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 @@ local function move_last_line(head)
-- 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 @@ end
--- @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 @@ local function replace_paragraph(head, paragraph_index)
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 @@ local function replace_paragraph(head, paragraph_index)
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,24 +1106,30 @@ function lwc.remove_widows(head)
-- 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
-- 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
-- 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 @@ function lwc.remove_widows(head)
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 @@ register_tex_cmd(
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
---
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 b8ae064c044..2e1dcef902e 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
@@ -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@enable
\let\lwcdisable=\lwc@disable
\let\lwcdebug=\lwc@debug
+\let\lwcdraft=\lwc@draft
\let\iflwc=\lwc@if@enabled
\let\lwcnobreak=\lwc@nobreak
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
index f1261e6c249..ff26f856c5f 100644
--- 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
@@ -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