cld-afewdetails.tex /size: 8848 b    last modification: 2023-12-21 09:43
1% language=us runpath=texruns:manuals/cld
2
3\startcomponent cld-afewdetails
4
5\environment cld-environment
6
7\startchapter[title=A few Details]
8
9\startsection[title=Variables]
10
11\index{user interface}
12
13Normally it makes most sense to use the English version of \CONTEXT. The
14advantage is that you can use English keywords, as in:
15
16\starttyping
17context.framed( {
18    frame = "on",
19  },
20  "some text"
21)
22\stoptyping
23
24If you use the Dutch interface it looks like this:
25
26\starttyping
27context.omlijnd( {
28    kader = "aan",
29  },
30  "wat tekst"
31)
32\stoptyping
33
34A rather neutral way is:
35
36\starttyping
37context.framed( {
38    frame = interfaces.variables.on,
39  },
40  "some text"
41)
42\stoptyping
43
44But as said, normally you will use the English user interface so you can forget
45about these matters. However, in the \CONTEXT\ core code you will often see the
46variables being used this way because there we need to support all user
47interfaces.
48
49\stopsection
50
51\startsection[title=Modes]
52
53\index{modes}
54\index{systemmodes}
55\index{constants}
56
57Context carries a concept of modes. You can use modes to create conditional
58sections in your style (and|/|or content). You can control modes in your styles
59or you can set them at the command line or in job control files. When a mode test
60has to be done at processing time, then you need constructs like the following:
61
62\starttyping
63context.doifmodeelse( "screen",
64  function()
65      ... -- mode == screen
66  end,
67  function()
68      ... -- mode ~= screen
69  end
70)
71\stoptyping
72
73However, often a mode does not change during a run, and then we can use the
74following method:
75
76\starttyping
77if tex.modes["screen"] then
78  ...
79else
80  ...
81end
82\stoptyping
83
84Watch how the \type {modes} table lives in the \type {tex} namespace. We also
85have \type {systemmodes}. At the \TEX\ end these are mode names preceded by a
86\type {*}, so the following code is similar:
87
88\starttyping
89if tex.modes["*mymode"] then
90  -- this is the same
91elseif tex.systemmodes["mymode"] then
92  -- test as this
93else
94  -- but not this
95end
96\stoptyping
97
98Inside \CONTEXT\ we also have so called constants, and again these can be
99consulted at the \LUA\ end:
100
101\starttyping
102if tex.constants["someconstant'] then
103  ...
104else
105  ...
106end
107\stoptyping
108
109But you will hardly need these and, as they are often not public, their
110meaning can change, unless of course they {\em are} documented as public.
111
112\stopsection
113
114\startsection[title={Token lists}]
115
116\index{tokens}
117
118There is normally no need to mess around with nodes and tokens at the \LUA\ end
119yourself. However, if you do, then you might want to flush them as well. Say that
120at the \TEX\ end we have said:
121
122\startbuffer
123\toks0 = {Don't get \inframed{framed}!}
124\stopbuffer
125
126\typebuffer \getbuffer
127
128Then at the \LUA\ end you can say:
129
130\startbuffer
131context(tex.toks[0])
132\stopbuffer
133
134\typebuffer
135
136and get: \ctxluabuffer\ In fact, token registers are exposed as strings so here,
137register zero has type \type {string} and is treated as such.
138
139\startbuffer
140context("< %s >",tex.toks[0])
141\stopbuffer
142
143\typebuffer
144
145This gives: \ctxluabuffer. But beware, if you go the reverse way, you don't get
146what you might expect:
147
148\startbuffer
149tex.toks[0] = [[\framed{oeps}]]
150\stopbuffer
151
152\typebuffer \ctxluabuffer
153
154If we now say \type{\the\toks0} we will get {\tttf \the\toks0} as
155all tokens are considered to be letters.
156
157\stopsection
158
159\startsection[title={Node lists}]
160
161\index{nodes}
162
163If you're not deep into \TEX\ you will never feel the need to manipulate node
164lists yourself, but you might want to flush boxes. As an example we put something
165in box zero (one of the scratch boxes).
166
167\startbuffer
168\setbox0 = \hbox{Don't get \inframed{framed}!}
169\stopbuffer
170
171\typebuffer \getbuffer
172
173At the \TEX\ end you can flush this box (\type {\box0}) or take a copy
174(\type{\copy0}). At the \LUA\ end you would do:
175
176\starttyping
177context.copy()
178context.direct(0)
179\stoptyping
180
181or:
182
183\starttyping
184context.copy(false,0)
185\stoptyping
186
187but this works as well:
188
189\startbuffer
190context(node.copylist(tex.box[0]))
191\stopbuffer
192
193\typebuffer
194
195So we get: \ctxluabuffer\ If you do:
196
197\starttyping
198context(tex.box[0])
199\stoptyping
200
201you also need to make sure that the box is freed but let's not go into those
202details now.
203
204Here is an example if messing around with node lists that get seen before a
205paragraph gets broken into lines, i.e.\ when hyphenation, font manipulation etc
206take place. First we define some colors:
207
208\startbuffer
209\definecolor[mynesting:0][r=.6]
210\definecolor[mynesting:1][g=.6]
211\definecolor[mynesting:2][r=.6,g=.6]
212\stopbuffer
213
214\typebuffer \getbuffer
215
216Next we define a function that colors nodes in such a way that we can see the
217different processing stages.
218
219\startbuffer
220\startluacode
221local enabled  = false
222local count    = 0
223local setcolor = nodes.tracers.colors.set
224
225function userdata.processmystuff(head)
226    if enabled then
227        local color = "mynesting:" .. (count % 3)
228     -- for n in node.traverse(head) do
229        for n in node.traverseid(nodes.nodecodes.glyph,head) do
230            setcolor(n,color)
231        end
232        count = count + 1
233        return head, true
234    end
235    return head, false
236end
237
238function userdata.enablemystuff()
239    enabled = true
240end
241
242function userdata.disablemystuff()
243    enabled = false
244end
245\stopluacode
246\stopbuffer
247
248\typebuffer \getbuffer
249
250We hook this function into the normalizers category of the processor callbacks:
251
252\startbuffer
253\startluacode
254nodes.tasks.appendaction("processors", "normalizers", "userdata.processmystuff")
255\stopluacode
256\stopbuffer
257
258\typebuffer \getbuffer
259
260We now can enable this mechanism and show an example:
261
262\startbuffer
263\startbuffer
264Node lists are processed \hbox {nested from \hbox{inside} out} which is not
265what you might expect. But, \hbox{coloring} does not \hbox {happen} really
266nested here, more \hbox {in} \hbox {the} \hbox {order} \hbox {of} \hbox
267{processing}.
268\stopbuffer
269
270\ctxlua{userdata.enablemystuff()}
271\par \getbuffer \par
272\ctxlua{userdata.disablemystuff()}
273\stopbuffer
274
275\typebuffer
276
277The \type {\par} is needed because otherwise the processing is already disabled
278before the paragraph gets seen by \TEX.
279
280\blank \getbuffer \blank
281
282\startbuffer
283\startluacode
284nodes.tasks.disableaction("processors", "userdata.processmystuff")
285\stopluacode
286\stopbuffer
287
288\typebuffer
289
290Instead of using an boolean to control the state, we can also do this:
291
292\starttyping
293\startluacode
294local count    = 0
295local setcolor = nodes.tracers.colors.set
296
297function userdata.processmystuff(head)
298    count = count + 1
299    local color = "mynesting:" .. (count % 3)
300    for n in node.traverseid(nodes.nodecodes.glyph,head) do
301        setcolor(n,color)
302    end
303    return head, true
304end
305
306nodes.tasks.appendaction("processors", "after", "userdata.processmystuff")
307\stopluacode
308\stoptyping
309
310\startbuffer
311\startluacode
312nodes.tasks.disableaction("processors", "userdata.processmystuff")
313\stopluacode
314\stopbuffer
315
316Disabling now happens with:
317
318\typebuffer \getbuffer
319
320As you might want to control these things in more details, a simple helper
321mechanism was made: markers. The following example code shows the way:
322
323\startbuffer
324\definemarker[mymarker]
325\stopbuffer
326
327\typebuffer \getbuffer
328
329Again we define some colors:
330
331\startbuffer
332\definecolor[mymarker:1][r=.6]
333\definecolor[mymarker:2][g=.6]
334\definecolor[mymarker:3][r=.6,g=.6]
335\stopbuffer
336
337\typebuffer \getbuffer
338
339The \LUA\ code like similar to the code presented before:
340
341\startbuffer
342\startluacode
343local setcolor   = nodes.tracers.colors.setlist
344local getmarker  = nodes.markers.get
345local hlist_code = nodes.nodecodes.hlist
346local traverseid = node.traverseid
347
348function userdata.processmystuff(head)
349    for n in traverseid(hlist_code,head) do
350        local m = getmarker(n,"mymarker")
351        if m then
352            setcolor(n.list,"mymarker:" .. m)
353        end
354    end
355    return head, true
356end
357
358nodes.tasks.appendaction("processors", "after", "userdata.processmystuff")
359nodes.tasks.disableaction("processors", "userdata.processmystuff")
360\stopluacode
361\stopbuffer
362
363\typebuffer \getbuffer
364
365This time we disabled the processor (if only because in this document we don't
366want the overhead.
367
368\startbuffer
369\startluacode
370nodes.tasks.enableaction("processors", "userdata.processmystuff")
371\stopluacode
372
373Node lists are processed \hbox \boxmarker{mymarker}{1} {nested from \hbox{inside}
374out} which is not what you might expect. But, \hbox {coloring} does not \hbox
375{happen} really nested here, more \hbox {in} \hbox \boxmarker{mymarker}{2} {the}
376\hbox {order} \hbox {of} \hbox \boxmarker{mymarker}{3} {processing}.
377
378\startluacode
379nodes.tasks.disableaction("processors", "userdata.processmystuff")
380\stopluacode
381\stopbuffer
382
383\typebuffer
384
385The result looks familiar:
386
387\getbuffer
388
389% We don't want the burden of this demo to cary on:
390
391% {\em If there's enough interest I will expand this section with some basic
392% information on what nodes are.}
393
394\stopsection
395
396\stopchapter
397
398\stopcomponent
399