% lua-widow-control % https://github.com/gucci-on-fleek/lua-widow-control % SPDX-License-Identifier: MPL-2.0+ % SPDX-FileCopyrightText: 2022 Max Chernoff % Formats built after 2015 include \LuaTeX{}Base, so this is the absolute % minimum version that we will run under. \NeedsTeXFormat{LaTeX2e}[2015/01/01] % For _really_ old formats \providecommand\DeclareRelease[3]{} \providecommand\DeclareCurrentRelease[2]{} \DeclareRelease{}{0000-00-00}{lua-widow-control-2022-02-22.sty} \DeclareRelease{v1.1.6}{2022-02-22}{lua-widow-control-2022-02-22.sty} \DeclareCurrentRelease{v2.0.0}{2022-03-07} %%version %%dashdate % If this version of LaTeX doesn't support command hooks, then we load % the last v1.1.X version of the package. \providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} \IfFormatAtLeastTF{2020/10/01}{}{\input{lua-widow-control-2022-02-22.sty}} \IfFormatAtLeastTF{2020/10/01}{}{\endinput} \ProvidesExplPackage {lua-widow-control} {2022/03/07} %%slashdate {v2.0.0} %%version {Use Lua to remove widows and orphans} % Unconditional Package Loads \RequirePackage { l3keys2e } % Message and String Constants \str_const:Nn \c__lwc_name_str { lua-widow-control } \msg_new:nnn { \c__lwc_name_str } { no-luatex } { LuaTeX~ is~ REQUIRED! \\ Make~ sure~ to~ compile~ your~ document~ with~ `lualatex'. } \msg_new:nnn { \c__lwc_name_str } { patch-failed } { Patching~ \c_backslash_str #1~ failed. \\ Please~ ensure~ that~ \c_backslash_str #1~ exists. } \msg_new:nnn { \c__lwc_name_str } { old-format-patch } { Patching~ not~ supported~ with~ old~ LaTeX. \\ Please~ use~ a~ LaTeX~ format~ >=~ 2021/06/01. } \msg_new:nnn { \c__lwc_name_str } { old-command } { \c_backslash_str #1~ has~ been~ REMOVED! \\ Please~ use~ \c_backslash_str setuplwc \c_left_brace_str #2 \c_right_brace_str\ instead. } % Don't let the user proceed unless they are using \LuaTeX{}. \sys_if_engine_luatex:F { \msg_critical:nn { \c__lwc_name_str } { no-luatex } } % Define (most of) the keys \keys_define:nn { \c__lwc_name_str } { emergencystretch .dim_gset:N = \g__lwc_emergencystretch_dim, emergencystretch .value_required:n = true, emergencystretch .initial:x = \dim_max:nn { 3em } { 30pt }, max-cost .int_gset:N = \g__lwc_maxcost_int, max-cost .value_required:n = true, max-cost .initial:x = \c_max_int, widowpenalty .code:n = \int_gset:Nn \tex_widowpenalty:D { #1 } \int_gset:Nn \tex_displaywidowpenalty:D { #1 }, widowpenalty .value_required:n = true, widowpenalty .initial:n = 1, orphanpenalty .code:n = \int_gset:Nn \tex_clubpenalty:D { #1 } \int_gset:Nn \@clubpenalty { #1 }, orphanpenalty .value_required:n = true, orphanpenalty .initial:n = 1, microtype .bool_gset:N = \g__lwc_use_microtype_bool, microtype .value_required:n = true, microtype .initial:n = true, microtype .usage:n = preamble, disablecmds .clist_gset:N = \g__lwc_disablecmds_cl, disablecmds .value_required:n = false, disablecmds .initial:n = { \@sect }, disablecmds .usage:n = preamble, nobreak .choice:, nobreak / keep .code:n = \lua_now:n { lwc.nobreak_behaviour = "keep" }, nobreak / split .code:n = \lua_now:n { lwc.nobreak_behaviour = "split" }, nobreak / warn .code:n = \lua_now:n { lwc.nobreak_behaviour = "warn" }, } % Load the Lua code \lua_now:n { require "lua-widow-control" } % Here, we enable font expansion/contraction. It isn't strictly necessary for % \lwc/'s functionality; however, it is required for the % lengthened paragraphs to not have terrible spacing. \bool_if:NT \g__lwc_use_microtype_bool { \hook_gput_code:nnn { begindocument / before } { \c__lwc_name_str } { \@ifpackageloaded { microtype } {} { \RequirePackage[ final, activate = { true, nocompatibility } ] { microtype } } } } % Core Function Definitions \cs_new:Npn \__lwc_enable: { \lua_now:n { lwc.enable_callbacks() } } \cs_new:Npn \__lwc_disable: { \lua_now:n { lwc.disable_callbacks() } } \prg_set_conditional:Nnn \__lwc_if_enabled: { T, F, TF } { \lua_now:n { lwc.if_lwc_enabled() } \prg_return_true: \else \prg_return_false: \fi } % Expansion of some parts of the document, such as section headings, is quite % undesirable, so we'll disable \lwc/ for certain commands. \bool_new:N \g__lwc_should_reenable_bool \cs_new:Npn \__lwc_patch_cmd:c #1 { \IfFormatAtLeastTF {2021/06/01 } { \hook_gput_code:nnn { cmd / #1 / before } { \c__lwc_name_str } { % We should only reenable \lwc/ at the end if it was already enabled. \__lwc_if_enabled:TF { \bool_gset_true:N \g__lwc_should_reenable_bool \__lwc_disable: } { \bool_gset_false:N \g__lwc_should_reenable_bool } } \hook_gput_code:nnn { cmd / #1 / after } { \c__lwc_name_str } { \bool_if:NT { \g__lwc_should_reenable_bool } { \__lwc_enable: } } } { \msg_warning:nn { \c__lwc_name_str } { old-format-patch } } } \cs_new:Npn \__lwc_patch_cmd:N #1 { \__lwc_patch_cmd:c { \cs_to_str:N #1 } } \hook_gput_code:nnn { begindocument / before } { \c__lwc_name_str } { \clist_map_function:NN \g__lwc_disablecmds_cl \__lwc_patch_cmd:N } % Define some final keys \keys_define:nn { \c__lwc_name_str } { enable .choice:, enable / true .code:n = \__lwc_enable:, enable / false .code:n = \__lwc_disable:, enable .initial:n = true, enable .default:n = true, enable .value_required:n = false, disable .code:n = \__lwc_disable:, disable .value_forbidden:n = true, debug .choice:, debug / true .code:n = \lua_now:n { lwc.debug = true }, debug / false .code:n = \lua_now:n { lwc.debug = false }, strict .meta:n = { emergencystretch = 0pt, max-cost = 2500, nobreak = warn, }, strict .value_forbidden:n = true, default .meta:n = { emergencystretch = 3em, max-cost = \c_max_int, nobreak = keep, }, default .value_forbidden:n = true, } % Add the user interface for the keys \ProcessKeysPackageOptions{ \c__lwc_name_str } \NewDocumentCommand \lwcsetup {m} { \keys_set:nn{\c__lwc_name_str}{#1} } % Legacy Commands \NewDocumentCommand \lwcemergencystretch { } { \msg_error:nnnnn { \c__lwc_name_str } { old-command } { lwcemergencystretch } { emergencystretch=XXXpt } } \NewDocumentCommand \lwcdisablecmd { m } { \msg_error:nnxx { \c__lwc_name_str } { old-command } { lwcdisablecmd } { disablecmds={\c_backslash_str aaa,~ \c_backslash_str bbb} } } \cs_new_eq:NN \lwcenable \__lwc_enable: \cs_new_eq:NN \lwcdisable \__lwc_disable: \endinput