summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/cld/cld-macros.tex
blob: a177db9f87e0efb72a7cb9dfdf15726519c491da (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
220
221
222
223
224
% language=uk

\startcomponent cld-macros

\environment cld-environment

\startchapter[title=Macros]

\startsection[title={Introduction}]

You can skip this chapter if you're not interested in defining macros or are
quite content with defining them in \TEX. It's just an example of possible future
interface definitions and it's not the fastest mechanism around.

\stopsection

\startsection[title={Parameters}]

Right from the start \CONTEXT\ came with several user interfaces. As a
consequence you need to take this into account when you write code that is
supposed to work with interfaces other than the English one. The \TEX\ command:

\starttyping
\setupsomething[key=value]
\stoptyping

and the \LUA\ call:

\starttyping
context.setupsomething { key = value }
\stoptyping

are equivalent. However, all keys at the \TEX\ end eventually become English, but
the values are unchanged. This means that when you code in \LUA\ you should use
English keys and when dealing with assigned values later on, you need to
translate them of compare with translations (which is easier). This is why in the
\CONTEXT\ code you will see:

\starttyping
if somevalue == interfaces.variables.yes then
  ...
end
\stoptyping

instead of:

\starttyping
if somevalue == "yes" then
  ...
end
\stoptyping

\stopsection

\startsection[title={User interfacing}]

Unless this is somehow inhibited, users can write their own macros and this is
done in the \TEX\ language. Passing data to macros is possible and looks like
this:

\starttyping
\def\test#1#2{.. #1 .. #2 .. }      \test{a}{b}
\def\test[#1]#2{.. #1 .. #2 .. }    \test[a]{b}
\stoptyping

Here \type {#1} and \type {#2} represent an argument and there can be at most 9
of them. The \type{[]} are delimiters and you can delimit in many ways so the
following is also right:

\starttyping
\def\test(#1><#2){.. #1 .. #2 .. }  \test(a><b)
\stoptyping

Macro packages might provide helper macros that for instance take care of
optional arguments, so that we can use calls like:

\starttyping
\test[1,2,3][a=1,b=2,c=3]{whatever}
\stoptyping

and alike. If you are familiar with the \CONTEXT\ syntax you know that we use
this syntax all over the place.

If you want to write a macro that calls out to \LUA\ and handles things at that
end, you might want to avoid defining the macro itself and this is possible.

\startbuffer
\startluacode
function test(opt_1, opt_2, arg_1)
    context.startnarrower()
    context("options 1: %s",interfaces.tolist(opt_1))
    context.par()
    context("options 2: %s",interfaces.tolist(opt_2))
    context.par()
    context("argument 1: %s",arg_1)
    context.stopnarrower()
end

interfaces.definecommand {
    name = "test",
    arguments = {
        { "option", "list" },
        { "option", "hash" },
        { "content", "string" },
    },
    macro = test,
}
\stopluacode

test: \test[1][a=3]{whatever}
\stopbuffer

An example of a definition and usage at the \LUA\ end is:

\typebuffer

The call gives:

\startpacked
\getbuffer
\stoppacked

\startbuffer
\startluacode
local function startmore(opt_1)
    context.startnarrower()
    context("start more, options: %s",interfaces.tolist(opt_1))
    context.startnarrower()
end

local function stopmore(opt_1)
    context.stopnarrower()
    context("stop more, options: %s",interfaces.tolist(opt_1))
    context.stopnarrower()
end

interfaces.definecommand ( "more", {
    environment = true,
    arguments = {
        { "option", "list" },
    },
    starter = startmore,
    stopper = stopmore,
} )
\stopluacode

more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
\stopbuffer

If you want to to define an environment (i.e.\ a \type {start}||\type {stop}
pair, it looks as follows:

\typebuffer

This gives:

\startpacked
\getbuffer
\stoppacked

The arguments are know in both \type {startmore} and \type {stopmore} and nesting
is handled automatically.

\stopsection

\startsection[title=Looking inside]

If needed you can access the body of a macro. Take for instance:

\startbuffer
\def\TestA{A}
\def\TestB{\def\TestC{c}}
\def\TestC{C}
\stopbuffer

\typebuffer \getbuffer

The following example demonsttaies how we can look inside these macros. You need
to be aware of the fact that the whole blob of \LUA\ codes is finished before we
return to \TEX, so when we pipe the meaning of \type {TestB} back to \TEX\ it
only gets expanded afterwards. We can use a function to get back to \LUA. It's
only then that the meaning of \type {testC} is changed by the (piped) expansion
of \type {TestB}.

\startbuffer
\startluacode
context(tokens.getters.macro("TestA"))
context(tokens.getters.macro("TestB"))
context(tokens.getters.macro("TestC"))
tokens.setters.macro("TestA","a")
context(tokens.getters.macro("TestA"))
context(function()
    context(tokens.getters.macro("TestA"))
    context(tokens.getters.macro("TestB"))
    context(tokens.getters.macro("TestC"))
end)
\stopluacode
\stopbuffer

\typebuffer \getbuffer

Here is another example:

\startbuffer
\startluacode
if tokens.getters.macro("fontstyle") == "rm" then
    context("serif")
else
    context("unknown")
end
\stopluacode
\stopbuffer

\typebuffer

Of course this assumes that you have some knowledge of the \CONTEXT\ internals.

\getbuffer

\stopsection

\stopchapter

\stopcomponent