cldf-int.lua /size: 12 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
cldf-int
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to mult-clm.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
-- another experiment
10
-- needs upgrading
11
-- needs checking
12
-- todo: multilingual
13 14
local
format
,
byte
=
string
.
format
,
string
.
byte
15
local
insert
,
remove
,
concat
=
table
.
insert
,
table
.
remove
,
table
.
concat
16
local
unpack
,
type
=
unpack
or
table
.
unpack
,
type
17 18
local
catcodenumbers
=
catcodes
.
numbers
19 20
local
ctxcatcodes
=
catcodenumbers
.
ctxcatcodes
21
local
vrbcatcodes
=
catcodenumbers
.
vrbcatcodes
22 23
local
context
=
context
24
local
contextsprint
=
context
.
sprint
25 26
local
trace_define
=
false
trackers
.
register
(
"
context.define
"
,
function
(
v
)
trace_define
=
v
end
)
27 28
interfaces
=
interfaces
or
{
}
29
local
implement
=
interfaces
.
implement
30
local
estart
=
interfaces
.
elements
.
start
31
local
estop
=
interfaces
.
elements
.
stop
32 33
if
CONTEXTLMTXMODE
>
0
then
34 35
local
scanners
=
tokens
.
scanners
36
local
shortcuts
=
tokens
.
shortcuts
37 38
local
scanpeek
=
scanners
.
peek
39
local
scankey
=
scanners
.
key
40
local
scanvalue
=
scanners
.
value
41
local
scanskip
=
scanners
.
skip
42 43
local
open
=
byte
(
'
[
'
)
44
local
close
=
byte
(
'
]
'
)
45
local
equal
=
byte
(
'
=
'
)
46
local
comma
=
byte
(
'
,
'
)
47 48
function
scanhash
(
scanners
)
49
if
scanpeek
(
)
=
=
open
then
50
local
data
=
{
}
51
scanskip
(
)
52
while
true
do
53
local
c
=
scanpeek
(
)
54
if
c
=
=
comma
then
55
scanskip
(
)
56
elseif
c
=
=
close
then
57
scanskip
(
)
58
break
59
else
60
local
key
=
scankey
(
equal
)
61
if
key
then
62
if
scanpeek
(
)
=
=
equal
then
63
scanskip
(
)
64
if
scanners
then
65
local
scanner
=
scanners
[
key
]
66
if
scanner
then
67
data
[
key
]
=
scanner
(
)
68
else
69
data
[
key
]
=
scanvalue
(
comma
,
close
)
or
"
"
70
end
71
else
72
data
[
key
]
=
scanvalue
(
comma
,
close
)
or
"
"
73
end
74
else
75
break
76
end
77
else
78
break
79
end
80
end
81
end
82
return
data
83
end
84
end
85 86
function
scanarray
(
)
87
if
scanpeek
(
)
=
=
open
then
88
local
data
=
{
}
89
local
d
=
0
90
scanskip
(
)
91
while
true
do
92
local
c
=
scanpeek
(
)
93
if
c
=
=
comma
then
94
scanskip
(
)
95
elseif
c
=
=
close
then
96
scanskip
(
)
97
break
98
else
99
local
v
=
scanvalue
(
comma
,
close
)
or
"
"
100
d
=
d
+
1
101
data
[
d
]
=
v
102
end
103
end
104
return
data
105
end
106
end
107 108
shortcuts
.
scanhash
=
scanhash
109
shortcuts
.
scanarray
=
scanarray
110 111
scanners
.
hash
=
scanhash
112
scanners
.
array
=
scanarray
113 114
local
function
remap
(
arguments
)
115
-- backward compatibility
116
if
type
(
arguments
)
=
=
"
table
"
then
117
for
i
=
1
,
#
arguments
do
118
local
a
=
arguments
[
i
]
119
if
type
(
a
)
=
=
"
table
"
then
120
local
t
=
a
[
2
]
121
arguments
[
i
]
=
t
=
=
"
list
"
and
"
array
"
or
t
122
end
123
end
124
return
arguments
125
end
126
end
127 128
function
interfaces
.
definecommand
(
name
,
specification
)
-- name is optional
129
if
type
(
name
)
=
=
"
table
"
then
130
specification
=
name
131
name
=
specification
.
name
132
end
133
if
name
and
specification
then
134
local
environment
=
specification
.
environment
135
local
arguments
=
remap
(
specification
.
arguments
)
136
if
environment
then
137
local
starter
=
specification
.
starter
138
local
stopper
=
specification
.
stopper
139
if
starter
and
stopper
then
140
implement
{
141
name
=
estart
.
.
name
,
142
arguments
=
arguments
,
143
public
=
true
,
144
protected
=
true
,
145
actions
=
starter
,
146
}
147
implement
{
148
name
=
estop
.
.
name
,
149
public
=
true
,
150
protected
=
true
,
151
actions
=
stopper
,
152
}
153
else
154
-- message
155
end
156
end
157
if
not
environment
or
environment
=
=
"
both
"
then
158
local
macro
=
specification
.
macro
159
if
macro
then
160
implement
{
161
name
=
name
,
162
arguments
=
arguments
,
163
public
=
true
,
164
protected
=
true
,
165
actions
=
macro
,
166
}
167
else
168
-- message
169
end
170
end
171
else
172
-- message
173
end
174
end
175 176 177
else
178 179
_clmh_
=
utilities
.
parsers
.
settings_to_hash
180
_clma_
=
utilities
.
parsers
.
settings_to_array
181 182
local
starters
,
stoppers
,
macros
,
stack
=
{
}
,
{
}
,
{
}
,
{
}
183 184
local
checkers
=
{
185
[
0
]
=
"
"
,
186
"
\\dosingleempty
"
,
187
"
\\dodoubleempty
"
,
188
"
\\dotripleempty
"
,
189
"
\\doquadrupleempty
"
,
190
"
\\doquintupleempty
"
,
191
"
\\dosixtupleempty
"
,
192
}
193 194
function
_clmm_
(
name
,
...
)
195
macros
[
name
]
(
...
)
196
end
197 198
function
_clmb_
(
name
,
...
)
199
local
sn
=
stack
[
name
]
200
insert
(
sn
,
{
...
}
)
201
starters
[
name
]
(
...
)
202
end
203 204
function
_clme_
(
name
)
205
local
sn
=
stack
[
name
]
206
local
sv
=
remove
(
sn
)
207
if
sv
then
208
stoppers
[
name
]
(
unpack
(
sv
)
)
209
else
210
-- nesting error
211
end
212
end
213 214
_clmn_
=
tonumber
215 216
local
estart
=
interfaces
.
elements
.
start
217
local
estop
=
interfaces
.
elements
.
stop
218 219
-- this is a bit old definition ... needs to be modernized
220 221
function
interfaces
.
definecommand
(
name
,
specification
)
-- name is optional
222
if
type
(
name
)
=
=
"
table
"
then
223
specification
=
name
224
name
=
specification
.
name
225
end
226
if
name
and
specification
then
227
local
arguments
=
specification
.
arguments
228
local
na
=
(
arguments
and
#
arguments
)
or
0
229
local
environment
=
specification
.
environment
230
if
na
=
=
0
then
231
if
environment
then
232
contextsprint
(
ctxcatcodes
,
"
\\setuvalue{
"
,
estart
,
name
,
"
}{\\ctxlua{_clmb_('
"
,
name
,
"
')}}
"
)
233
contextsprint
(
ctxcatcodes
,
"
\\setuvalue{
"
,
estop
,
name
,
"
}{\\ctxlua{_clme_('
"
,
name
,
"
')}}
"
)
234
end
235
if
not
environment
or
environment
=
=
"
both
"
then
236
contextsprint
(
ctxcatcodes
,
"
\\setuvalue{
"
,
name
,
"
}{\\ctxlua{_clmm_('
"
,
name
,
"
')}}
"
)
237
end
238
else
239
-- we could flush immediate but tracing is bad then
240
stack
[
name
]
=
{
}
241
local
opt
=
0
242
local
done
=
false
243
local
snippets
=
{
}
-- we can reuse it
244
local
mkivdo
=
"
\\mkivdo
"
.
.
name
-- maybe clddo
245
snippets
[
#
snippets
+
1
]
=
"
\\def
"
246
snippets
[
#
snippets
+
1
]
=
mkivdo
247
for
i
=
1
,
na
do
248
local
a
=
arguments
[
i
]
249
local
variant
=
a
[
1
]
250
if
variant
=
=
"
option
"
then
251
snippets
[
#
snippets
+
1
]
=
"
[#
"
252
snippets
[
#
snippets
+
1
]
=
i
253
snippets
[
#
snippets
+
1
]
=
"
]
"
254
if
not
done
then
255
opt
=
opt
+
1
256
end
257
else
258
done
=
true
-- no more optional checking after this
259
snippets
[
#
snippets
+
1
]
=
"
#
"
260
snippets
[
#
snippets
+
1
]
=
i
261
end
262
end
263
if
environment
then
264
snippets
[
#
snippets
+
1
]
=
"
{\\ctxlua{_clmb_('
"
265
snippets
[
#
snippets
+
1
]
=
name
266
snippets
[
#
snippets
+
1
]
=
"
'
"
267
else
268
snippets
[
#
snippets
+
1
]
=
"
{\\ctxlua{_clmm_('
"
269
snippets
[
#
snippets
+
1
]
=
name
270
snippets
[
#
snippets
+
1
]
=
"
'
"
271
end
272
for
i
=
1
,
na
do
273
local
a
=
arguments
[
i
]
274
local
variant
=
a
[
2
]
275
if
variant
=
=
"
list
"
then
276
snippets
[
#
snippets
+
1
]
=
"
,_clma_([==[#
"
277
snippets
[
#
snippets
+
1
]
=
i
278
snippets
[
#
snippets
+
1
]
=
"
]==])
"
279
elseif
variant
=
=
"
hash
"
then
280
snippets
[
#
snippets
+
1
]
=
"
,_clmh_([==[#
"
281
snippets
[
#
snippets
+
1
]
=
i
282
snippets
[
#
snippets
+
1
]
=
"
]==])
"
283
elseif
variant
=
=
"
number
"
then
284
snippets
[
#
snippets
+
1
]
=
"
,_clmn_([==[#
"
285
snippets
[
#
snippets
+
1
]
=
i
286
snippets
[
#
snippets
+
1
]
=
"
]==])
"
287
else
288
snippets
[
#
snippets
+
1
]
=
"
,[==[#
"
289
snippets
[
#
snippets
+
1
]
=
i
290
snippets
[
#
snippets
+
1
]
=
"
]==]
"
291
end
292
end
293
snippets
[
#
snippets
+
1
]
=
"
)}}
"
294
contextsprint
(
ctxcatcodes
,
unpack
(
snippets
)
)
295
if
environment
then
296
-- needs checking
297
contextsprint
(
ctxcatcodes
,
"
\\setuvalue{
"
,
estart
,
name
,
"
}{
"
,
checkers
[
opt
]
,
mkivdo
,
"
}
"
)
298
contextsprint
(
ctxcatcodes
,
"
\\setuvalue{
"
,
estop
,
name
,
"
}{\\ctxlua{_clme_('
"
,
name
,
"
')}}
"
)
299
end
300
if
not
environment
or
environment
=
=
"
both
"
then
301
contextsprint
(
ctxcatcodes
,
"
\\setuvalue{
"
,
name
,
"
}{
"
,
checkers
[
opt
]
,
mkivdo
,
"
}
"
)
302
end
303
end
304
if
environment
then
305
starters
[
name
]
=
specification
.
starter
306
stoppers
[
name
]
=
specification
.
stopper
307
else
308
macros
[
name
]
=
specification
.
macro
309
end
310
end
311
end
312 313
end
314 315
function
interfaces
.
tolist
(
t
)
316
if
t
then
317
local
r
=
{
}
318
for
i
=
1
,
#
t
do
319
r
[
i
]
=
t
[
i
]
320
end
321
local
n
=
#
r
322
for
k
,
v
in
table
.
sortedhash
(
t
)
do
323
if
type
(
k
)
~
=
"
number
"
then
324
n
=
n
+
1
325
r
[
n
]
=
k
.
.
"
=
"
.
.
v
326
end
327
end
328
return
concat
(
r
,
"
,
"
)
329
else
330
return
"
"
331
end
332
end
333 334
-- \startluacode
335
-- function test(opt_1, opt_2, arg_1)
336
-- context.startnarrower()
337
-- context("options 1: %s",interfaces.tolist(opt_1))
338
-- context.par()
339
-- context("options 2: %s",interfaces.tolist(opt_2))
340
-- context.par()
341
-- context("argument 1: %s",arg_1)
342
-- context.stopnarrower()
343
-- end
344
--
345
-- interfaces.definecommand {
346
-- name = "test",
347
-- arguments = {
348
-- { "option", "list" },
349
-- { "option", "hash" },
350
-- { "content", "string" },
351
-- },
352
-- macro = test,
353
-- }
354
-- \stopluacode
355
--
356
-- test: \test[1][a=3]{whatever}
357
--
358
-- \startluacode
359
-- local function startmore(opt_1)
360
-- context.startnarrower()
361
-- context("start more, options: %s",interfaces.tolist(opt_1))
362
-- context.startnarrower()
363
-- end
364
--
365
-- local function stopmore()
366
-- context.stopnarrower()
367
-- context("stop more")
368
-- context.stopnarrower()
369
-- end
370
--
371
-- interfaces.definecommand ( "more", {
372
-- environment = true,
373
-- arguments = {
374
-- { "option", "list" },
375
-- },
376
-- starter = startmore,
377
-- stopper = stopmore,
378
-- } )
379
-- \stopluacode
380
--
381
-- more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
382
--
383
-- More modern (no need for option or content):
384
--
385
-- \startluacode
386
-- interfaces.definecommand {
387
-- name = "test",
388
-- arguments = {
389
-- "array", -- or list
390
-- "hash",
391
-- "string",
392
-- "number",
393
-- },
394
-- macro = test,
395
-- }
396
-- \stopluacode
397
--
398 399