mk-code.tex /size: 5208 b    last modification: 2023-12-21 09:43
1% language=us
2
3\startcomponent mk-code
4
5\environment mk-environment
6
7\chapter{User code}
8
9Previous versions of \LUATEX\ had multiple \LUA\ instances but in
10practice this was not that useful and therefore we decided to
11remove that feature and stick to one instance. One reason is that
12all activities take place in the zero instance anyway and other
13instance could not access variables defined there. Another reason
14was that every \type {\directlua} call is in fact a function call
15(and as such a closure) and \LUATEX\ catches errors nicely.
16
17The formal \type {\directlua} primitive originally can be called
18in two ways:
19
20\starttyping
21\directlua <instance> {lua code}
22\directlua name {some text} <instance> {lua code}
23\stoptyping
24
25The optional text is then part of the error message when one is
26issued. The new approach is that the number is used for the error
27message in case no \type {name} is specified. The exact string is
28set in \LUA. This means that in principle the command is backward
29compatible. Old usage will basically ignore the number and use
30the one and only instance, while new usage will use the number for
31an eventual message:
32
33\starttyping
34\directlua <message id> {lua code}
35\directlua name {some text} <message id> {lua code}
36\stoptyping
37
38In the second case the id is ignored. The advantage of the first
39call is that it saves tokens at the \TEX\ end and can be
40configured at the \LUA\ end. In \CONTEXT\ \MKIV\ we have adapted
41the code that invokes multiple instances by compatible code that
42provides a modest form of isolation. We don't want to enforce too
43many constraints, first of all because users will often use high
44level interfaces anyway, and also because we assume that users have
45no bad intentions.
46
47The main \LUA\ instance in \CONTEXT\ is accessible by: \footnote {Note
482016: you can of course also use \type {context("lua")} here.}
49
50\startbuffer
51\startluacode
52global.tex.print("lua")
53\stopluacode
54\stopbuffer
55
56\typebuffer
57
58This gives: \quote {\getbuffer}.
59
60However, sometimes you don't want user code to interfere too much
61with the main code but still provide access to useful data. This
62is why we also provide:
63
64\startbuffer
65\startusercode
66global.tex.print("user 1")
67global.tex.print("user 2")
68if characters then
69    global.tex.print("access")
70else
71    global.tex.print("no access")
72end
73global.tex.print(global.characters.data[0xA9].contextname)
74\stopusercode
75\stopbuffer
76
77\typebuffer
78
79This gives: \quote {\getbuffer}.
80
81If you're writing a module, you might want to reserve a private
82namespace. This is done with:
83
84\startbuffer
85\definenamedlua[mymodule][my interesting module]
86\stopbuffer
87
88\typebuffer \getbuffer
89
90Now we can say:
91
92\startbuffer
93\startmymodulecode
94help = { "help" }
95global.tex.print(help[1])
96\stopmymodulecode
97\stopbuffer
98
99\typebuffer
100
101This gives: \quote {\getbuffer}. The information is remembered:
102
103\startbuffer
104\startmymodulecode
105global.tex.print(help[1])
106\stopmymodulecode
107\stopbuffer
108
109\typebuffer
110
111Indeed we get: \quote {\getbuffer}.
112
113Just to check the isolation we try:
114
115\startbuffer
116\startusercode
117global.tex.print(help and help[1] or "no help")
118\stopusercode
119\stopbuffer
120
121\typebuffer
122
123As expected this gives: \quote {\getbuffer} but when we do the
124following we will get an error message:
125
126\startbuffer
127\startusercode
128global.tex.print(help[1])
129\stopusercode
130\stopbuffer
131
132\typebuffer
133
134% {\batchmode \getbuffer} % somehow quits in context but not in texexec
135
136\starttyping
137! LuaTeX error <private user instance>:2: attempt to index global
138'help' (a nil value)
139stack traceback:
140	<private user instance>:2: in main chunk.
141<inserted text> ...userdata")
142global.tex.print(help[1])
143}
144\stoptyping
145
146An even more isolated variant is:
147
148\startbuffer
149\startisolatedcode
150help = { "help" }
151global.tex.print(help and help[1] or "no help")
152\stopisolatedcode
153\stopbuffer
154
155\typebuffer
156
157We get: \quote {\getbuffer}, while
158
159
160\startbuffer
161\startisolatedcode
162global.tex.print(help and help[1] or "no help")
163\stopisolatedcode
164\stopbuffer
165
166\typebuffer
167
168gives: \quote {\getbuffer}.
169
170You can get access to the global data of other named code blocks
171by using the \type {global} prefix. At that level you have also
172access to the instances, but this time we append \type {data}, so
173\type {user} has a table \type {userdata}:
174
175\startbuffer
176\startmymodulecode
177global.userdata.whatever = "be careful!"
178\stopmymodulecode
179\stopbuffer
180
181For convenience we have made \type {tex} as well as some \LUA\ tables
182directly accessible within an instance. However, we recommend not to
183extend these yourself (even if we do it in the core of \MKIV).
184
185% not yet ok:
186%
187% The next example is inspired by a question of Wolfgang Schuster who
188% wanted to write a module. Say that we have a file \type {demo.lua}:
189%
190% \starttyping
191% local demo = { }
192%
193% function demo.whow(str)
194%     global.tex.print("[" .. string.reverse(str) .. "]")
195% end
196%
197% return demo
198% \stoptyping
199%
200% The module can be \type {demo.tex}:
201%
202% \starttyping
203% \definenamedlua[demo][demo module example]
204%
205% \startdemocode
206% demo = global.require("demo.lua")
207% \stopdemocode
208%
209% \def\whow#1{\democode{demo.whow("#1"}}
210% \stoptyping
211%
212% We can now use this module:
213%
214% \starttyping
215% \usemodule[demo]
216% \whow{123}
217% \stoptyping
218
219\stopcomponent
220