r3tex

custom LuaTeX format
git clone git://git.rr3.xyz/r3tex
Log | Files | Refs | README | LICENSE

util.tex (6640B)


      1 % Special constants
      2 \chardef\maxchar=1114111
      3 \newcount\maxcount  \maxcount="7FFFFFFF
      4 \newdimen\maxdimen  \maxdimen=16383.99999pt
      5 \newskip\centering  \centering=0pt plus1000pt minus1000pt
      6 \newbox\voidbox
      7 
      8 % These macros help cope with TeX's bad behaviour regarding \afterassignment
      9 % and \setbox with a literal box (e.g., \hbox{...}).
     10 \newcount\@grouplevel
     11 \def\@checkgrouplevel{\ifnum\currentgrouplevel>\@grouplevel \ea\aftergroup \fi}
     12 \def\@savegrouplevel{\@grouplevel\currentgrouplevel}
     13 
     14 % \defevent defines an "event". Hooks can be attached to events with \addhook,
     15 % and all hooks are run in order when the event is triggered with \event.
     16 % Events can have parameters like macros, and hooks have access to these
     17 % parameters. For example,
     18 %     \defevent#1#2[myevent]
     19 %     \addhook[myevent]{Hello from my 1st hook! (\#1 = #1)}
     20 %     \addhook[myevent]{Hello from my 2nd hook! (\#2 = #2)}
     21 %     \event[myevent]{abc}{xyz}
     22 % produces
     23 %     Hello from my 1st hook! (#1 = abc)Hello from my 2nd hook! (#2 = xyz)
     24 % Events are always defined globally, but hooks can be local (the default) or
     25 % global (prefix \addhook with \global).
     26 \protected\def\defevent#1[#2]{%
     27 	\toksA={#1}% Double hashes
     28 	\xcsdef{event:#2}{\def\nx\@hooks\the\toksA}%
     29 	\ea\gnewtoks\begcs hooks:#2\endcs \cs{hooks:#2}={}%
     30 }
     31 \protected\def\event[#1]{%
     32 	\relax % Events can appear in weird places (e.g., the standard \par event)
     33 	\begcs event:#1\ea\endcs\ea{\the\cs{hooks:#1}}%
     34 	\@hooks
     35 }
     36 \protected\def\addhook[#1]#2{\cs{hooks:#1}\ea{\the\cs{hooks:#1}#2}}
     37 
     38 % \begparser...\endparser defines a "parser". Usage:
     39 %   \begparser\x
     40 %       \stage<param 0>{<body 0>}<assign 0>...
     41 %       \stage<param 1>{<body 1>}<assign 1>...
     42 %       etc...
     43 %       \stage<param n-1>{<body n-1>}<assign n-1>...
     44 %       \stage<param n>{<body n>}...
     45 %   \endparser
     46 %
     47 % This defines a series of macros of form
     48 %   \csdef{x:0}<param 0>{<body 0> \afterassignment\x:1 <assign 0>}
     49 %   \csdef{x:1}<param 1>{<body 1> \afterassignment\x:2 <assign 1>}
     50 %   etc...
     51 %   \csdef{x:n-1}<param n-1>{<body n-1> \afterassignment\x:n <assign n-1>}
     52 %   \csdef{x:n}<param n>{<body n>}
     53 %
     54 % Any of the <assign i>'s may be empty, in which case the corresponding
     55 % \afterassignment is omitted. Also, any of the \stage's may be replaced by a
     56 % \boxstage, in which case an intermediate stage is inserted to deal with the
     57 % behaviour of \afterassignment on box assignments with literal boxes
     58 % (e.g., \hbox{...}).
     59 %
     60 % Note that the text between \begparser\x and \endparser is essentially
     61 % arbitrary, so one can employ tricks such as
     62 %   \toksA={ }
     63 %   \ea\stage\the\toksA{<body>}<assign>...
     64 %
     65 % Parsers are always defined locally.
     66 % TODO: Add version of \begparser that defines each stage globally.
     67 \newcount\@parsern
     68 \newif\if@boxstage
     69 \newtoks\@stageparam
     70 \def\@parsercs{\@parsername:\number\numexpr\@parsern}
     71 \protected\def\begparser#1{%
     72 	\@parsern=0
     73 	\edef\@parsername{\csstring#1}%
     74 	\def\@prevstage##1{}%
     75 }
     76 \protected\def\boxstage{\@boxstagetrue \stage}
     77 \protected\def\stage#1#{\@stageparam={#1}\@stage}
     78 \def\@stage#1#2...{%
     79 	\@prevstage\iftrue % Define the prev stage with linkage to the curr stage.
     80 	\def\@stageasn{#2}%
     81 	\if@boxstage
     82 		\ifx\@stageasn\empty \else
     83 			\ecsdef{\@parsercs!}{%
     84 				\nx\@checkgrouplevel \ea\nx\begcs\@parsercs+1\endcs
     85 			}%
     86 		\fi
     87 	\fi
     88 	\edef\@stagedef{\csdef{\@parsercs}\the\@stageparam}%
     89 	\edef\@stagelinkage{%
     90 		\ifx\@stageasn\empty % Omit \afterassignment?
     91 			\ea\nx\begcs\@parsercs+1\endcs
     92 		\else
     93 			\if@boxstage
     94 				\nx\@savegrouplevel
     95 				\afterassignment\ea\nx\begcs\@parsercs!\endcs
     96 			\else
     97 				\afterassignment\ea\nx\begcs\@parsercs+1\endcs
     98 			\fi
     99 			\unexpanded{#2}%
    100 		\fi
    101 	}%
    102 	\def\@prevstage##1{%
    103 		\edef\@stagebody{{%
    104 			\unexpanded{#1}%
    105 			##1% Include linkage?
    106 				\unexpanded\ea{\@stagelinkage}%
    107 			\fi
    108 		}}%
    109 		\ea\@stagedef\@stagebody
    110 	}%
    111 	\incr\@parsern
    112 	\@boxstagefalse
    113 }
    114 \protected\def\endparser{%
    115 	\ifnum\@parsern=0
    116 		\errmessage{parser misuse: no stages}%
    117 	\fi
    118 	\ifx\@stageasn\empty \else
    119 		\errmessage{parser misuse: last stage must have no assignment}%
    120 	\fi
    121 	\@prevstage\iffalse % Define last stage with no linkage.
    122 	\csletcs\@parsername{\@parsername:0}%
    123 }
    124 
    125 % White space control
    126 \def\^^M{\ } % control <return> = control <space>
    127 \def\^^I{\ } % control <tab> = control <space>
    128 {
    129 	\catcode`\^^M=13 % These lines must end with %.
    130 	% In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
    131 	% since this allows, for example, `\let\par=\cr \obeylines \halign{...'.
    132 	\gdef\obeylines{\catcode`\^^M=13 \let^^M=\par}%
    133 	\glet^^M=\par % See The TeXBook, page 254.
    134 }
    135 \def\obeyspaces{\catcode`\ =13 }
    136 {\obeyspaces\glet =\space} % See The TeXBook, page 254.
    137 \def\obeytabs{\catcode`\^^I=13 }
    138 {\obeytabs\glet^^I=\tab} % See The TeXBook, page 254.
    139 {
    140 \obeytabs % These lines can not have tab indents.
    141 \gdef\@expandtabs{%
    142 \toksA={}%
    143 \loop\ifnum\countA>0 \toksA\ea{\the\toksA\ }\decr\countA\repeat
    144 \obeytabs \edef^^I{\the\toksA}%
    145 }
    146 \gdef\expandtabs{\afterassignment\@expandtabs \countA=}
    147 }
    148 \def\gobblespace{\let\csA= }
    149 \def\@optionalspace{\ifcat\next\space \ea\gobblespace \fi}
    150 \def\optionalspace{\futurelet\next\@optionalspace}
    151 
    152 % Mode control
    153 \def\leavevmode{\relax \ifvmode \unhbox\voidbox \fi}
    154 \def\leavehmode{\relax \ifhmode \par \fi}
    155 \def\modechoice#1#2#3{%
    156 	\relax
    157 	\ifvmode
    158 		\def\next{#1}%
    159 	\else\ifhmode
    160 		\def\next{#2}%
    161 	\else % mmode
    162 		\def\next{#3}%
    163 	\fi\fi
    164 	\next
    165 }
    166 
    167 % Generalized mathpalette---gives number to be used with \ifcase
    168 \def\mathpalette#1#2{\mathchoice{#10{#2}}{#11{#2}}{#12{#2}}{#13{#2}}}
    169 
    170 \protected\def\sty#1{%
    171 	\ifcase\numexpr#1\relax
    172 		\displaystyle
    173 		\or\textstyle
    174 		\or\scriptstyle
    175 		\or\scriptscriptstyle
    176 	\fi
    177 }
    178 
    179 \protected\def\styfont#1{%
    180 	\ifcase\numexpr#1\relax
    181 		\textfont
    182 		\or\textfont
    183 		\or\scriptfont
    184 		\or\scriptscriptfont
    185 	\fi
    186 }
    187 
    188 % Usage: \styfontdimen<sty><fam><number>
    189 \def\styfontdimen#1#2#3{\fontdimen\numexpr#3\relax\styfont{#1}\numexpr#2\relax}
    190 
    191 % \defer defers execution of the given tokens until after the current group
    192 % (like \aftergroup, but with multiple tokens).
    193 \newcount\@defernext \@defernext=0
    194 \protected\def\defer#1{%
    195 	\ifnum\currentgrouplevel>0
    196 		\gcsdef{defer:\the\@defernext}{#1}%
    197 		\ea\aftergroup\begcs defer:\the\@defernext\endcs
    198 		\incr\@defernext
    199 	\fi
    200 }
    201 
    202 % \deferasn defers execution of the given tokens until after the next
    203 % assignment (like \afterassignment, but with multiple tokens). For box
    204 % register assignments, the tokens are placed after the entire assignment,
    205 % unlike with \afterassignment. \deferasn does not use any temporary registers.
    206 \def\@deferasnA{\@checkgrouplevel\@deferasnB}
    207 \protected\def\deferasn#1{%
    208 	\@savegrouplevel
    209 	\def\@deferasnB{#1}%
    210 	\afterassignment\@deferasnA
    211 }
    212 
    213 \endinput