summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/mk/mk-code.tex
blob: e150531ebaf7cd0456e22dc9aadf61536bf97564 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
% language=uk

\startcomponent mk-code

\environment mk-environment

\chapter{User code}

Previous versions of \LUATEX\ had multiple \LUA\ instances but in
practice this was not that useful and therefore we decided to
remove that feature and stick to one instance. One reason is that
all activities take place in the zero instance anyway and other
instance could not access variables defined there. Another reason
was that every \type {\directlua} call is in fact a function call
(and as such a closure) and \LUATEX\ catches errors nicely.

The formal \type {\directlua} primitive originally can be called
in two ways:

\starttyping
\directlua <instance> {lua code}
\directlua name {some text} <instance> {lua code}
\stoptyping

The optional text is then part of the error message when one is
issued. The new approach is that the number is used for the error
message in case no \type {name} is specified. The exact string is
set in \LUA. This means that in principle the command is backward
compatible. Old usage will basically ignore the number and use
the one and only instance, while new usage will use the number for
an eventual message:

\starttyping
\directlua <message id> {lua code}
\directlua name {some text} <message id> {lua code}
\stoptyping

In the second case the id is ignored. The advantage of the first
call is that it saves tokens at the \TEX\ end and can be
configured at the \LUA\ end. In \CONTEXT\ \MKIV\ we have adapted
the code that invokes multiple instances by compatible code that
provides a modest form of isolation. We don't want to enforce too
many constraints, first of all because users will often use high
level interfaces anyway, and also because we assume that users have
no bad intentions.

The main \LUA\ instance in \CONTEXT\ is accessible by: \footnote {Note
2016: you can of course also use \type {context("lua")} here.}

\startbuffer
\startluacode
global.tex.print("lua")
\stopluacode
\stopbuffer

\typebuffer

This gives: \quote {\getbuffer}.

However, sometimes you don't want user code to interfere too much
with the main code but still provide access to useful data. This
is why we also provide:

\startbuffer
\startusercode
global.tex.print("user 1")
global.tex.print("user 2")
if characters then
    global.tex.print("access")
else
    global.tex.print("no access")
end
global.tex.print(global.characters.data[0xA9].contextname)
\stopusercode
\stopbuffer

\typebuffer

This gives: \quote {\getbuffer}.

If you're writing a module, you might want to reserve a private
namespace. This is done with:

\startbuffer
\definenamedlua[mymodule][my interesting module]
\stopbuffer

\typebuffer \getbuffer

Now we can say:

\startbuffer
\startmymodulecode
help = { "help" }
global.tex.print(help[1])
\stopmymodulecode
\stopbuffer

\typebuffer

This gives: \quote {\getbuffer}. The information is remembered:

\startbuffer
\startmymodulecode
global.tex.print(help[1])
\stopmymodulecode
\stopbuffer

\typebuffer

Indeed we get: \quote {\getbuffer}.

Just to check the isolation we try:

\startbuffer
\startusercode
global.tex.print(help and help[1] or "no help")
\stopusercode
\stopbuffer

\typebuffer

As expected this gives: \quote {\getbuffer} but when we do the
following we will get an error message:

\startbuffer
\startusercode
global.tex.print(help[1])
\stopusercode
\stopbuffer

\typebuffer

% {\batchmode \getbuffer} % somehow quits in context but not in texexec

\starttyping
! LuaTeX error <private user instance>:2: attempt to index global
'help' (a nil value)
stack traceback:
	<private user instance>:2: in main chunk.
<inserted text> ...userdata")
global.tex.print(help[1])
}
\stoptyping

An even more isolated variant is:

\startbuffer
\startisolatedcode
help = { "help" }
global.tex.print(help and help[1] or "no help")
\stopisolatedcode
\stopbuffer

\typebuffer

We get: \quote {\getbuffer}, while


\startbuffer
\startisolatedcode
global.tex.print(help and help[1] or "no help")
\stopisolatedcode
\stopbuffer

\typebuffer

gives: \quote {\getbuffer}.

You can get access to the global data of other named code blocks
by using the \type {global} prefix. At that level you have also
access to the instances, but this time we append \type {data}, so
\type {user} has a table \type {userdata}:

\startbuffer
\startmymodulecode
global.userdata.whatever = "be careful!"
\stopmymodulecode
\stopbuffer

For convenience we have made \type {tex} as well as some \LUA\ tables
directly accessible within an instance. However, we recommend not to
extend these yourself (even if we do it in the core of \MKIV).

% not yet ok:
%
% The next example is inspired by a question of Wolfgang Schuster who
% wanted to write a module. Say that we have a file \type {demo.lua}:
%
% \starttyping
% local demo = { }
%
% function demo.whow(str)
%     global.tex.print("[" .. string.reverse(str) .. "]")
% end
%
% return demo
% \stoptyping
%
% The module can be \type {demo.tex}:
%
% \starttyping
% \definenamedlua[demo][demo module example]
%
% \startdemocode
% demo = global.require("demo.lua")
% \stopdemocode
%
% \def\whow#1{\democode{demo.whow("#1"}}
% \stoptyping
%
% We can now use this module:
%
% \starttyping
% \usemodule[demo]
% \whow{123}
% \stoptyping

\stopcomponent