summaryrefslogtreecommitdiff
path: root/macros/luatex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex')
-rw-r--r--macros/luatex/generic/lua-widow-control/README.md34
-rw-r--r--macros/luatex/generic/lua-widow-control/lua-widow-control.lua59
-rw-r--r--macros/luatex/generic/lua-widow-control/lua-widow-control.pdfbin272679 -> 304194 bytes
-rw-r--r--macros/luatex/generic/lua-widow-control/lua-widow-control.sty36
-rw-r--r--macros/luatex/generic/lua-widow-control/lua-widow-control.tex34
-rw-r--r--macros/luatex/generic/lua-widow-control/lwc-documentation.bib2
-rw-r--r--macros/luatex/generic/lua-widow-control/lwc-documentation.mkxl66
-rw-r--r--macros/luatex/generic/lua-widow-control/lwc-documentation.tex114
-rw-r--r--macros/luatex/generic/lua-widow-control/lwc-sample.tex2
-rw-r--r--macros/luatex/generic/lua-widow-control/t-lua-widow-control.mkxl27
-rw-r--r--macros/luatex/generic/lutabulartools/README.md2
-rw-r--r--macros/luatex/generic/lutabulartools/lutabulartools.lua3
-rw-r--r--macros/luatex/generic/lutabulartools/lutabulartools.pdfbin0 -> 59544 bytes
-rw-r--r--macros/luatex/generic/lutabulartools/lutabulartools.sty13
-rw-r--r--macros/luatex/generic/lutabulartools/lutabulartools.tex166
-rw-r--r--macros/luatex/generic/penlight/README.md3
-rw-r--r--macros/luatex/generic/penlight/penlight.pdfbin22977 -> 29537 bytes
-rw-r--r--macros/luatex/generic/penlight/penlight.sty19
-rw-r--r--macros/luatex/generic/penlight/penlight.tex41
-rw-r--r--macros/luatex/generic/penlight/penlightextras.lua16
20 files changed, 441 insertions, 196 deletions
diff --git a/macros/luatex/generic/lua-widow-control/README.md b/macros/luatex/generic/lua-widow-control/README.md
index 6f113569b4..abf44e5efc 100644
--- a/macros/luatex/generic/lua-widow-control/README.md
+++ b/macros/luatex/generic/lua-widow-control/README.md
@@ -1,17 +1,45 @@
<!-- lua-widow-control
https://github.com/gucci-on-fleek/lua-widow-control
SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+
- SPDX-FileCopyrightText: 2021 gucci-on-fleek
+ SPDX-FileCopyrightText: 2021 Max Chernoff
-->
lua-widow-control
=================
-Lua-widow-control is a Plain TeX/LaTeX/ConTeXt package that removes widows and orphans without any user intervention. Using the power of LuaTeX, it does so _without_ stretching any glue or shortening any pages. Instead, lua-widow-control automatically lengthens a paragraph on a page where a widow or orphan would otherwise occur.
+Lua-widow-control is a Plain TeX/LaTeX/ConTeXt package that removes widows and orphans without any user intervention. Using the power of LuaTeX, it does so _without_ stretching any glue or shortening any pages or columns. Instead, lua-widow-control automatically lengthens a paragraph on a page or column where a widow or orphan would otherwise occur.
+
+Please see the [**full documentation**](https://github.com/gucci-on-fleek/lua-widow-control/releases/latest/download/lua-widow-control.pdf) for more.
+
+Usage
+-----
+### Installation
+Lua-widow-control is included in TeX&nbsp;Live and MikTeX. Provided that you have an up-to-date installation, you should not need to explicitly install the package.
+
+If you are using ConTeXt or want to manually install the package, you may download it from one of the below links:
+
+|Latest Release|Other Releases|
+|--------------|--------------|
+|[GitHub](https://github.com/gucci-on-fleek/lua-widow-control/releases/latest/)|[GitHub](https://github.com/gucci-on-fleek/lua-widow-control/releases)|
+|[CTAN](https://www.ctan.org/pkg/lua-widow-control)||
+|[ConTeXt Garden](https://modules.contextgarden.net/cgi-bin/module.cgi/action=view/id=127)||
+
+### Usage
+To load the package, add the relevant line to your preamble:
+
+|Macro Package|Code |
+|-------------|--------------------------------|
+|LaTeX |`\usepackage{lua-widow-control}`|
+|ConTeXt |`\usemodule[lua-widow-control]` |
+|Plain TeX |`\input lua-widow-control` |
-Please see the [full documentation](https://github.com/gucci-on-fleek/lua-widow-control/releases/latest/download/lua-widow-control.pdf) for more.
Licence
-------
Lua-widow-control is licensed under the [_Mozilla Public License_, version 2.0](https://www.mozilla.org/en-US/MPL/2.0/) or greater. The documentation is additionally licensed under [CC-BY-SA, version 4.0](https://creativecommons.org/licenses/by-sa/4.0/legalcode) or greater.
+
+Please note that a compiled document is absolutely **not** considered to be an "Executable Form" as defined by the MPL. The use of lua-widow-control in a document does not place **any** obligations on the document's author or distributors. The MPL and CC-BY-SA licenses **only** apply to you if you distribute the lua-widow-control source code or documentation.
+
+---
+_v1.1.0 (2021-11-08)_ <!--%%version %%date-->
diff --git a/macros/luatex/generic/lua-widow-control/lua-widow-control.lua b/macros/luatex/generic/lua-widow-control/lua-widow-control.lua
index a85793d3a9..62f1867b62 100644
--- a/macros/luatex/generic/lua-widow-control/lua-widow-control.lua
+++ b/macros/luatex/generic/lua-widow-control/lua-widow-control.lua
@@ -2,7 +2,7 @@
lua-widow-control
https://github.com/gucci-on-fleek/lua-widow-control
SPDX-License-Identifier: MPL-2.0+
- SPDX-FileCopyrightText: 2021 gucci-on-fleek
+ SPDX-FileCopyrightText: 2021 Max Chernoff
]]
lwc = {}
@@ -34,6 +34,7 @@ local glue_id = node.id("glue")
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
local flush_list = node.flush_list or node.flushlist
+local free = node.free
local min_col_width = tex.sp("25em")
local maxdimen = 1073741823 -- \\maxdimen in sp
@@ -63,8 +64,8 @@ if lwc.context then
elseif lwc.plain or lwc.latex then
luatexbase.provides_module {
name = lwc.name,
- date = "2021/10/09", --%%date
- version = "1.0.0", --%%version
+ date = "2021/11/08", --%%date
+ version = "1.1.0", --%%version
description = [[
This module provides a LuaTeX-based solution to prevent
@@ -77,7 +78,11 @@ elseif lwc.plain or lwc.latex then
lwc.attribute = luatexbase.new_attribute(lwc.name)
lwc.contrib_head = 'contrib_head' -- For \LuaTeX{}
else -- uh oh
- error("Unsupported format. Please use (Lua)LaTeX, Plain (Lua)TeX, or ConTeXt (MKXL/LMTX)")
+ error [[
+ Unsupported format.
+
+ Please use (Lua)LaTeX, Plain (Lua)TeX, or ConTeXt (MKXL/LMTX)
+ ]]
end
lwc.paragraphs = {} -- List to hold the alternate paragraph versions
@@ -163,7 +168,7 @@ function lwc.save_paragraphs(head)
local parfillskip = last(new_head)
if parfillskip.id == glue_id and tex.hsize > min_col_width then
parfillskip.stretch_order = 0
- parfillskip.stretch = 0.9 * tex.hsize -- Last line must be at least 10% long
+ parfillskip.stretch = 0.8 * tex.hsize -- Last line must be at least 20% long
end
-- Break the paragraph 1 line longer than natural
@@ -211,6 +216,31 @@ function lwc.mark_paragraphs(head)
end
+--- A "safe" version of the last/slide function.
+---
+--- Sometimes the node list can form a loop. Since there is no last element
+--- of a looped linked-list, the `last()` function will never terminate. This
+--- function provides a "safe" version of the `last()` function that returns
+--- `nil` if the list is circular.
+local function safe_last(head)
+ local ids = {}
+
+ while head.next do
+ local id = node.is_node(head) -- Returns the internal node id
+
+ if ids[id] then
+ lwc.warning("Circular node list detected!")
+ return nil
+ end
+
+ ids[id] = true
+ head = head.next
+ end
+
+ return head
+end
+
+
--- Remove the widows and orphans from the page, just after the output routine.
---
--- This function holds the "meat" of the module. It is called just after the
@@ -264,7 +294,16 @@ function lwc.remove_widows(head)
while head do
-- Insert the start of the replacement paragraph
if has_attribute(head, lwc.attribute, paragraph_index) then
+ local current = head
head.prev.next = target_node
+
+ -- Abort if we've created a loop
+ if not safe_last(target_node) then
+ head.prev.next = current
+ lwc.warning("Widow/Orphan NOT removed!")
+ break
+ end
+
clear_flag = true
end
@@ -286,7 +325,7 @@ function lwc.remove_widows(head)
end
if clear_flag then
- head = node.free(head)
+ head = free(head)
else
head = head.next
end
@@ -359,5 +398,13 @@ function lwc.disable_callbacks()
end
end
+function lwc.if_lwc_enabled()
+ if enabled then
+ tex.sprint("\\iftrue")
+ else
+ tex.sprint("\\iffalse")
+ end
+end
+
return lwc
diff --git a/macros/luatex/generic/lua-widow-control/lua-widow-control.pdf b/macros/luatex/generic/lua-widow-control/lua-widow-control.pdf
index 28acd457c6..f004a1404e 100644
--- a/macros/luatex/generic/lua-widow-control/lua-widow-control.pdf
+++ b/macros/luatex/generic/lua-widow-control/lua-widow-control.pdf
Binary files differ
diff --git a/macros/luatex/generic/lua-widow-control/lua-widow-control.sty b/macros/luatex/generic/lua-widow-control/lua-widow-control.sty
index d5ef8194f1..ff3781944f 100644
--- a/macros/luatex/generic/lua-widow-control/lua-widow-control.sty
+++ b/macros/luatex/generic/lua-widow-control/lua-widow-control.sty
@@ -1,11 +1,11 @@
% lua-widow-control
% https://github.com/gucci-on-fleek/lua-widow-control
% SPDX-License-Identifier: MPL-2.0+
-% SPDX-FileCopyrightText: 2021 gucci-on-fleek
+% SPDX-FileCopyrightText: 2021 Max Chernoff
\NeedsTeXFormat{LaTeX2e}[2015/01/01] % Formats built after 2015 include \LuaTeX{}Base
\ProvidesPackage{lua-widow-control}%
- [2021/10/09 v1.0.0] %%version %%date
+ [2021/11/08 v1.1.0] %%version %%date
\setlength{\clubpenalty}{1}
\setlength{\widowpenalty}{1}
@@ -24,10 +24,42 @@
% lengthened paragraphs to not have terrible spacing.
\RequirePackage[final]{microtype}
+% Define \TeX{} wrappers for Lua functions
\newcommand{\lwcenable}{\directlua{lwc.enable_callbacks()}}
\newcommand{\lwcdisable}{\directlua{lwc.disable_callbacks()}}
+\newcommand{\iflwc}{\directlua{lwc.if_lwc_enabled()}}
% Enable \lwc/ by default when the package is loaded.
\lwcenable
+% Expansion of some parts of the document, such as section headings, is quite
+% undesirable, so we'll disable \lwc/ for certain commands.
+\RequirePackage{etoolbox}
+
+\newcommand{\lwc@patch@warning}[1]{\PackageWarning{lua-widow-control}{%
+ Patching the \protect#1 command failed%
+}}
+
+% We should only reenable \lwc/ at the end if it was already enabled.
+\newif\iflwc@should@reenable
+
+\newcommand{\lwc@patch@pre}{\iflwc%
+ \lwc@should@reenabletrue%
+ \lwcdisable%
+\fi}
+
+\newcommand{\lwc@patch@post}{\iflwc@should@reenable%
+ \lwcenable%
+\fi}
+
+\newcommand{\lwcdisablecmd}[1]{%
+ \ifdefined#1
+ \pretocmd{#1}{\lwc@patch@pre}{}{\lwc@patch@warning{#1}}%
+ \apptocmd{#1}{\lwc@patch@post}{}{\lwc@patch@warning{#1}}%
+ \fi
+}
+
+\lwcdisablecmd{\@sect} % Sectioning
+
+
\endinput
diff --git a/macros/luatex/generic/lua-widow-control/lua-widow-control.tex b/macros/luatex/generic/lua-widow-control/lua-widow-control.tex
index fc10ff0ebb..904ee03c69 100644
--- a/macros/luatex/generic/lua-widow-control/lua-widow-control.tex
+++ b/macros/luatex/generic/lua-widow-control/lua-widow-control.tex
@@ -1,9 +1,9 @@
% lua-widow-control
% https://github.com/gucci-on-fleek/lua-widow-control
% SPDX-License-Identifier: MPL-2.0+
-% SPDX-FileCopyrightText: 2021 gucci-on-fleek
+% SPDX-FileCopyrightText: 2021 Max Chernoff
-\wlog{lua-widow-control v1.0.0} %%version
+\wlog{lua-widow-control v1.1.0} %%version
\input ltluatex % \LuaTeX{}Base
@@ -24,10 +24,40 @@
\expandglyphsinfont\the\font 20 20 5
\adjustspacing=2
+% Define \TeX{} wrappers for Lua functions
\def\lwcenable{\directlua{lwc.enable_callbacks()}}
\def\lwcdisable{\directlua{lwc.disable_callbacks()}}
+\def\iflwc{\directlua{lwc.if_lwc_enabled()}}
% Enable \lwc/ by default when the package is loaded.
\lwcenable
+% Expansion of some parts of the document, such as section headings, is quite
+% undesirable, so we'll disable \lwc/ for certain commands.
+\catcode`@=11
+
+% We should only reenable \lwc/ at the end if it was already enabled.
+\newif\iflwc@should@reenable
+
+\def\lwc@patch@pre{\iflwc%
+ \lwc@should@reenabletrue%
+ \lwcdisable%
+\fi}
+
+\def\lwc@patch@post{\iflwc@should@reenable%
+ \lwcenable%
+\fi}
+
+\def\lwcdisablecmd#1{%
+ \ifdefined#1
+ \expandafter\def\expandafter#1\expandafter{\lwc@patch@pre #1\lwc@patch@post}
+ \fi
+}
+\catcode`@=12
+
+\begingroup
+ \suppressoutererror=1
+ \lwcdisablecmd{\beginsection} % Sectioning
+\endgroup
+
\endinput
diff --git a/macros/luatex/generic/lua-widow-control/lwc-documentation.bib b/macros/luatex/generic/lua-widow-control/lwc-documentation.bib
index 4778435f1e..009c0e5cfa 100644
--- a/macros/luatex/generic/lua-widow-control/lwc-documentation.bib
+++ b/macros/luatex/generic/lua-widow-control/lwc-documentation.bib
@@ -1,7 +1,7 @@
% lua-widow-control
% https://github.com/gucci-on-fleek/lua-widow-control
% SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+
-% SPDX-FileCopyrightText: 2021 gucci-on-fleek
+% SPDX-FileCopyrightText: 2021 Max Chernoff
@book{texbook,
author = {Donald E. Knuth},
diff --git a/macros/luatex/generic/lua-widow-control/lwc-documentation.mkxl b/macros/luatex/generic/lua-widow-control/lwc-documentation.mkxl
index f8208bcc4c..a4d153de5b 100644
--- a/macros/luatex/generic/lua-widow-control/lwc-documentation.mkxl
+++ b/macros/luatex/generic/lua-widow-control/lwc-documentation.mkxl
@@ -1,9 +1,10 @@
% lua-widow-control
% https://github.com/gucci-on-fleek/lua-widow-control
% SPDX-License-Identifier: MPL-2.0+
-% SPDX-FileCopyrightText: 2021 gucci-on-fleek
+% SPDX-FileCopyrightText: 2021 Max Chernoff
\startenvironment[lwc-documentation]
+\unprotect
\mainlanguage[en]
@@ -85,6 +86,8 @@ fonts.handlers.otf.addfeature {
%%%%%%%%%%%%%%%%%%%%%%
\setuppagenumbering[location=footer, style=\ss\lining]
+\let\old@tex=\tex
+\def\tex#1{\expandafter\old@tex\normalexpanded{{#1}}} % Allow expansion in the \tex macro (for \allowbreak)
% Acronym styling
\definecharacterkerning[acronymkerning][factor=0.05]
@@ -103,7 +106,7 @@ setbounds currentpicture to boundingbox OverlayBox;
\defineoverlay[warning][\useMPgraphic{warning}]
\define[1]\warning{
- \blank[big]
+ \blank[line]
\midaligned{\framed[
frame=off,
background=warning,
@@ -115,11 +118,17 @@ setbounds currentpicture to boundingbox OverlayBox;
#1
}}
- \blank[big]
+ \blank[line]
}
-\setupitemize[each][packed][style=\lining]
-\setupcaptions[headstyle=\ssbf\lining, style=\ss]
+\setupitemize[each][
+ style=\lining,
+ inbetween={\blank[quarterline]},
+]
+\setupcaptions[
+ headstyle=\ssbf\lining,
+ style=\ss,
+]
\setupdelimitedtext[blockquote][
style=\ss,
@@ -140,13 +149,13 @@ setbounds currentpicture to boundingbox OverlayBox;
\word
\bfb
\feature[+][smallcaps]
- \spaceskip=0.4em
+ \interwordspace=0.4em
\veryraggedcenter
\stopsetups
\setuphead[section][
- before={\setuplwc[state=stop]\blank[big, preference]},
- after={\blank[medium, samepage]\setuplwc[state=start]},
+ before={\blank[big, preference]},
+ after={\blank[medium, samepage]},
textstyle=\setups{style:section},
number=no,
]
@@ -190,8 +199,30 @@ setbounds currentpicture to boundingbox OverlayBox;
title={},
author={},
version={},
+ ctan={},
+ github={},
]
+\startluacode
+local function strip_url(str)
+ local url_table = url.hashed(str)
+ url_table.fragment = nil
+ url_table.scheme = nil
+ url_table.authority = url_table.authority:gsub("^www%.", "")
+ tex.sprint(-2, url.decode(url.construct(url_table)))
+end
+
+interfaces.implement {
+ name = "strip_url",
+ actions = strip_url,
+ arguments = "1 string"
+}
+\stopluacode
+
+\define[1]\strippedurl{%
+ \goto{\tt\hyphenatedurl{\clf_strip_url{#1}}}[url(#1)]
+}
+
\startsetups[titleblock]
\startalignment [middle]
\begingroup
@@ -204,6 +235,8 @@ setbounds currentpicture to boundingbox OverlayBox;
\begingroup
\ssa\lining
+ \documentvariable{author}
+ \blank[medium]
v\,\documentvariable{version}
\par
\endgroup
@@ -212,7 +245,8 @@ setbounds currentpicture to boundingbox OverlayBox;
\blackrule[depth=-0.25\baselineskip, height=\dimexpr0.25\baselineskip + 0.4pt, width=8em]
\par
- \from[projecturl]
+ \strippedurl{\documentvariable{ctan}}
+ \strippedurl{\documentvariable{github}}
\blank[big]
\noindentation
@@ -269,24 +303,16 @@ setbounds currentpicture to boundingbox OverlayBox;
\setupbtxlist[apa][
alternative=a,
before=,
- after=,
+ after={\blank[quarterline]},
style=\lining,
margin=0pt,
width=1.5em,
]
-\unprotect
\starttexdefinition mutable protected btx:apa:url
- \goto{
- \hyphenatedurl{
- \clf_btxflush{\currentbtxdataset}{\currentbtxtag}{url}
+ \strippedurl{\clf_btxflush{\currentbtxdataset}{\currentbtxtag}{url}
}
- }[
- url(
- \clf_btxflush{\currentbtxdataset}{\currentbtxtag}{url}
- )
- ]
\stoptexdefinition
-\protect
+\protect
\stopenvironment
diff --git a/macros/luatex/generic/lua-widow-control/lwc-documentation.tex b/macros/luatex/generic/lua-widow-control/lwc-documentation.tex
index adc8e119aa..40923c3707 100644
--- a/macros/luatex/generic/lua-widow-control/lwc-documentation.tex
+++ b/macros/luatex/generic/lua-widow-control/lwc-documentation.tex
@@ -3,7 +3,7 @@
% lua-widow-control
% https://github.com/gucci-on-fleek/lua-widow-control
% SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+
-% SPDX-FileCopyrightText: 2021 gucci-on-fleek
+% SPDX-FileCopyrightText: 2021 Max Chernoff
% Warning: Compiles slowly
@@ -13,7 +13,8 @@
\usebtxdataset[lwc-documentation.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][][latest release]
+\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}}
@@ -28,42 +29,41 @@
\def\titlecite[#1]{\cite[title][#1]\cite[#1]}
\usemodule[vim]
-\definevimtyping[TEX][syntax=tex, lines=split, escape=comment]
-\definevimtyping[LUA][syntax=lua, lines=split, escape=comment]
+\definevimtyping[TEX][syntax=tex, lines=split, escape=comment, directory=tmp]
+\definevimtyping[LUA][syntax=lua, lines=split, escape=comment, directory=tmp]
\input lwc-sample
\startdocument[
title=lua-widow-control,
- author=gucci-on-fleek,
- version=1.0.0, %%version
+ author=Max Chernoff,
+ version=1.1.0, %%version
+ github=https://github.com/gucci-on-fleek/lua-widow-control,
+ ctan=https://www.ctan.org/pkg/lua-widow-control,
]
-\Lwc/ is a Plain~\TeX/\LaTeX/\ConTeXt{} package that removes \waos/ without any user intervention. Using the power of \LuaTeX{}, it does so \emph{without} stretching any glue or shortening any pages. Instead, \lwc/ automatically lengthens a paragraph on a page where a \woo/ would otherwise occur.
-
-\section{Quick Start}
-Install \lwc/ by unzipping the \from[download] in your \type{TEXMFLOCAL} directory. Rebuild the filename database. Place \inlineTEX{\usepackage{lua-widow-control}} in the preamble of your document.
-
-For a more detailed explanation of the steps involved and a description of some of the finer points involved with using \lwc/, keep reading.
+\Lwc/ is a Plain~\TeX/\LaTeX/\ConTeXt{} package that removes \waos/ without any user intervention. Using the power of \LuaTeX{}, it does so \emph{without} stretching any glue or shortening any pages or columns. Instead, \lwc/ automatically lengthens a paragraph on a page or column where a \woo/ would otherwise occur.
\subject{Contents}
\placecontent[criterium=all]
+\page
-\warning{\Lwc/ works by modifying the internal structure of each page. In \bold{rare} scenarios, this could delete or duplicate paragraphs or lines when a page break is triggered. All known bugs have been fixed, but I would still caution against using \lwc/ in any document where a single missing line would be disastrous. \Lwc/ should be sufficiently stable to use in typical documents.}
+\section{Quick Start}
+Ensure that your \TeX~Live/Mik\TeX{} distribution is up-to-date. Then, \LaTeX{} users just need to place \inlineTEX{\usepackage{lua-widow-control}} in the preamble of your document. For more details, see the \goto{Installation and Usage sections}[sec:install].
\section{Motivation}
\TeX{} provides top-notch typesetting: even 40 years after its first release, no other program produces higher quality mathematical typesetting, and its paragraph-breaking algorithm is still state-of-the-art. However, its page breaking is not quite as sophisticated as its paragraph breaking and thus suffers from some minor issues.
-Unmodified \TeX{} typically has only 2 ways of dealing with \waos/: it can either shorten a page by 1 line, or it can stretch out some 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 behavior works quite well; however, for prose or any other document composed almost entirely of text, there is no vertical whitespace to stretch.
+Unmodified \TeX{} typically has only 2 ways of dealing with \waos/: it can either shorten a page by 1 line, or it can stretch out some 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 behavior works quite well; however, for prose or any other document composed almost entirely of text, there is no vertical whitespace to stretch.
-Since there were no ready-made and fully-automated solutions to remove \waos/ from prosaic documents, I decided to create \lwc/.
+Since there were no ready-made and fully-automated solutions to remove \waos/ from all types of documents, I decided to create \lwc/.
\section{Widows and Orphans}
\subsection{Widows}
-Widows occur when when the majority of a paragraph is on one page, but the last line is on the following page. Widows are undesirable for both aesthetics and readability. Aesthetically, it looks quite odd for a lone line to be at the start of the page. Functionally, the separation of a paragraph and its last line disconnects the two, causing the reader to lose context for the widowed line.
+Widows occur when when the majority of a paragraph is on one page or column, but the last line is on the following page or column. Widows are undesirable for both aesthetics and readability. Aesthetically, it looks quite odd for a lone line to be at the start of the page. Functionally, the separation of a paragraph and its last line disconnects the two, causing the reader to lose context for the widowed line.
\subsection{Orphans}
-Orphans are when the first line of a paragraph occurs on the page before the remainder of they paragraph. They are not nearly 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 do, so they tend to be ignored more often.
+Orphans are when the first line of a paragraph occurs on the page or column before the remainder of they paragraph. They are not nearly 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 do, so they tend to be ignored more often.
\startplacefigure[location={here, top, bottom}, title={A visual comparison of \waos/.}, reference=tab:widow]
\getbuffer[widow-orphan]
@@ -71,26 +71,26 @@ Orphans are when the first line of a paragraph occurs on the page before the rem
\section{\TeX's Pagination}
\subsection{Algorithm}
-It is tricky to understand how \lwc/ works if you aren't familiar with how \TeX{} breaks pages. Chapter~15 of \titlecite[texbook] (\q{How \TeX{} Makes
+It is tricky to understand how \lwc/ works if you aren't familiar with how \TeX{} breaks pages and columns. Chapter~15 of \titlecite[texbook] (\q{How \TeX{} Makes
Lines into Pages}) is the best reference for this; however, it goes into much more detail than most users require. As a supplemental resource, I can also recommend Section~27 of \titlecite[texbytopic], \goto{available online}[url(https://texdoc.org/serve/texbytopic/0#page=227)] for free. Below follows a \emph{very} simplified (and likely error-ridden) 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 vertical spaces.
However, some objects have penalties attached. These penalties make \TeX{} treat the object as if it is longer or shorter for the sake of page breaking. By default, \TeX{} assigns a penalties to the first and last lines of a paragraph (\waos/). This makes \TeX{} treat them as if they are larger or smaller than their actual size such that \TeX{} tends not to break them up.
-One important note: once \TeX{} begins breaking a page, it only breaking a page. That is, it will never go back and modify any content that has previously been added to its \emph{main vertical list}. That is, page breaking is a localized algorithm, without any backtracking.
+One important note: once \TeX{} begins breaking a page, it never goes back and modifies any content on the page. Page breaking is a localized algorithm, without any backtracking.
\subsection{Behavior}
Of course, this algorithm doesn't allow us to intuitively understand how \TeX{} deals with \waos/.
Due to the penalties attached to \waos/, \TeX{} treats them as if they are longer than they actually are. Widows and orphans with small penalties attached---like \LaTeX's default values of 150---are only treated as slightly taller than 1 line, while \waos/ with large penalties---values near 10\,000---are treated as if they are 2 lines tall. Because potential \wao/ lines are broken as if they are taller than they actually are, \TeX{} will tend to group them together on the same pages.
-However, when these lines are moved as a group, \TeX{} will have to make a page with less lines. \about[sec:demo] goes into further detail about how \TeX{} deals with these too-short pages. The main takeaway is that for a page exclusively filled with text, all of \TeX's builtin solutions come with compromises.
+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. The main takeaway is that for a page exclusively filled with text, all of \TeX's builtin solutions come with compromises.
-\section{Previous Work}
+\section{Other Solutions}
There have been a few previous attempts to improve upon \TeX's previously-discussed \wao/-handling abilities; however, none of these have been able to automatically remove \waos/ without stretching any glue or shortening any pages.
-\titlecite[tugboat-strategies] and \titlecite[tugboat-widows] both begin with comprehensive discussions of the methods of preventing \waos/. They both agree that \waos/ are bad and ought to be avoided; however, they each differ in solutions. \italic{Strategies}\cite[tugboat-strategies] proposes an output routine that reduces the length of facing pages by 1 line if necessary to remove \waos/ while \italic{Managing}\cite[tugboat-widows] proposes that the author manually rewrites or adjusts the \tex{looseness} when needed.
+\titlecite[tugboat-strategies] and \titlecite[tugboat-widows] both begin with comprehensive discussions of the methods of preventing \waos/. They both agree that \waos/ are bad and ought to be avoided; however, they each differ in solutions. \italic{Strategies}\cite[tugboat-strategies] proposes an output routine that reduces the length of facing pages by 1~line when necessary to remove \waos/ while \italic{Managing}\cite[tugboat-widows] proposes that the author manually rewrites or adjusts the \tex{looseness} when needed.
\titlecite[widow-assist] contains a file \type{widow-assist.lua} that automatically detects which paragraphs can be safely shortened or lengthened by 1 line. \titlecite[widows-and-orphans] alerts the author to the pages that contain widows or orphans. Combined, these packages make it very simple for the author to quickly remove \waos/ by adjusting the \tex{looseness} values; however, it still requires the author to make manual source changes after each revision.
@@ -149,7 +149,7 @@ This page also has no widows and it has a flushed bottom margin. However, the sp
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 behavior. However, in a page with mostly text, these paragraph gaps can look unsightly.
-In addition, this method is incompatible with typesetting on a grid since all glue stretch is quantized to the height of a line.
+In addition, this method is incompatible with typesetting on a grid since all glue stretch must be quantized to the height of a line.
\subsection{\lwc/}
\Lwc/ has none of these issues: it eliminates the widows in a document while keeping a flushed bottom margin and constant paragraph spacing.
@@ -158,28 +158,42 @@ To do so, \lwc/ lengthened the second paragraph by one line. If you look closely
\Lwc/ automatically finds the \q{best} paragraph to stretch, so the increase in interword spaces should almost always be minimal.
-\section{Installation}
+\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}
-Mik\TeX{} should automatically install the package when you include it in your document.
+Run \type{mpm --install=lua-widow-control} in a terminal, or install using the \q{Mik\TeX{} Maintenance} \acronym{GUI}.
\subsection{Manual}
-Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install the package. Most other users will be better served by using the \lwc/ supplied by \TeX{}Live and Mik\TeX{}; however, all users may manually install the package if desired. The procedure should be fairly similar regardless of your \acronym{OS}, \TeX{} distribution, or format.
+Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install the package. Most other users will be better served by using the \lwc/ supplied by \TeX~Live and Mik\TeX{}; however, all users may manually install the package if desired. The procedure should be fairly similar regardless of your \acronym{OS}, \TeX{} distribution, or format.
\subsection{Steps}
\startitemize[N]
- \item Download \type{lua-widow-control.tds.zip} from the \from[download] on GitHub.
+ \item Download \type{lua-widow-control.tds.zip} from \goto{\acronym{CTAN}}[url(ctan)] or \goto{GitHub}[url(download)].
\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 \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$ 2015/01/01), \sans{microtype} (any version), and \sans{etoolbox} (any version). Any version of \TeX~Live $\ge$ 2016 will meet these requirements.
+
+\subsection{\ConTeXt{}}
+\Lwc/ requires \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}).
+
+
\section{Loading the Package}
\subsection{Plain \TeX}
@@ -194,6 +208,10 @@ Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install
\inlineTEX{\usemodule[lua-widow-control]}
+\section{Columns}
+
+Since \TeX{} implements column breaking and page breaking through the same internal mechanisms, \lwc/ should remove \waos/ between columns just as well as it does with \waos/ between pages. This has been tested with the standard \LaTeX{} class option \type{twocolumn} and the two-column output routine from Chapter~23 of \cite[title][texbook].\cite[texbook] \Lwc/ should presumably work with any other multi-column implementation; however, due to the diversity and complexity of output~routines, this cannot be guaranteed.
+
\section{Advanced Usage}
\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 does provide a few commands.
@@ -204,7 +222,8 @@ Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install
\startTABLE
\NC Enable (default) \NC \inlineTEX{\lwcenable} \NC\NR
\NC Disable \NC \inlineTEX{\lwcdisable} \NC\NR
-\NC \estretch/ \NC \inlineTEX{\lwcemergencystretch = 3em} \NC\NR
+\NC \estretch/ \NC \inlineTEX{\lwcemergencystretch=3em} \NC\NR
+\NC Selectively Disable \NC \inlineTEX{\lwcdisablecmd{\cmd}} \NC\NR
\stopTABLE
\subsection{\LaTeX{}}
@@ -212,6 +231,7 @@ Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install
\NC Enable (default) \NC \inlineTEX{\lwcenable} \NC\NR
\NC Disable \NC \inlineTEX{\lwcdisable} \NC\NR
\NC \estretch/ \NC \inlineTEX{\setlength{\lwcemergencystretch}{3em}} \NC\NR
+\NC Selectively Disable \NC \inlineTEX{\lwcdisablecmd{\cmd}} \NC\NR
\stopTABLE
\subsection{\ConTeXt{}}
@@ -219,6 +239,8 @@ Currently, \ConTeXt{} \acronym{MKXL} (\LuaMetaTeX{}) users must manually install
\NC Enable (default) \NC \inlineTEX{\setuplwc[state = start]} \NC\NR
\NC Disable \NC \inlineTEX{\setuplwc[state = stop]} \NC\NR
\NC \estretch/ \NC \inlineTEX{\setuplwc[emergencystretch = 3em]} \NC\NR
+\NC Selectively Disable \NC \inlineTEX{\prependtoks\lwc@patch@pre \to\everybeforefoo} \NC\NR
+\NC \NC \inlineTEX{\prependtoks\lwc@patch@post\to\everyafterfoo} \NC\NR
\stopTABLE
\subsection{\estretch/}
@@ -227,19 +249,27 @@ You can configure the \estretch/ used when stretching a paragraph. The default v
\Lwc/ will only use 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{} still accumulates badness when \estretch/ is used, so its pretty rare that a paragraph that requires any \estretch/ will actually be used on the page.
-\section{Known Issues}
+\subsection{Selectively Disabling}
+Sometimes, you may want to disable \lwc/ for certain commands where stretching is undesirable. For example, you typically wouldn't want section headings to be stretched.
+
+You could just disable then reenable \lwc/ every time that you use the command; however, \lwc/ provides a convenience macro that will do this automatically for you. Place \inlineTEX{\lwcdisablecmd{\cmd}} in the preamble, and \lwc/ will not expand any arguments of \tex{cmd} in the document.
+
+\Lwc/ automatically patches the default \LaTeX{}, \ConTeXt{}, and Plain~\TeX{} section commands, so you shouldn't need to patch these yourself; however, \lwc/ does \bold{not} patch the non-standard section commands provided by \sans{memoir}, \sans{\acronym{KOMA}-script}, \sans{titlesec}, and others. You'll need to patch these yourself.
+
+Under \ConTeXt{}, you need to use a different method to selectively disable \lwc/. Instead of using \tex{lwcdisablecmd}, you should use one of the preexisting \tex{everyfoo} hooks as shown in the table above since patching commands is rarely advisable in \ConTeXt{}
+\section[sec:issues]{Known Issues}
\startitemize
- \item \Lwc/ will rarely fail to correctly move the last line on an expanded page to the next page in documents with \emph{very} small paper sizes. This tends to only occur with paper narrower than $\approx\unit{8 cm}$ or shorter than $\approx\unit{10 cm}$ and should not affect any typical documents.
+ \item \Lwc/ will not expand the first paragraph of a document.
- \item In multicolumn layouts, \lwc/ will remove \waos/ that occur between pages, but it will not remove \waos/ between columns. To do so would likely require modifying the output routine which would be a very difficult task.
+ \item \Lwc/ will rarely fail to correctly move the last line on an expanded page to the next page in documents with \emph{very} small paper sizes.
\item When a 3-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 better than widows, so this is still an improvement.
- \item Sometimes a \woo/ just cannot be eliminated because no paragraph has enough \q{stretch}. This can \emph{sometimes} be remediated by increasing \lwc/'s \estretch/; however, some pages just don't have enough \q{stretchy} paragraphs. Long paragraphs with short words tend to be \q{stretchier} than short paragraphs with long words since these long paragraphs will have more interword glue. Narrow columns also stretch easier than wide columns since you need to expand a paragraph by less to make a new line.
+ \item Sometimes a \woo/ cannot be eliminated because no paragraph has enough \q{stretch}. This can \emph{sometimes} be remediated by increasing \lwc/'s \estretch/; however, some pages just don't have enough \q{stretchy} paragraphs. Long paragraphs with short words tend to be \q{stretchier} than short paragraphs with long words since these long paragraphs will have more interword glue. Narrow columns also stretch easier than wide columns since you need to expand a paragraph by less to make a new line.
\item When running under \LuaMetaTeX, the log may be filled with lines like \q{\tt luatex warning > tex: left parfill skip is gone}. This is harmless and can be ignored. % I have no idea how to fix this. The LMTX manual has "\parfillleftskip" in the indices, but that's all that I can find about it.
- \item \Lwc/ will not expand the first paragraph of a document. This should never be an issue in any real-world documents.
+ \item \Lwc/ will rarely raise a \q{\tt Circular node list detected!} warning. This occurs when the replacement paragraph node list loops back on itself. Since there is no \q{end} to the paragraph, \lwc/ cannot splice the paragraph into the page. The only reasonable option in this scenario is to stop processing the page, without removing the \woo/.
\stopitemize
\section{The Algorithm}
@@ -248,29 +278,29 @@ You can configure the \estretch/ used when stretching a paragraph. The default v
\subsection{Paragraph Breaking}
First, \lwc/ hooks into the paragraph breaking process.
-Before a paragraph is broken by \TeX{}, \lwc/ grabs the unbroken paragraph. \Lwc/ then breaks the paragraph 1~line longer than its natural length and stores it for later.
-
-\Lwc/ does not interfere with how \TeX{} breaks paragraphs into their natural length.
+Before a paragraph is broken by \TeX{}, \lwc/ grabs the unbroken paragraph. \Lwc/ then breaks the paragraph 1~line longer than its natural length and stores it for later, \emph{without} interfering with how \TeX{} breaks paragraphs into their natural length.
After \TeX{} has broken its paragraph into its natural length, \lwc/ appears once again. Before the broken paragraph is added to the main vertical list, \lwc/ tags the first and last nodes of the paragraph. These tags create a relationship between the previously-saved lengthened paragraph and the start/end of the naturally-typeset paragraph on the page.
\subsection{Page Breaking}
-\Lwc/ intercepts \tex{box255} after the output routine and before it is shipped out.
+\Lwc/ intercepts \tex{box255} immediately before the output routine.
-First, \lwc/ analyzes the \openalty/ of the page. If the page was broken at a \woo/, the \openalty/ will have been set to the respective values of \tex{widow\allowbreak penalty} and \tex{orphan\allowbreak penalty}. If the \openalty/ is not indicative of a \woo/, \lwc/ will abort and return \tex{box255} unmodified.
+First, \lwc/ analyzes the \openalty/ of the page or column. If the page was broken at a \woo/, the \openalty/ will equal either \tex{widow\allowbreak penalty} or \tex{orphan\allowbreak penalty}. If the \openalty/ is not indicative of a \woo/, \lwc/ will stop and return \tex{box255} unmodified.
-At this point, we know that we have a \woo/ on the page, so we know that we need to lengthen the page by 1~line. We can iterate through the list of saved paragraphs to find the lengthened paragraph with the least demerits. Once we've selected a paragraph to replace, we can now traverse through the page to find the original version of this paragraph so that we can splice in the lengthened paragraph.
+At this point, we know that we have a \woo/ on the page, so we must lengthen the page by 1~line. We iterate through the list of saved paragraphs to find the lengthened paragraph with the least demerits. Once we've selected a paragraph to replace, we can now traverse through the page to find the original version of this paragraph that \TeX{} originally typeset. Once we find the original paragraph, we \q{splice} the lengthened paragraph in the place of the original.
-Finally, we pull the last line off of the page and then we place it onto the top of the \emph{recent contributions} list. Now, we can ship out the new, widow-free page.
+Since the page is now 1~line longer than it was before, we pull the last line off of the page to bring it back to its original length. We place the line onto the top of the \emph{recent contributions} list so that it is added to the start of the next page. Now, we can return the new, widow-free page to the output routine.
\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 are willing to help with any improvements, \goto{submit a \acronym{PR}}[url(projecturl)].
+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
diff --git a/macros/luatex/generic/lua-widow-control/lwc-sample.tex b/macros/luatex/generic/lua-widow-control/lwc-sample.tex
index eb844301cd..787b91e8dc 100644
--- a/macros/luatex/generic/lua-widow-control/lwc-sample.tex
+++ b/macros/luatex/generic/lua-widow-control/lwc-sample.tex
@@ -1,7 +1,7 @@
% lua-widow-control
% https://github.com/gucci-on-fleek/lua-widow-control
% SPDX-License-Identifier: MPL-2.0+ OR CC-BY-SA-4.0+
-% SPDX-FileCopyrightText: 2021 gucci-on-fleek
+% SPDX-FileCopyrightText: 2021 Max Chernoff
\startbuffer[demo-text]
\definepapersize[smallpaper][
diff --git a/macros/luatex/generic/lua-widow-control/t-lua-widow-control.mkxl b/macros/luatex/generic/lua-widow-control/t-lua-widow-control.mkxl
index 66eeadec57..62d091aea6 100644
--- a/macros/luatex/generic/lua-widow-control/t-lua-widow-control.mkxl
+++ b/macros/luatex/generic/lua-widow-control/t-lua-widow-control.mkxl
@@ -1,11 +1,11 @@
%D \module
%D [ file=t-lua-widow-control,
-%D version=1.0.0, %%version
+%D version=1.1.0, %%version
%D title=lua-widow-control,
%D subtitle=\ConTeXt module for lua-widow-control,
-%D author=gucci-on-fleek,
-%D date=2021-10-09, %%date
-%D copyright=gucci-on-fleek,
+%D author=Max Chernoff,
+%D date=2021-11-08, %%date
+%D copyright=Max Chernoff,
%D license=MPL-2.0+,
%D url=https://github.com/gucci-on-fleek/lua-widow-control]
\startmodule[lua-widow-control]
@@ -28,6 +28,8 @@
}
\to\everysetuplwc
+\define\iflwc{\ctxlua{lwc.if_lwc_enabled()}}
+
\ctxloadluafile{lua-widow-control}
\setuplwc[emergencystretch=3em, \c!state=\v!start]
@@ -50,5 +52,22 @@
\definefontfeature[default][default][expansion=quality]
\setupalign[hz]
+% Expansion of some parts of the document, such as section headings, is quite
+% undesirable, so we'll disable \lwc/ for certain commands.
+% We should only reenable \lwc/ at the end if it was already enabled.
+\newif\iflwc@should@reenable
+
+\define\lwc@patch@pre{\iflwc%
+ \lwc@should@reenabletrue%
+ \setuplwc[state=stop]%
+\fi}
+
+\define\lwc@patch@post{\iflwc@should@reenable%
+ \setuplwc[state=start]%
+\fi}
+
+\prependtoks\lwc@patch@pre\to\everybeforesectionheadhandle % Sectioning
+\prependtoks\lwc@patch@post\to\everyaftersectionheadhandle
+
\protect
\stopmodule
diff --git a/macros/luatex/generic/lutabulartools/README.md b/macros/luatex/generic/lutabulartools/README.md
index 34da5ee1e5..90b5a86b15 100644
--- a/macros/luatex/generic/lutabulartools/README.md
+++ b/macros/luatex/generic/lutabulartools/README.md
@@ -4,7 +4,7 @@ This LuaLaTeX package offers some useful macros for tabular matter. The `\MC` co
-# License
+# License (MIT)
Copyright (C) 2021 Kale Ewasiuk
diff --git a/macros/luatex/generic/lutabulartools/lutabulartools.lua b/macros/luatex/generic/lutabulartools/lutabulartools.lua
index 40f916e3bc..ca6b1aa0b4 100644
--- a/macros/luatex/generic/lutabulartools/lutabulartools.lua
+++ b/macros/luatex/generic/lutabulartools/lutabulartools.lua
@@ -1,6 +1,5 @@
--% Kale Ewasiuk (kalekje@gmail.com)
---% 2021-10-13
---%
+--% 2021-11-07
--% Copyright (C) 2021 Kale Ewasiuk
--%
--% Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/macros/luatex/generic/lutabulartools/lutabulartools.pdf b/macros/luatex/generic/lutabulartools/lutabulartools.pdf
new file mode 100644
index 0000000000..96488bd83a
--- /dev/null
+++ b/macros/luatex/generic/lutabulartools/lutabulartools.pdf
Binary files differ
diff --git a/macros/luatex/generic/lutabulartools/lutabulartools.sty b/macros/luatex/generic/lutabulartools/lutabulartools.sty
index 450a0d0cbe..b4eda9c3cf 100644
--- a/macros/luatex/generic/lutabulartools/lutabulartools.sty
+++ b/macros/luatex/generic/lutabulartools/lutabulartools.sty
@@ -1,6 +1,5 @@
% Kale Ewasiuk (kalekje@gmail.com)
-% 2021-10-13
-%
+% 2021-11-07
% Copyright (C) 2021 Kale Ewasiuk
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,7 +23,7 @@
% OR OTHER DEALINGS IN THE SOFTWARE.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{lutabulartools}[2021-10-13]
+\ProvidesPackage{lutabulartools}[2021-11-07]
\RequirePackage{booktabs}
\RequirePackage{multirow}
@@ -53,7 +52,7 @@
\aftergroup\aftergroup\aftergroup\midruleXaux
}
\newif\ifmidruleX
-\makeatletter
+
\newcommand*{\midruleXaux}{%
\noalign{%
\stepcounter{midruleX}%
@@ -67,7 +66,7 @@
\ifmidruleX\midruleXrule\fi
}
\newcommand*{\resetmidruleX}{\setcounter{midruleX}{0}} %%% todo maybe put noalign in here
-\makeatother
+
\resetmidruleX
@@ -100,7 +99,7 @@
% http://mirrors.ctan.org/macros/latex/contrib/booktabs/booktabs.dtx
% and modify it for insertion of \arrayrulecolor{lightgray} at the start,
% and \arrayrulecolor{black} at the end
-\makeatletter
+
\def\oldgcmidrule{\arrayrulecolor{lightgray}% Switch colour to lightgray
\noalign{\ifnum0=`}\fi
\@ifnextchar[{\@gcmidrule}{\@gcmidrule[\cmidrulewidth]}}
@@ -129,7 +128,7 @@
\fi\fi
\ifnum0=`{\fi}
\arrayrulecolor{black}}% Switch colour back to black
-\makeatother
+
%%%
diff --git a/macros/luatex/generic/lutabulartools/lutabulartools.tex b/macros/luatex/generic/lutabulartools/lutabulartools.tex
index cc0aa0ea8a..65c7f2f694 100644
--- a/macros/luatex/generic/lutabulartools/lutabulartools.tex
+++ b/macros/luatex/generic/lutabulartools/lutabulartools.tex
@@ -1,6 +1,5 @@
% Kale Ewasiuk (kalekje@gmail.com)
-% 2021-10-13
-%
+% 2021-11-07
% Copyright (C) 2021 Kale Ewasiuk
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,30 +22,51 @@
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
% OR OTHER DEALINGS IN THE SOFTWARE.
-\documentclass{article}
-\usepackage{lutabulartools}
-\usepackage{url}
+
+\documentclass[11pt,parskip=half]{scrartcl}
\setlength{\parindent}{0ex}
-\setlength{\parskip}{0.75em}
-\newcommand{\PARA}[1]{\leavevmode\llap{\texttt{#1}\ \ \ }}
-\newcommand{\CMD}[1]{\texttt{\textbackslash #1}}
-\newcommand{\tMC}{\CMD{MC}}
-\newcommand{\ttt}[1]{``\texttt{#1}''}
-
-\newcommand{\Example}[1]{
- \texttt{\detokenize{#1}}\par
-will produce:\par
-#1
+\newcommand{\llcmd}[1]{\leavevmode\llap{\texttt{\detokenize{#1}\ }}}
+\newcommand{\cmd}[1]{\texttt{\detokenize{#1}}}
+\newcommand{\qcmd}[1]{``\cmd{#1}''}
+\usepackage{url}
+\usepackage{showexpl}
+\lstset{explpreset={justification=\raggedright,pos=r,wide=true}}
+\setlength\ResultBoxRule{0mm}
+\lstset{
+ language=[LaTeX]TeX,
+ basicstyle=\ttfamily\small,
+ commentstyle=\ttfamily\small\color{gray},
+ frame=none,
+ numbers=left,
+ numberstyle=\ttfamily\small\color{gray},
+ prebreak=\raisebox{0ex}[0ex][0ex]{\color{gray}\ensuremath{\hookleftarrow}},
+ extendedchars=true,
+ breaklines=true,
+ tabsize=4,
}
+\addtokomafont{title}{\raggedright}
+\addtokomafont{author}{\raggedright}
+\addtokomafont{date}{\raggedright}
+\author{Kale Ewasiuk (\url{kalekje@gmail.com})}
+\usepackage[yyyymmdd]{datetime}\renewcommand{\dateseparator}{--}
+\date{\today}
+
+
+
+
+
+\newcommand{\tMC}{\cmd{\\MC}}
+
+\RequirePackage{lutabulartools}
+\title{lutabulartools}
+\subtitle{some useful tabular tools (LuaLaTeX-based)}
\begin{document}
-\vspace*{-4em}
- {\noindent\huge\bfseries lutabulartools \large -- some useful tabular tools\\(LuaLaTeX-based)}\\
- 2021-09-24, Kale Ewasiuk, \url{kalekje@gmail.com}
+\maketitle
lutabulartools is a package that contains a few useful macros to help with tables.
Most functions require LuaLaTeX. The following packages are loaded:
-{\tt
+\texttt{
{booktabs},
{multirow},
{makecell},
@@ -60,67 +80,68 @@ Most functions require LuaLaTeX. The following packages are loaded:
\section{\texttt{\textbackslash MC} -- Magic Cell}
\texttt{\textbackslash MC} (magic cell) combines the facilities of
-\CMD{multirow} and \CMD{multicolumn} from the \texttt{multirow} package, and \CMD{makcell} from the titular package.
+\cmd{\multirow} and \cmd{\multicolumn} from the \texttt{multirow} package, and \cmd{\makcell} from the titular package.
With the help of LuaLaTeX, it takes an easy-to-use cell specification and employs said commands as required.
Here is the usage:
\texttt{\textbackslash MC * [cell spec] <cell format> (override multicolumn col) \{contents\} }
-\PARA{*}This will wrap the entire command in \{\}. This is necessary for \texttt{siunitx} single-column width columns.
+\llcmd{*}This will wrap the entire command in \{\}. This is necessary for \texttt{siunitx} single-column width columns.
However, the \tMC\ command attempts to detect this automatically.
-\PARA{[cell spec]}%
+\llcmd{[cell spec]}%
Any letters placed in this argument are used for cell alignment.
-You can use one of three: \ttt{t}, \ttt{m}, \ttt{b} for top, middle, bottom (vertical alignment),
-or \ttt{l}, \ttt{c}, \ttt{r} for horizontal alignment.
+You can use one of three: \qcmd{t}, \qcmd{m}, \qcmd{b} for top, middle, bottom (vertical alignment),
+or \qcmd{l}, \qcmd{c}, \qcmd{r} for horizontal alignment.
By default, \tMC\ will try to autodetect the horizontal alignment based on the current column.
If it can't, it will be left-aligned.
The default vertical alginment is top.
This argument can also contain two integers, separated by a comma (if two are used).
-\ttt{C,R}, \ttt{C}, or \ttt{,R} are a valid inputs,
+\qcmd{C,R}, \qcmd{C}, or \qcmd{,R} are a valid inputs,
where R=rows (int), and C=columns, (int).
If you want a 1 column wide, multirow cell,
-you can pass \ttt{,R}. These numbers can be negative.
+you can pass \qcmd{,R}. These numbers can be negative.
If no spec is passed, (argument empty), \tMC\
acts like a \texttt{makecell}.
-Additionally, you can pass \ttt{+} in place of C (number of columns wide),
+Additionally, you can pass \qcmd{+} in place of C (number of columns wide),
and it will make the cell width fill until the end of the current row.
Examples:\\
-\ttt{\textbackslash MC[2,2]} means two columns wide, two rows tall.\\
-\ttt{\textbackslash MC[2,1]} or \ttt{\textbackslash MC[2]} or means two columns wide, one row tall.\\
-\ttt{\textbackslash MC[1,2]} or \ttt{\textbackslash MC[,2]} means one column wide, two rows tall.\\
+\qcmd{\MC[2,2]} means two columns wide, two rows tall.\\
+\qcmd{\MC[2,1]} or \qcmd{\MC[2]} or means two columns wide, one row tall.\\
+\qcmd{\MC[1,2]} or \qcmd{\MC[,2]} means one column wide, two rows tall.\\
In any of these examples, you can place the alignment letters anywhere.
-\PARA{(override}%
+\llcmd{(override}%
You may want to adjust the column specification of a multicolumn cell,\\
-\PARA{multicolumn)}for example, using
+\llcmd{multicolumn)}for example, using
\texttt{@\{\}c@\{\}} to remove padding between the cell.
-\PARA{<cell format>}%
-You can place formatting like \CMD{bfseries} here.
+\llcmd{<cell format>}%
+You can place formatting like \cmd{\bfseries} here.
Here's an example.
-\Example{
+\begin{LTXexample}
\begin{tabular}{| c | c | c | c | c | c |}\toprule
- \MC[2,2cm]<\tt>{2,2cm} & \MC[2r]<\tt>{2r} & 5 & \MC[,2b]<\tt>{,2b}\\
+ \MC[2,2cm]<\ttfamily>{2,2cm} & \MC[2r]<\ttfamily>{2r} & 5 & \MC[,2b]<\ttfamily>{,2b}\\
& & 3 & 4 & 5 & \\\midrule
- 1 & 2 & \MC[2l](@{}l)<\tt>{2l (\@\{\}l)} & 5 & 6666\\\cmidrule{3-4}
- 1 & \MC[+r]<\tt>{+r} \\
+ 1 & 2 & \MC[2l](@{}l)<\ttfamily>{2l (\@\{\}l)} & 5 & 6666\\\cmidrule{3-4}
+ 1 & \MC[+r]<\ttfamily>{+r} \\
\\
- 1 & 2 & 3 & 4 & 5 & \MC[,-2]<\tt>{,\\-2}\\
+ 1 & 2 & 3 & 4 & 5 & \MC[,-2]<\ttfamily>{,\\-2}\\
\end{tabular}
-}
+\end{LTXexample}
+
%%% https://tex.stackexchange.com/questions/287346/width-of-column-after-multicolumn-header
%\textbackslash MC[<spec>]{<contents}
\subsection{Notes}
-This package redefines the {\tt tabular} and {\tt tabular*| environments.
+This package redefines the {\ttfamily tabular} and {\ttfamily tabular*} environments.
It uses Lua pattern matching to parse the column specification of the table to know how many columns there are,
and what the current column type is. If you have defined a column that creates many, it will not work.
This will be worked out in later package revisions.
@@ -134,33 +155,34 @@ This will be worked out in later package revisions.
\section{Some additional rules}
This package also redefines the \texttt{booktabs} midrules.\\
-\PARA{\textbackslash gmidrule}is a full gray midrule.\\
+\llcmd{\gmidrule}is a full gray midrule.\\
By taking advantage of knowing how many columns there are (if you chose to redefine \texttt{tabular}),
you can specify individual column numbers (for a one column wide rule),
or reference with respect to the last column (blank, \texttt{+1}, \texttt{+0}, or \texttt{+} means last column,
\texttt{+2} means second last column, for example)
or omit the last number.\\
-\PARA{\textbackslash cmidrule}is a single partial rule, with the above features\\
-\PARA{\textbackslash gcmidrule}is a single partial gray rule, with the above features\\
-You can add multiple \ttt{cmidrule}'s with the \texttt{(g)cmidrules} command. Separate with a comma.
-You can apply global trimming of the rules with the \ttt{()} optional argument, and then
-override it for a specific rule by placing \ttt{r} or \ttt{l} with the span specification.\\
-\PARA{\textbackslash gcmidrules}Can produce multiple, light gray partial rules\\
-\PARA{\textbackslash cmidrules}Can produce multiple black partial rules.\\
+\llcmd{\cmidrule}is a single partial rule, with the above features\\
+\llcmd{\gcmidrule}is a single partial gray rule, with the above features\\
+You can add multiple \qcmd{cmidrule}'s with the \texttt{(g)cmidrules} command. Separate with a comma.
+You can apply global trimming of the rules with the \qcmd{()} optional argument, and then
+override it for a specific rule by placing \qcmd{r} or \qcmd{l} with the span specification.\\
+\llcmd{\gcmidrules}Can produce multiple, light gray partial rules\\
+\llcmd{\cmidrules}Can produce multiple black partial rules.\\
Here's an example:
-\Example{
+\begin{LTXexample}
\begin{tabular}{c c c c c c}\toprule
1 & 2 & 3 & 4 & 5 & 6\\ \cmidrule{+1} % rule on last column
1 & 2 & 3 & 4 & 5 & 6\\ \cmidrules{1,3-+3,+} % rule on first col, third to third last col, and last col
1 & 2 & 3 & 4 & 5 & 6\\ \cmidrules{1,3-+3rl,+} % same as above, but trim middle
1 & 2 & 3 & 4 & 5 & 6\\ \cmidrules(l){1,r3-+3,+1}% trim left for all, but only trim right for middle rule
\end{tabular}
-}
+\end{LTXexample}
+
\subsection{Midrule every X\textsuperscript{th} row}
-\PARA{\textbackslash midruleX}%
+\llcmd{\midruleX}%
With this command, you can place a rule
every X rows.
You can change the step size and what kind of midrule you prefer.
@@ -170,37 +192,18 @@ You can change the step size and what kind of midrule you prefer.
\end{verbatim}
-Usage: Insert midrulex at the end of each row in the column spec. Before you want counting to beg
-\begin{verbatim}
-
-\def\midruleXstep{4}
-\def\midruleXrule{\cmidrules{1,3-4}}
-\begin{tabular}{rclc@{\midruleX}} % inject midrule
-\toprule
-Num & . & . & . \\\midrule\resetmidruleX % reset to 0
-1 & & & \\
-2 & & & \\
-3 & & & \\
-4 & & & \\
-5 & & & \\
-6 & & & \\
-7 & & & \\
-8 & & & \\
-9 & & & \\
-10 & & & \\
-11 & & & \\\resetmidruleX % dont want a bottom rule
-12 & & & \\
-\bottomrule
-\end{tabular}
-\end{verbatim}
-
- will produce
+Usage: Insert midrulex at the end of each row using the column spec.
+Before you want counting to begin, you should
+apply resetmidruleX (also to avoid header rows).
+\begin{LTXexample}
\def\midruleXstep{4}
\def\midruleXrule{\cmidrules{1,3-4}}
-\begin{tabular}{rclc@{\midruleX}} % inject midrule
+\begin{tabular}{rclc@{\midruleX}}
+ % ^^^ inject midrule
\toprule
-Num & . & . & . \\\midrule\resetmidruleX % reset to 0
+Num & . & . & . \\
+\midrule\resetmidruleX % reset
1 & & & \\
2 & & & \\
3 & & & \\
@@ -211,10 +214,11 @@ Num & . & . & . \\\midrule\resetmidruleX % reset to 0
8 & & & \\
9 & & & \\
10 & & & \\
-11 & & & \\\resetmidruleX % dont want a bottom rule
+11 & & & \\
+\resetmidruleX % no bottom rule
12 & & & \\
\bottomrule
\end{tabular}
+\end{LTXexample}
\end{document}
- \ No newline at end of file
diff --git a/macros/luatex/generic/penlight/README.md b/macros/luatex/generic/penlight/README.md
index 55544e7d9f..818fb7d4ea 100644
--- a/macros/luatex/generic/penlight/README.md
+++ b/macros/luatex/generic/penlight/README.md
@@ -1,7 +1,6 @@
# penlight -- Lua libraries for use in LuaLaTeX
-This LuaLaTeX package provides a thin-wrapper to use the [penlight](https://github.com/lunarmodules/Penlight) Lua libraries with LuaLaTeX. It uses the `luapackageloader` package.
-
+This LuaLaTeX package provides a thin-wrapper to use the [penlight](https://github.com/lunarmodules/Penlight) Lua libraries with LuaLaTeX.
# License
diff --git a/macros/luatex/generic/penlight/penlight.pdf b/macros/luatex/generic/penlight/penlight.pdf
index 688706ad51..8d07293e47 100644
--- a/macros/luatex/generic/penlight/penlight.pdf
+++ b/macros/luatex/generic/penlight/penlight.pdf
Binary files differ
diff --git a/macros/luatex/generic/penlight/penlight.sty b/macros/luatex/generic/penlight/penlight.sty
index 9b0baed08b..1f1fccc042 100644
--- a/macros/luatex/generic/penlight/penlight.sty
+++ b/macros/luatex/generic/penlight/penlight.sty
@@ -1,6 +1,5 @@
% Kale Ewasiuk (kalekje@gmail.com)
-% 2021-09-20
-%
+% 2021-11-07
% Copyright (C) 2021 Kale Ewasiuk
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,21 +22,21 @@
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
% OR OTHER DEALINGS IN THE SOFTWARE.
-\ProvidesPackage{penlight}[2021-09-20]
+\ProvidesPackage{penlight}[2021-11-07]
-\RequirePackage{luapackageloader}
+\RequirePackage{luacode}
-\DeclareOption{pl}{\directlua{
+\DeclareOption{pl}{\luadirect{
pl = require('penlight')
__PENLIGHT__ = 'pl'
}}
-\DeclareOption{penlight}{\directlua{
+\DeclareOption{penlight}{\luadirect{
penlight = require('penlight')
__PENLIGHT__ = 'penlight'
}}
-\DeclareOption{stringx}{\directlua{_G[__PENLIGHT__].stringx.import()}}
-\DeclareOption{format}{\directlua{_G[__PENLIGHT__].text.format_operator()}}
-\DeclareOption{func}{\directlua{_G[__PENLIGHT__].utils.import(__PENLIGHT__..'.func')}}
-\DeclareOption{extras}{\directlua{require('penlightextras')}}
+\DeclareOption{stringx}{\luadirect{_G[__PENLIGHT__].stringx.import()}}
+\DeclareOption{format}{\luadirect{_G[__PENLIGHT__].text.format_operator()}}
+\DeclareOption{func}{\luadirect{_G[__PENLIGHT__].utils.import(__PENLIGHT__..'.func')}}
+\DeclareOption{extras}{\luadirect{require('penlightextras')}}
\ProcessOptions*\relax
diff --git a/macros/luatex/generic/penlight/penlight.tex b/macros/luatex/generic/penlight/penlight.tex
index 9d3330bc9b..68b8f1bb40 100644
--- a/macros/luatex/generic/penlight/penlight.tex
+++ b/macros/luatex/generic/penlight/penlight.tex
@@ -1,6 +1,5 @@
% Kale Ewasiuk (kalekje@gmail.com)
-% 2021-09-20
-%
+% 2021-11-07
% Copyright (C) 2021 Kale Ewasiuk
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,12 +22,42 @@
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
% OR OTHER DEALINGS IN THE SOFTWARE.
-\documentclass{article}
+
+\documentclass[11pt,parskip=half]{scrartcl}
+\setlength{\parindent}{0ex}
+\newcommand{\llcmd}[1]{\leavevmode\llap{\texttt{\detokenize{#1}\ }}}
+\newcommand{\cmd}[1]{\texttt{\detokenize{#1}}}
+\newcommand{\qcmd}[1]{``\cmd{#1}''}
\usepackage{url}
-\begin{document}
+\usepackage{showexpl}
+\lstset{explpreset={justification=\raggedright,pos=r,wide=true}}
+\setlength\ResultBoxRule{0mm}
+\lstset{
+ language=[LaTeX]TeX,
+ basicstyle=\ttfamily\small,
+ commentstyle=\ttfamily\small\color{gray},
+ frame=none,
+ numbers=left,
+ numberstyle=\ttfamily\small\color{gray},
+ prebreak=\raisebox{0ex}[0ex][0ex]{\color{gray}\ensuremath{\hookleftarrow}},
+ extendedchars=true,
+ breaklines=true,
+ tabsize=4,
+}
+\addtokomafont{title}{\raggedright}
+\addtokomafont{author}{\raggedright}
+\addtokomafont{date}{\raggedright}
+\author{Kale Ewasiuk (\url{kalekje@gmail.com})}
+\usepackage[yyyymmdd]{datetime}\renewcommand{\dateseparator}{--}
+\date{\today}
+
+
+\RequirePackage{penlight}
+\title{penlight}
+\subtitle{Lua libraries for use in LuaLaTeX}
- \section*{Penlight -- Lua libraries for use in LuaLaTeX}
- v. 2021-09-20, Kale Ewasiuk, \url{kalekje@gmail.com}\\\\
+\begin{document}
+\maketitle
The official documentation for the Lua library can be found here:\\
\mbox{\url{https://stevedonovan.github.io/Penlight/api/manual/01-introduction.md.html#}}
diff --git a/macros/luatex/generic/penlight/penlightextras.lua b/macros/luatex/generic/penlight/penlightextras.lua
index f612bd3370..13d0ab5817 100644
--- a/macros/luatex/generic/penlight/penlightextras.lua
+++ b/macros/luatex/generic/penlight/penlightextras.lua
@@ -2,17 +2,22 @@
local pl = _G['penlight'] or _G['pl'] -- penlight for this namespace is pl
local bind = bind or pl.func.bind
+-- some bonus string operations, % text operator, and functional programmng
+pl.stringx.import()
+pl.text.format_operator()
+pl.utils.import('pl.func')
+
function help_wrt(s1, s2) -- helpful printing, makes it easy to debug, s1 is object, s2 is note
local wrt = wrt or texio.write_nl
local wrt = wrt or print
s2 = s2 or ''
- wrt('\nvvvvv '..s2)
+ wrt('\nvvvvv '..s2..'\n')
if type(s1) == 'table' then
wrt(pl.pretty.write(s1))
else
wrt(tostring(s1))
end
- wrt('^^^^^\n')
+ wrt('\n^^^^^\n')
end
@@ -129,7 +134,7 @@ local function like(M1, v)
return pl.array2d.new(r,c,v)
end
-function from_table(t) -- turns a labelled table to a 2d, label-free array
+local function from_table(t) -- turns a labelled table to a 2d, label-free array
t_new = {}
for k, v in pairs(t) do
if type(v) == 'table' then
@@ -145,7 +150,7 @@ function from_table(t) -- turns a labelled table to a 2d, label-free array
return t_new
end
-function toTeX(M, EL) --puts & between columns, can choose to end line with \\ if EL is true (end-line)
+local function toTeX(M, EL) --puts & between columns, can choose to end line with \\ if EL is true (end-line)
EL = EL or false
if EL then EL = '\\\\' else EL = '' end
return pl.array2d.reduce2(_1..EL.._2, _1..'&'.._2, M)..EL
@@ -221,10 +226,9 @@ function mod2(a) -- math modulo 2
end
function hasval(x) -- if something has value
- -- todo check for Lists, other penlight objects
if (x == nil) or (x == false) or (x == 0) or (x == '') then
return false
- elseif type(x) == 'table' then
+ elseif (type(x) ~= 'number') or (type(x) ~= 'string') then
if #x == 0 then
return false
else