diff options
Diffstat (limited to 'macros/context/contrib/context-lua-widow-control/tex/lualatex/lua-widow-control/lua-widow-control.sty')
-rw-r--r-- | macros/context/contrib/context-lua-widow-control/tex/lualatex/lua-widow-control/lua-widow-control.sty | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/macros/context/contrib/context-lua-widow-control/tex/lualatex/lua-widow-control/lua-widow-control.sty b/macros/context/contrib/context-lua-widow-control/tex/lualatex/lua-widow-control/lua-widow-control.sty new file mode 100644 index 0000000000..ad3e95a28a --- /dev/null +++ b/macros/context/contrib/context-lua-widow-control/tex/lualatex/lua-widow-control/lua-widow-control.sty @@ -0,0 +1,331 @@ +% 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{v3.0.0}{2022-11-22} %%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/11/22} %%slashdate + {v3.0.0} %%version + {Use Lua to remove widows and orphans} + +% 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 +\cs_generate_variant:Nn \keys_define:nn { Vn } + +\keys_define:Vn { \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 }, + + draftoffset .dim_gset:N = \g__lwc_draftoffset_dim, + draftoffset .value_required:n = true, + draftoffset .initial:x = 1in, + + 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, + + brokenpenalty .int_gset:N = \tex_brokenpenalty:D, + brokenpenalty .value_required:n = true, + brokenpenalty .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, % LaTeX default + \@ssect, % LaTeX starred + \M@sect, % Memoir + \@mem@old@ssect, % Memoir Starred + \ttl@straight@ii, % titlesec normal + \ttl@top@ii, % titlesec top + \ttl@part@ii, % titlesec part + }, + disablecmds .usage:n = preamble, +} + +% Load the Lua code +\cs_if_exist:NTF \lua_load_module:n { + \lua_load_module:n { lua-widow-control } +} { + \lua_now:n { require "lua-widow-control" } +} + +% Here, we enable font expansion/contraction. It isn't strictly necessary for +% \lwc/'s functionality; however, it is required for the +% lengthened paragraphs to not have terrible spacing. +\hook_gput_code:nnn { begindocument / before } { \c__lwc_name_str } { + \bool_if:NT \g__lwc_use_microtype_bool { + \@ifpackageloaded { microtype } {} { + \RequirePackage[ + final, + activate = { true, nocompatibility } + ] + { microtype } + } + } +} + +% Core Function Definitions +\cs_new_eq:NN \iflwc \__lwc_iflwc: + +\prg_new_conditional:Nnn \__lwc_if_enabled: { T, F, TF } { + \__lwc_if_enabled: + \prg_return_true: + \else + \prg_return_false: + \fi +} + +\prg_new_conditional:Nnn \__lwc_if_lmtx: { T, F, TF } { + \int_compare:nNnTF { \tex_luatexversion:D } > { 200 } { + \prg_return_true: + } { + \prg_return_false: + } +} + +% Expansion of some parts of the document, such as section headings, is quite +% undesirable, so we'll disable \lwc/ for certain commands. +\int_new:N \g__lwc_disable_int + +\cs_new:Npn \__lwc_patch_pre: { + % We should only reenable \lwc/ at the end if it was already enabled. + \__lwc_if_enabled:T { + \int_gincr:N \g__lwc_disable_int + \__lwc_disable: + } +} + +\cs_new:Npn \__lwc_patch_post: { + \int_compare:nT { \g__lwc_disable_int > 0 } { + \__lwc_enable: + \int_gdecr:N \g__lwc_disable_int + } +} + +\cs_new:Npn \__lwc_patch_cmd:c #1 { + \IfFormatAtLeastTF { 2021/06/01 } { + \hook_gput_code:nnn { cmd / #1 / before } { \c__lwc_name_str } { + \__lwc_patch_pre: + } + \hook_gput_code:nnn { cmd / #1 / after } { \c__lwc_name_str } { + \__lwc_patch_post: + } + } { + \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 } +} + +\cs_new:Npn \__lwc_patch_cmd:n #1 { + % If the item provided is a single token, we'll assume that it's a \macro. + % If it is multiple tokens, we'll assume that it's a `csname`. + \tl_if_single:nTF { #1 } { + \__lwc_patch_cmd:c { \cs_to_str:N #1 } + } { + \__lwc_patch_cmd:c { #1 } + } +} + +\hook_gput_code:nnn { begindocument / before } { \c__lwc_name_str } { + \clist_map_function:NN \g__lwc_disablecmds_cl \__lwc_patch_cmd:n +} + +\__lwc_if_lmtx:T { + \int_gset:Nn \normalizelinemode { + \numexpression\normalizelinemode bor 2\relax + } +} + +%%% Class and package-specifc patches + +% KOMA-Script +\cs_if_exist:NT \AddtoDoHook { + \AddtoDoHook { heading / begingroup } { \__lwc_patch_pre: \use_none:n } + \AddtoDoHook { heading / endgroup } { \__lwc_patch_post: \use_none:n } +} + +% Memoir +\cs_gset_nopar:Npn \pen@ltyabovepfbreak { 23 } % Issue #32 + +% Define some final keys +\keys_define:Vn { \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 = \__lwc_debug:n { true }, + debug / false .code:n = \__lwc_debug:n { false }, + debug .default:n = true, + debug .value_required:n = false, + + showcolours .choice:, + showcolours / true .code:n = \__lwc_show_colours:n { true }, + showcolours / false .code:n = \__lwc_show_colours:n { false }, + showcolours .default:n = true, + showcolours .value_required:n = false, + + showcosts .choice:, + showcosts / true .code:n = \__lwc_show_costs:n { true }, + showcosts / false .code:n = \__lwc_show_costs:n { false }, + showcosts .default:n = true, + showcosts .value_required:n = false, + + draft .meta:n = { + showcolours = { #1 }, + showcosts = { #1 }, + }, + draft .default:n = true, + draft .value_required:n = false, + + nobreak .code:n = \__lwc_nobreak:n { #1 }, + nobreak .value_required:n = true, + nobreak .initial:n = keep, + + strict .meta:n = { emergencystretch = 0pt, + max-cost = 5000, + nobreak = warn, + widowpenalty = 1, + orphanpenalty = 1, + brokenpenalty = 1, + }, + strict .value_forbidden:n = true, + + default .meta:n = { emergencystretch = 3em, + max-cost = \c_max_int, + nobreak = keep, + widowpenalty = 1, + orphanpenalty = 1, + brokenpenalty = 1, + }, + default .value_forbidden:n = true, + + balanced .meta:n = { emergencystretch = 1em, + max-cost = 10000, + nobreak = keep, + widowpenalty = 500, + orphanpenalty = 500, + brokenpenalty = 500, + }, + balanced .value_forbidden:n = true, +} + +% Add the user interface for the keys +\IfFormatAtLeastTF { 2022-06-01 } { + \ProcessKeyOptions [ \c__lwc_name_str ] +}{ + \RequirePackage { l3keys2e } + \exp_args:NV \ProcessKeysOptions { \c__lwc_name_str } +} + +\cs_generate_variant:Nn \keys_set:nn { Vn } +\NewDocumentCommand \lwcsetup {m} { + \keys_set:Vn { \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 |