% 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 \doifnot{\contextmark}{LMTX}{ \errhelp{LMTX/MkXL is required to compile this file.} \errmessage{Fatal error, exiting.} } \environment lwc-manual \usemodule[lua-widow-control] \usebtxdataset[\jobname.bib] \useURL[projecturl][https://github.com/gucci-on-fleek/lua-widow-control] \useURL[download][https://github.com/gucci-on-fleek/lua-widow-control/releases/latest] \useURL[ctan][https://www.ctan.org/pkg/lua-widow-control] % Abbreviations \def\lwc/{\sans{lua-\allowbreak widow-\allowbreak control}} \def\Lwc/{\sans{Lua-\allowbreak widow-\allowbreak control}} \def\estretch/{\tex{emergency\allowbreak stretch}} \def\openalty/{\tex{output\allowbreak penalty}} \def\waos/{widows and orphans} \def\wao/{widow and orphan} \def\woo/{widow or orphan} \def\mkxl/{\ConTeXt~Mk\acronym{XL}} \def\mkiv/{\ConTeXt~Mk\acronym{IV}} \define\OpTeX{Op\kern-.05em\TeX} \def\LuaMeta{Lua\-Meta\-} \def\LuaMetaTeX{\LuaMeta\TeX} \def\plainop/{Plain~\TeX{}/\OpTeX{}} \let\q=\quotation \def\titlecite[#1]{\cite[title][#1]\cite[#1]} \definetype[inlineTEX][option=tex, escape={$,$}, lines=hyphenated] \definetype[inlineLUA][option=lua, escape={$,$}, lines=hyphenated] \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] \definecolor[cost] [r=0.50, g=0.50, b=0.50] \startdocument[ title=lua-widow-control, author=Max Chernoff, version=3.0.1, %%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{}/\OpTeX{} 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 their document. For more details, see the \goto{Usage sections}[sec:usage]. \subject{Contents} \placecontent[criterium=all] \section{Preliminaries} This manual begins with a brief introduction to widows, orphans, and \lwc/. For an extended introduction and discussion of these topics, please see the \emph{Zpravodaj} article\cite[zpravodaj] distributed with this manual (Links: \goto{local}[lwc-zpravodaj::], \goto{\acronym{CTAN}}[url(http://mirrors.ctan.org/macros/luatex/generic/lua-widow-control/lwc-zpravodaj.pdf)], \goto{GitHub}[url(https://github.com/gucci-on-fleek/lua-widow-control/releases/latest/download/lwc-zpravodaj.pdf)]). This same material is also available in two \emph{TUGboat} articles\cite[tugboat1, tugboat2] (Links: \goto{local}[tb133chernoff-widows::], \goto{\acronym{CTAN}}[url(http://mirrors.ctan.org/macros/luatex/generic/lua-widow-control/tb133chernoff-widows.pdf)], \goto{GitHub}[url(https://github.com/gucci-on-fleek/lua-widow-control/releases/latest/download/tb133chernoff-widows.pdf)]) if you prefer. You can also skip ahead to the \goto{installation instructions on \at{page}[sec:install]}[sec:install] or the \goto{usage section starting at \at{page}[sec:usage]}[sec:usage]. \section[sec:motivation]{Motivation} Unmodified \TeX{} has only two familiar ways of dealing with \waos/: it can either shorten a page by one line, or it can stretch vertical whitespace. \TeX{} was designed for mathematical and scientific typesetting, where a typical page has multiple section headings, tables, figures, and equations. For this style of document, \TeX's default behaviour works quite well, since the slight stretching of whitespace between the various document elements is nearly imperceptible; however, for prose or other documents composed almost entirely of paragraphs, there is little vertical whitespace to stretch. \Lwc/ offers an alternative method of removing \waos/: instead of shortening a page or stretching vertical whitespace, \lwc/ simply chooses a paragraph to lengthen by one~line such that the \woo/ is eliminated. \section{Widows and Orphans} \subsection{Widows} A \q{widow} occurs when the majority of a paragraph is on one page or column, but the last line is on the following page or column. It not only looks quite odd for a lone line to be at the start of the page, but it makes a paragraph harder to read since the separation of a paragraph and its last line disconnects the two, causing the reader to lose context for the widowed line. \subsection{Orphans} An \q{orphan} occurs when the first line of a paragraph is at the end of the page or column preceding the remainder of the paragraph. They are not as distracting for the reader, but they are still not ideal. Visually, \waos/ are about equally disruptive; however, orphans tend not to decrease the legibility of a text as much as widows, so some authors choose to ignore them. \subsection{Broken Hyphens} \q{Broken} hyphens occur whenever a page break occurs in a hyphenated word. These are not related to \waos/; however, breaking a word across two pages is at least as disruptive for the reader as \waos/. \TeX{} identifies broken hyphens in the same ways as \waos/, so \lwc/ treats broken hyphens in the same way. \startplacefigure[location={here, top, bottom}, title={A visual comparison of \waos/.}, reference=tab:widow] \getbuffer[widow-orphan] \stopplacefigure \section{\TeX's Pagination} \subsection{Algorithm} It is tricky to understand how \lwc/ works if you aren't familiar with how \TeX{} breaks pages and columns. For a full description, you should consult Chapter~15 of \titlecite[texbook] (\q{How \TeX{} Makes Lines into Pages}); however, this goes into much more detail than most users require, so here is a \emph{very} simplified summary of \TeX{}'s page breaking algorithm: \TeX{} fills the page with lines and other objects until the next object will no longer fit. Once no more objects will fit, \TeX{} will align the bottom of the last line with the bottom of the page by stretching any available vertical spaces if (in \LaTeX) \tex{flushbottom} is set; otherwise, it will break the page and leave the bottom empty. However, some objects have \q{penalties} attached. Penalties encourage or discourage page breaks from occurring at specific places. For example, \LaTeX{} sets a negative penalty before section headings to encourage a page break there; conversely, it sets a positive penalty after section headings to discourage breaking. To reduce \waos/, \TeX{} sets weakly-positive penalties between the first and second lines of a paragraph to prevent orphans, and between the penultimate and final lines to prevent widows. \subsection{Behaviour} Due to these \q{penalties} attached to \waos/, \TeX{} tries to avoid creating them. Widows and orphans with small penalties attached---like \LaTeX's default values of 150---are only lightly coupled to the rest of the paragraph, while \waos/ with large penalties---values of 10\,000 or more---are treated as infinitely bad and are thus unbreakable. Intermediate values behave just as you would expect, discouraging page breaks proportional to their value. However, when these lines are moved as a group, \TeX{} will have to make a page or column with less lines. \about[sec:demo] goes into further detail about how \TeX{} deals with these too-short pages or columns. \startpostponing \startTEXpage[ align=normal, width=100cm, autowidth=force, offset=5pt, pagestate=start, ] \veryraggedcenter \setupTABLE[row][first][style=\ssbf, align=middle] \setupTABLE[frame=off, offset=5pt] \startTABLE \NC Ignore \NC Shorten \NC Stretch \NC \Lwc/ \NC\NR \NC \typesetbuffer[ignore][frame=on,page=1] \NC \typesetbuffer[shorten][frame=on,page=1] \NC \typesetbuffer[stretch][frame=on,page=1] \NC \typesetbuffer[lwc][frame=on,page=1] \NC\NR \NC \typesetbuffer[ignore][frame=on,page=2] \NC \typesetbuffer[shorten][frame=on,page=2] \NC \typesetbuffer[stretch][frame=on,page=2] \NC \typesetbuffer[lwc][frame=on,page=2] \NC\NR \NC \typebuffer[ignore-code][option=TEX] \NC \typebuffer[shorten-code][option=TEX] \NC \typebuffer[stretch-code][option=TEX] \NC \typebuffer[lwc-code][option=TEX] \NC\NR \stopTABLE \placefloatcaption[table][reference=tab:demo, title={A visual comparison of various automated widow handling techniques.}] \stopTEXpage \stoppostponing \section[sec:demo]{Demonstration} Although \TeX{}'s page breaking algorithm is reasonably straightforward, it can lead to complex behaviour when \waos/ are involved. The usual choices, when rewriting is not possible, are to ignore them, stretch some glue, or shorten the page. \in{Table}[tab:demo] has a visual comparison of these options, which we'll discuss in the following: \subsection{\q{Ignore}} As you can see, the last line of the page is on a separate page from the rest of its paragraph, creating a widow. This is usually highly distracting for the reader, so it is best avoided for the reasons previously discussed. \subsection{\q{Shorten}} This page did not leave any widows, but it did shorten the previous page by one line. Sometimes this is acceptable, but usually it looks bad because pages will then have different text-block heights. This can make the pages look quite uneven, especially when typesetting with columns or in a book with facing pages. \subsection{\q{Stretch}} This page also has no widows and it has a flush bottom margin. However, the space between each pair of paragraphs had to be stretched. If this page had many equations, headings, and other elements with natural space between them, the stretched out space would be much less noticeable. \TeX{} was designed for mathematical typesetting, so it makes sense that this is its default behaviour. However, in a page with mostly text, these paragraph gaps look unsightly. Also, this method is incompatible with grid typesetting, where all glue stretching must be quantised to the height of a line. \subsection{\q{\lwc/}} \Lwc/ has none of these issues: it eliminates the widows in a document while keeping a flush bottom margin and constant paragraph spacing. To do so, \lwc/ lengthened the second paragraph by one line. If you look closely, you can see that this stretched the interword spaces. This stretching is noticeable when typesetting in a narrow text block, but is mostly imperceptible with larger widths. \Lwc/ automatically finds the \q{best} paragraph to stretch, so the increase in interword spaces should almost always be minimal. \section[sec:install]{Installation} Most up-to-date \TeX~Live and Mik\TeX{} systems should already have \lwc/ installed. However, a manual installation may occasionally be required. \subsection{\TeX~Live} Run \type{tlmgr install lua-widow-control} in a terminal, or install using the \q{\TeX~Live Manager} \acronym{GUI}. \subsection{Mik\TeX} Run \type{mpm --install=lua-widow-control} in a terminal, or install using the \q{Mik\TeX{} Maintenance} \acronym{GUI}. \subsection{Manual} Currently, \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. \subsection{Steps} \startitemize[N] \item Download \type{lua-widow-control.tds.zip} from \goto{\acronym{CTAN}}[url(ctan)], \goto{GitHub}[url(download)] or the \goto{\ConTeXt{}~Garden}[url(https://modules.contextgarden.net/cgi-bin/module.cgi/action=view/id=127)]. \item Unzip the release into your \type{TEXMFLOCAL/} directory. (You can find its location by running \type{kpsewhich --var-value TEXMFHOME} in a terminal) \item Refresh the filename database: \startitemize[1] \item \ConTeXt: \type{mtxrun --generate} \item \TeX~Live: \type{mktexlsr} \item Mik\TeX: \type{initexmf --update-fndb} \stopitemize \stopitemize \section{Dependencies} \Lwc/ does have a few dependencies; however, these will almost certainly be met by all but the most minimal of \TeX{} installations. \subsection{Plain~\TeX{}} \Lwc/ requires \LuaTeX{} ($\ge$ 0.85) and the most recent version of \sans{luatexbase} (2015/10/04). Any version of \TeX~Live $\ge$ 2016 will meet these requirements. \subsection{\LaTeX{}} \Lwc/ requires \LuaTeX{} ($\ge$ 0.85), \LaTeX{} ($\ge$ 2020/10/01), and \sans{microtype} (any version). Any version of \TeX~Live $\ge$ 2021 will meet these requirements. \Lwc/ also supports a \q{legacy} mode for older \LaTeX{} kernels. This uses an older version of the \LaTeX{} code while still using the most recent Lua code. This mode 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. Please note that when running in legacy mode, you cannot use the key--value interface. This legacy interface is undocumented, but mostly the same as the \q{Plain~\TeX{}} interface. \subsection{\ConTeXt{}} \Lwc/ supports both \mkxl/ (\LuaMetaTeX{}) and \mkiv/ (\LuaTeX{}). \subsection{\OpTeX{}} \Lwc/ works with any version of \OpTeX{} and has no dependencies. \subsection{LuaMeta\TeX{}} \Lwc/ has preliminary support for LuaMeta\LaTeX{} and LuaMetaPlain. All features should work identically to the \LuaTeX{}-based version, although there are a few minor bugs. You should always make sure to use the latest engine, format, and \lwc/ since these formats are under rapid development. \section[sec:usage]{Loading the Package} \startTABLE[setups=commandtable] \NC Plain~\TeX{} \NC\inlineTEX{\input lua-widow-control} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\usepackage{lua-widow-control}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\usemodule[lua-widow-control]} \NC\NR \NC \OpTeX{} \NC\inlineTEX{\load[lua-widow-control]} \NC\NR \stopTABLE \section{Options} \Lwc/ is automatically enabled with the default settings as soon as you load it. Most users should not need to configure \lwc/; however, the packages provides a few commands. \subsection{Overview} \LaTeX{} users can set the options either when loading the package (\inlineTEX{\usepackage[$\meta{options}$]{lua-widow-control}}) or at any point using \inlineTEX{\lwcsetup{$\meta{options}$}}. \ConTeXt{} users should use the \inlineTEX{\setuplwc[$\meta{options}$]} command for setting options at any point. Plain~\TeX{} and \OpTeX{} are a little different. Some options require you to set a register (i.e., \inlineTEX{\lwcemergencystretch = $\meta{dimension}$}), while others use macro arguments (i.e., \inlineTEX{\lwcnobreak{$\meta{option}$}}). \subsection{Disabling} You may want to disable \lwc/ for certain portions of your document. You can do so with the following commands: \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcdisable} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{disable}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[state = stop]} \NC\NR \stopTABLE This prevents \lwc/ from stretching any paragraphs that follow. If a page has earlier paragraphs where \lwc/ was still enabled and a \woo/ is detected, \lwc/ will still attempt to remove the \woo/. \subsection{Enabling} \Lwc/ is enabled as soon as the package is loaded. If you have previously disabled it, you will need to re-enable it to save new paragraphs. \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcenable} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{enable}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[state = start]} \NC\NR \stopTABLE \subsection{Automatically disabling} You may want to disable \lwc/ for certain commands where stretching is undesirable such as section headings. Of course, manually disabling and then enabling \lwc/ multiple times throughout a document would quickly become tedious, so \lwc/ provides some options to do this automatically for you. \Lwc/ automatically patches the default \LaTeX{}, \ConTeXt{}, Plain~\TeX{}, \OpTeX{}, \sans{memoir}, \sans{\acronym{KOMA}-Script}, and \sans{titlesec} section commands, so you don't need to patch these. Any others, though, you'll need to patch yourself. \startTABLE[setups=commandtable] \NC \plainop/ \NC \inlineTEX{\lwcdisablecmd $\meta{\backslash macro}$} \NC\NR \NC \LaTeX{} \NC \inlineTEX{\lwcsetup{disablecmds = {$\meta{macronameone}$, $\meta{macronametwo}$}}} \NC\NR \NC \ConTeXt{} \NC \inlineTEX{\prependtoks\lwc$\hskip-0.5em\relax$@patch@pre\to\everybefore$\hskip-0.5em\relax\meta{hook}$} \NC\NR\NC\NC \inlineTEX{\prependtoks\lwc$\hskip-0.5em\relax$@patch@pre\to\everyafter$\hskip-0.5em\relax\meta{hook}$} \NC\NR \stopTABLE The Plain~\TeX{}, \OpTeX{}, and \ConTeXt{} commands \emph{append} to the list of patched commands: they simply patch the provided commands while leaving the original patches in place. The \LaTeX{} option \emph{sets} the list of patched commands: it replaces the default list with the provided list. \subsection{\estretch/} \Lwc/ defaults to an \estretch/ value of 3~em for stretched paragraphs, but you can configure this. \Lwc/ will only use the \estretch/ when it cannot lengthen a paragraph in any other way, so it is fairly safe to set this to a large value. \TeX{} accumulates badness when \estretch/ is used, so it's pretty rare that a paragraph that requires any \estretch/ will actually be used on the page. \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcemergencystretch = $\meta{dimension}$} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{emergencystretch = $\meta{dimension}$}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[emergencystretch = $\meta{dimension}$]} \NC\NR \stopTABLE \subsection{Penalties} You can also manually adjust the penalties that \TeX{} assigns to \waos/. Usually, the defaults are fine, but there are a few circumstances where you may want to change them. \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\widowpenalty = $\meta{integer}$} \NC\NR\NC\NC\inlineTEX{\clubpenalty = $\meta{integer}$} \NC\NR\NC\NC\inlineTEX{\brokenpenalty = $\meta{integer}$} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{widowpenalty = $\meta{integer}$}} \NC\NR\NC\NC\inlineTEX{\lwcsetup{orphanpenalty = $\meta{integer}$}} \NC\NR\NC\NC\inlineTEX{\lwcsetup{brokenpenalty = $\meta{integer}$}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[widowpenalty = $\meta{integer}$]} \NC\NR\NC\NC\inlineTEX{\setuplwc[orphanpenalty = $\meta{integer}$]} \NC\NR\NC\NC\inlineTEX{\setuplwc[brokenpenalty = $\meta{integer}$]} \NC\NR \stopTABLE \page % TODO The value of these penalties determines how much \TeX{} should attempt to stretch glue before passing the \woo/ to \lwc/. If you set the values to~1 (default), \TeX{} will stretch nothing and immediately trigger \lwc/; if you set the values to 10\,000, \TeX{} will stretch infinitely and \lwc/ will never be triggered. If you set the value to some intermediate number, \TeX{} will first attempt to stretch some glue to remove the \woo/; only if it fails will \lwc/ come in and lengthen a paragraph. As a special case, if you set the values to~0, both \TeX{} and \lwc/ will completely ignore the \woo/. \Lwc/ will pick up on the values of \tex{widowpenalty}, \tex{clubpenalty}, and \tex{brokenpenalty} regardless of how you set them, so the use of these dedicated keys is entirely optional. \subsection{\tex{nobreak} Behaviour} When \lwc/ encounters an orphan, it removes it by moving the orphaned line to the next page. The majority of the time, this is an appropriate solution. However, if the orphan is immediately preceded by a section heading (or \tex{nobreak}\slash\tex{penalty 10000}), \lwc/ would na\"ively separate a section heading from the paragraph that follows. This is almost always undesirable, so \lwc/ provides some options to configure this. \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcnobreak{$\meta{value}$}} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{nobreak = $\meta{value}$}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[nobreak = $\meta{value}$]} \NC\NR \stopTABLE The default value, \type{keep}, \emph{keep}s the section heading with the orphan by moving both to the next page. The advantage to this option is that it removes the orphan and retains any \tex{nobreak}s; the disadvantage is that moving the section heading can create a large blank space at the end of the page. The value \type{split} \emph{split}s up the section heading and the orphan by moving the orphan to the next page while leaving the heading behind. This is usually a bad idea, but exists for the sake of flexibility. The value \type{warn} causes \lwc/ to give up on the page and do nothing, leaving an orphaned line. \Lwc/ \emph{warn}s the user so that they can manually remove the orphan. \startplacefigure[location={here, top, bottom}, title={A visual comparison of the various \type{nobreak} options, where each box represents a different page.}, reference=tab:nobreak] \getbuffer[nobreak] \stopplacefigure \subsection{Maximum Cost} \Lwc/ ranks each paragraph on the page by how much it would \q{cost} to lengthen that paragraph. By default, \lwc/ selects the paragraph on the page with the lowest cost; however, you can configure it to only select paragraphs below a selected cost. If there aren't any paragraphs below the set threshold, then \lwc/ won't remove the \woo/ and will instead issue a warning. \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcmaxcost = $\meta{integer}$} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{max-cost = $\meta{integer}$}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[maxcost = $\meta{integer}$]} \NC\NR \stopTABLE Based on my testing, \type{max-cost} values less than 1\,000 cause completely imperceptible changes in interword spacing; values less than 5\,000 are only noticeable if you are specifically trying to pick out the expanded paragraph on the page; values less than 15\,000 are typically acceptable; and larger values may become distracting. \Lwc/ defaults to an infinite \type{max-cost}, although the \q{strict} and \q{balanced} modes sets the values to~5\,000 and 10\,000 respectively. \Lwc/ uses a \q{cost function} $C$ that is initially defined as \startformula 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. \subsection{Draft Mode} \setuplwc[draft=start] \definecolor[lwc_expanded][s=0] \definecolor[lwc_failure][s=0] \definecolor[lwc_moved][s=0] 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 \color[cost]{cost of each paragraph is shown in the right margin} as it is here. \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}, \type{moved}, and \type{cost}. The table values are \acronym{RGB} 3-tuples, where each element is a float between zero and one. You can also show or hide the costs and colours independently of each other. \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcshowcosts 1} \NC\NR\NC\NC\inlineTEX{\lwcshowcolours 1} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{showcosts = true}} \NC\NR\NC\NC\inlineTEX{\lwcsetup{showcolours = true}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[showcosts = start]} \NC\NR\NC\NC\inlineTEX{\setuplwc[showcolours = start]} \NC\NR \stopTABLE Plain~\TeX{} users will need to modify their output routines to be able to see the costs. Before you ship out the page, you should call \inlineTEX{\lwcpreshipout} with a box number as its argument. For example, here is some sample code to correctly reproduce the standard Plain~\TeX{} output routine: \startTEX \newbox\tempshipoutbox \output={ \setbox\tempshipoutbox=\vbox{ \makeheadline \pagebody \makefootline } \lwcpreshipout\the\tempshipoutbox \shipout\box\tempshipoutbox \advancepageno } \stopTEX Setting the output routine like this is automatic in all other formats. \Lwc/ does not modify the output routine in Plain~\TeX{} since most of its users likely have their own output routines. \subsection{Draft Offset} In draft mode, the paragraph costs are printed in the margins, offset a certain distance from the page edge. By default, this offset is set to \unit{1 inch}; however, you can change this to any value that you want: \startTABLE[setups=commandtable] \NC \plainop/ \NC\inlineTEX{\lwcdraftoffset = $\meta{dimension}$} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{draftoffset = $\meta{dimension}$}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[draftoffset = $\meta{dimension}$]} \NC\NR \stopTABLE \setuplwc[draft=stop] \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, 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/ \NC\inlineTEX{\lwcdebug 1} \NC\NR\NC\NC\inlineTEX{\lwcdebug 0} \NC\NR \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{debug = true}} \NC\NR\NC\NC\inlineTEX{\lwcsetup{debug = false}} \NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[debug = start]} \NC\NR\NC\NC\inlineTEX{\setuplwc[debug = stop]} \NC\NR \stopTABLE \section{Presets} As you can see, \lwc/ provides quite a few options. Luckily, there are a few presets that you can use to set multiple options at once. These presets are a good starting point for most documents, and you can always manually override individual options. Presets are available only with \LaTeX{} and \ConTeXt{}. \startTABLE[setups=commandtable] \NC \LaTeX{} \NC\inlineTEX{\lwcsetup{$\meta{preset}$}}\NC\NR \NC \ConTeXt{} \NC\inlineTEX{\setuplwc[$\meta{preset}$]}\NC\NR \stopTABLE \subsection{\type{default}} If you use \lwc/ without any options, it defaults to this preset. In default mode, \lwc/ takes all possible measures to remove \waos/ and will not attempt to stretch any vertical glue. This usually removes~$\mathord{>}\,95\%$ of all possible \waos/. The catch here is that this mode is quite aggressive, so it often leaves behind some fairly \q{spacey} paragraphs. This mode is good if you want to remove (nearly) all \waos/ from your document, without fine-tuning the results. \subsection{\type{strict}} \Lwc/ also offers a strict mode. This greatly restricts \lwc/'s tolerance and makes it so that it will only lengthen paragraphs where the change will be imperceptible. The caveat with strict mode is that---depending on the document--- \lwc/ will be able to remove less than a third of the \waos/. For the \waos/ that can't be automatically removed, a warning will be printed to your terminal and log file so that a human can manually fix the situation. This mode is good if you want the best possible typesetting and are willing to do some manual editing. \subsection{\type{balanced}} Balanced mode sits somewhere between default mode and strict mode. This mode first lets \TeX{} stretch a little glue to remove the \woo/; only if that fails will it then trigger \lwc/. Even then, the maximum paragraph cost is capped. Here, \lwc/ can usually remove 90\% of a document's potential \waos/, and it does so while making a minimal visual impact. This mode is recommended for most users who care about their document's typography. This mode is not the default since it doesn't remove all \waos/: it still requires a little manual intervention. % % \startplacetable[location={here, top, bottom}, title={\Lwc/ options set by each mode.}, reference=tab:modes] \startTABLE[setups=booktabs, style=tt, loffset=0.5em] \NC {\rm Option} \NC default \NC balanced \NC strict \NC\NR \NC max-cost \NC $\infty$ \NC 10000 \NC 5000 \NC\NR \NC emergencystretch \NC 3em \NC 1em \NC 0pt \NC\NR \NC nobreak \NC keep \NC keep \NC warn \NC\NR \NC widowpenalty \NC 1 \NC 500 \NC 1 \NC\NR \NC orphanpenalty \NC 1 \NC 500 \NC 1 \NC\NR \NC brokenpenalty \NC 1 \NC 500 \NC 1 \NC\NR \stopTABLE \stopplacetable \section{Lua Interface} \Lwc/ provides a few public functions and tables that you can safely use or modify as documented. Any Lua interfaces that aren't documented below are subject to change at any time, but ff you do want to use an undocumented interface, please let me know and can easily document it. \subsection{Costs} \Lwc/ uses a \q{cost function} to select which paragraph to expand. Typically, this depends on the number of lines and demerits in the broken paragraph; however, you can redefine this function to do something else if you want. The default function is defined as: \startLUA --- The "cost function" to use. --- --- @param demerits number The demerits of the broken paragraph --- @param lines number The number of lines in the broken paragraph --- @param nat_demerits number The demerits of the naturally-broken paragraph --- @param nat_lines number The number of lines in the naturally-broken paragraph --- @param head node The head of the broken paragraph --- @return number cost The cost of the broken paragraph function lwc.paragraph_cost(demerits, lines, nat_demerits, nat_lines, head) return demerits / math.sqrt(lines) end \stopLUA \subsection{Activation} Typically, \lwc/ determines if there are \waos/ at the end of a page by checking the \tex{outputpenalty} register. However, you can use a custom check if you want. The default check is defined as: \startLUA --- Determines if we should "activate" lwc for the current page/column. --- --- @param penalty number The \outputpenalty for the current page/column --- @param paragraphs table> The `paragraphs` table --- @param head node The head of the current page/column --- @return boolean activate True if lwc should move the last line on this page function lwc.should_remove_widows(penalty, paragraphs, head) return is_matching_penalty(penalty) end \stopLUA By setting a custom activation and cost function, you can transform \lwc/ from a \wao/ remover into a custom layout customization tool. \section{Compatibility} The \lwc/ implementation is almost entirely in Lua, with only a minimal \TeX{} footprint. It doesn't modify the output routine, \tex{everypar}, and it doesn't insert any whatsits. This means that it should be compatible with nearly any \TeX{} package, class, and format. Most changes that \lwc/ makes are not observable on the \TeX{} side. However, on the Lua side, \lwc/ modifies much of a page's internal structure. This should not affect any \TeX{} code; however, it may surprise Lua code that modifies or depends on the page's low-level structure. This does not matter for Plain~\TeX{} or \LaTeX{}, where even most Lua-based packages don't depend on the node list structure; nevertheless, there are a few issues with \ConTeXt{}. However, on the Lua side, \lwc/ modifies much of a page's internal structure. This should not affect any \TeX{} code; however, it may surprise Lua code that modifies or depends on the page's low-level structure. This does not affect Plain~\TeX{} or \LaTeX{} where even most Lua-based packages don't depend on the node list structure. \ConTeXt{} \emph{does} depend on this internal node structure; however, I have carefully tested the package to ensure that this causes no issues. Finally, keep in mind that adding \lwc/ to a document will almost certainly change its page break locations. \subsection{Formats} \Lwc/ runs on all known Lua\TeX{}-based formats: Plain~Lua\TeX{}, Lua\LaTeX{}, \ConTeXt{} Mk\acronym{IV}, and~\OpTeX{}. Unless otherwise documented, all features should work equally well in all formats. \Lwc/ is also fully-compatible with the \LuaMeta\TeX{}-based formats: \ConTeXt{} Mk\acronym{XL}\slash\acronym{LMTX}, \LuaMeta\LaTeX{}, and \LuaMeta{}Plain. \ConTeXt{} Mk\acronym{XL} works equally well as \ConTeXt{} Mk\acronym{IV} and Lua\LaTeX{}; however, \LuaMeta\LaTeX{} and \LuaMeta{}Plain support is still quite early. All features should work, although there are still a few minor bugs. All told, \lwc/ supports 7 different format\slash{}engine combinations. \subsection{Columns} Since \TeX{} and the formats implement column breaking and page breaking through the same internal mechanisms, \lwc/ removes \waos/ between columns just as it does with \waos/ between pages. \Lwc/ is known to work with the \LaTeX{} class option \type{twocolumn} and the two-column output routine from Chapter~23 of \titlecite[texbook]. \subsection{Performance} \Lwc/ runs entirely in a single pass, without depending on any \type{.aux} files or the like. Thus, it shouldn't meaningfully increase compile times. Although \lwc/ internally breaks each paragraph twice, modern computers break paragraphs near-instantaneously, so you are not likely to notice any slowdown. \subsection{\eTeX{} penalties} Knuth's original \TeX{} has three basic line penalties: \tex{interlinepenalty}, which is inserted between all lines; \tex{club\-penalty}, which is inserted after the first line; and \tex{widow\-penalty}, which is inserted before the last line. The \eTeX{} extensions generalize these commands with a syntax similar to \tex{parshape}: with \tex{widow\-penalties} you can set the penalty between the last, second last, and $n$th last lines of a paragraph; \tex{inter\-line\-penalties} and \tex{club\-penalties} behave similarly. \Lwc/ makes no explicit attempts to support these new -\type{penalties} commands. Specifically, if you give a line a penalty that matches either \tex{widowpenalty} or \tex{clubpenalty}, \lwc/ will treat the lines exactly as it would a \woo/. So while these commands won't break \lwc/, they are likely to lead to some unexpected behaviour. \subsection{Grids} \Lwc/ is fully compatible with the grid snapping features of \ConTeXt{} \mkiv/ and \mkxl/. \subsection{Footnotes} If there are footnotes (or any other type of inline \tex{insert}) present in the moved line, \lwc/ will move both the \q{footnote mark} and the \q{footnote text} such that both are on the same page. However, this may lead to an odd blank space at the bottom of the page since \lwc/ needs to move both the line and its footnotes. Footnotes cause the same page-breaking issues in unmodified Plain~\TeX{} and \LaTeX{}, so this is mostly unavoidable. \section{Stability} The documented interfaces of \lwc/ can be considered stable: I'm not planning on removing or modifying any existing options or commands in any way that would break documents. However, \lwc/'s page breaking \emph{is} subject to change. I will attempt to keep page breaks the same whenever reasonable; however, I will \emph{rarely} make modifications to the algorithm when I can improve the output quality. Any such changes will be clearly noted in the release notes. \section{Short last lines} When lengthening a paragraph with \tex{looseness}, it is common advice to insert ties (\type{~}) between the last few words of the paragraph to avoid overly-short last lines\cite[texbook]. \Lwc/ does this automatically, but instead of using ties or \tex{hbox}es, it uses the \tex{par\allowbreak fill\allowbreak skip} parameter. When lengthening a paragraph (and only when lengthening a paragraph---remember, \lwc/ doesn't interfere with \TeX{}'s output unless it detects a \woo/), \lwc/ sets \tex{parfillskip} to \type{0.75\hsize plus 0.05\hsize minus 0.75\hsize}. This normally makes the last line of a paragraph be at least 20\% of the overall paragraph's width, thus preventing ultra-short~lines. \section[sec:issues]{Known Issues} \startitemize \item When a three-line paragraph is at the end of a page forming a widow, \lwc/ will remove the widow; however, it will leave an orphan. This issue is inherent to any process that removes widows through paragraph expansion and is thus unavoidable. Orphans are considered to be better than widows\cite[elements], so this is still an improvement. \item \Lwc/ only attempts to expand paragraphs; it never attempts to shrink them. See the \emph{TUGboat}~article\cite[tugboat1] ยง15.3 for further discussion. \githubissue{33} \item \Lwc/ can only expand paragraphs that fit completely on a page. This is unavoidable due to the one-page-at-a-time model: you can't modify the bottom half of a paragraph since its top half has already shipped out, and you can't expand the top half of a paragraph since that can't remove orphans. This only causes issues if your document has paragraphs so long that a page only has two half-paragraphs and zero whole paragraphs. \item Sometimes a \woo/ cannot be eliminated because no paragraph has enough stretch. Sometimes this can be remediated by increasing \lwc/'s \estretch/; however, some pages just don't have any suitable paragraph. Long paragraphs with short words tend to be stretchier than short paragraphs with long words since these long paragraphs have more interword glue. Narrow columns also stretch more easily than wide columns since you need to expand a paragraph by less to make a new line. \item \Lwc/ only attempts to expand paragraphs on a page with a \woo/. A global system like in \titlecite[global] would solve this; however, this is both \acronym{NP}-complete\cite[plass] and impossible to solve in a single pass. Very rarely would such a system remove widows or orphans that \lwc/ cannot. \stopitemize \section{Contributions} If you have any issues with \lwc/, please create an issue at the \goto{project's GitHub page}[url(projecturl)]. Or, if you think that you can solve any of the \about[sec:issues] or add any new features, \goto{submit a \acronym{PR}}[url(projecturl)]. Thanks! \section{License} \Lwc/ is licensed under the \goto{\emph{Mozilla Public License}, version 2.0}[url(https://www.mozilla.org/en-US/MPL/2.0/)] or greater. The documentation is licensed under \goto{\acronym{CC-BY-SA}, version 4.0}[url(https://creativecommons.org/licenses/by-sa/4.0/legalcode)] or greater as well as the \acronym{MPL}. Please note that a compiled document is \bold{not} considered to be an \q{Executable Form} as defined by the \acronym{MPL}. The \acronym{MPL} and \acronym{CC-BY-SA} licenses \bold{only} apply to you if you distribute the \lwc/ source code or documentation. \section{References} \placelistofpublications \page \setuphead[subsection][ alternative=normal, style=\ssitb, after={\blank[disable, penalty:10000]} ] \markdownInput{../../CHANGELOG.md} \page \setuplayout[ width=middle, backspace=1in, height=9.25in, ] \section[sec:implementation]{Implementation} From here and until the end of this manual is the raw source code of \lwc/. This is primarily of interest to developers; most users need not read further. This code vaguely resembles the typical \LaTeX{} literate programming style, although I use extensive inline comments instead of arcane \sans{docstrip} macros. Hopefully this is useful as a reference for advanced \lwc/ users as well as anyone doing extensive node manipulation in \LuaTeX{}. If want to offer any improvements to the code below, please open an issue or a \acronym{PR} on \goto{GitHub}[url(projecturl)]. \usemodule[scite] \setupbodyfont[10pt] \setuphead[subsection][ page=yes, continue=yes, ] \subsection{lua-widow-control.lua} \typeLUAfile{../source/lua-widow-control.lua} \subsection{lua-widow-control.tex} \typeTEXfile{../source/lua-widow-control.tex} \subsection{lua-widow-control.sty} \typeTEXfile{../source/lua-widow-control.sty} \subsection{lua-widow-control-2022-02-22.sty} \typeTEXfile{../source/lua-widow-control-2022-02-22.sty} \subsection{t-lua-widow-control.mkxl} \typeTEXfile{../source/t-lua-widow-control.mkxl} \subsection{lua-widow-control.opm} \typeTEXfile{../source/lua-widow-control.opm} \subsection{Demo from \in{Table}[tab:demo]} \typeTEXfile{\jobname-demo-text.tmp} \stopdocument