% \iffalse meta-comment % % Copyright 2009, 2010 by Élie Roux % Copyright 2010, 2011 by Manuel Pégourié-Gonnard % % This work is under the CC0 license. % % This work consists of the main source file luatexbase-cctb.dtx % and the derived files % luatexbase-cctb.sty cctb.lua % test-cctb-plain.tex test-cctb-latex.tex % % Unpacking: % tex luatexbase-cctb.dtx % Documentation: % pdflatex luatexbase-cctb.dtx % %<*ignore> \begingroup \def\x{LaTeX2e}% \expandafter\endgroup \ifcase 0\ifx\install y1\fi\expandafter \ifx\csname processbatchFile\endcsname\relax\else1\fi \ifx\fmtname\x\else 1\fi\relax \else\csname fi\endcsname % %<*install> \input docstrip.tex \keepsilent \askforoverwritefalse \let\MetaPrefix\relax \preamble See the aforementioned source file(s) for copyright and licensing information. \endpreamble \let\MetaPrefix\DoubleperCent \generate{% \usedir{tex/luatex/luatexbase}% \file{luatexbase-cctb.sty}{\from{luatexbase-cctb.dtx}{texpackage}}% } \generate{% \usedir{doc/luatex/luatexbase}% \file{test-cctb-plain.tex}{\from{luatexbase-cctb.dtx}{testplain}}% \file{test-cctb-latex.tex}{\from{luatexbase-cctb.dtx}{testlatex}}% } \def\MetaPrefix{-- } \def\luapostamble{% \MetaPrefix^^J% \MetaPrefix\space End of File `\outFileName'.% } \def\currentpostamble{\luapostamble}% \generate{% \usedir{tex/luatex/luatexbase}% \file{cctb.lua}{\from{luatexbase-cctb.dtx}{luamodule}}% } \obeyspaces \Msg{************************************************************************} \Msg{*} \Msg{* To finish the installation you have to move the following} \Msg{* files into a directory searched by TeX:} \Msg{*} \Msg{* luatexbase-cctb.sty cctb.lua} \Msg{*} \Msg{* Happy TeXing!} \Msg{*} \Msg{************************************************************************} \endbatchfile % %<*ignore> \fi % %<*driver> \documentclass{ltxdoc} \input{lltxb-dtxstyle} \begin{document} \DocInput{luatexbase-cctb.dtx}% \end{document} % % \fi % % \CheckSum{0} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \pkdate{luatexbase-cctb}{v0.6 2013-05-11} % % \maketitle % % \begin{abstract} % In addition to the registers existing in \tex and \etex, \luatex introduces % a new concept: catcode tables. This package takes care of catcode table % allocation just like Plain TeX and LaTeX do for other registers. It also % provides a few handy macros from common use cases. % \end{abstract} % % \tableofcontents % % \section{Documentation} % % \subsection{Allocation and setting} % % The main macro defined here is |\newluatexcatcodetable|. It behaves the same % as |\newbox|. Additionally, the newly allocated catcode table is initialised % to the catcodes of Ini\tex. In order to help you define the catcode tables % (once they are allocated), two helper macros are available. % % \begin{quote} % \cs{SetCatcodeRange}\marg{from}\marg{to}\marg{value} % \end{quote} % Set all characters code in the range \meta{from}--\meta{to} to the given % catcode \meta{value}. % % \begin{quote} % \cs{setluatexcatcodetable}\marg{table}\marg{catcode statements} % \end{quote} % Set a previously allocated \meta{table} to the catcodes given by executing % \meta{catcode statements}. Note that \meta{table} must not be the current % active catcode table. You may, however, load another catcode table in your % \meta{catcode statements} (if you don't, then the current catcodes will be % used as a basis). % % For your convenience, a few catcode tables are predefined: % \begin{itemize} % \item |\CatcodeTableIniTeX|: Ini\tex catcodes. % \item |\CatcodeTableString|: the catcode regime used by |\string| and % |\meaning|: everything has catcode 12, except space (U+0020) that has % catcode 10. % \item |\CatcodeTableOther|: everything (included space) has catcode 12. % \item |\CatcodeTableLaTeX|: basic \LaTeXe\ catcodes. % \item |\CatcodeTableLaTeXAtLetter|: same as above, but |@| is a letter. % \item |\CatcodeTableExpl|: catcodes used by \latex{}3 with |\ExplSyntaxOn|. % Be aware that this does not provide the exact same environment as % |\ExplSyntaxOn|: most noticibly, some booleans are not set, and % |\endlinechar| is not adjusted (it should be 32). % \end{itemize} % % \subsection{Access from Lua} % % Various Lua functions, such as |tex.print| accept a catcode table number as % argument. In order to use in Lua the catcode tables allocated in \tex, the % package writer needs to know their number. Since |\chardef| is used for the % definition of the control sequence, this is rather easy to do. However, for % extra ease of use, the numbers are also directly accessible from Lua as the % value of the table |luatexbase.catcodetables|, whose keys is the name of the % control sequence (without any leading backslash). For example, after % \begin{quote} % |\newluatexcatcodetable\mycatcodes| % \end{quote} % the variable |luatexbase.catcodetables.mycatcodes| will hold the number of % the catcode table |\mycatcodes|. You will usually want to do % \begin{quote} % |local mycatcodes = luatexbase.catcodetables.mycatcodes| % \end{quote} % at the beginning of your Lua module (assuming it is loaded after the catcode % table has been allocated) and then use |tex.print(mycatcodes, ...)| in the % rest of your Lua code. % % Also, nicknames are available for the predefined catcode tables: % \begin{itemize} % \item |CatcodeTableIniTeX| = |ini|, % \item |CatcodeTableString| = |string|, % \item |CatcodeTableOther| = |other|, % \item |CatcodeTableLaTeX| = |latex|, % \item |CatcodeTableLaTeXAtLetter| = |latex-atletter| = |latex-package|, % \item |CatcodeTableExpl| = |expl| = |expl3|, % \end{itemize} % % \subsection{High-level stack interface} % % In many situations, you want to ensure a proper set of catcodes for some % time, then go back to the previous catcodes without using a group. The % obvious use case is a package, which may be loaded while unexpected % catcodes are active. A pair of macros is provided to deal precisely with % this situation. % \begin{quote} % \cs{BeginCatcodeRegime}\marg{catcode table}\\ % \meta{code}\\ % \cs{EndCatcodeRegime} % \end{quote} % \cs{BeginCatcodeRegime} remembers the current catcode table, then % initializes a new one with a copy of the \meta{catcode table} given (so that % this table is not changed by anything in \meta{code}), and makes it the % active table. \cs{EndCatcodeRegime} restores the previous catcode table. % % For example, a \latex package might do: % \begin{quote} % |\BeginCatcodeRegime\CatcodeTableLaTeXAtLetter|\\ % |% package code|\\ % |\EndCatcodeRegime| % \end{quote} % Every catcode change made in the package code will be lost avec % \cs{EndCatcodeRegime}; if you want them to survive, please use % \cs{AtEndOfPackage} or \cs{AtBeginDocument}. % % By the way, you may add catcode statements in the argument of % \cs{BeginCatcodeRegime} after the name of a catcode table. So the first line % of the previous example is equivalent to % \begin{quote} % |\BeginCatcodeRegime{\CatcodeTableLaTeX \makeatletter}| % \end{quote} % % \subsection{Low-level stack interface} % % The previous macros use internally two stacks : the first on holds the % numbers of the active catcodes tables, so remembering the current table % means pushing its number on the stack, and restoring the previously active % table means popping it off the stack. This is done with: % \begin{quote} % \cs{PushCatcodeTableNumStack}\\ % \cs{PopCatcodeTableNumStack} % \end{quote} % Note that \cs{PushCatcodeTableNumStack} doesn't change current catcodes % but \cs{PopCatcodeTableNumStack} does. % % The second stack consists of temporary tables, mainly used to hold copies of % existing tables. A temporary table are allocated with % \cs{IncCatcodeTableStack}, accessed with \cs{CatcodeTableStack} and the % freed with \cs{DecCatcodeTableStack}, none of which changes the current % table. % % As an illustration, \cs{BeginCatcodeRegime} does % \begin{quote} % |\PushCatcodeTableNumStack|\\ % |\IncCatcodeTableStack|\\ % |\setluatexcatcodetable\CatcodeTableStack{\luatexcatcodetable#1}%|\\ % |\luatexcatcodetable\CatcodeTableStack| % \end{quote} % and \cs{EndCatcodeRegime} is defined as % \begin{quote} % |\DecCatcodeTableStack|\\ % |\PopCatcodeTableNumStack| % \end{quote} % % If you choose to use this low-level interface, it is your responsibility to % ensure proper balancing of push-pop and inc-dec, as well as making sure that % a temporary table is never used after it has been freed. % % \section{Implementation} % % \subsection{\tex package} % % \begin{macrocode} %<*texpackage> % \end{macrocode} % % \subsubsection{Preliminaries} % % Catcode defenses and reload protection. % % \begin{macrocode} \begingroup\catcode61\catcode48\catcode32=10\relax% = and space \catcode123 1 % { \catcode125 2 % } \catcode 35 6 % # \toks0\expandafter{\expandafter\endlinechar\the\endlinechar}% \edef\x{\endlinechar13}% \def\y#1 #2 {% \toks0\expandafter{\the\toks0 \catcode#1 \the\catcode#1}% \edef\x{\x \catcode#1 #2}}% \y 13 5 % carriage return \y 61 12 % = \y 32 10 % space \y 123 1 % { \y 125 2 % } \y 35 6 % # \y 64 11 % @ (letter) \y 10 12 % new line ^^J \y 39 12 % ' \y 40 12 % ( \y 41 12 % ) \y 44 12 % , \y 45 12 % - \y 46 12 % . \y 47 12 % / \y 58 12 % : \y 60 12 % < \y 62 12 % > \y 91 12 % [ \y 93 12 % ] \y 94 7 % ^ \y 95 8 % _ \y 96 12 % ` \toks0\expandafter{\the\toks0 \relax\noexpand\endinput}% \edef\y#1{\noexpand\expandafter\endgroup% \noexpand\ifx#1\relax \edef#1{\the\toks0}\x\relax% \noexpand\else \noexpand\expandafter\noexpand\endinput% \noexpand\fi}% \expandafter\y\csname luatexbase@cctb@sty@endinput\endcsname% % \end{macrocode} % % Package declaration. % % \begin{macrocode} \begingroup \expandafter\ifx\csname ProvidesPackage\endcsname\relax \def\x#1[#2]{\immediate\write16{Package: #1 #2}} \else \let\x\ProvidesPackage \fi \expandafter\endgroup \x{luatexbase-cctb}[2013/05/11 v0.6 Catcodetable allocation for LuaTeX] % \end{macrocode} % % Make sure \luatex is used. % % \begin{macrocode} \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty \else \RequirePackage{ifluatex} \fi \ifluatex\else \begingroup \expandafter\ifx\csname PackageError\endcsname\relax \def\x#1#2#3{\begingroup \newlinechar10 \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup} \else \let\x\PackageError \fi \expandafter\endgroup \x{luatexbase-cctb}{LuaTeX is required for this package. Aborting.}{% This package can only be used with the LuaTeX engine^^J% (command `lualatex' or `luatex').^^J% Package loading has been stopped to prevent additional errors.} \expandafter\luatexbase@cctb@sty@endinput% \fi % \end{macrocode} % % \subsubsection{Load supporting Lua module} % % First load \pk{luatexbase-modutils} (hence \pk{luatexbase-loader} % and \pk{luatexbase-compat}), then the supporting Lua module. % % \begin{macrocode} \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input luatexbase-modutils.sty \else \RequirePackage{luatexbase-modutils} \fi \luatexbase@directlua{require('luatexbase.cctb')} % \end{macrocode} % % \subsubsection{Primitives needed} % % \pk{luatexbase-compat} is already loaded; just make sure the primitives % we need are available. % % \begin{macrocode} \luatexbase@ensure@primitive{luaescapestring} \luatexbase@ensure@primitive{catcodetable} \luatexbase@ensure@primitive{initcatcodetable} \luatexbase@ensure@primitive{savecatcodetable} % \end{macrocode} % % \subsubsection{Allocation and temporary tables} % % Counters for the allocated and temporary tables. % % \begin{macrocode} \newcount\lltxb@catcodetable@alloc \lltxb@catcodetable@alloc\m@ne \newcount\CatcodeTableStack \CatcodeTableStack\z@ % \end{macrocode} % % The allocation macro. Allocate only odd numbers to allow using even % numbers for temporary tables. % % \begin{macrocode} \def\newluatexcatcodetable#1{% \ifnum\lltxb@catcodetable@alloc<65535\relax \global\advance\lltxb@catcodetable@alloc\tw@ \allocationnumber\lltxb@catcodetable@alloc \global\chardef#1\allocationnumber \luatexinitcatcodetable\allocationnumber \begingroup\escapechar\m@ne \luatexbase@directlua{luatexbase.catcodetabledef_from_tex( '\luatexluaescapestring{\string#1}', '\number\allocationnumber')}% \endgroup \wlog{\string#1=\string\luatexcatcodetable\the\allocationnumber}% \else \errmessage{No room for a new \string\luatexcatcodetable}% \fi} % \end{macrocode} % % Allocate a new temporary table, using even numbers. % % \begin{macrocode} \def\IncCatcodeTableStack{% \ifnum\CatcodeTableStack<65534\relax \global\advance\CatcodeTableStack\tw@ \else \errmessage{CatcodeTableStack overflow}% \fi} % \end{macrocode} % % Free a temporary table. % % \begin{macrocode} \def\DecCatcodeTableStack{% \ifnum\CatcodeTableStack>\z@ \global\advance\CatcodeTableStack-2\relax \else \errmessage{CatcodeTableStack underflow}% \fi} % \end{macrocode} % % \subsubsection{Setting catcode tables} % % A small patch to get two new counters in Plain too. % % \begin{macrocode} \expandafter\ifx\csname @tempcnta\endcsname\relax \csname newcount\endcsname\@tempcnta \fi \expandafter\ifx\csname @tempcntb\endcsname\relax \csname newcount\endcsname\@tempcntb \fi % \end{macrocode} % % Set the catcodes for a range of characters. % % \begin{macrocode} \def\SetCatcodeRange#1#2#3{% \edef\luaSCR@temp{% \noexpand\@tempcnta=\the\@tempcnta \noexpand\@tempcntb=\the\@tempcntb \noexpand\count@=\the\count@ \relax}% \@tempcnta=#1\relax \@tempcntb=#2\relax \count@=#3\relax \loop\unless\ifnum\@tempcnta>\@tempcntb \catcode\@tempcnta=\count@ \advance\@tempcnta\@ne \repeat \luaSCR@temp} % \end{macrocode} % % Make \cs{SetCatcodeRange} available with its old name. % % \begin{macrocode} \def\lltxb@synonym#1#2{% \def#1{% \begingroup \ifdefined\PackageWarning \let\x\PackageWarning \else \def\x####1####2{% \begingroup \endlinechar10 \message{Package ####1 warning: ####2}% \endgroup} \fi \expandafter\endgroup \x{luatex}{\string#1 is deprecated^^J% and will be removed in the next version of the package.^^J% Please use \string#2 instead.} \let#1#2% #1}} \lltxb@synonym \setcatcoderange \SetCatcodeRange % \end{macrocode} % % Set a catcode table. % % \begin{macrocode} \def\setluatexcatcodetable#1#2{% \begingroup #2% \luatexsavecatcodetable#1% \endgroup} % \end{macrocode} % % \subsubsection{Predefined tables} % % The |IniTeX| catcode table needs no extra initialisation. % % \begin{macrocode} \newluatexcatcodetable\CatcodeTableIniTeX % \end{macrocode} % % The |String| and |Other| catcode tables. % % \begin{macrocode} \newluatexcatcodetable\CatcodeTableString \setluatexcatcodetable\CatcodeTableString{% \luatexcatcodetable\CatcodeTableIniTeX \catcode0 12 % nul \catcode13 12 % carriage return \catcode37 12 % percent \SetCatcodeRange{65}{90}{12}% A-Z \SetCatcodeRange{97}{122}{12}% a-z \catcode92 12 % backslash \catcode127 12 } % \end{macrocode} % % \begin{macrocode} \newluatexcatcodetable\CatcodeTableOther \setluatexcatcodetable\CatcodeTableOther{% \luatexcatcodetable\CatcodeTableString \catcode32 12 } % \end{macrocode} % % Tables for \LaTeXe. % % \begin{macrocode} \newluatexcatcodetable\CatcodeTableLaTeX \setluatexcatcodetable\CatcodeTableLaTeX{% \luatexcatcodetable\CatcodeTableIniTeX \SetCatcodeRange{0}{31}{15}% \catcode9 10 % tab \catcode10 12 % newline \catcode12 13 % form feed \catcode13 5 % carriage return \catcode35 6 % hash \catcode36 3 % dollar \catcode38 4 % ampersand \catcode94 7 % circumflex \catcode95 8 % underscore \catcode123 1 % brace left \catcode125 2 % brace right \catcode126 13 % tilde \catcode127 15 } % \end{macrocode} % % \begin{macrocode} \newluatexcatcodetable\CatcodeTableLaTeXAtLetter \setluatexcatcodetable\CatcodeTableLaTeXAtLetter{% \luatexcatcodetable\CatcodeTableLaTeX \catcode64=11 } % \end{macrocode} % % A table for \pk{expl3}. % % \begin{macrocode} \newluatexcatcodetable\CatcodeTableExpl \setluatexcatcodetable\CatcodeTableExpl{% \luatexcatcodetable\CatcodeTableLaTeX \catcode126 10 % tilde is a space char \catcode32 9 % space is ignored \catcode9 9 % tab also ignored \catcode95 11 % underscore letter \catcode58 11 % colon letter } % \end{macrocode} % % Now do the shortcuts. % % \begin{macrocode} \luatexbase@directlua{luatexbase.catcodetable_do_shortcuts()} % \end{macrocode} % % \subsubsection{Catcode table number stack and regimes} % % The stack is implemented as a list of (brace-enclosed) \tex arguments. % Initially, in contains only $0$, the number of the active table when % \luatex starts. % % \begin{macrocode} \def\lltxb@cctb@numstack{0} % \end{macrocode} % % Pushing a number on the stack actually means adding it to the beginning % of the list (ie, unshifting it). % % \begin{macrocode} \def\PushCatcodeTableNumStack{% \xdef\lltxb@cctb@numstack{{\the\luatexcatcodetable}\lltxb@cctb@numstack}} % \end{macrocode} % % Popping a number off the stack means shifting it. % % \begin{macrocode} \def\PopCatcodeTableNumStack{% \expandafter\lltxb@cctb@numstack@pop\lltxb@cctb@numstack\@nil} \def\lltxb@cctb@numstack@pop#1#2\@nil{% \ifx\empty#2\empty \begingroup \ifdefined\PackageWarning \let\x\PackageWarning \else \def\x####1####2{% \begingroup \endlinechar10 \message{Package ####1 warning: ####2}% \endgroup}% \fi \expandafter\endgroup \x{luatexbase-cctb}{Popping from an empty CatcodeTableNumStack}% \luatexcatcodetable\z@ \else \gdef\lltxb@cctb@numstack{#2}% \luatexcatcodetable#1\relax \fi} % \end{macrocode} % % Now the catcode regime pseudo-environment as presented in the % documentation. % % \begin{macrocode} \def\BeginCatcodeRegime#1{% \PushCatcodeTableNumStack \IncCatcodeTableStack \setluatexcatcodetable\CatcodeTableStack{\luatexcatcodetable#1}% \luatexcatcodetable\CatcodeTableStack} % \end{macrocode} % % \begin{macrocode} \def\EndCatcodeRegime{% \DecCatcodeTableStack \PopCatcodeTableNumStack} % \end{macrocode} % % That's all, folks! % % \begin{macrocode} \luatexbase@cctb@sty@endinput% % % \end{macrocode} % % \subsection{Lua module} % % \begin{macrocode} %<*luamodule> luatexbase = luatexbase or { } local luatexbase = luatexbase luatexbase.provides_module({ name = "luatexbase-cctb", version = 0.6, date = "2013/05/11", description = "Catcodetable allocation for LuaTeX", author = "Heiko Oberdiek, Elie Roux and Manuel Pegourie-Gonnard", copyright = "Heiko Oberdiek, Elie Roux and Manuel Pegourie-Gonnard", license = "CC0", }) % \end{macrocode} % % The number associated to a CS name is remembered in the |catcodetables| % table. % % \begin{macrocode} luatexbase.catcodetables = luatexbase.catcodetables or { } local catcodetables = luatexbase.catcodetables local function catcodetabledef_from_tex(name, number) catcodetables[name] = tonumber(number) end luatexbase.catcodetabledef_from_tex = catcodetabledef_from_tex % \end{macrocode} % % The next function creates some shortcuts for better readability in lua % code. This makes |luatexbase.catcodetables.latex| equivalent to % |luatexbase.catcodetables.CatcodeTableLaTeX|. % % \begin{macrocode} local function catcodetable_do_shortcuts() local cat = catcodetables cat['latex'] = cat.CatcodeTableLaTeX cat['latex-package'] = cat.CatcodeTableLaTeXAtLetter cat['latex-atletter'] = cat.CatcodeTableLaTeXAtLetter cat['ini'] = cat.CatcodeTableIniTeX cat['expl3'] = cat.CatcodeTableExpl cat['expl'] = cat.CatcodeTableExpl cat['string'] = cat.CatcodeTableString cat['other'] = cat.CatcodeTableOther end luatexbase.catcodetable_do_shortcuts = catcodetable_do_shortcuts % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \section{Test files} % % The tests done are very basic: we just make sure that the package loads % correctly and the macros don't generate any error, under both LaTeX en % Plain TeX. % % \begin{macrocode} %\catcode00 15 %\input luatexbase-cctb.sty %\RequirePackage{luatexbase-cctb} %<*testplain,testlatex> \begingroup \catcode64 11 \global\let\lua\luatexbase@directlua \endgroup % \end{macrocode} % % Also check that the catcodetable's number is remembered well, % independently of the current value of |\escapechar|. % \begin{macrocode} \newluatexcatcodetable\testcctb \lua{assert(luatexbase.catcodetables.testcctb)} \begingroup \escapechar64 \newluatexcatcodetable\anothercctb \endgroup \lua{assert(luatexbase.catcodetables.anothercctb)} % \end{macrocode} % % Now, play a little bit with predefined tables. Be careful to change % catcodes only inside a group to avoid chaos. % % \begin{macrocode} \def\test#1#2#3{% \begingroup \ifcsname CatcodeTable#1\endcsname \else \INTERR \fi \luatexcatcodetable\csname CatcodeTable#1\endcsname \ifnum\catcode#2=#3 \else \ERROR \fi \endgroup} \test {IniTeX} {00} {09} \test {IniTeX} {92} {00} \test {IniTeX} {64} {12} \test {IniTeX} {65} {11} \test {String} {92} {12} \test {String} {65} {12} \test {String} {32} {10} \test {Other} {92} {12} \test {Other} {65} {12} \test {Other} {32} {12} \test {LaTeXAtLetter} {64} {11} \test {LaTeX} {64} {12} \test {Expl} {32} {09} %\documentclass{minimal} \lua{% tex.sprint('\string\\setbox0=\string\\hbox{') tex.sprint(luatexbase.catcodetables.string, "\string\\undef # _^&") tex.sprint('}') } % \end{macrocode} % % \begin{macrocode} % %\bye %\stop % \end{macrocode} % % \Finale \endinput