From 712c5abd10e75e4612c5fcb73629423fc5cce1a0 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 27 May 2022 20:41:39 +0000 Subject: lua-widow-control (27may22) git-svn-id: svn://tug.org/texlive/trunk@63413 c570f23f-e606-0410-a88d-b1316a301751 --- .../lua-widow-control/lwc-manual-samples.tex | 178 +++++++++++++++++++++ .../luatex/lua-widow-control/lwc-manual.mkxl | 2 +- .../source/luatex/lua-widow-control/lwc-manual.tex | 26 ++- .../source/luatex/lua-widow-control/lwc-sample.tex | 178 --------------------- 4 files changed, 200 insertions(+), 184 deletions(-) create mode 100644 Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual-samples.tex delete mode 100644 Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex (limited to 'Master/texmf-dist/source') diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual-samples.tex b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual-samples.tex new file mode 100644 index 00000000000..6951f7a5bbd --- /dev/null +++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual-samples.tex @@ -0,0 +1,178 @@ +% 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 + +\startbuffer[demo-text] + \definepapersize[smallpaper][ + width=6cm, + height=8.3cm + ]\setuppapersize[smallpaper] + + \setuplayout[ + topspace=0.1cm, + backspace=0.1cm, + width=middle, + height=middle, + header=0pt, + footer=0pt, + ] + + \def\lwc/{\sans{lua-\allowbreak widow-\allowbreak control}} + \def\Lwc/{\sans{Lua-\allowbreak widow-\allowbreak control}} + + \setupbodyfont[9pt] + \setupindenting[yes, 2em] + + \definepalet[layout][grid=middlegray] + \showgrid[nonumber, none, lines] + + \definefontfeature[default][default][expansion=quality,protrusion=quality] + + \usetypescript[modern-base] + \setupbodyfont[reset,modern] + + \setupalign[hz,hanging,tolerant] + + \setuplanguage[en][spacing=packed] + + \starttext + \Lwc/ can remove most widows and orphans from a document, \emph{without} stretching any glue or shortening any pages. + + It does so by automatically lengthening a paragraph on a page where a widow or orphan would otherwise occur. While \TeX{} breaks paragraphs into their natural length, \lwc/ is breaking the paragraph 1~line longer than its natural length. \TeX{}'s paragraph is output to the page, but \lwc/'s paragraph is just stored for later. When a widow or orphan occurs, \lwc/ can take over. It selects the previously-saved paragraph with the least badness; then, it replaces \TeX{}'s paragraph with its saved paragraph. This increases the text block height of the page by 1~line. + + Now, the last line of the current page can be pushed to the top of the next page. This removes the widow or the orphan without creating any additional work. + \stoptext +\stopbuffer +\savebuffer[list=demo-text] + +\startbuffer[shorten] + \parskip=0pt + \input lwc-manual-demo-text.tmp +\stopbuffer + +\startbuffer[shorten-code] + \parskip=0pt + + \clubpenalty=10000 + \widowpenalty=10000 +\stopbuffer + +\startbuffer[stretch] + \parskip=0pt plus 1fill + \input lwc-manual-demo-text.tmp +\stopbuffer + +\startbuffer[stretch-code] + \parskip=0pt plus 1fill + + \clubpenalty=10000 + \widowpenalty=10000 +\stopbuffer + +\startbuffer[ignore] + \startsetups[*default] + \clubpenalty=0 + \widowpenalty=0 + \displaywidowpenalty=0 + \interlinepenalty=0 + \brokenpenalty=0 + \stopsetups + + \setups[*default] + + \input lwc-manual-demo-text.tmp +\stopbuffer + +\startbuffer[ignore-code] + \parskip=0pt + + \clubpenalty=0 + \widowpenalty=0 +\stopbuffer + +\startbuffer[lwc] + \usemodule[lua-widow-control] + \input lwc-manual-demo-text.tmp +\stopbuffer + +\startbuffer[lwc-code] + \usepackage{lua-widow-control} +\stopbuffer + +\startbuffer[widow-orphan] + % TODO This is all really quite hacky + \define[1]\rulewords{\dorecurse{#1}{\blackrule[height=1.5ex, width=1em] \blackrule[height=1.5ex, width=2em] \blackrule[height=1.5ex, width=1.5em] \blackrule[height=1.5ex, width=3em] }} + + \define[2]\fakestart{\framed[width=broad, align=normal, frame=off]{\parfillskip=0pt\spaceskip=0.2em plus 1fill\hskip 5em\rulewords{#1}\blackrule[height=1.5ex, width=#2]}} + + \define[2]\fakeend{\framed[width=broad, align=normal, frame=off]{\parfillskip=5em\spaceskip=0.2em plus 1fill\rulewords{#1}\blackrule[height=1.5ex, width=#2]}} + + \setupTABLE[width=broad, frame=off] + \setupTABLE[row][1][align=middle, style=\ssbf] + \setupTABLE[row][2][align=low, frame=on] + \setupTABLE[row][3][align=high, frame=on] + \setupTABLE[column][2][frame=off, width=1em] + \startTABLE + \NC Widow \NC\NC Orphan \NC\NR + \NC\fakestart{5}{1.5em}\NC\NC\fakestart{1}{2em}\NC\NR + \NC\fakeend{1}{2em}\NC\NC\fakeend{5}{1.5em}\NC\NR + \stopTABLE +\stopbuffer + +\startbuffer[nobreak] + % This is also really hacky and terrible + \parfillskip=0pt + \define\lineone{% + \hbox to 0.3\textwidth{\blackrule[height=1.5ex, width=1em]\hfill% + \blackrule[height=1.5ex, width=3em]\hfill% + \blackrule[height=1.5ex, width=1em]\hfill% + \blackrule[height=1.5ex, width=3em]\hfill% + \blackrule[height=1.5ex, width=1em]}% + } + + \define\linetwo{% + \hbox to 0.3\textwidth{\blackrule[height=1.5ex, width=2em]\hfill% + \blackrule[height=1.5ex, width=1em]\hfill% + \blackrule[height=1.5ex, width=2.5em]\hfill% + \blackrule[height=1.5ex, width=1em]\hfill% + \blackrule[height=1.5ex, width=2.5em]}% + } + + \define\linethree{% + \hbox to 0.3\textwidth{\blackrule[height=1.5ex, width=1em]\hfill% + \blackrule[height=1.5ex, width=3em]\hfill% + \blackrule[height=1.5ex, width=1em]\hfill% + \blackrule[height=1.5ex, width=3em]\hfill% + \hskip1em\relax}% + } + + \define\heading{\bold{Heading}} + + \setupTABLE[ + width=broad, + topframe=off, + bottomframe=off, + leftframe=on, + rightframe=on, + height=1.2\baselineskip + ] + \setupTABLE[row][1][ + align=middle, + style=\ttbf, + bottomframe=on, + leftframe=off, + rightframe=off + ] + \setupTABLE[row][3][bottomframe=on] + \setupTABLE[row][5][bottomframe=on] + \setupTABLE[column][2][bottomframe=off, width=1em] + \setupTABLE[column][4][bottomframe=off, width=1em] + \startTABLE + \NC keep \NC\NC split \NC\NC warn \NC\NR + \NC \NC\NC \NC\NC \heading \NC\NR + \NC \NC\NC \heading \NC\NC \lineone \NC\NR + \NC \heading \NC\NC \lineone \NC\NC \linetwo \NC\NR + \NC \lineone \NC\NC \linetwo \NC\NC \linethree \NC\NR + \stopTABLE +\stopbuffer diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.mkxl b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.mkxl index 7623b51d1ce..e4f49861b9e 100644 --- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.mkxl +++ b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-manual.mkxl @@ -93,7 +93,7 @@ fonts.handlers.otf.addfeature { % Acronym styling \definecharacterkerning[acronymkerning][factor=0.05] -\definealternativestyle[acronymstyle][{\feature[+][allsmall]\switchtobodyfont[1.1em]\setcharacterkerning[acronymkerning]}][] +\definealternativestyle[acronymstyle][{\feature[+][allsmall]\switchtobodyfont[1.2em]\setcharacterkerning[acronymkerning]}][] \definehighlight[acronym][style=acronymstyle] \startsetups[commandtable] 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 7d68de6201a..d2eb12c82ea 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 @@ -37,12 +37,12 @@ \definetype[inlineTEX][option=tex, escape={$,$}, lines=hyphenated] \definetype[inlineLUA][option=lua, escape={$,$}, lines=hyphenated] -\input lwc-sample +\input lwc-manual-samples \startdocument[ title=lua-widow-control, author=Max Chernoff, - version=2.1.1, %%version + version=2.1.2, %%version github=https://github.com/gucci-on-fleek/lua-widow-control, ctan=https://www.ctan.org/pkg/lua-widow-control, ] @@ -621,7 +621,7 @@ 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 \cite[texbook]. +and the two-column output routine from Chapter~23 of \titlecite[texbook]. \subsection{Performance} @@ -648,11 +648,19 @@ commands. Specifically, if you give a line a penalty that matches either 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 wherever reasonable; however, I will rarely make modifications to the algorithm when I can improve the output quality. +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} @@ -681,6 +689,8 @@ ultra-short~lines. \item \Lwc/ only attempts to expand paragraphs; it never attempts to shrink them. See the \emph{TUGboat}~article\cite[article] ยง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 @@ -701,7 +711,7 @@ ultra-short~lines. impossible to solve in a single pass. Very rarely would such a system remove widows or orphans that \lwc/ cannot. - \item If there is a footnote on the last line of the page with a \woo/, \lwc/ will sometimes move the \q{footnote mark} but not the \q{footnote text}, thus breaking up a footnote. \githubissue{26} + \item \Lwc/ does not move footnotes in \mkxl/ due to limitations with the \LuaMetaTeX{} engine. \stopitemize \section{Contributions} @@ -726,6 +736,12 @@ Please note that a compiled document is \bold{not} considered to be an \q{Execut ] \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][ diff --git a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex b/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex deleted file mode 100644 index 6951f7a5bbd..00000000000 --- a/Master/texmf-dist/source/luatex/lua-widow-control/lwc-sample.tex +++ /dev/null @@ -1,178 +0,0 @@ -% 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 - -\startbuffer[demo-text] - \definepapersize[smallpaper][ - width=6cm, - height=8.3cm - ]\setuppapersize[smallpaper] - - \setuplayout[ - topspace=0.1cm, - backspace=0.1cm, - width=middle, - height=middle, - header=0pt, - footer=0pt, - ] - - \def\lwc/{\sans{lua-\allowbreak widow-\allowbreak control}} - \def\Lwc/{\sans{Lua-\allowbreak widow-\allowbreak control}} - - \setupbodyfont[9pt] - \setupindenting[yes, 2em] - - \definepalet[layout][grid=middlegray] - \showgrid[nonumber, none, lines] - - \definefontfeature[default][default][expansion=quality,protrusion=quality] - - \usetypescript[modern-base] - \setupbodyfont[reset,modern] - - \setupalign[hz,hanging,tolerant] - - \setuplanguage[en][spacing=packed] - - \starttext - \Lwc/ can remove most widows and orphans from a document, \emph{without} stretching any glue or shortening any pages. - - It does so by automatically lengthening a paragraph on a page where a widow or orphan would otherwise occur. While \TeX{} breaks paragraphs into their natural length, \lwc/ is breaking the paragraph 1~line longer than its natural length. \TeX{}'s paragraph is output to the page, but \lwc/'s paragraph is just stored for later. When a widow or orphan occurs, \lwc/ can take over. It selects the previously-saved paragraph with the least badness; then, it replaces \TeX{}'s paragraph with its saved paragraph. This increases the text block height of the page by 1~line. - - Now, the last line of the current page can be pushed to the top of the next page. This removes the widow or the orphan without creating any additional work. - \stoptext -\stopbuffer -\savebuffer[list=demo-text] - -\startbuffer[shorten] - \parskip=0pt - \input lwc-manual-demo-text.tmp -\stopbuffer - -\startbuffer[shorten-code] - \parskip=0pt - - \clubpenalty=10000 - \widowpenalty=10000 -\stopbuffer - -\startbuffer[stretch] - \parskip=0pt plus 1fill - \input lwc-manual-demo-text.tmp -\stopbuffer - -\startbuffer[stretch-code] - \parskip=0pt plus 1fill - - \clubpenalty=10000 - \widowpenalty=10000 -\stopbuffer - -\startbuffer[ignore] - \startsetups[*default] - \clubpenalty=0 - \widowpenalty=0 - \displaywidowpenalty=0 - \interlinepenalty=0 - \brokenpenalty=0 - \stopsetups - - \setups[*default] - - \input lwc-manual-demo-text.tmp -\stopbuffer - -\startbuffer[ignore-code] - \parskip=0pt - - \clubpenalty=0 - \widowpenalty=0 -\stopbuffer - -\startbuffer[lwc] - \usemodule[lua-widow-control] - \input lwc-manual-demo-text.tmp -\stopbuffer - -\startbuffer[lwc-code] - \usepackage{lua-widow-control} -\stopbuffer - -\startbuffer[widow-orphan] - % TODO This is all really quite hacky - \define[1]\rulewords{\dorecurse{#1}{\blackrule[height=1.5ex, width=1em] \blackrule[height=1.5ex, width=2em] \blackrule[height=1.5ex, width=1.5em] \blackrule[height=1.5ex, width=3em] }} - - \define[2]\fakestart{\framed[width=broad, align=normal, frame=off]{\parfillskip=0pt\spaceskip=0.2em plus 1fill\hskip 5em\rulewords{#1}\blackrule[height=1.5ex, width=#2]}} - - \define[2]\fakeend{\framed[width=broad, align=normal, frame=off]{\parfillskip=5em\spaceskip=0.2em plus 1fill\rulewords{#1}\blackrule[height=1.5ex, width=#2]}} - - \setupTABLE[width=broad, frame=off] - \setupTABLE[row][1][align=middle, style=\ssbf] - \setupTABLE[row][2][align=low, frame=on] - \setupTABLE[row][3][align=high, frame=on] - \setupTABLE[column][2][frame=off, width=1em] - \startTABLE - \NC Widow \NC\NC Orphan \NC\NR - \NC\fakestart{5}{1.5em}\NC\NC\fakestart{1}{2em}\NC\NR - \NC\fakeend{1}{2em}\NC\NC\fakeend{5}{1.5em}\NC\NR - \stopTABLE -\stopbuffer - -\startbuffer[nobreak] - % This is also really hacky and terrible - \parfillskip=0pt - \define\lineone{% - \hbox to 0.3\textwidth{\blackrule[height=1.5ex, width=1em]\hfill% - \blackrule[height=1.5ex, width=3em]\hfill% - \blackrule[height=1.5ex, width=1em]\hfill% - \blackrule[height=1.5ex, width=3em]\hfill% - \blackrule[height=1.5ex, width=1em]}% - } - - \define\linetwo{% - \hbox to 0.3\textwidth{\blackrule[height=1.5ex, width=2em]\hfill% - \blackrule[height=1.5ex, width=1em]\hfill% - \blackrule[height=1.5ex, width=2.5em]\hfill% - \blackrule[height=1.5ex, width=1em]\hfill% - \blackrule[height=1.5ex, width=2.5em]}% - } - - \define\linethree{% - \hbox to 0.3\textwidth{\blackrule[height=1.5ex, width=1em]\hfill% - \blackrule[height=1.5ex, width=3em]\hfill% - \blackrule[height=1.5ex, width=1em]\hfill% - \blackrule[height=1.5ex, width=3em]\hfill% - \hskip1em\relax}% - } - - \define\heading{\bold{Heading}} - - \setupTABLE[ - width=broad, - topframe=off, - bottomframe=off, - leftframe=on, - rightframe=on, - height=1.2\baselineskip - ] - \setupTABLE[row][1][ - align=middle, - style=\ttbf, - bottomframe=on, - leftframe=off, - rightframe=off - ] - \setupTABLE[row][3][bottomframe=on] - \setupTABLE[row][5][bottomframe=on] - \setupTABLE[column][2][bottomframe=off, width=1em] - \setupTABLE[column][4][bottomframe=off, width=1em] - \startTABLE - \NC keep \NC\NC split \NC\NC warn \NC\NR - \NC \NC\NC \NC\NC \heading \NC\NR - \NC \NC\NC \heading \NC\NC \lineone \NC\NR - \NC \heading \NC\NC \lineone \NC\NC \linetwo \NC\NR - \NC \lineone \NC\NC \linetwo \NC\NC \linethree \NC\NR - \stopTABLE -\stopbuffer -- cgit v1.2.3