%% %% longmath.sty is part of longmath version 0.1. %% %% (c) 2024 Hans-Jürgen Matschull %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% http://www.latex-project.org/lppl.txt %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status 'maintained'. %% %% The Current Maintainer of this work is Hans-Jürgen Matschull %% %% see README for a list of files belonging to longmath. %% \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{longmath}[2024/03/25] \RequirePackage{luatexbase} % generic attribute used to mark special objects and send mathstyle to Lua. \newattribute\longmath@info % attribute to tag large operators. \newattribute\longmath@limits \def\ignorelimits{\setattribute{\longmath@limits}{1}} \def\includelimits{\unsetattribute{\longmath@limits}} % Save original primitives. \let \longmath@left \left \let \longmath@middle \middle \let \longmath@right \right \directlua{ require( 'longmath.lua' ) } % Registers. \newcount\delimiterscale \delimiterscale 902 \newdimen\longmathlinesep \longmathlinesep 3pt \newif\iflongmath@star \newcount\longmath@lines \newdimen\longmath@extra \newdimen\longmath@width \newcount\longmath@xscale \newcount\longmath@yscale \newbox\longmath@box % The prefix for tags. \def\longmath@prefix{} \def\delimiterprefix#1{\def\longmath@prefix{#1}} % User macros \def\lleft {\longmath@delimA \mathopen {1000}{opn}} \def\rright {\longmath@delimA \mathclose {1000}{cls}} \def\mleft {\longmath@delimA \mathopen {1000}{mid}} \def\mright {\longmath@delimA \mathclose {1000}{mid}} \def\mmord {\longmath@delimA \mathord \delimiterscale {mid}} \def\mmbin {\longmath@delimA \mathbin \delimiterscale {mid}} \def\mmrel {\longmath@delimA \mathrel \delimiterscale {mid}} \def\mmpunct{\longmath@delimA \mathpunct \delimiterscale {mid}} \def\mmiddle{\longmath@delimA \mathinner \delimiterscale {mid}} \def\mmop {\longmath@delimA \mathop \delimiterscale {mid}} % This sets the math atom type, the default scale factor, and the command to be send to Lua, % then checks if a tag in {} is following. \def\longmath@delimA #1#2#3{\begingroup \let\longmath@type #1 \longmath@xscale = #2 \relax \edef\longmath@comm{#3} \futurelet \longmath@token \longmath@delimB } % If a tag is following, read it. Otherwise, skip this step. \def\longmath@delimB{\ifx\longmath@token\bgroup \expandafter \longmath@delimC \else \expandafter \longmath@delimD \fi } % Read the tag, prepend the prefix and append a @, then add it to the command. \def\longmath@delimC #1{\edef\longmath@comm{\longmath@comm:\longmath@prefix#1@} \longmath@delimD } % Read the optional scale factor. If none is given, the scale is set to 0. \def\longmath@delimD #1{\afterassignment\longmath@delimE \longmath@yscale = 0#1} % This creates a \special whatsit with the command as string argument, followed by % a fake delimiter group with the requested delimiter always being the right one. % For the delimiter nodes, the info attribute is set to the current math style. % For the empty \hbox, it is set to the requested scale factor. \def\longmath@delimE{ \setattribute\longmath@info{\mathstyle} \special{\longmath@comm} \longmath@type\bgroup \longmath@left . \aftergroup\egroup \aftergroup\endgroup \begingroup \setattribute\longmath@info{\ifnum \longmath@yscale < 1 \longmath@xscale \else \longmath@yscale \fi} \hbox to -\nulldelimiterspace{} \endgroup \longmath@right } % magic number to identify the variable delimiter. \delcode`* = "FEFEFE %" % scanner to read the delimiter sample and create a nested \left-\right-group. \def\longmath@autoL #1#2\relax{\ifx *#1 \longmath@autoR #2\relax \else \longmath@left #1 \longmath@autoL #2\relax \fi } \def\longmath@autoR #1#2\relax{\ifx *#1 \else \longmath@right #1 \longmath@autoR #2\relax \fi} % Read the sample provided by the user, insert a set command, and typeset it into a box. \def\autodelimiters #1{\begingroup \longmath@info = 0 \setbox\longmath@box\hbox{$ \special{set} \longmath@autoL #1***\relax $} \endgroup\aftergroup\longmath@autoreset} % To make the setting local to the current TeX group, send a reset command at the end of the group. \def\longmath@autoreset{\begingroup \longmath@info = 0 \setbox\longmath@box\hbox{$ \special{res} {} $} \endgroup} % Counter for automatic tag generation. \newcount\longmath@tagnum % Stack to store pushed tags, separated by spaces. \def\longmath@stack{} % Create a unique tag. \def\longmath@unique{ \global\advance\longmath@tagnum\@ne \global\edef\longmath@stack{@\the\longmath@tagnum\space\longmath@stack} } % Create an invisible closing delimiter. \def\pushdelimiter{\longmath@unique \expandafter\longmath@push\longmath@stack\relax} \def\longmath@push #1 #2\relax{\ifmmode\begingroup \def\longmath@comm{mid:#1} \let\longmath@type\mathclose \longmath@yscale=1\relax \longmath@delimE . \fi} % Create an invisible opening delimiter. \def\pulldelimiter{\ifx\longmath@stack\empty \longmath@unique \fi \expandafter\longmath@pull\longmath@stack\relax} \def\longmath@pull #1 #2\relax{\global\edef\longmath@stack{#2}\ifmmode\begingroup \def\longmath@comm{mid:#1} \let\longmath@type\mathopen \longmath@yscale=1\relax \longmath@delimE . \fi} % Read width argument for the longmath environment. % Expects to numbers or dimensions terminted by +. % Numbers are multplied by \hsize. \def\longmath@gobble #1\relax{} \def\longmath@setwidth #1+#2+#3\relax{ \afterassignment\longmath@gobble \longmath@width = #1 \hsize \relax \afterassignment\longmath@gobble \longmath@extra = #2 \hsize \relax } % Alignment for the longmath box. \let\longmath@align@t@\vtop \let\longmath@align@b@\vbox \let\longmath@align@c@\vcenter % Save and restore the current math style. \newcount\longmath@style \def\longmath@getstyle{\longmath@style = \mathstyle \relax} \def\longmath@setstyle{\ifcase\longmath@style \relax \displaystyle \or \crampeddisplaystyle \or \textstyle \or \crampedtextstyle \or \scriptstyle \or \crampedscriptstyle \or \scriptscriptstyle \or \crampedscriptscriptstyle \else \textstyle \fi } % Begin of longmath environment. % Set alignment and width and save the current math style. % Then start a horizontal box in math mode. \def\longmath@begin #1#2{\begingroup \expandafter\let\expandafter\longmath@align\csname longmath@align@#1@\endcsname \ifx \longmath@align\relax \let\longmath@align\longmath@align@c@ \fi \longmath@getstyle \longmath@setwidth #2+0+\relax %\rlap{\textcolor{green}{\rule{\longmath@width}{0.1pt}}\textcolor{yellow}{\rule{\longmath@extra}{0.1pt}}} \setbox\longmath@box\hbox\bgroup $ \mathpenaltiesmode = 1 \longmath@setstyle } % End of longmath environment. % If the width of the box is smaller than the requsted width, just use it as is. % Otherwise, modify the requested width if the * version was used. % Then \unhbox the content into a paragraph with the requested width. % \box0 and \box1 are used to adapt the baselineskip to the math style. % \leftskip and \rightskip are set such that lines are centered but not justified. % The glue is removed from the beginning of the first line with \hskip, % and from the end of the last line with \parfilskip. % If \longmath@extra is non-zero, Lua will stack the lines of the paragraph. \def\longmath@end{$\egroup \ifdim \wd\longmath@box < \dimexpr \longmath@width + \longmath@extra \relax \longmath@extra = \z@ \box\longmath@box \else \iflongmath@star \longmath@lines = \dimexpr ( 1.1\wd\longmath@box + 0.5\longmath@width ) / \longmath@width \relax \longmath@width = \dimexpr ( 1.1\wd\longmath@box / \longmath@lines ) \fi \setbox0\hbox{$1$} \setbox1\hbox{$\longmath@setstyle 1$} \longmath@align{\hsize\longmath@width \baselineskip \dimexpr \baselineskip * \ht1 / \ht0 \relax \lineskip\z@ \lineskiplimit\z@ \openup \longmathlinesep \leftskip 0pt plus 0.6\longmath@width \rightskip 0pt plus 0.6\longmath@width \parfillskip-\rightskip \noindent\hskip-\leftskip \unhbox\longmath@box} \longmath@extra = \z@ \fi \endgroup } \newenvironment{longmath}[2][c] {\longmath@starfalse\longmath@begin{#1}{#2}}{\longmath@end} \newenvironment{longmath*}[2][c] {\longmath@startrue\longmath@begin{#1}{#2}}{\longmath@end} % Read the dimensions of tagged groups from the aux file. \def\longmath@group#1#2{\directlua{longmath.read_group({#1},{#2})}} \def\longmath@skip#1#2{} % Save the dimensions of the tagged groups at the end of the document. \def\longmath@save{\let\longmath@group\longmath@skip\directlua{longmath.save_groups(\the\@auxout)}} \AtEndDocument{\longmath@save}