cld-macros.tex /size: 5260 b    last modification: 2021-10-28 13:50
1% language=us runpath=texruns:manuals/cld
2
3\startcomponent cld-macros
4
5\environment cld-environment
6
7\startchapter[title=Macros]
8
9\startsection[title={Introduction}]
10
11You can skip this chapter if you're not interested in defining macros or are
12quite content with defining them in \TEX. It's just an example of possible future
13interface definitions and it's not the fastest mechanism around.
14
15\stopsection
16
17\startsection[title={Parameters}]
18
19Right from the start \CONTEXT\ came with several user interfaces. As a
20consequence you need to take this into account when you write code that is
21supposed to work with interfaces other than the English one. The \TEX\ command:
22
23\starttyping
24\setupsomething[key=value]
25\stoptyping
26
27and the \LUA\ call:
28
29\starttyping
30context.setupsomething { key = value }
31\stoptyping
32
33are equivalent. However, all keys at the \TEX\ end eventually become English, but
34the values are unchanged. This means that when you code in \LUA\ you should use
35English keys and when dealing with assigned values later on, you need to
36translate them of compare with translations (which is easier). This is why in the
37\CONTEXT\ code you will see:
38
39\starttyping
40if somevalue == interfaces.variables.yes then
41  ...
42end
43\stoptyping
44
45instead of:
46
47\starttyping
48if somevalue == "yes" then
49  ...
50end
51\stoptyping
52
53\stopsection
54
55\startsection[title={User interfacing}]
56
57Unless this is somehow inhibited, users can write their own macros and this is
58done in the \TEX\ language. Passing data to macros is possible and looks like
59this:
60
61\starttyping
62\def\test#1#2{.. #1 .. #2 .. }      \test{a}{b}
63\def\test[#1]#2{.. #1 .. #2 .. }    \test[a]{b}
64\stoptyping
65
66Here \type {#1} and \type {#2} represent an argument and there can be at most 9
67of them. The \type{[]} are delimiters and you can delimit in many ways so the
68following is also right:
69
70\starttyping
71\def\test(#1><#2){.. #1 .. #2 .. }  \test(a><b)
72\stoptyping
73
74Macro packages might provide helper macros that for instance take care of
75optional arguments, so that we can use calls like:
76
77\starttyping
78\test[1,2,3][a=1,b=2,c=3]{whatever}
79\stoptyping
80
81and alike. If you are familiar with the \CONTEXT\ syntax you know that we use
82this syntax all over the place.
83
84If you want to write a macro that calls out to \LUA\ and handles things at that
85end, you might want to avoid defining the macro itself and this is possible.
86
87\startbuffer
88\startluacode
89function test(opt_1, opt_2, arg_1)
90    context.startnarrower()
91    context("options 1: %s",interfaces.tolist(opt_1))
92    context.par()
93    context("options 2: %s",interfaces.tolist(opt_2))
94    context.par()
95    context("argument 1: %s",arg_1)
96    context.stopnarrower()
97end
98
99interfaces.definecommand {
100    name = "test",
101    arguments = {
102        { "option", "list" },
103        { "option", "hash" },
104        { "content", "string" },
105    },
106    macro = test,
107}
108\stopluacode
109
110test: \test[1][a=3]{whatever}
111\stopbuffer
112
113An example of a definition and usage at the \LUA\ end is:
114
115\typebuffer
116
117The call gives:
118
119\startpacked
120\getbuffer
121\stoppacked
122
123\startbuffer
124\startluacode
125local function startmore(opt_1)
126    context.startnarrower()
127    context("start more, options: %s",interfaces.tolist(opt_1))
128    context.startnarrower()
129end
130
131local function stopmore()
132    context.stopnarrower()
133    context("stop more")
134    context.stopnarrower()
135end
136
137interfaces.definecommand ( "more", {
138    environment = true,
139    arguments = {
140        { "option", "list" },
141    },
142    starter = startmore,
143    stopper = stopmore,
144} )
145\stopluacode
146
147more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
148\stopbuffer
149
150If you want to to define an environment (i.e.\ a \type {start}||\type {stop}
151pair, it looks as follows:
152
153\typebuffer
154
155This gives:
156
157\startpacked
158\getbuffer
159\stoppacked
160
161The arguments are know in both \type {startmore} and \type {stopmore} and nesting
162is handled automatically.
163
164\stopsection
165
166\startsection[title=Looking inside]
167
168If needed you can access the body of a macro. Take for instance:
169
170\startbuffer
171\def\TestA{A}
172\def\TestB{\def\TestC{c}}
173\def\TestC{C}
174\stopbuffer
175
176\typebuffer \getbuffer
177
178The following example demonstrates how we can look inside these macros. You need
179to be aware of the fact that the whole blob of \LUA\ codes is finished before we
180return to \TEX, so when we pipe the meaning of \type {TestB} back to \TEX\ it
181only gets expanded afterwards. We can use a function to get back to \LUA. It's
182only then that the meaning of \type {testC} is changed by the (piped) expansion
183of \type {TestB}.
184
185\startbuffer
186\startluacode
187context(tokens.getters.macro("TestA"))
188context(tokens.getters.macro("TestB"))
189context(tokens.getters.macro("TestC"))
190tokens.setters.macro("TestA","a")
191context(tokens.getters.macro("TestA"))
192context(function()
193    context(tokens.getters.macro("TestA"))
194    context(tokens.getters.macro("TestB"))
195    context(tokens.getters.macro("TestC"))
196end)
197\stopluacode
198\stopbuffer
199
200\typebuffer \getbuffer
201
202Here is another example:
203
204\startbuffer
205\startluacode
206if tokens.getters.macro("fontstyle") == "rm" then
207    context("serif")
208else
209    context("unknown")
210end
211\stopluacode
212\stopbuffer
213
214\typebuffer
215
216Of course this assumes that you have some knowledge of the \CONTEXT\ internals.
217
218\getbuffer
219
220\stopsection
221
222\stopchapter
223
224\stopcomponent
225