diff options
Diffstat (limited to 'macros/luatex/optex/base/more-macros.opm')
-rw-r--r-- | macros/luatex/optex/base/more-macros.opm | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/macros/luatex/optex/base/more-macros.opm b/macros/luatex/optex/base/more-macros.opm new file mode 100644 index 0000000000..a022375360 --- /dev/null +++ b/macros/luatex/optex/base/more-macros.opm @@ -0,0 +1,241 @@ +%% This is part of OpTeX project, see http://petr.olsak.net/optex + +\_codedecl \eoldef {OpTeX useful macos <2020-05-03>} % preloaded in format + + \_doc ----------------------------- + We define \`\opinput` `{<file name>}` macro which + does `\input {<file name>}` but catocodes are set to normal catcodes + (like \OpTeX/ initializes them) and the catodes setting is return back to + the current values when the file is read. You can use `\optinput` + in any situation inside the document and you will be sure that the file + is read correctly with correct catcode settings. + + In order to achieve this, we declare \`\optexcatcodes` catcode table + and \`\plaintexcatocdes`. They save the commonly used catcode tables. + Note that `\catcodetable` is a part of \LuaTeX/ extension. + The catcodetable stack is implemented by \OpTeX/ macros. + The \`\setctable` `<catcode table>` pushes + current catcode table to the stack and activates catcodes from + the `<catcode table>`. The \`\restorectable` returns to the saved catocdes + from the catcode table stack. So, the `\opinput` macro can be implemented simply: + \_cod ----------------------------- + +\_def\_opinput #1{\_setctable\_optexcatcodes \_input {#1}\_relax\_restorectable} + +\_newcatcodetable \_optexcatcodes +\_newcatcodetable \_plaintexcatcodes + +\_public \optexcatcodes \plaintexcatcodes \opinput ; + +\_savecatcodetable\_optexcatcodes +{\_catcode`_=8 \savecatcodetable\plaintexcatcodes} + + \_doc ----------------------------- + The implementation of the catcodetable stack follows. + + The current catodes are + managed in the `\catcodetable0`. If the `\setctable` is used first (or at + the outer level of the stack), then the `\catcodetable0` is pushed to the + stack and the current table is re-set to the given `<catcode table>`. + The numbers of these tables are stacked to the \`\_ctablelist` macro. + The `\restorectable` reads the last saved catcode table number from the + `\_ctablelist` and uses it. + \_cod ----------------------------- + +\_newcount\_currctable \_currctable=0 +\_catcodetable0 + +\_def\_setctable#1{\_edef\_ctablelist{{\_the\_currctable}\_ctablelist}% + \_catcodetable#1\_relax \_currctable=#1\_relax +} +\_def\_restorectable{\_ea\_restorectableA\_ctablelist\_relax} +\_def\_restorectableA#1#2\_relax{% + \_ifx^#2^\_opwarning + {You can't use \_noindent\restorectable without previous \_string\setctable}% + \_else \_def\_ctablelist{#2}\_catcodetable#1\_relax \_currctable=#1\_relax \_fi +} +\_def\_ctablelist{.} + +\_public \setctable \restorectable ; + + \_doc ----------------------------- + When a special macro is defined with different catcodes then + \`\normalcatcodes` can be used at the end of such definition. + The normal catcodes are restored. + The macro reads + catcodes from `\optecatodes` table and sets it to the main catcode table 0. + \_cod ----------------------------- + +\_def\_normalcatcodes {\_catcodetable\_optexcatcodes \_savecatcodetable0 \_catcodetable0 } +\_public \normalcatodes ; + + \_doc ----------------------------- + The \`\load` `[<filename-list>]` loads files specfied in + comma separated `<filename-list>`. The first space (after comma) + is ignored using the trick `#1#2,`: first parameter is unseparated. + The `\load` macro saves the information about loaded files by setting + `\_load:<filename>` as a defined macro. + + If the \`\_afterload` macro is defined then it is run after `\_opinput`. + The catcode setting should be here. Note that catcode setting done in the + loaded file is forgotten after the `\opinput`. + \_cod ----------------------------- + +\_def \_load [#1]{\_loadA #1,,,\_end} +\_def \_loadA #1#2,{\_ifx,#1 \_ea \_loadE \_else \_loadB{#1#2}\_ea\_loadA\_fi} +\_def \_loadB #1{% + \_ifcsname _load:#1\_endcsname \_else + \_isfile {#1.opm}\_iftrue \_opinput {#1.opm}\_else \_opinput {#1}\_fi + \_sxdef{_load:#1}{}% + \_trycs{_afterload}{}\_let\_afterload=\_undefined + \_fi +} +\_def \_loadE #1\_end{} +\_public \load ; + + \_doc ----------------------------- + The declarator \`\optdef``\macro [<opt default>] <params>{<replacement text>}` + defines the `\macro` with the optional parameter followed by normal parameters + declared in `<params>`. The optional parameter must be used as the first + first parameter in brackets `[...]`. If it isn't used then <opt default> + is taken into account. The `<replacement text>` can use `\the\opt` + because optional parameter is saved to the \`\opt` tokens register. + Note the difference from \LaTeX/ concept where the optional parameter is + in `#1`. \OpTeX/ uses `#1` as the first normal parameter (if declared). + + The \`\_nospaceafter` ignores the following optional space at expand + processor level using the negative `\romannumeral` trick. + \_cod ----------------------------- + +\_def\_optdef#1[#2]{% + \_def#1{\_opt={#2}\_isnextchar[{\_cs{_oA:\_string#1}}{\_cs{_oB:\_string#1}}}% + \_sdef{_oA:\_string#1}[##1]{\_opt={##1}\_cs{_oB:\_string#1\_nospaceafter}}% + \_sdef{_oB:\_string#1\_nospaceafter}% +} +\_def\_nospaceafter#1{\_ea#1\_romannumeral-`\.} +\_newtoks\_opt + +\_public \opt \optdef ; + + \_doc ----------------------------- + The declarator \`\eoldef``\macro #1{<replacement text>}` defines a `\macro` + which scans its parameter to the end of the current line. + This is the parameter `#1` which can be used in the `<replacement text>`. + The catcode of the `\endlinechar` is reset temporarily when the parameter is scanned. + + The macro defined by `\eoldef` cannot be used with its parameter inside + other macros because the catcode dancing is not possible here. But the + \`\bracedparam``\macro{<parameter>}` can be used here. The `\bracedparam` + is a prefix which re-sets temporarily the `\macro` to a `\macro` with + normal one parameter. + + The \`\skiptoeol` macro reads the text to the end of the current line + and ignores it. + \_cod ----------------------------- + +\_def\_eoldef #1{\_def #1{\_begingroup \_catcode`\^^M=12 \_eoldefA #1}% + \_ea\_def\_csname _\_csstring #1:M\_endcsname} +\_catcode`\^^M=12 % +\_def\_eoldefA #1#2^^M{\_endgroup\_csname _\_csstring #1:M\_endcsname{#2}}% +\_normalcatcodes % + +\_eoldef\_skiptoeol#1{} +\_def\_bracedparam#1{\_ifcsname _\_csstring #1:M\_endcsname + \_csname _\_csstring #1:M\_ea \_endcsname + \_else \_csname __in\_csstring #1:M\_ea \_endcsname \_fi +} +\_public \eoldef \skiptoeol \bracedparam ; + + \_doc ----------------------------- + The \`\replstring``\macro{<textA>}{<textB>}` + replaces all occurrences of `<textA>` by `<textB>` in the `\macro` body. + The `\macro` must be defined without parameters. The occurrences of + `<textA>` are not replaced if they are \"hidden" in braces, for example + `...{...<textA>...}...`. The category codes in the `<textA>` must exactly + match. + \_cod ----------------------------- + +\_catcode`!=3 \_catcode`?=3 +\_def\_replstring #1#2#3{% \replstring #1{stringA}{stringB} + \_long\_def\_replacestringsA##1#2{\_def #1{##1}\_replacestringsB}% + \_long\_def\_replacestringsB##1#2{\_ifx!##1\_relax \_else \_addto #1{#3##1}% + \_ea\_replacestringsB\_fi}% + \_ea\_replacestringsA #1?#2!#2% + \_long\_def\_replacestringsA##1?{\_def #1{##1}}\_ea\_replacestringsA #1} +\_normalcatcodes + +\_public \replstring ; + + \_doc ----------------------------- + The \`\catcode` primitive is redefined here. Why? + There is very common cases like \code{\\catcode`}`<something>` + or `\catcode"<number>` but these characters + \code{\`} or \code{"} can be set as active (typically by `\activettchar` macro). + Nothing problematic happens if re-defined `\catcode` is used in this case. + + If you really need primitive `\catcode` then you can use `\_catcode`. + \_cod ----------------------------- + +\_def\catcode{\_catcode\_string} % more robust in cases \catcode` or \catcode" + + \_doc ----------------------------- + The \`\removespaces` `<text with spaces >{}` expands to <textwithoutspaces>. + \nl + The `\_ea`\`\ignorept``\the<dimen>` expands to a decimal + number `\the<dimen>` but without `pt` unit. + \nl + The \`\ignoreit``<token>` just ignores the `<token>`. + \_cod ----------------------------- + +\_def\_removespaces #1 {\_isempty{#1}\_iffalse #1\_ea\_removespaces\_fi} +\_ea\_def \_ea\_ignorept \_ea#\_ea1\_detokenize{pt}{#1} +\_def\_ignoreit#1{} + +\public \removespaces \ignorept \ignoreit ; + + \_doc ----------------------------- + You can use expandable \`\bp``{<dimen>}` convertor from + \TeX/ `<dimen>` (or from an expression accepted by + `\dimexpr` primitive) to a decimal value in big points + (used as natural unit in the PDF format). So, you can write, for example: + \begtt + \pdfliteral{q \_bp{.3\hsize-2mm} \_bp{2mm} m 0 \_bp{-4mm} l S Q} + \endtt + You can use expandable \`\expr``{<expression>}` for analogical purposes. + It expands to the value of the `<expression>` at expand processor level + with \`\_decdigits` digits after decimal point. + The `<expression>` can include `+-*/()` and decimal numbers in common syntax. + + The usage of prefixed versions \`\_expr` or \`\_bp` is more recommended + because user can re-define the control sequences `\expr` or `\bp`. + \_cod ----------------------------- + +\_def\_decdigits{3} % digits after decimal point in \_bp and \_expr outputs. +\_def\_pttopb{% + \_directlua{tex.print(string.format('\_pcent.\_decdigits f', + token.scan_dimen()/65781.76))}% pt to bp conversion +} +\def\_bp#1{\_ea\_pttopb\_dimexpr#1\_relax} +\def\_expr#1{\_directlua{tex.print(string.format('\_pcent.\_decdigits f',#1))}} + +\_public \expr \bp ; + + \_doc ------------------ + The pair {\`\_doc` ... \`\_cod`} is used for documenting macros and to + printing the technical documentation of the \OpTeX/. The syntax is: + {\begtt + \_doc <ignored text> + <documentation> + \_cod <ignored text> + \endtt + } + The `<documentation>` (and `<ignored text>` too) must be `<balanced text>`. + It means that you cannot document only the `{` but you must document the `}` too. + \_cod ------------------ + +\_long\_def\_doc #1\_cod {\_skiptoeol} + +\_endcode % ------------------------------------- + +2020-05-03 \load macro introduced +2020-03-15 released |