x-asciimath.mkxl /size: 18 Kb    last modification: 2024-01-16 10:22
1%D \module
2%D   [       file=x-asciimath,
3%D        version=2014.06.01, % 2006.04.24, % 1999.11.06,
4%D          title=\CONTEXT\ Modules,
5%D       subtitle=AsciiMath,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\registerctxluafile{x-asciimath}{autosuffix}
15
16%D When the Math4All project started, we immediately started using content \MATHML.
17%D Because in school math there is often a reference to calculator input, we also
18%D provided what we called \quote {calcmath}: a predictable expression based way
19%D entering math. At some point \OPENMATH\ was also used but that was later
20%D abandoned because editing is more cumbersome.
21%D
22%D Due to limitations in the web variant (which is independent of rendering for
23%D paper but often determines the coding of document, not seldom for the worse) the
24%D switch was made to presentational \MATHML. But even that proved to be too complex
25%D for rendering on the web, so it got converted to so called \ASCIIMATH\ which
26%D can be rendered using some \JAVASCRIPT\ magic. However, all the formulas (and
27%D we're talking of tens of thousands of them) were very precisely coded by the main
28%D author. Because in intermediate stages of the editing (by additional authors) a
29%D mixture of \MATHML\ and \ASCIIMATH\ was used, we wrote the first version of this
30%D module. As reference we took \url
31%D {http://www1.chapman.edu/~jipsen/mathml/asciimath.html} and. The idea was to
32%D stick to \MATHML\ as reference and if needed use \ASCIIMATH\ as annotation.
33%D
34%D Eventually we ended up with supporting several math encodings in \CONTEXT\ that
35%D could be used mixed: content \MATHML\ (preferred), presentation \MATHML\ (often
36%D messy), \OPENMATH\ (somewhat minimalistic) calcmath (handy for students who are
37%D accustomed to calculators), \ASCIIMATH\ (to make web support easier) and of
38%D course \TEX.
39%D
40%D The first version had some limitations as we didn't want to support all quirks of
41%D \ASCIIMATH\ and also because I was not really in the mood to write a complex parser
42%D when a bit of sane coding can work equally well. Some comments from that version:
43%D
44%D \startnarrower
45%D \startitemize
46%D \item We support only the syntactically clear variants and as long as lpeg does
47%D       not support left recursion this is as far as we want to go.
48%D \item The parser is rather insensitive for spaces but yet the advice is to avoid
49%D       weird coding like \type {d/dxf(x)} but use \type {d/dx f(x)} instead. After
50%D       all we're not in a compact coding cq.\ parser challenge.
51%D \item We also don't support the somewhat confusing \type {sqrt sqrt 2} nor \type
52%D       {root3x} (although the second one kind of works). A bit of defensive coding
53%D       does not hurt.
54%D \item We can process \type {a/b/c/d} but it's not compatible with the default
55%D       behaviour of \ASCIIMATH. Use grouping instead. Yes, we do support the somewhat
56%D       nonstandard grouping token mix.
57%D \item You should use explicit \type {text(..)} directives as one can never be sure
58%D       what is a reserved word and  not.
59%D \stopitemize
60%D
61%D Actually, as the only parsing sensitive elements of \TEX\ are fractions (\type {\over}
62%D and friends, a restricted use of \TEX\ coding is probably as comprehensive and
63%D parsable. The webpage with examples served as starting point so anything beyond
64%D what can be found there isn't supported.
65%D \stopnarrower
66%D
67%D Then in 2014 something bad happened. Following the fashion of minimal encoding
68%D (which of course means messy encoding of complex cases and which can make authors
69%D sloppy too) the web based support workflow of the mentioned project ran into some
70%D limitations and magically one day all carefully coded \MATHML\ was converted into
71%D \ASCIIMATH. As there was no way to recover the original thousands of files and
72%D tens of thousands of formulas we were suddenly stuck with \ASCIIMATH. Because the
73%D conversion had be done automagically, we also saw numerous errors and were forced
74%D to come up with some methods to check formulas. Because \MATHML\ poses some
75%D restrictions it has predictable rendering; \ASCIIMATH\ on the other hand enforces
76%D no structure. Also, because \MATHML\ has to be valid \XML\ it always processes.
77%D Of course, during the decade that the project had run we also had to built in
78%D some catches for abuse but at least we had a relatively stable and configurable
79%D subsystem. So, in order to deal with less predictable cases as well as extensive
80%D checking, a new \ASCIIMATH\ parser was written, one that could also be used to
81%D trace bad coding.
82%D
83%D Because the formal description is incomplete, and because some links to resources
84%D are broken, and because some testing on the web showed that sequences of characters
85%D are interpreted that were not mentioned anywhere (visible), and because we noticed
86%D that the parser was dangerously tolerant, the new code is quite different from the
87%D old code.
88%D
89%D One need to keep in mind that because spaces are optional, the only robust way to
90%D edit \ASCIIMATH\ is to use a \WYSIWYG\ editor and hope that the parser doesn't
91%D change ever. Keys are picked up from spaceless sequences and when not recognized
92%D a (sequence) of characters is considered to be variables. So, \type {xsqrtx} is
93%D valid and renders as \type {$x\sqrt{x}$}, \type {xx} becomes \type {×} (times)
94%D but \type {ac} becomes \type {$a c$} (a times c). We're lucky that \type {AC} is
95%D not turned into Alternating Current, but who knows what happens a few years from
96%D now. So, we do support this spaceless mess, but users are warned: best use a
97%D spacy sequence. The extra amount of spaces (at one byte each) an author has to
98%D include in his|/|her active writing time probably stays below the size of one
99%D holiday picture. Another complication is that numbers (in Dutch) use commas instead
100%D of periods, but vectors use commas as well. We also hav esome different names for
101%D functions which then can conflict with the expectations about collapsed variables.
102%D
103%D It must be noted that simplified encodings (that seem to be the fashion today)
104%D can demand from applications to apply fuzzy logic to make something work out
105%D well. Because we have sequential data that gets rendered, sometimes wrong input
106%D gets obscured simply by the rendering: like the comma's in numbers as well as
107%D for separators (depending on space usage), or plain wrong symbols that somehow
108%D get a representation anyway. This in itself is more a side effect of trying to
109%D use the simplified encoding without applying rules (in the input) or to use it
110%D beyong its intended usage, which then of course can lead to adapted parsers and
111%D catches that themselves trigger further abuse. Imagine that instead of developing
112%D new cars, planes, space ships, mobile phones, computers we would have adapted
113%D horse cars, kites, firework, old fashioned phones and mechanical calculators in a
114%D similar way: patch upon patch of traditional means for sure would not have
115%D worked. So, when you use \ASCIIMATH\ best check immediately how it gets rendered
116%D in the browser as well as on paper. And be prepared to check the more complex
117%D code in the future again. We don't offer any guarantees but of course will try to
118%D keep up.
119%D
120%D In retrospect I sometimes wonder if the energy put into constantly adapting to
121%D the fashion of the day pays off. Probably not. It definitely doesn't pay of.
122%D
123%D More complex crap:
124%D
125%D 1: $x + \stackrel{comment}{\stackrel{\utfchar{"23DE}}{yyyyyyyy}} = y$ \blank
126%D 2: \asciimath{x + stackrel{\utfchar{"23DE}}{yyyyyyyy} = y} \blank
127%D 3: \asciimath{x + stackrel{yyyyyyyy}{\utfchar{"23DE}} = y} \blank
128%D 4: \asciimath{x + stackrel{"comment"}{stackrel{\utfchar{"23DE}}{yyyyyyyy}} = y} \blank
129
130\usemodule[mathml-basics]
131
132\startmodule[asciimath]
133
134\unprotect
135
136\writestatus{asciimath}{beware, this is an experimental (m4all only) module}
137
138%D Hacks:
139
140\permanent\protected\def\asciimathoptext        #1{\ifmmode\mathoptext{#1}\else#1\fi}
141\permanent\protected\def\asciimathoptexttraced  #1{\ifmmode\mathoptext{\color[darkgreen]{#1}}\else\color[darkgreen]{#1}\fi}
142\permanent\protected\def\asciimathstackrel    #1#2{\mathematics{\mathop{\math_relax_limits\mover{#2}{#1}}}}
143\permanent\protected\def\asciimathroot        #1#2{\sqrt[#1]{#2}}
144\permanent\protected\def\asciimathsqrt          #1{\sqrt{#1}}
145
146%D The core commands:
147
148\installsetuponlycommandhandler {asciimath} {asciimath}
149
150\appendtoks
151    \ctxlua{moduledata.asciimath.setup {
152        splitmethod = "\asciimathparameter\c!splitmethod",
153        separator   = "\asciimathparameter\c!separator",
154        symbol      = "\asciimathparameter\c!symbol",
155    }}%
156\to \everysetupasciimath
157
158\newtoks\everyasciimath
159
160% \appendtoks
161%     \ignorediscretionaries % yes or no
162% \to \everyasciimath
163
164% \appendtoks
165%     \enableautofences
166%     \enableautofencemode
167% \to \everyasciimath
168
169\permanent\tolerant\protected\def\asciimath[#1]#:#2%
170  {\mathematics
171    [#1]%
172    {\expand\everyasciimath
173     \clf_texasciimath{\detokenize\expandafter{\normalexpanded{#2}}}}}
174
175\permanent\tolerant\protected\def\xmlasciimath[#1]#:#2%
176  {\mathematics
177    [#1]%
178    {\expand\everyasciimath
179     \clf_xmlasciimath{#2}}}
180
181\permanent\protected\def\ctxmoduleasciimath#1%
182  {\ctxlua{moduledata.asciimath.#1}}
183
184%D Some tracing commands. Using tex commands is 10\% slower that directly piping
185%D from \LUA, but this is non|-|critical code.
186
187\permanent\protected\def\ShowAsciiMathLoad  [#1]{\ctxlua{moduledata.asciimath.show.load("#1")}}
188\permanent\protected\def\ShowAsciiMathIgnore[#1]{\ctxlua{moduledata.asciimath.show.ignore("#1")}}
189\permanent\protected\def\ShowAsciiMathXML   #1#2{\ctxlua{moduledata.asciimath.show.filter("#1","#2")}}
190\permanent\protected\def\ShowAsciiMathStats     {\ctxlua{moduledata.asciimath.show.statistics()}}
191\permanent\protected\def\ShowAsciiMathMax       {\ctxlua{moduledata.asciimath.show.max()}}
192
193\permanent\protected\def\ShowAsciiMathResult#1%
194  {\begingroup
195     \blank
196     % if we are in vmode, we don't get positions i.e. a smaller tuc file
197     \inleft{\ttbf#1\hfill\ctxlua{moduledata.asciimath.show.count(#1,true)}}%
198     \dontleavehmode
199     \begingroup
200       \ttbf
201       \ctxlua{moduledata.asciimath.show.files(#1)}
202     \endgroup
203     \blank[\v!medium,\v!samepage]
204     \startcolor[darkblue]
205     \ctxlua{moduledata.asciimath.show.input(#1,true)}
206     \stopcolor
207     \blank[medium,samepage]
208     \doifmode{asciimath:show:dirty} {
209        \dorecurse{\ctxlua{moduledata.asciimath.show.nofdirty(#1)}} {
210          \ctxlua{moduledata.asciimath.show.dirty(\recurselevel,true)}
211          \blank[\v!medium,\v!samepage]
212        }
213     }
214     \ctxlua{moduledata.asciimath.show.result(#1)}
215     \blank
216   \endgroup}
217
218\permanent\protected\def\ShowAsciiMathStart
219  {\begingroup
220   \let\asciimathoptext\asciimathoptexttraced
221   \setuptyping[\v!buffer][\c!before=,\c!after=]
222   \setupmargindata[\v!left][\c!style=]}
223
224\permanent\protected\def\ShowAsciiMathStop
225  {\endgroup}
226
227\permanent\tolerant\protected\def\ShowAsciiMath[#1]#*[#2]%
228  {\ifparameter#1\or
229     \ShowAsciiMathStart
230     \ShowAsciiMathLoad[#1]
231     \ifparameter#2\or
232       \ShowAsciiMathIgnore[#2]
233     \fi
234     \dorecurse{\ShowAsciiMathMax}{\ShowAsciiMathResult\recurselevel}
235     \page
236     \ShowAsciiMathStats
237     \ShowAsciiMathStop
238  \fi}
239
240\permanent\protected\def\xmlShowAsciiMath#1#2%
241  {\ifparameter#1\or
242     \ShowAsciiMathStart
243     \ShowAsciiMathXML{#1}{#2}%
244     \dorecurse{\ShowAsciiMathMax}{\ShowAsciiMathResult\recurselevel}
245     \page
246     \ShowAsciiMathStats
247     \ShowAsciiMathStop
248  \fi}
249
250\permanent\tolerant\protected\def\ShowAsciiMathSave[#1]%
251  {\ctxlua{moduledata.asciimath.show.save("#1")}}
252
253% extras:
254
255% if not then we need an extra class
256
257% \inherited\setmathspacing \mathclosecode \mathmiddlecode \alldisplaystyles \thickmuskip
258% \inherited\setmathspacing \mathclosecode \mathmiddlecode \allunsplitstyles \pettymuskip
259
260\protect
261
262\startsetups asciimath:layout
263
264    \setupbodyfont
265    % [pagella,10pt]
266      [dejavu,10pt]
267
268    \setuplayout
269      [backspace=35mm,
270       leftmargin=20mm,
271       rightmargindistance=0pt,
272       leftmargindistance=5mm,
273       cutspace=1cm,
274       topspace=1cm,
275       bottomspace=1cm,
276       width=middle,
277       height=middle,
278       header=0cm,
279       footer=1cm]
280
281    \setupheadertexts
282      []
283
284    \setupfootertexts
285      [\currentdate][\pagenumber]
286
287    \setupalign
288      [flushleft,verytolerant,stretch]
289
290    \dontcomplain
291
292\stopsetups
293
294\stopmodule
295
296\continueifinputfile{x-asciimath.mkxl}
297
298%D This will become an extra.
299
300\starttext
301
302\setups[asciimath:layout]
303
304% \enabletrackers[modules.asciimath.mapping]
305% \enabletrackers[modules.asciimath.detail]
306
307% \starttext
308%     \enablemode[asciimath:show:dirty]
309%     \ShowAsciiMath[e:/temporary/asciimath/*.xml]
310%   % \ShowAsciiMathSave[e:/temporary/asciimath/asciimath.lua]
311% \stoptext
312
313\subject{Some tests}
314
315\enabletrackers[modules.asciimath.mapping]
316
317\showglyphs
318
319\asciimath{x + (a/b)//(d/c) + x}
320
321% $\mathoptext{\meaning|!}$
322
323\asciimath{a text(|) b}
324
325% a \asciimathoptext{{|}} b
326
327% {\left.{\left\lparent \frac{a}{b} \right\rparent}\middle/{\left\lparent \frac{d}{c} \right\rparent}\right.}
328% \vfrac
329 %   {\left.{\left\lparent \frac{a}{b} \right\rparent}}
330 %   {{\left\lparent \frac{d}{c} \right\rparent}\right.}
331
332% \protected\def\MyAsciiMath#1{\startformula\asciimath{#1}\stopformula}
333%
334% \startlines
335% \MyAsciiMath{x^2 / 10 // z_12^34 / 20}
336% \MyAsciiMath{{:{:x^2:} / 10:} // {:{:z_12^34 :} / 20:}}
337% \MyAsciiMath{x^2+y_1+z_12^34}
338% \MyAsciiMath{sin^-1(x)}
339% \MyAsciiMath{d/dx f(x)=lim_(h->0) (f(x+h)-f(x))/h}
340% \MyAsciiMath{f(x)=sum_(n=0)^oo(f^((n))(a))/(n!)(x-a)^n}
341% \MyAsciiMath{int_0^1 f(x)dx}
342% \MyAsciiMath{int^1_0 f(x)dx}
343% \MyAsciiMath{a//b}
344% \MyAsciiMath{a//\alpha}
345% \MyAsciiMath{(a/b)/(d/c)}
346% \MyAsciiMath{((a*b))/(d/c)}
347% \MyAsciiMath{[[a,b],[c,d]]((n),(k))}
348% \MyAsciiMath{1/x={(1,text{if } x!=0),(text{undefined},if x=0):}}
349% \MyAsciiMath{{ (1,2), (x,(x + text(x))) }}
350% \MyAsciiMath{{(1,2),(x,(x+text(x))),(x,text(x))}}
351% \MyAsciiMath{{(1,2),(x,(x+text(x))),(x,x text(x))}}
352% \MyAsciiMath{{(1,2/2),(x,(x+x^22+sqrt(xx))),(x,x text(xyz))}}
353% \MyAsciiMath{{(1,2/2),(x,(x+x^22+sqrt(xx))),(x,text(xyz)+1+text(hans))}}
354% \MyAsciiMath{<<a,b>> text{and} {:(x,y),(u,v):}}
355% \MyAsciiMath{(a,b] = {x text(in) RR | a < x <= b}}
356% \MyAsciiMath{a/b / c/d = (a * d) / (b * d) / (b * c) / (b * d) = (a * d) / (b * c)}
357% \MyAsciiMath{ (a/b) // (c/d) =  ( (a * d) / (b * d) ) // ( (b * c) / (b * d) ) = (a * d) / (b * c)}
358% \MyAsciiMath{sin(x+1)_3^2/b / c/d}
359% \MyAsciiMath{{:{:sin(x+1)_3^2:}/b:} / {:c/d:}}
360% \MyAsciiMath{cos(a) + sin(x+1)_3^2/b / c/d = (a * d) / (b * d) / (b * c) / (b * d) = (a * d) / (b * c)}
361% \MyAsciiMath{S_(11)}
362% \MyAsciiMath{f(x)}
363% \MyAsciiMath{sin(x)}
364% \MyAsciiMath{sin(x+1)}
365% \MyAsciiMath{sin^-1(x)}
366% \MyAsciiMath{sin(2x)}
367% \MyAsciiMath{a_2^2}
368% \MyAsciiMath{( (S_(11),S_(12),S_(1n)),(vdots,ddots,vdots),(S_(m1),S_(m2),S_(mn)) ]}
369% \MyAsciiMath{frac a b}
370% \MyAsciiMath{sin(x)/2 // cos(x)/pi}
371% \MyAsciiMath{a/13 // c/d}
372% \MyAsciiMath{a/b // c/d}
373% \MyAsciiMath{x}
374% \MyAsciiMath{x^2}
375% \MyAsciiMath{sqrt x}
376% \MyAsciiMath{sqrt (x)}
377% \MyAsciiMath{root 2 x}
378% \MyAsciiMath{x+x}
379% \MyAsciiMath{x/3}
380% \MyAsciiMath{x^2 / 10}
381% \MyAsciiMath{x^2 / 10 // z_12^34 / 20}
382% \MyAsciiMath{a^23}
383% \MyAsciiMath{a^{:b^23:}+3x}
384% \MyAsciiMath{a/b / c/d}
385% \MyAsciiMath{sin(x)/b / c/d}
386% \MyAsciiMath{sin(x)/b // c/d}
387% \MyAsciiMath{a/b / c/d = (a * d) / (b * d) / (b * c) / (b * d) = (a * d) / (b * c) }
388% \MyAsciiMath{{:{:x^2:} / 10:} // {:{:z_12^34 :} / 20:}}
389% \MyAsciiMath{x^2+y_1+z_12^34}
390% \MyAsciiMath{sin^-1(x)}
391% \MyAsciiMath{d/dx f(x)=lim_(h->0) (f(x+h)-f(x))/h}
392% \MyAsciiMath{f(x)=sum_(n=0)^oo(f^((n))(a))/(n!)(x-a)^n}
393% \MyAsciiMath{int_0^1 f(x)dx}
394% \MyAsciiMath{int^1_0 f(x)dx}
395% \MyAsciiMath{2x}
396% \MyAsciiMath{a//b}
397% \MyAsciiMath{a//\alpha}
398% \MyAsciiMath{(a/b)/(d/c)}
399% \MyAsciiMath{((a*b))/(d/c)}
400% \MyAsciiMath{[[a,b],[c,d]]((n),(k))}
401% \MyAsciiMath{1/x={(1,text{if } x!=0),(text{undefined},if x=0):}}
402% \MyAsciiMath{{ (1,2), (x,(x + text(x))) }}
403% \MyAsciiMath{{(1,2),(x,(x+text(x))),(x,text(x))}}
404% \MyAsciiMath{{(1,2),(x,(x+text(x))),(x,x text(x))}}
405% \MyAsciiMath{{(1,2/2),(x,(x+x^22+sqrt(xx))),(x,x text(xyz))}}
406% \MyAsciiMath{{(1,2/2),(x,(x+x^22+sqrt(xx))),(x,text(xyz)+1+text(hans))}}
407% \MyAsciiMath{<<a,b>> text{and} {:(x,y),(u,v):}}
408% \MyAsciiMath{(a,b] = {x text(in) RR | a < x <= b}}
409% \MyAsciiMath{x^-2}
410% \MyAsciiMath{x^2(x-1/16)=0}
411% \MyAsciiMath{y= ((1/4)) ^x}
412% \MyAsciiMath{log (0,002) / (log(1/4))}
413% \MyAsciiMath{x=ax+b \ oeps}
414% \MyAsciiMath{x=\ ^ (1/4) log(x)}
415% \MyAsciiMath{x=\ ^ (1/4) log(0 ,002 )= log(0,002) / (log(1/4))}
416% \MyAsciiMath{x^ (-1 1/2) =1/x^ (1 1/2)=1/ (x^1*x^ (1/2)) =1/ (xsqrt(x))}
417% \MyAsciiMath{x^2(10 -x)&gt;2 x^2}
418% \MyAsciiMath{x^4&gt;x}
419% \stoplines
420
421% \setupasciimath[splitmethod=3,symbol={{,}}]
422%
423% \startlines
424% \asciimath{sqrt 1}
425% \asciimath{sqrt 1.2}
426% \asciimath{sqrt 1.2}
427% \asciimath{1}
428% \asciimath{12}
429% \asciimath{123}
430% \asciimath{1234}
431% \asciimath{12345}
432% \asciimath{123456}
433% \asciimath{1234567}
434% \asciimath{12345678}
435% \asciimath{123456789}
436% \asciimath{1.1}
437% \asciimath{12.12}
438% \asciimath{1234.123}
439% \asciimath{1234.1234}
440% \asciimath{12345.1234}
441% \asciimath{1234.12345}
442% \asciimath{12345.12345}
443% \asciimath{123456.123456}
444% \asciimath{1234567.1234567}
445% \asciimath{12345678.12345678}
446% \asciimath{123456789.123456789}
447% \asciimath{0.1234}
448% \asciimath{1234.0}
449% \asciimath{1234.00}
450% \asciimath{0.123456789}
451% \stoplines
452
453% \definemixedcolumns[asciimath][n=3,balance=yes]
454%
455% \startluacode
456%     local asciimath = moduledata.asciimath
457%     local variables = { "w", "x", "y", "z", "p", "q", "r" }
458%     local constants = { "a", "b", "c" }
459%     local functions = { "g", "h", "i" }
460%     local iterators = { "i", "j", "k" }
461%     local vectors   = { "A", "B", "C", "D", "E", "P", "Q", "R" }
462%     local reserved  = { }
463%     local reserved  = {
464%      -- "vdots","ddots","oint",
465%         "grad", "prod", "prop", "sube", "supe", "sum",
466%         "vvv", "nnn", "uuu", "sub", "sup",
467%         "iff", "int", "del",
468%         "sinh", "cosh", "tanh", "sin", "cos", "tan", "csc", "sec", "cot",
469%         "atan", "asin", "acos", "arctan", "arcsin", "arccos",
470%         "log", "ln", "det", "lim", "mod", "gcd", -- "lcm",
471%         "min", "max",
472%         "xx", "in", "ox", "vv", "nn", "uu", "oo",  "bb",
473%         "not", "and", "or", "if",
474%         "AA", "EE", "TT",
475%         "sqrt", "root", "frac", "stackrel",
476%         "hat", "overbar", "underline", "vec",
477%         "dx", "dy", "dz",
478%     }
479%     for c=1,#constants do
480%         for r=1,#reserved do
481%             context.startmixedcolumns { "asciimath" }
482%             for v1=1,#variables do
483%                 for v2=1,#variables do
484%                     local str = constants[c] .. variables[v1] .. reserved[r] .. variables[v2]
485%                     context.type(str)
486%                     context.quad()
487%                     commands.asciimath(str)
488%                     context.par()
489%                 end
490%             end
491%             context.stopmixedcolumns()
492%             context.blank()
493%         end
494%     end
495% \stopluacode
496
497\stoptext
498