% language=us % TAKE FROM LOWLEVEL-EXPANSION.TEX \usemodule[system-tokens] \usemodule[present-boring,abbreviations-logos] \definehighlight[nb][style=bold,color=middlegray,define=no] \startdocument [title={PROGRAMMING}, banner={local control}, location={context\enspace {\bf 2021}\enspace meeting}] \starttitle[title=Expansion] \TEX\ can be in several so called input reading modes: Users mostly see it reading from the source file(s). Characters are picked up and interpreted. Depending on what token it becomes some action takes place. \starttyping 1 \setbox0\hbox to 10pt{2} \count0=3 \the\count0 \multiply\count0 by 4 \stoptyping \startitemize \startitem The \type {1} gets typeset because characters like that are seen as text. \stopitem \startitem The \type {\setbox} primitive triggers picking up a register number, then goes on scanning for a box specification and that itself will typeset a sequence of whatever until the group ends. \stopitem \startitem The \type {count} primitive triggers scanning for a register number (or reference) and then scans for a number; the equal sign is optional. \stopitem \startitem The \type {the} primitive injects some value into the current input stream (it does so by entering a new input level). \stopitem \startitem The \type {multiply} primitive picks up a register specification and multiplies that by the next scanned number. The \type {by} is optional. \stopitem \startitem Printing from \LUA\ and scanning tokens with e.g.\ \type {\scantokens} is like reading (pseudo) files. \stopitem \stopitemize \stoptitle \starttitle[title=Expansion] \startbuffer[def] \def\TestA {1 \setbox0\hbox{2} \count0=3 \the\count0} \stopbuffer \startbuffer[edef] \edef\TestB{1 \setbox0\hbox{2} \count0=3 \the\count0} \stopbuffer \typebuffer[def] \typebuffer[edef] \getbuffer[def] \getbuffer[edef] \blank[2*big] \startcolumns[n=2] \switchtobodyfont[8pt] \luatokentable\TestA \column \luatokentable\TestB \stopcolumns \stoptitle \starttitle[title=Local control] \startbuffer[edef] \edef\TestB{1 \setbox0\hbox{2} \count0=3 \the\count0} \stopbuffer \startbuffer[ldef] \edef\TestC{1 \setbox0\hbox{2} \localcontrolled{\count0=3} \the\count0} \stopbuffer \typebuffer[edef] \typebuffer[ldef] \getbuffer[edef] \getbuffer[ldef] \blank[2*big] \startcolumns[n=2] \switchtobodyfont[8pt] \luatokentable\TestB \column \luatokentable\TestC \stopcolumns \stoptitle \starttitle[title=Side effects] \startbuffer[edef] \edef\TestB{1 \setbox0\hbox{2} \count0=3 \the\count0} \stopbuffer \startbuffer[ldef] \edef\TestD{\localcontrolled{1 \setbox0\hbox{2} \count0=3 \the\count0}} \stopbuffer \typebuffer[edef] \typebuffer[ldef] \getbuffer[edef]\getbuffer[ldef]\quad{\darkgray\leftarrow\space Watch how the results end up here!} \blank[2*big] \startcolumns[n=2] \switchtobodyfont[8pt] \luatokentable\TestB \column \luatokentable\TestD \stopcolumns \stoptitle \starttitle[title=Usage] \startbuffer[def] \def\WidthOf#1% {\beginlocalcontrol \setbox0\hbox{#1}% \endlocalcontrol \wd0 } \stopbuffer \startbuffer[use] \scratchdimen\WidthOf{The Rite Of Spring} \the\scratchdimen \stopbuffer \typebuffer[def] \typebuffer[use] \getbuffer[def]\getbuffer[use] \stoptitle \starttitle[title=Not always pretty] \startbuffer[def] \def\WidthOf#1% {\dimexpr \beginlocalcontrol \begingroup \setbox0\hbox{#1}% \expandafter \endgroup \expandafter \endlocalcontrol \the\wd0 \relax} \stopbuffer \startbuffer[use] \scratchdimen\WidthOf{The Rite Of Spring} \the\scratchdimen \stopbuffer \typebuffer[def] \typebuffer[use] \getbuffer[def]\getbuffer[use] \stoptitle \starttitle[title=The \LUA\ end] Right from the start the way to get something into \TEX\ from \LUA\ has been the print functions. But we can also go local (immediate). There are several methods: \startitemize \startitem via a set token register \stopitem \startitem via a defined macro \stopitem \startitem via a string \stopitem \stopitemize Among the things to keep in mind are catcodes, scope and expansion (especially in when the result itself ends up in macros). \stoptitle \starttitle[title=Via a token register] % runlocal : macro|toks expand group \startbuffer[set] \toks0={\setbox0\hbox{The Rite Of Spring (Igor Stravinsky)}} \toks2={\setbox0\hbox{The Rite Of Spring (Joe Parrish)}} \stopbuffer \typebuffer[set] \startbuffer[run] \startluacode tex.runlocal(0) context("[1: %p]",tex.box[0].width) tex.runlocal(2) context("[2: %p]",tex.box[0].width) \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[set,run] \stop \stoptitle \starttitle[title=Via a token macro] \startbuffer[set] \def\TestA{\setbox0\hbox{The Rite Of Spring (Igor Stravinsky)}} \def\TestB{\setbox0\hbox{The Rite Of Spring (Joe Parrish)}} \stopbuffer \typebuffer[set] \startbuffer[run] \startluacode tex.runlocal("TestA") context("[3: %p]",tex.box[0].width) tex.runlocal("TestB") context("[4: %p]",tex.box[0].width) \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[set,run] \stop \stoptitle \starttitle[title=Via a string] \startbuffer[run] \startluacode tex.runstring([[\setbox0\hbox{The Rite Of Spring (Igor Stravinsky)}]]) context("[5: %p]",tex.box[0].width) tex.runstring([[\setbox0\hbox{The Rite Of Spring (Joe Parrish)}]]) context("[6: %p]",tex.box[0].width) \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[run] \stop \blank[2*big] A bit more high level: \starttyping context.runstring([[\setbox0\hbox{(Here \bf 1.2345)}]]) context.runstring([[\setbox0\hbox{(Here \bf %.3f)}]],1.2345) \stoptyping \stoptitle \starttitle[title=Locked in \LUA] \startbuffer[run] \startluacode token.setmacro("TestX",[[\setbox0\hbox{The Rite Of Spring (Igor)}]]) tex.runlocal("TestX") context("[7: %p]",tex.box[0].width) \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[run] \stop \startbuffer[run] \startluacode tex.scantoks(0,tex.ctxcatcodes,[[\setbox0\hbox{The Rite Of Spring (Joe)}]]) tex.runlocal(0) context("[8: %p]",tex.box[0].width) \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[run] \stop \stoptitle \starttitle[title=Order matters] A lot this relates to pushing stuff into the input which is stacked. Compare: \startbuffer[run] \startluacode context("[HERE 1]") context("[HERE 2]") \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[run] \stop with this: \startbuffer[run] \startluacode tex.pushlocal() context("[HERE 1]") tex.poplocal() tex.pushlocal() context("[HERE 2]") tex.poplocal() \stopluacode \stopbuffer \typebuffer[run] \start \getbuffer[run] \stop % \startluacode % tex.runlocal(function() context("[Here 1]") end) % context("[Here 12]") % tex.runlocal(function() context("[Here 2]") end) % \stopluacode % tex.pushlocal % swaps order % tex.poplocal % tex.quitlocal % token.expandmacro % str : serialized % true : wrap next {} % table : {serialzed} {serialzed} {serialzed} % token : inject % number: catcode table % tex.expandasvalue: % (kind, like expand_macro) % tex.runstring: % [catcode] string expand grouped % tex.runlocal % function|number(register)|string(macro)|userdata(token) / expand / grouped % mplib.expandtex % mpx, kind, macro, arguments \stopdocument