% language=us runpath=texruns:manuals/luametatex \environment luametatex-style \startdocument[title=\TEX,xtitle=\TEX] \startsection[title={Introduction}] Here we don't explain \TEX\ itself but the interface between \TEX\ and \LUA. We don't need to talk nodes and tokens because they have their own chapters. \stopsection \startsection[title={Status information}] The \type {status} library provides information not only about the current run and system setup but also about all kind of variables and constants used in the engine. A difference between \LUATEX\ and \LUAMETATEX\ is that every quantity that is hard coded is available as a constant to be used. The same is true for various bit sets for instance those use in setting options, as we will see in the \type {tex} library. A number of run|-|time configuration items that you may find useful in message reporting, as well as an iterator function that gets all of the names and values as a table. \starttyping[option=LUA] function status.list ( ) return end \stoptyping The keys in the returned table are the known items, the value is the current value. There are top level items and items that are tables with sub entries. The current list gives: \startluacode local list = status.list() context.starttabulate { "|T|Tp|" } context.FL() context.BC() context("toplevel statistics") context.BC() context.NC() context.NR() context.TL() for k, v in table.sortedhash(list) do if type(v) ~= "table" then context.NC() context(k) context.NC() context(tostring(v)) context.NC() context.NR() end end context.LL() context.stoptabulate() for k, v in table.sortedhash(list) do if type(v) == "table" then context.starttabulate { "|Tw(10em)|Tp|" } context.FL() context.BC() context(k ..".*") context.BC() context.NC() context.NR() context.TL() for k, v in table.sortedhash(v) do context.NC() context(k) context.NC() context(v == "" and "unset" or tostring(v)) context.NC() context.NR() end context.LL() context.stoptabulate() end end \stopluacode The \type {getconstants} query gives back a table with all kind of internal quantities and again these are only relevant for diagnostic and development purposes. Many are good old \TEX\ constants that are describes in the original documentation of the source but some are definitely \LUAMETATEX\ specific. \starttyping[option=LUA] function status.getconstants ( ) return end \stoptyping The returned table contains: \startluacode context.starttabulate { "|T|Tr|" } context.FL() context.BC() context("constants.*") context.BC() context.NC() context.NR() context.TL() for k, v in table.sortedhash(status.getconstants()) do if type(v) ~= "table" then context.NC() context(k) context.NC() context(tostring(v)) context.NC() context.NR() end end context.LL() context.stoptabulate() \stopluacode Most variables speak for themselves, some are more obscure. For instance the \type {runstate} variable indicates what the engine is doing: \getbuffer[engine:syntax:runstates] These overviews can get asked for, for instance with \type {getrunstatevalues} in the \type {tex} library. Most of these constants are stable but especially for those that relate to evolving engine functionality there can be changes, so keep an eye on these mappings! The individual states can be fetched with the following helpers: \starttyping[option=LUA] function status.getbufferstate ( ) return end function status.getcallbackstate ( ) return end function status.geterrorlinestate ( ) return end function status.geterrorstate ( ) return end function status.getexpandstate ( ) return end function status.getextrastate ( ) return end function status.getfilestate ( ) return end function status.getfontstate ( ) return end function status.gethalferrorlinestate ( ) return end function status.gethashstate ( ) return end function status.gethyphenationstate ( ) return end function status.getinputstate ( ) return end function status.getinsertstate ( ) return end function status.getlanguagestate ( ) return end function status.getlinebreakstate ( ) return end function status.getlookupstate ( ) return end function status.getluastate ( ) return end function status.getmarkstate ( ) return end function status.getneststate ( ) return end function status.getnodestate ( ) return end function status.getparameterstate ( ) return end function status.getpoolstate ( ) return end function status.getreadstate ( ) return end function status.getsavestate ( ) return end function status.getsparsestate ( ) return end function status.getstringstate ( ) return end function status.gettexstate ( ) return end function status.gettokenstate ( ) return end function status.getwarningstate ( ) return end \stoptyping The error and warning messages can be wiped with: \starttyping[option=LUA] function status.resetmessages ( ) -- no return values end \stoptyping \stopsection \startsection[title={Everything \TEX}] \startsubsection[title={Introduction}] The \type {tex} library contains a large list of (possibly virtual) internal \TEX\ parameters that are partially writable. The designation \quote {virtual} means that these items are not properly defined in \LUA, but are only front-ends that are handled by a metatable that operates on the actual \TEX\ values. As a result, most of the \LUA\ table operators (like \type {pairs} and \type {#}) do not work on such items. In addition to this kind of access we have getters and setters, which are the preferred way, but e keep the field like accessors around for compatibility reasons. At the moment, it is possible to access almost every parameter that you can use after \type {\the}, is a single token or is sort of special in \TEX. This excludes parameters that need extra arguments, like \typ {\the \scriptfont}. The subset comprising simple integer and dimension registers are writable as well as readable (like \type {\tracingcommands} and \type {\parindent}). \stopsubsection \startsubsection[title=Registers] Among of the oldest accessors to internals are \type {tex.dimen} and \type {tex.count}. This permits calls like this: \startbuffer \setbox0\hbox{test} \directlua{tex.sprint(tex.box[0].width)} \stopbuffer \typebuffer to give us (in this case typeset): \inlinebuffer\ scaled points. Here we access a box register, get back a userdata node, and access one of its fields. The skip registers also are stored on userdata. The register are accessed in the following way; watch the different value types that you get: \starttyping[option=LUA] value = tex.attribute [index] value = tex.skip [index] value = tex.glue [index] value = tex.muskip [index] value = tex.muglue [index] value = tex.dimen [index] value = tex.count [index] value = tex.posit [index] value = tex.toks [index] value = tex.box [index] \stoptyping You can also assign values: \starttyping[option=LUA] tex.attribute [index] = value -- tex.skip [index] = value -- tex.glue [index] = value -- tex.muskip [index] = value -- tex.muglue [index] = value -- tex.dimen [index] = value -- tex.count [index] = value -- tex.posit [index] = value -- tex.toks [index] = value -- tex.box [index] = value -- \stoptyping Be warned that an assignment like \starttyping[option=LUA] tex.box[0] = tex.box[2] \stoptyping does not copy the node list, it just duplicates a node pointer. If \type {\box2} will be cleared by \TEX\ commands later on, the contents of \type {\box0} becomes invalid as well. To prevent this from happening, always use \type {node.copylist} unless you are assigning to a temporary variable: \starttyping tex.box[0] = node.copylist(tex.box[2]) \stoptyping When you access a \TEX\ parameter a look up takes place. For read||only variables that means that you will get something back, but when you set them you create a new entry in the table thereby making the original invisible. Although these are actually not stored in arrays but in hashes, the various \quote {codes} can also be accessed this way: \starttyping[option=LUA] value = tex.sfcode = [index] value = tex.lccode = [index] value = tex.uccode = [index] value = tex.hccode = [index] value = tex.hmcode = [index] value = tex.amcode = [index] value = tex.cccode = [index] value = tex.catcode = [index] value = tex.mathcode = [index] value = tex.delcode = [index] \stoptyping and \starttyping[option=LUA] tex.sfcode = [index] = value -- tex.lccode = [index] = value -- tex.uccode = [index] = value -- tex.hccode = [index] = value -- tex.hmcode = [index] = value -- tex.amcode = [index] = value -- tex.cccode = [index] = value -- tex.catcode = [index] = value -- tex.mathcode = [index] = value -- tex.delcode = [index] = value -- \stoptyping The getters are \starttyping[option=LUA] function tex.getamcode ( character ) return end function tex.getcatcode ( character ) return end function tex.getcccode ( character ) return end function tex.gethccode ( character ) return end function tex.gethmcode ( character ) return end function tex.getlccode ( character ) return end function tex.getsfcode ( character ) return end function tex.getuccode ( character ) return end \stoptyping and the setters: \starttyping[option=LUA] function tex.setamcode ( character, value ) end function tex.setcatcode ( character, value ) end function tex.setcccode ( character, value ) end function tex.sethccode ( character, value ) end function tex.sethmcode ( character, value ) end function tex.setlccode ( character, value ) end function tex.setsfcode ( character, value ) end function tex.setuccode ( character, value ) end \stoptyping The \type {setlccode} and \type {setuccode} additionally allow you to set the associated sibling at the same time by passing an extra argument. \starttyping[option=LUA] function tex.setlccode ( character, lcvalue, ucvalue ) end function tex.setuccode ( character, ucvalue, lcvalue ) end \stoptyping The function call interface for \type {setcatcode} also allows you to specify a category table to use on assignment or on query (default in both cases is the current one): \starttyping[option=LUA] function tex.setcatcode ( catcodetable, character, value ) -- no return values end \stoptyping All these setters accept an initial \type{global} string. \stopsubsection \startsubsection[title={Setters and getters}] Most of \TEX's parameters can be accessed directly by using their names as index in the \type {tex} table, or by using one of the functions \type {tex.get} and \type {tex.set}. The exact parameters and return values differ depending on the actual parameter. In most cases we have integers but especially glue have more properties than just the amount. For the parameters that {\em can} be set, it is possible to use \type {global} as the first argument to \type {tex.set}. Them being more complete is an argument for using setters instead of assignments. The \type {set} function is meant for what we call internal parameter. These can be registers but without a known number (one can actually figure out the internal number via the token library). \starttyping[option=LUA] function tex.set ( name, value ) -- no return values end function tex.set ( "global", name, value ) -- no return values end \stoptyping You can get back a value with: \starttyping[option=LUA] function tex.get ( name ) return end \stoptyping Glue is kind of special because there are five values involved. The return value is a \type {glue_spec} node but when you pass \type {false} as last argument to \type {tex.get} you get the width of the glue and when you pass \type {true} you get all five values. Otherwise you get a node which is a copy of the internal value so you are responsible for its freeing at the \LUA\ end. When you set a glue quantity you can either pass a \type {glue_spec} or upto five numbers. Traditional \TEX\ has 256 registers per type, \ETEX\ bumps that to 32K and \LUAMETATEX\ doubles that. But how many are enough? Do we really need that many different attributes and glue specifiers? In \LUAMETATEX\ on the one hand can go lower on registers and at the same time go beyond with alternatives when using named quantities. It is possible to define named registers with t\type {\attributedef}, \type {\countdef}, \type {\dimendef}, \type {\skipdef}, \type {\floatdef} or \type {\toksdef} control sequences as indices to these tables and these can be accessed by name at the \LUA\ end. Here are some examples: \starttyping tex.count.scratchcounter = 123 tex.dimen.scratchdimen = "20pt" tex.setcount( "scratchcounter", 123) tex.setdimen( "scratchdimen", 10 *65536) tex.setdimen("global", "scratchdimen", "10pt") enormous = tex.dimen.maxdimen enormous = tex.getdimen("maxdimen") unknown = tex.dimen[3] unknown = tex.getdimen(3) \stoptyping Of course this assumes that these registers are defined. What you can do depends on the type: \startitemize \startitem The count registers accept and return \LUA\ numbers (integers in this case). \stopitem \startitem The dimension registers accept \LUA\ numbers (in scaled points) or strings with a dimension. \stopitem \startitem The token registers accept and return \LUA\ strings. \LUA\ strings are converted to and from token lists using \type {\the \toks} style expansion: all category codes are either space (10) or other (12). \stopitem \startitem The skip registers accept and return \type {glue_spec} userdata node objects (see the description of the node interface elsewhere in this manual). \stopitem \startitem The glue registers are just skip registers but instead of userdata accept verbose (integers). \stopitem \startitem Like the counts, the attribute registers accept and return integers. \stopitem \startitem Float (aka posit) registers accept and return floating point numbers. \stopitem \stopitemize The \type {setglue} function accepts upto five arguments: \starttyping[option=LUA] function tex.setskip ( register, -- can also be an index value -- glue_spec ) -- no return values end function tex.setglue ( register, -- can also be an index amount, stretch, shrink, stretchorder, shrinkorder ) -- no return values end \stoptyping Actually there can be one more argument here because as first argument we can pass \type {"global"}. The whole repertoire is: \starttyping[option=LUA] function tex.getattribute ( name ) return end function tex.getcount ( name ) return end function tex.getdimen ( name ) return end function tex.getfloat ( name ) return end function tex.getskip ( name ) return end function tex.getmuskip ( name ) return end function tex.gettoks ( name ) return end function tex.getglue ( name ) return , ... end function tex.getmuglue ( name ) return , ... end function tex.getglue ( name, false ) return end function tex.getmuglue ( name, false ) return end \stoptyping and \starttyping[option=LUA] function tex.setattribute ( name, value) end function tex.setcount ( name, value) end function tex.setdimen ( name, value) end function tex.setfloat ( name, value) end function tex.setmuskip ( name, value) end function tex.setskip ( name, value) end function tex.settoks ( name, value) end function tex.setglue ( name, value, ...) end function tex.setmuglue ( name, value, ...) end \stoptyping Just to be clear, getting a glue has two variants, the third one is just a reduced variant: \starttyping[option=LUA] function tex.getskip ( register -- can also be an index ) return -- a glue_spec end function tex.getglue ( register -- can also be an index ) return -- amount, -- stretch, -- shrink, -- stretchorder, -- shrinkorder end function tex.getglue ( register, -- can also be an index false ) return amount, end \stoptyping When \type {tex.gettoks} gets an extra argument \type {true} it will return a table with userdata tokens. For tokens registers we have an alternative where a catcode table is specified: \starttyping[option=LUA] function tex.scantoks ( catcodetable, registerindex, -- or just a name data ) -- no return values end \stoptyping Again there is the option to pass \type {"global"} as first argument. Here is an example that used the default \CONTEXT\ catcode table index \typ {tex.ctxcatcodes}. \starttyping[option=LUA] local t = tex.scantoks("global",tex.ctxcatcodes,3,"$e=mc^2$") \stoptyping This is a bit different getter that was introduced to accommodate interfacing between \TEX\ and \METAPOST. We specify what kind of parsing takes place: \starttyping[option=LUA] function tex.expandasvalue ( kind, -- how interpreted name -- macro name ) return | | end \stoptyping \startfourrows \getbuffer[engine:syntax:functioncodes] \stopfourrows \stopsubsection \startsubsection[title=Fonts] There are a few functions that deal with fonts. The next function relates a control sequence to a font identifier. This is not to be confused with registering font data in the engine which happens with the functions in the \type {font} library. This is basically a setter that as one some in the \type {token} library also accepts prefixes (like \type {global}): \starttyping[option=LUA] function tex.definefont ( name, fontid, prefix -- there can be more prefixes ) -- no return values end \stoptyping In \LUATEX\ and other engines the file names are stored in the table of equivalents but not so in \LUAMETATEX. But for old times sake we keep some getters in the \type {tex} library, as they are basically \quote {convert} commands. The next two are like \type {\fontid} and \type {\fontname}: \starttyping[option=LUA] function tex.fontidentifier ( id ) return end function tex.fontname ( id ) return end \stoptyping When no \type {id} is given the current font is assumed, as if \type {\font} was the argument to the mentioned equivalent macros, so here we have: {\tttf \cldcontext {tex.fontidentifier ()}} and {\tttf \cldcontext {tex.fontname ()}}. We can query the font id bound to a family (and optionally style): \starttyping[option=LUA] function tex.getfontoffamily ( family, style -- 0, 1, 2 ) return -- id end \stoptyping This is a good place to mention a pitfall when it comes to accessing some internals. Many variables are just that, variables, but there are also some that need an argument. This means that we get the following: \starttabulate[|lT|lT|] \FL \BC \LUA\ call \BC result (if any) \NC \NR \TL \NC tex.fontname \NC \cldcontext {tex.fontname } \NC \NR \NC tex.fontidentifier \NC \cldcontext {tex.fontidentifier } \NC \NR \NC tex.fontname() \NC \cldcontext {tex.fontname ()} \NC \NR \NC tex.fontidentifier() \NC \cldcontext {tex.fontidentifier ()} \NC \NR \NC tex.get("fontname",-1) \NC \cldcontext {tex.get("fontname",-1)} \NC \NR \NC tex.get("fontidentifier",-1) \NC \cldcontext {tex.get("fontidentifier",-1)} \NC \NR \LL \stoptabulate When called as \quote {field} we get nothing. When called as a function we get the font info of the id passes as argument. When no argument is given the current font is used. When we use a getter the id is mandate but a negative value will again make that the current font is used. Making the first two use the current font and the last two accept no second argument is technically possible but complicating the code for these few cases makes no sense. We already handle more than in \LUATEX\ anyway. \stopsubsection \startsubsection[title={Box registers}] It is possible to set and query actual boxes, coming for instance from \prm {hbox}, \prm {vbox} or \prm {vtop}, using the node interface as defined in the \type {node} library. In the setters you can pass as first argument \type {global} if needed. Alternatively you can use the \type {tex.box} array interface. \starttyping[option=LUA] function tex.setbox ( index, packedlist ) -- no return values end function tex.setbox ( name, packedlist ) -- no return values end \stoptyping The getters return a packed list or \type {nil} when the register is void. \starttyping[option=LUA] function tex.getbox ( index ) return end function tex.getbox ( name ) return end \stoptyping You can split a box: \starttyping[option=LUA] local vlist = function tex.splitbox ( index, height, mode ) \stoptyping The remainder is kept in the original box and a packaged vlist is returned. This operation is comparable to the \type {\vsplit} operation. The mode can be \type {additional} or \type {exactly} and concerns the split off box. \stopsubsection \startsubsection[title=Marks] There is a dedicated getter for marks: \starttyping[option=LUA] function tex.getmark ( name, markindex ) -- no return values end function tex.getmark ( ) return -- max mark class end \stoptyping The first argument can also be an integer, actually the subtype of a mark node: \starttworows \getbuffer[engine:syntax:marknames] \stoptworows The largest used mark class is returned by: \starttyping[option=LUA] function tex.getlargestusedmark ( ) return -- max mark class end \stoptyping \stopsubsection \startsubsection[title=Inserts] Access to inserts is kind of special and often only makes sense when we are constructing the final page. Where in traditional \TEX\ inserts use a \type {\dimen}, \type {\count}, \type {\skip} and \type {\box}, registers, in \LUAMETATEX\ we can use dedicted storage instead. This is why we need setters and getters. \starttyping[option=LUA] function tex.getinsertdistance ( class ) return end function tex.getinsertmultiplier ( class ) return end function tex.getinsertlimit ( class ) return end function tex.getinsertcontent ( class ) return end function tex.getinsertheight ( class ) return end function tex.getinsertdepth ( class ) return end function tex.getinsertwidth ( class ) return end \stoptyping Only some properties can be set: \starttyping[option=LUA] function tex.setinsertdistance ( class, distance ) end function tex.setinsertmultiplier ( class, multiplier ) end function tex.setinsertlimit ( class, limit ) end function tex.setinsertcontent ( class, list ) end \stoptyping \stopsubsection \startsubsection[title=Local boxes] Local boxes, \typ {\localleftbox}, \typ {\localrightbox} and specific for \LUAMETATEX, \typ {\localmiddlebox}, are not regular box registers so they have dedicated accessors: \starttyping[option=LUA] function tex.getlocalbox ( location ) return end function tex.setlocalbox ( location, list ) -- no return values end \stoptyping Instead of integers you can also use the name. Valid local box locations are: \getbuffer[engine:syntax:localboxlocations] \stopsubsection \startsubsection[title=Constants] The name of this section is a bit misleading but reflects history. At some point \LUAMETATEX\ got a way to store values differently than in registers because it felt a bit weird to use registers for what actually are constant values. However, it was not that hard to make them behave like registers which opens up the possibility to reduce the number of registers at some point. At the \TEX\ end we have \type {\integerdef}, \type {\dimensiondef}, \type {\floatdef}, \type {\gluespecdef} and \type {\mugluespecdef} but at the \LUA\ end we (currently) only handle the first three. \starttyping[option=LUA] function tex.dimensiondef ( name ) end function tex.integerdef ( name ) end function tex.positdef ( name ) end \stoptyping These are the setters: \starttyping[option=LUA] function tex.setdimensionvalue ( name, value ) end function tex.setintegervalue ( name, value ) end function tex.setcardinalvalue ( name, value ) end function tex.setpositvalue ( name, value ) end \stoptyping and these the getters: \starttyping[option=LUA] function tex.getdimensionvalue ( name ) return end function tex.getintegervalue ( name ) return end function tex.getcardinalvalue ( name ) return end function tex.getpositvalue ( name ) return end \stoptyping Now, in order to make access more convenient, the getters and setters that deal with these quantities that we discussed in a previous section also handle these \quote {constants}. The following helper is a bit tricky: \starttyping[option=LUA] function tex.getregisterindex ( name ) return end \stoptyping The integer that is returned can be used instead of a name when accessing a register, \startbuffer \newcount \MyCount \newinteger \MyInteger \newdimen \MyDimen \newdimension \MyDimension \startluacode context("[%s] [%s] [%s] [%s]", tex.getregisterindex("MyCount"), tex.getregisterindex("MyInteger"), tex.getregisterindex("MyDimen"), tex.getregisterindex("MyDimension") ) \stopluacode \stopbuffer \typebuffer[option=LUA] This will only show something for the registers: \getbuffer This is why we have a more complete completed solution: \starttyping[option=LUA] tex.isattribute ( name ) return end tex.iscount ( name ) return end tex.isdimen ( name ) return end tex.isfloat ( name ) return end tex.isglue ( name ) return end tex.ismuglue ( name ) return end tex.ismuskip ( name ) return end tex.isskip ( name ) return end tex.istoks ( name ) return end tex.isbox ( name ) return end \stoptyping We now use this: \startbuffer \startluacode context("[%s] [%s] [%s] [%s]", tex.iscount("MyCount"), tex.iscount("MyInteger"), tex.isdimen("MyDimen"), tex.isdimen("MyDimension") ) \stopluacode \stopbuffer \typebuffer[option=LUA] This time all four names are resolved: \getbuffer The larger numbers are references to these \quote {constants}. Using these instead of names in the getters (like \type {getcount} and \type {getdimen} can be more efficient when the number times we need access is very large because we bypass a hash lookup. Of course these numbers are to be seen as abstract references, so these larger numbers are unpredictable. \stopsubsection \startsubsection[title=Nesting] The virtual table \type {nest} contains the currently active semantic nesting state (think building boxes). It has two main parts: a zero-based array of userdata for the semantic nest itself, and the numerical value \type {ptr}, which gives the highest available index. Neither the array items in \type {nest[]} nor \type {ptr} can be assigned to, because this would confuse the typesetting engine beyond repair, but you can assign to the individual values inside the array items. The zero entry \type {nest[0]} is the outermost (main vertical list) level while \typ {tex.nest [tex.nest.ptr]} is the current nest state. The next example shows all of this: \startbuffer \setbox\scratchbox\vbox\bgroup \vbox\bgroup \startluacode for i=0,tex.nest.ptr do context(tostring(tex.nest[i])) context.space() context(tostring(tex.nest[i].prevdepth)) context.par() end \stopluacode \egroup \egroup \stopbuffer \typebuffer \start \forgetall \getbuffer \startlinecorrection \box\scratchbox \stoplinecorrection \stop The current nest level (\type {tex.nest.ptr} is also available with: \starttyping[option=LUA] function tex.getnestlevel ( ) return end \stoptyping The getter function is \type {tex.getnest}. You can pass a number (which gives you a list), nothing or \type {top}, which returns the topmost list, or the string \type {ptr} which gives you the index of the topmost list. The complete list of fields is: \showenginekeylist {tex.getnestfields()}. Possible modes are: \starttworows \getbuffer[engine:syntax:modes] \stoptworows Valid directions are: \starttworows \getbuffer[engine:syntax:directioncodes] \stoptworows Math styles conforms to: \starttworows \getbuffer[engine:syntax:mathstyles] \stoptworows The math begin and end classes can be built-in or \CONTEXT\ specific: \startfourrows \getbuffer[engine:syntax:mathclasses] \stopfourrows The helpers are: \starttyping[option=LUA] function tex.getnest ( level ) return -- nest end function tex.getnest ( level, name ) return -- value end function tex.setnest ( level, name ), value ) -- no return values end \stoptyping Instead of an integer level you can use the keywords \type {ptr} and \type {top} instead of the current level or zero. There are a few special cases that we make an exception for: \type {prevdepth}, \type {prevgraf} and \type {spacefactor}. These normally are accessed via the \type {tex.nest} table: \starttyping tex.nest[tex.nest.ptr].prevdepth = value tex.nest[tex.nest.ptr].spacefactor = value \stoptyping However, the following also works for the current level: \starttyping tex.prevdepth = value tex.spacefactor = value \stoptyping Keep in mind that when you mess with node lists directly at the \LUA\ end you might need to update the top of the nesting stack's \type {\prevdepth} explicitly as there is no way \LUATEX\ can guess your intentions. By using the accessor in the \type {tex} tables, you get and set the values at the top of the nesting stack. \stopsubsection \startsubsection[title={Directions}] In \LUAMETATEX\ we only have left-to-right (l2r) and right-to-left (r2l) directions, contrary to \LUATEX\ that has few more. In the end those made no sense because the typesetter is not geared for that and demands can be met by a combination of \TEX\ macros and \LUA\ code. There are two sets of helpers: \starttyping[option=LUA] function tex.gettextdir ( ) return direction ) end -- no return values function tex.setlinedir ( direction ) end -- no return values function tex.setmathdir ( direction ) end -- no return values function tex.setpardir ( direction ) end -- no return values function tex.setboxdir ( direction ) end -- no return values \stoptyping For old times sake you can also set them using the virtual interfaces, like \starttyping[option=LUA] tex.textdirection = 1 \stoptyping but in \CONTEXT\ we consider this obsolete. In \LUAMETATEX\ we dropped the direction related keywords and only use numbers: \getbuffer[engine:syntax:directioncodes] \stopsubsection \startsubsection[title={Special lists}] The virtual table \type {tex.lists} contains the set of internal registers that keep track of building page lists. We have the following lists plus some extras: \showenginekeylist {tex.getlistfields()}. Using these assumes that you know what \TEX\ is doing. The getter and setter functions are \type {getlist} and \type {setlist}. You have to be careful with what you set as \TEX\ can have expectations with regards to how a list is constructed or in what state it is. \starttyping[option=LUA] function tex.getlist ( name ) return -- value end function tex.setlist ( name ), value ) -- no return values end \stoptyping You can mess up I ways that make the engine fail, for instance due to wrongly linked lists, for instance maybe circular, or invalid nodes. \stopsubsection \startsubsection[title=Printing] The engine reads tokens from file, token lists and \LUA. When we print from \LUA\ it ends up in a special data structure that efficiently handle strings, tokens and nodes because we can push all three back to \TEX. It is important to notice that when we have a call to \LUA, that new input is collected and only pushed onto the input stack when we are done. The total amount of returnable text from a \type {\directlua} command or primitive driven function call is only limited by available system \RAM. However, each separate printed string has to fit completely in \TEX's input buffer. The result of using these functions from inside callbacks is undefined at the moment. First we look at \type {tex.print} and \type {tex.sprint}. \starttyping[option=LUA] function tex.print ( -- also tex.sprint data, -- more strings ) -- nothing to return end function tex.print ( -- also tex.sprint catcodetable, data, -- more strings ) -- nothing to return end function tex.print ( -- also tex.sprint data ) -- nothing to return end function tex.print ( -- also tex.sprint catcodetable, data ) -- nothing to return end \stoptyping With \type {tex.print} each string argument is treated by \TEX\ as a separate input line. If there is a table argument instead of a list of strings, this has to be a consecutive array of strings to print (the first non-string value will stop the printing process). The optional first integer parameter can be used to print the strings using the catcode regime defined by \type {\catcodetable}. A value of $-1$ means that the currently active catcode regime is used while $-2$ gives a result similar to \type {\the\toks}: all category codes are 12 (other) except for the space character, that has category code 10 (space). An invalid catcode table index is silently ignored, and the currently active catcode regime is used instead. The very last string of the very last \type {tex.print} command in a \type {\directlua} call will not have the \type {\endlinechar} appended, all others do. In the case if \type {tex.sprint} each string argument is treated by \TEX\ as a special kind of input line that makes it suitable for use as a partial line input mechanism: \startitemize[packed] \startitem \TEX\ does not switch to the \quote {new line} state, so that leading spaces are not ignored. \stopitem \startitem No \type {\endlinechar} is inserted. \stopitem \startitem Trailing spaces are not removed. Note that this does not prevent \TEX\ itself from eating spaces as result of interpreting the line. For example, in \starttyping before\directlua{tex.sprint("\\relax")tex.sprint(" in between")}after \stoptyping the space before \type {in between} will be gobbled as a result of the \quote {normal} scanning of \prm {relax}. \stopitem \stopitemize Although this needs to be used with care, in both function you can also pass token or node userdata objects. These get injected into the stream. Tokens had best be valid tokens, while nodes need to be around when they get injected. Therefore it is important to realize the following: \startitemize \startitem When you inject a token, you need to pass a valid token userdata object. This object will be collected by \LUA\ when it no longer is referenced. When it gets printed to \TEX\ the token itself gets copied so there is no interference with the \LUA\ garbage collection. You manage the object yourself. Because tokens are actually just numbers, there is no real extra overhead at the \TEX\ end. \stopitem \startitem When you inject a node, you need to pass a valid node userdata object. The node related to the object will not be collected by \LUA\ when it no longer is referenced. It lives on at the \TEX\ end in its own memory space. When it gets printed to \TEX\ the node reference is used assuming that node stays around. There is no \LUA\ garbage collection involved. Again, you manage the object yourself. The node itself is freed when \TEX\ is done with it. \stopitem \stopitemize If you consider the last remark you might realize that we have a problem when a printed mix of strings, tokens and nodes is reused. Inside \TEX\ the sequence becomes a linked list of input buffers. So, \type {"123"} or \type {"\foo{123}"} gets read and parsed on the fly, while \typ {} already is tokenized and effectively is a token list now. A \typ {} is also tokenized into a token list but it has a reference to a real node. Normally this goes fine. But now assume that you store the whole lot in a macro: in that case the tokenized node can be flushed many times. But, after the first such flush the node is used and its memory freed. You can prevent this by using copies which is controlled by setting \type {\luacopyinputnodes} to a non|-|zero value. This is one of these fuzzy areas you have to live with if you really mess with these low level issues. The \type {tex.cprint} function is similar to \type {tex,sprint} but instead of am optional first catcodetable it takes a catcode value, like: \starttyping[option=LUA] function tex.cprint ( catcode, data -- more strings ) -- no return values end \stoptyping Of course the other three ways to call it are also supported. This might explain better: \startbuffer \startluacode tex.cprint( 1," 1: $&{\\foo}") tex.print("\\par") -- a lot of \bgroup s tex.cprint( 2," 2: $&{\\foo}") tex.print("\\par") -- matching \egroup s tex.cprint( 9," 9: $&{\\foo}") tex.print("\\par") -- all get ignored tex.cprint(10,"10: $&{\\foo}") tex.print("\\par") -- all become spaces tex.cprint(11,"11: $&{\\foo}") tex.print("\\par") -- letters tex.cprint(12,"12: $&{\\foo}") tex.print("\\par") -- other characters tex.cprint(14,"14: $&{\\foo}") tex.print("\\par") -- comment triggers \stopluacode \stopbuffer \typebuffer We get two lines separate by one with only spaces: \getbuffer A variant on \type {tex.sprint} is the next one: \starttyping[option=LUA] function tex.tprint ( { catcodetable, data}, -- more tables ) -- no return values end \stoptyping The \type {tex.write} function is a quick way to dump information. Each string argument is treated as a special kind of input line that only has spaces and letters. \starttyping[option=LUA] function tex.write ( data, ... ) -- no return values end function tex.write ( data) -- no return values end \stoptyping Often you can mix strings, nodes and tokens in a print but you might want to check beforehand what you pass: \starttyping[option=LUA] function tex.isprintable ( object ) return end \stoptyping \stopsubsection \startsubsection [title=Numbers and dimensions] We can rounds a \LUA\ number to an integer that is in the range of a valid \TEX\ register value. If the number starts out of range, it generates a \quote {number too big} error as well. \starttyping[option=LUA] function tex.round ( n ) return end \stoptyping In many places the engine multiplies and divides integers and ensures proper rounding. In \LUAMETATEX\ some (new) mechanisms use doubles and round, especially when multiple scale value accumulate beyond the available integer range. The next function multiplies two \LUA\ numbers and returns a rounded number that is in the range of a valid \TEX\ register value. In the table version, it creates a copy of the table with all numeric top||level values scaled in that manner. If the multiplied number(s) are of range, it generates \quote {number too big} error(s) as well. \starttyping[option=LUA] function tex.scale ( original, factor ) return -- result end function tex.scale ( originals, factor ) return -- results end \stoptyping Here are companions to the primitives \type {\number} and \type {\romannumeral}. Both take the long route: the string goes to \TEX, gets tokenized, then converted to what is wanted and finally ends up in \LUA. They can be used like: \starttyping[option=LUA] function tex.number ( original ) return end function tex.romannumeral ( original ) return end \stoptyping The dimension converter takes a string and returns an integer that represents an dimension in scaled points. When a number is passed it gets rounded. \starttyping[option=LUA] function tex.toscaled ( original ) return end function tex.toscaled ( original ) return end \stoptyping For completeness the engine also provides \type {tex.tonumber}: \starttyping[option=LUA] function tex.tonumber ( original ) return end function tex.tonumber ( original ) return end \stoptyping For parsing the string, the same scanning and conversion rules are used that \LUATEX\ would use if it was scanning a dimension specifier in its \TEX|-|like input language (this includes generating errors for bad values), expect for the following: \startitemize[n,packed] \startitem only explicit values are allowed, control sequences are not handled \stopitem \startitem infinite dimension units (\type {fil...}) are forbidden \stopitem \startitem \type {mu} units do not generate an error (but may not be useful either) \stopitem \stopitemize \stopsubsection \startsubsection[title={Primitives}] Where in \LUATEX\ we explicitly need to enable the core set of primitives, \LUAMETATEX\ does that for you. The only reason that we still have a way to enable them is that it's a convenient way to create prefixed copies. \starttyping[option=LUA] function tex.enableprimitives ( prefix, names ) -- no return values end \stoptyping Only valid primitive names are processed. Because it is no fun to enter the names, there is this one. It has two variants, where the boolean variant returns a table with all primitives. \starttyping[option=LUA] function tex.extraprimitives ( subset, ... ) return -- names end function tex.extraprimitives ( ) return -- names end \stoptyping Possible values for \type {subset} are: \getbuffer[engine:syntax:primitiveorigins] You can feed the result of the last one in \type {tex.enableprimitives}. If there is already a macro with that name if will not be overloaded. \starttyping[option=LUA] tex.enableprimitives('normal',tex.extraprimitives(true)) \stoptyping A complete list of primitives can be requested by: \starttyping[option=LUA] function tex.primitives ( ) return -- names end \stoptyping of course the fact that the name is there doesn't mean that it has the same meaning. A complete list of all hash entries can be asked for by the following function, but in \CONTEXT\ it will be a big one, a bit more that 50.000 names, many of which are kind of weird because they use some namespace. \starttyping[option=LUA] function tex.hashtokens ( ) return -- names end \stoptyping \stopsubsection \startsubsection[title=Values (constants)] The engine uses lots of very specific values (constants) for control. These can be status values (where are we currently), options (in nodes), control parameters (typesetting), etc.\ and all are available in lists that relate numbers to strings. Here is the complete list. We show the results in various places in the documentation. The advantage is that the engine is partly self documenting. \starttyping[option=LUA] function tex.getadjustoptionvalues ( ) return end function tex.getalignmentcontextvalues ( ) return end function tex.getappendlinecontextvalues ( ) return end function tex.getautomigrationvalues ( ) return end function tex.getautoparagraphvalues ( ) return end function tex.getbalancestepoptionvalues ( ) return end function tex.getbalancecallbackvalues ( ) return end function tex.getboxoptionvalues ( ) return end function tex.getbreakcontextvalues ( ) return end function tex.getbuildcontextvalues ( ) return end function tex.getcharactercontrolvalues ( ) return end function tex.getcharactertagvalues ( ) return end function tex.getdirectionvalues ( ) return end function tex.getdiscoptionvalues ( ) return end function tex.getdiscpartvalues ( ) return end function tex.getdoublescriptoptionvalues ( ) return end function tex.geterrorvalues ( ) return end function tex.getfillvalues ( ) return end function tex.getflagvalues ( ) return end function tex.getfrozenparvalues ( ) return end function tex.getglueoptionvalues ( ) return end function tex.getglyphdiscvalues ( ) return end function tex.getglyphoptionvalues ( ) return end function tex.getglyphprotectionvalues ( ) return end function tex.getgroupvalues ( ) return end function tex.gethyphenationvalues ( ) return end function tex.getiftypes ( ) return end function tex.getinteractionmodes ( ) return end function tex.getiovalues ( ) return end function tex.getkernoptionvalues ( ) return end function tex.getkerneloptionvalues ( ) return end function tex.getlinebreakparameterfields ( ) return end function tex.getlinebreakresultfields ( ) return end function tex.getlinebreakstatevalues ( ) return end function tex.getlistanchorvalues ( ) return end function tex.getlistfields ( ) return end function tex.getlistgeometryvalues ( ) return end function tex.getlistsignvalues ( ) return end function tex.getlocalboxlocations ( ) return end function tex.getmathclassoptionvalues ( ) return end function tex.getmathcontrolvalues ( ) return end function tex.getmathgluevalues ( ) return end function tex.getmathoptionvalues ( ) return end function tex.getmathparametervalues ( ) return end function tex.getmathscriptordervalues ( ) return end function tex.getmathscriptsmodevalues ( ) return end function tex.getmathstylenamevalues ( ) return end function tex.getmathstylevalues ( ) return end function tex.getmathsurroundvalues ( ) return end function tex.getmathvariantpresets ( ) return end function tex.getmathvariantvalues ( ) return end function tex.getmarknames ( ) return end function tex.getmvloptionvalues ( ) return end function tex.getmodevalues ( ) return end function tex.getnestfields ( ) return end function tex.getnoadoptionvalues ( ) return end function tex.getnormalizelinevalues ( ) return end function tex.getnormalizeparvalues ( ) return end function tex.getpacktypevalues ( ) return end function tex.getpagecontextvalues ( ) return end function tex.getpagestatevalues ( ) return end function tex.getparametermodevalues ( ) return end function tex.getparcontextvalues ( ) return end function tex.getparmodevalues ( ) return end function tex.getpartriggervalues ( ) return end function tex.getpenaltyoptionvalues ( ) return end function tex.getprepoststatevalues ( ) return end function tex.getprimitiveorigins ( ) return end function tex.getprotrusionboundaryvalues ( ) return end function tex.getruleoptionvalues ( ) return end function tex.getrunstatevalues ( ) return end function tex.getshapingpenaltiesvalues ( ) return end function tex.getspecialmathclassvalues ( ) return end function tex.getspecificationoptionvalues ( ) return end function tex.gettextcontrolvalues ( ) return end function tex.getuleaderlocationvalues ( ) return end function tex.getunitclassvalues ( ) return end \stoptyping \stopsubsection \startsubsection [title={Glyphs}] There are a few (internal) integer parameters that relate to glyphs, \typ {\glyphdatafield}, \typ {\glyphstatefield}, \typ {\glyphscriptfield} as well as the three scales \typ {\glyphscale}, \typ {\glyphxscale} and \typ {\glyphyscale}, and for these we have fast accessors: \starttyping[option=LUA] function tex.setglyphdata ( ) end function tex.setglyphstate ( ) end function tex.setglyphscript ( ) end \stoptyping and \starttyping[option=LUA] function tex.getglyphdata ( ) return end function tex.getglyphstate ( ) return end function tex.getglyphscript ( ) return end \stoptyping The scale getter returns more: \starttyping[option=LUA] function tex.getglyphscales ( ) return , -- scale , -- xscale , -- yscale -- data end \stoptyping \stopsubsection \startsubsection [title={Whatever}] We have no backend so all that the next does is wiping the box: \starttyping[option=LUA] function tex.shipout ( index ) -- no return values end \stoptyping This helper function is useful during line break calculations. The arguments \type {t} and \type {s} are scaled values; the function returns the badness for when total \type {t} is supposed to be made from amounts that sum to \type {s}. The returned number is a reasonable approximation of \mathematics {100 ( t / s) ^ 3}. \starttyping[option=LUA] function tex.badness ( t, s ) return end \stoptyping The page builder can be in different states, so here is how you get the current state: \starttyping[option=LUA] function tex.getpagestate ( ) return end \stoptyping possible states are: \starttworows \getbuffer[engine:syntax:pagestatecodes] \stoptworows You can also check if we're in the output routine: \starttyping[option=LUA] function tex.getoutputactive ( ) return end \stoptyping An example of a (possible error triggering) complication is that \TEX\ expects to be in some state, say horizontal mode, and you have to make sure it is when you start feeding back something from \LUA\ into \TEX. Normally a user will not run into issues but when you start writing tokens or nodes or have a nested run there can be situations that you need to enforce horizontal mode. There is no recipe for this and intercepting possible cases would weaken \LUATEX's flexibility. Therefore we provide \type {forcehmode} which is similar to \type {\quitvmode} at the \TEX\ end, although in \CONTEXT, that had it already, we always use \type {\dontleavehmode} as name. \starttyping[option=LUA] function tex.forcehmode ( ) -- no return values end \stoptyping The last node in the current list is queried with the following helper. If there is no node you get \type {nil}'s back. \starttyping[option=LUA] function tex.lastnodetype ( ) return , -- type -- subtype end \stoptyping The current mode is available with: \starttyping[option=LUA] function tex.getmode ( ) return end \stoptyping Currently we're in mode {\tttf 0x\tohexadecimal\cldcontext {tex.getmode()}}, a number that you can give meaning with \type {tex.getmodevalues()}: \getbuffer[engine:syntax:modes] The run state can be fetched with: \starttyping[option=LUA] function tex.getrunstate ( ) return end \stoptyping which returns one of: \getbuffer[engine:syntax:runstates] When we load create the format file we're initializing and when we then do a regular run we are in production. The updating state is just there so that we can deal with overload protection. In that case we need to honor the \type {\enforced} prefix, that can only be used when not in production mode. When a runtime module nevertheless wants to use that prefix it can (from \LUA) set the mode to updating. This is all kind of \CONTEXT\ specific because there we use the overload protection mechanism. \stopsubsection \startsubsection[title=Files and lines] You can register a file id and line number in a \type {glyph}, \type {hlist} and \type {vlist} nodes, for instance for implementing a \SYNCTEX\ emulator. There are some helpers that relate to this. When the mode is zero, no registering will done, when set to one, lists will be tagged and larger values make that glyphs will be tagged too. \starttyping[option=LUA] function tex.setinputstatemode ( mode ) -- no return values end \stoptyping The file is registered as a number and the engine is agnostic about what it refers too. The same is true for lines. In fact, you can use these fields for whatever purpose you like. \starttyping[option=LUA] function tex.setinputstatefile ( fileid ) -- no return values end function tex.setinputstateline ( linenumber ) -- no return values end \stoptyping The getters just return the currently set values: \starttyping[option=LUA] function tex.getinputstatemode ( ) return end function tex.getinputstatefile ( ) return end function tex.getinputstateline ( ) return end \stoptyping The file and line number are bound to the current input which can be nested. So, nesting is handled by the engine. However, you can overload that with the following two helpers. The values set will win over the ones bound to the current input file. \starttyping[option=LUA] function tex.forceinputstatefile ( fileid ) -- no return values end function tex.forceinputstateline ( linenumber ) -- no return values end \stoptyping \stopsubsection \startsubsection[title=Interacting] In \LUAMETATEX\ valid interaction modes are: \starttworows \getbuffer[engine:syntax:interactionmodes] \stoptworows You can get and set the mode with: \starttyping[option=LUA] function tex.getinteraction ( ) return -- mode end function tex.setinteraction ( mode ) -- no return values end \stoptyping When an error occurs it can be intercepted by a callback in which case you have to handle the feedback yourself. For this we have two helpers: \starttyping[option=LUA] function tex.showcontext ( ) end function tex.gethelptext ( ) end \stoptyping An error can be triggered with: \starttyping[option=LUA] function tex.error ( error, help ) -- no return values end \stoptyping Of course these are also intercepted by the callback, when set, in which case the help text can be fetched. There can arise a situation where the engine is in a state where properly dealing with errors has become a problem. In that case you can use: \starttyping[option=LUA] function tex.fatalerror ( error) end \stoptyping In this case the run will be aborted. For the record: in \CONTEXT\ any error will quit the run, just because it makes no sense to try to recover from unpredictable situations and a fix is needed anyway. \stopsubsection \startsubsection[title=Save levels] When you start a group or any construct that behaves like one, for instance boxing, the save stack is \quote {pushed} which means that a boundary is set. When the group ends the values that were saved in the current region (bounded) are restored. You can also do this in \LUA: \starttyping[option=LUA] function tex.pushsavelevel ( ) end function tex.popsavelevel ( ) end \stoptyping This is a way to create grouping when in \LUA\ so that when you set some register the engine will handle the restore. \stopsubsection \startsubsection[title=Local control] When we talk about local control we mean expanding \TEX\ code in a nested main loop. We start with explaining \type {tex.runlocal}. The first argument can be a number (of a token register), a macro name, the name of a token list or some (userdata) token made at the \LUA\ end. The second argument is optional and when true forces expansion inside a definition. The optional third argument can be used to force grouping. The return value indicates an error: 0 means no error, 1 means that a bad register number has been passed, a value of 2 indicated an unknown register or macro name, while 3 reports that the macro is not suitable for local control because it takes arguments. \startbuffer \scratchtoks{This is {\bf an example} indeed.}% \startluacode tex.runlocal("scratchtoks") \stopluacode \stopbuffer \typebuffer This typesets: \inlinebuffer However, the neat thing about local control is that it happens immediately, so not after the \LUA\ blob ended as with \typ [option=LUA] {tex.print ("\\the\scratchtoks")}. \startbuffer \scratchtoks{\setbox\scratchbox\hbox{This is {\bf an example} indeed.}}% \startluacode tex.runlocal("scratchtoks") context("The width is: %p",tex.box.scratchbox.width) \stopluacode \stopbuffer \typebuffer This typesets: \inlinebuffer \starttyping[option=LUA] function tex.runlocal ( name, expand, group ) return -- state end \stoptyping You can quit a local controlled expansion with the following, but if it works depends on the situation. \starttyping[option=LUA] function tex.quitlocal ( ) -- no return values end \stoptyping There might be situations that you push something from \LUA\ to \TEX\ in a local call and don't want interference. In that case wrapping might help but it is not that well tested yet: \starttyping[option=LUA] function tex.pushlocal ( ) -- no return values end function tex.poplocal ( ) -- no return values end \stoptyping The current level of local calls is available with: \starttyping[option=LUA] function tex.getlocallevel ( ) return end \stoptyping You can also run a string through \TEX; the last three booleans are optional. \starttyping[option=LUA] function tex.runlocal ( str, expand_in_definitions, group, ignore_undefind_cs ) -- no return values end function tex.runlocal ( catcodetable, str, expand_in_definitions, group, ignore_undefind_cs ) -- no return values end \stoptyping \stopsubsection \startsubsection[title=Math] There are some setters and getters that relate to the math sub engine. The setter has two variants: \starttyping[option=LUA] function tex.setmathcode ( target, class, family, character ) -- no return values end function tex.setmathcode ( target, { , -- class , -- family -- character } ) -- no return values end \stoptyping But there are two getters: \starttyping[option=LUA] function tex.getmathcode ( target ) return { , -- class , -- family -- character } end function tex.getmathcodes ( target ) return , -- class , -- family -- character end \stoptyping Delcodes have different properties: % { "setdelcode", texlib_setdelcode }, % { "getdelcode", texlib_getdelcode }, % { "getdelcodes", texlib_getdelcodes }, \starttyping[option=LUA] function tex.setdelcode ( target, smallfamily, smallcharacter, largefamily, largecharacter ) -- no return values end function tex.setdelcode ( target, { , -- smallfamily, , -- smallcharacter, , -- largefamily, -- largecharacter } ) -- no return values end \stoptyping Again there two getters: \starttyping[option=LUA] function tex.getdelcode ( target ) return { , -- smallfamily, , -- smallcharacter, , -- largefamily, -- largecharacter } end function tex.getdelcodes ( target ) return , -- smallfamily, , -- smallcharacter, , -- largefamily, -- largecharacter end \stoptyping In \LUAMETATEX\ the engine can do without these delimiter specifications so they might eventually go way. The reason is that when a delimiter is needed we also accent a math character. When we use an \OPENTYPE\ model it's likely that the large character comes from the same font as the small character. And because the font is loaded under \LUA\ control one can always use a virtual character to refer to an other font, something that we do in \CONTEXT\ when we load a \TYPEONE\ based math font. A named math character is defined with \type {mathchardef} but contrary to its \TEX\ counterpart \typ {\mathchardef} it accepts three four extra parameters. The \typ {properties}, \type {group} and \type {index} are data fields that the (for instance) the backend can use. We make no assumptions about their use because it is macro package dependent. There can be flags before the three optional parameters. \starttyping[option=LUA] function tex.mathchardef ( name class, family, character, flags, -- zero or more properties, group, index ) -- no return values end \stoptyping The \type {\chardef} equivalent is: \starttyping[option=LUA] function tex.chardef ( name character, flags, -- zero or more ) -- no return values end \stoptyping Math parameters have their own setter and getter. The first string is the parameter name minus the leading \type {Umath}, and the second string is the style name minus the trailing \type {style}. A value is either an integer (representing a dimension or number) or a list of glue components. \starttyping[option=LUA] function tex.setmath ( prefix, -- zero or more parameter, style, value, -- one or more ) -- no return values end \stoptyping \starttyping[option=LUA] function tex.setmath ( parameter, style ) return -- one or more value end \stoptyping For the next one you need to know what style variants which we will not discuss here: \starttyping[option=LUA] function tex.getmathstylevariant ( style, parameter ) , -- value -- variant end \stoptyping \stopsubsection \startsubsection[title=Processing] You should not expect to much from the \type {triggerbuildpage} helpers because often \TEX\ doesn't do much if it thinks nothing has to be done, but it might be useful for some applications. It just does as it says it calls the internal function that build a page, given that there is something to build. \starttyping[option=LUA] function tex.triggerbuildpage ( ) -- no return values end \stoptyping This function resets the parameters that \TEX\ normally resets when a new paragraph is seen. \starttyping[option=LUA] function tex.resetparagraph ( ) -- no return values end \stoptyping The linebreak algorithm can also be applied explicitly to a node list that better be right. There is some checking done with respect to the beginning and paragraph and interfering glue. \starttyping[option=LUA] function tex.linebreak ( listhead, parameters ) return , -- nodelist -- info end \stoptyping There are a lot of parameters that drive the process and many can be set. The interface might be extended in the future. Valid parameter fields are: \showenginekeylist {tex.getlinebreakparameterfields()}. There is no need to set them (at all) because the usual \TEX\ parameters apply when they are absent. The result is a node list, it still needs to be vpacked if you want to assign it to a \type {\vbox}. The returned \type {info} table contains the following fields: \showenginekeylist {tex.getlinebreakresultfields()}. A list can be \quote {prepared} for a linebreak call with the next function. Normally the linebreak routine will do this. The return values are pointers to some relevant nodes. \starttyping[option=LUA] function tex.preparelinebreak ( listhead ) return , -- nodelist -- info , -- par (head) , -- tail , -- parinitleftskip , -- parinitrightskip , -- parfillleftskip -- parfillrightskip end \stoptyping \starttyping[option=LUA] function tex.snapshotpar ( bitset ) return -- state (bitset) end \stoptyping The bitset is made from: \startthreerows \getbuffer[engine:syntax:frozenparcodes] \stopthreerows This one is handy when you mess with lists and want to take some parameters into account that matter when building a paragraph. The returned fields are: \showenginekeylist {tex.getparstatefields()}. \starttyping[option=LUA] function tex.getparstate ( ) return end \stoptyping A par shape normally is discarded when the paragraph ends but we can continue using it if needed. In that case we can shift the current array and either or not rotate. \starttyping[option=LUA] function tex.shiftparshape ( shift, rotate ) -- no return values end \stoptyping A specification, like \type {\parshape} or \type {\widowpenalties} can be fetched with: \starttyping[option=LUA] function tex.getspecification ( name ) return end \stoptyping \stopsubsection \startsubsection[title=MVL] This returns the currently active main vertical list: \starttyping[option=LUA] function tex.getcurrentmvl ( ) return end \stoptyping \stopsubsection \startsubsection[title=Balancing] At the moment we only have a few balance related helpers. One of them can set the current \prm {balanceshape}. \starttyping[option=LUA] function tex.setbalanceshape ( steps ) return end \stoptyping The indexed table has subtables with fields: \starttabulate[|l|l|] \NC \type {index} \NC \type[option=lua]{} \NC \NR \NC \type {options} \NC \type[option=lua]{} \NC \NR \NC \type {vsize} \NC \type[option=lua]{} \NC \NR \NC \type {topskip} \NC \type[option=lua]{ } \NC \NR \NC \type {bottomskip} \NC \type[option=lua]{ } \NC \NR \NC \type {extra} \NC \type[option=lua]{} \NC \NR \stoptabulate \stopsubsection \stopsection \startsection[title={The configuration}] The global \type {texconfig} table is created empty. A startup \LUA\ script could fill this table with a number of settings that are read out by the executable after loading and executing the startup file. Watch out: some keys are different from \LUATEX, which is a side effect of a more granular and dynamic memory management. \starttabulate[|l|l|l|l|] \FL \BC key \BC type \BC default \BC comment \NC \NR \TL \NC \type {buffersize} \NC number/table \NC 1000000 \NC input buffer bytes \NC \NR \NC \type {filesize} \NC number/table \NC 1000 \NC max number of open files \NC \NR \NC \type {fontsize} \NC number/table \NC 250 \NC number of permitted fonts \NC \NR \NC \type {hashsize} \NC number/table \NC 150000 \NC number of hash entries \NC \NR \NC \type {inputsize} \NC number/table \NC 10000 \NC maximum input stack \NC \NR \NC \type {languagesize} \NC number/table \NC 250 \NC number of permitted languages \NC \NR \NC \type {marksize} \NC number/table \NC 50 \NC number of mark classes \NC \NR \NC \type {nestsize} \NC number/table \NC 1000 \NC max depth of nesting \NC \NR \NC \type {nodesize} \NC number/table \NC 1000000 \NC max node memory (various size) \NC \NR \NC \type {parametersize} \NC number/table \NC 20000 \NC max size of parameter stack \NC \NR \NC \type {poolsize} \NC number/table \NC 10000000 \NC max number of string bytes \NC \NR \NC \type {savesize} \NC number/table \NC 100000 \NC mas size of save stack \NC \NR \NC \type {stringsize} \NC number/table \NC 150000 \NC max number of strings \NC \NR \NC \type {tokensize} \NC number/table \NC 1000000 \NC max token memory \NC \NR \NC \type {mvlsize} \NC number/table \NC 10 \NC max mvl memory \NC \NR \ML \NC \type {expandsize} \NC number/table \NC 10000 \NC max expansion nesting \NC \NR \NC \type {propertiessize} \NC number \NC 0 \NC initial size of node properties table \NC \NR \NC \type {functionsize} \NC number \NC 0 \NC initial size of \LUA\ functions table \NC \NR \NC \type {errorlinesize} \NC number \NC 79 \NC how much or an error is shown \NC \NR \NC \type {halferrorlinesize} \NC number \NC 50 \NC idem \NC \NR \ML \NC \type {formatname} \NC string \NC \NC \NC \NR \NC \type {jobname} \NC string \NC \NC \NC \NR \ML \NC \type {starttime} \NC number \NC \NC for testing only \NC \NR \NC \type {useutctime} \NC number \NC \NC for testing only \NC \NR \NC \type {permitloadlib} \NC number \NC \NC for testing only \NC \NR \LL \stoptabulate If no format name or jobname is given on the command line, the related keys will be tested first instead of simply quitting. The statistics library has methods for tracking down how much memory is available and has been configured. The size parameters take a number (for the maximum allocated size) or a table with three possible keys: \type {size}, \type {plus} (for extra size) and \type {step} for the increment when more memory is needed. They all start out with a hard coded minimum and also have an hard coded maximum, the the configured size sits somewhere between these. \stopsection \startsection[title={Input and output}] This library takes care of the low|-|level I/O interface: writing to the log file and|/|or the console. The log file is registered with the following function: \starttyping[option=LUA] function texio.setlogfile ( handle ) -- no return values end \stoptyping When \TEX\ serializes something it uses a seslector to determine where it goes. The public selectors are: \getbuffer[engine:syntax:selectorvalues] Internal we have a string selector, \LUA\ buffer selector, and a so called pseudo selector that is used when we want to show the context of an error and that keeps track of the position. These are not opened up. We start with \type {texio.write}. Without the \type {target} argument, it writes all given strings to the same location(s) that \TEX\ writes messages to at that moment. If \type {\batchmode} is in effect, it writes only to the log, otherwise it writes to the log and the terminal. A target can be a number or string. \starttyping[option=LUA] function texio.write ( target, s, ...) -- no return values end function texio.write ( s, ... ) -- no return values end \stoptyping If several strings are given, and if the first of these strings is or might be one of the targets above, the \type {target} must be specified explicitly to prevent \LUA\ from interpreting the first string as the target. The next function behaves like the above, but makes sure that the given strings will appear at the beginning of a new line. You can pass a single empty string if you only want to move to the next line. One reason why log output can slow down a run is that the engine works piecewise instead of printing lines. Deep down many writes go character by character because messages can occur everywhere during the expansion process. \starttyping[option=LUA] function texio.writenl ( s, ... ) -- no return values end \stoptyping The selector variants below always expect a selector, so there is no misunderstanding if \type {logfile} is a string or selector. \starttyping[option=LUA] function texio.writeselector ( s, ... ) -- no return values end function texio.writeselectornl ( s, ... ) -- no return values end function texio.writeselectorlf ( s, ... ) -- no return values end \stoptyping The next function should be used with care. It acts as \type {\endinput} but at the \LUA\ end. You can use it to (sort of) force a jump back to \TEX. Normally a \LUA\ call will just collect prints and at the end bump an input level and flush these prints. This function can help you stay at the current level but you need to know what you're doing (or more precise: what \TEX\ is doing with input). \starttyping[option=LUA] function texio.closeinput ( ) -- no return values end \stoptyping % These are temporary helpers, for testing only: % % getinputindex % getsourcefilename % forceendoffile \stopsection \stopdocument % musical timestamp: the french band lazulli, end october 2024 in de boerderij % (zoetermeer nl) ... as usual a pretty good performance, also sound wise; let's % hope we finish this manual before we see rendezvous point in the same venue end % march 2025