1if not modules then modules = { } end modules ['strc-ini'] = {
2 version = 1.001,
3 comment = "companion to strc-ini.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
22
23local lpegmatch = lpeg.match
24local type, next, tonumber, select = type, next, tonumber, select
25
26local formatters = string.formatters
27local settings_to_array = utilities.parsers.settings_to_array
28local settings_to_hash = utilities.parsers.settings_to_hash
29local allocate = utilities.storage.allocate
30
31local catcodenumbers = catcodes.numbers
32
33local ctxcatcodes = catcodenumbers.ctxcatcodes
34local xmlcatcodes = catcodenumbers.xmlcatcodes
35local notcatcodes = catcodenumbers.notcatcodes
36local txtcatcodes = catcodenumbers.txtcatcodes
37
38local context = context
39local commands = commands
40
41local trace_processors = false
42local report_processors = logs.reporter("processors","structure")
43
44trackers.register("typesetters.processors", function(v) trace_processors = v end)
45
46local xmlconvert = lxml.convert
47local xmlstore = lxml.store
48
49local ctx_pushcatcodes = context.pushcatcodes
50local ctx_popcatcodes = context.popcatcodes
51local ctx_xmlsetup = context.xmlsetup
52local ctx_xmlprocessbuffer = context.xmlprocessbuffer
53
54
55
56
57
58
59structures = structures or { }
60local structures = structures
61
62structures.blocks = structures.blocks or { }
63structures.sections = structures.sections or { }
64structures.pages = structures.pages or { }
65structures.registers = structures.registers or { }
66structures.references = structures.references or { }
67structures.lists = structures.lists or { }
68structures.helpers = structures.helpers or { }
69structures.documents = structures.documents or { }
70structures.notes = structures.notes or { }
71structures.descriptions = structures.descriptions or { }
72structures.itemgroups = structures.itemgroups or { }
73structures.specials = structures.specials or { }
74structures.counters = structures.counters or { }
75structures.tags = structures.tags or { }
76structures.formulas = structures.formulas or { }
77structures.sets = structures.sets or { }
78structures.marks = structures.marks or { }
79structures.floats = structures.floats or { }
80structures.synonyms = structures.synonyms or { }
81
82
83
84local processors = typesetters.processors
85
86
87
88
89
90
91local specials = structures.specials
92
93local collected = allocate()
94local tobesaved = allocate()
95
96specials.collected = collected
97specials.tobesaved = tobesaved
98
99local function initializer()
100 collected = specials.collected
101 tobesaved = specials.tobesaved
102end
103
104if job then
105 job.register('structures.specials.collected', tobesaved, initializer)
106end
107
108function specials.store(class,data)
109 if class and data then
110 local s = tobesaved[class]
111 if not s then
112 s = { }
113 tobesaved[class] = s
114 end
115 s[#s+1] = data
116 context(#s)
117 else
118 context(0)
119 end
120end
121
122function specials.retrieve(class,n)
123 if class and n then
124 local c = collected[class]
125 return c and c[n]
126 end
127end
128
129
130
131local helpers = structures.helpers
132
133
134
135
136
137
138
139
140function helpers.touserdata(data)
141 if type(data) == "string" then
142 if data == "" then
143 return nil
144 else
145 data = settings_to_hash(data)
146 end
147 end
148 if data and next(data) then
149 return data
150 end
151end
152
153local function simplify(d,nodefault)
154 if d then
155 local t = { }
156 for k, v in next, d do
157 local tv = type(v)
158 if tv == "table" then
159 if next(v) then
160 t[k] = simplify(v)
161 end
162 elseif tv == "string" then
163 if v ~= "" then
164 t[k] = v
165 end
166 elseif tv == "boolean" then
167 if v then
168 t[k] = v
169 end
170 else
171 t[k] = v
172 end
173 end
174 return next(t) and t
175 elseif nodefault then
176 return nil
177 else
178 return { }
179 end
180end
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
210helpers.simplify = simplify
211
212function helpers.merged(...)
213 local t = { }
214 for k=1, select("#",...) do
215 local v = select(k,...)
216 if v and v ~= "" and not t[k] then
217 t[k] = v
218 end
219 end
220 return t
221end
222
223local tags = {
224 generic = "ctx:genericentry",
225 section = "ctx:sectionentry",
226 entry = "ctx:registerentry",
227}
228
229
230
231
232
233
234
235
236local overload_catcodes = true
237
238directives.register("typesetters.processors.overloadcatcodes",function(v)
239
240 overload_catcodes = v
241end)
242
243local experiment = true
244
245function helpers.title(title,metadata)
246 if title and title ~= "" then
247 if metadata then
248 local xmlsetup = metadata.xmlsetup
249 if metadata.coding == "xml" then
250
251 local tag = tags[metadata.kind] or tags.generic
252 local xmldata = formatters["<?xml version='1.0'?><%s>%s</%s>"](tag,title,tag)
253 if not experiment then
254 buffers.assign(tag,xmldata)
255 end
256 if trace_processors then
257 report_processors("putting xml data in buffer: %s",xmldata)
258 report_processors("processing buffer with setup %a and tag %a",xmlsetup,tag)
259 end
260 if experiment then
261
262 local xmltable = xmlconvert("temp",xmldata or "")
263 xmlstore("temp",xmltable)
264 ctx_xmlsetup("temp",xmlsetup or "")
265 else
266 ctx_xmlprocessbuffer("dummy",tag,xmlsetup or "")
267 end
268 elseif xmlsetup then
269 if trace_processors then
270 report_processors("feeding xmlsetup %a using node %a",xmlsetup,title)
271 end
272 ctx_xmlsetup(title,metadata.xmlsetup)
273 else
274 local catcodes = metadata.catcodes
275 if overload_catcodes == false then
276 if trace_processors then
277 report_processors("catcodetable %a, text %a",catcodes,title)
278 end
279
280
281
282
283
284
285 ctx_pushcatcodes(catcodes)
286 context(title)
287 ctx_popcatcodes()
288 elseif overload_catcodes == true then
289 if catcodes == notcatcodes or catcodes == xmlcatcodes then
290
291 if trace_processors then
292 report_processors("catcodetable %a, overloads %a, text %a",ctxcatcodes,catcodes,title)
293 end
294 context(title)
295 else
296 ctx_pushcatcodes(catcodes)
297 context(title)
298 ctx_popcatcodes()
299 end
300 else
301 if trace_processors then
302 report_processors("catcodetable %a, overloads %a, text %a",catcodes,overload_catcodes,title)
303 end
304 ctx_pushcatcodes(overload_catcodes)
305 context(title)
306 ctx_popcatcodes()
307 end
308 end
309 else
310
311 context(title)
312 end
313 end
314end
315
316
317
318local sets = structures.sets
319
320sets.setlist = sets.setlist or { }
321
322storage.register("structures/sets/setlist", structures.sets.setlist, "structures.sets.setlist")
323
324local setlist = sets.setlist
325
326function sets.define(namespace,name,values,default,numbers)
327 local dn = setlist[namespace]
328 if not dn then
329 dn = { }
330 setlist[namespace] = dn
331 end
332 if values == "" then
333 dn[name] = { { }, default }
334 else
335 local split = settings_to_array(values)
336 if numbers then
337
338 for i=1,#split do
339 split[i] = tonumber(split[i]) or 0
340 end
341 end
342 dn[name] = { split, default }
343 end
344end
345
346function sets.getall(namespace,block,name)
347 local ds = setlist[namespace]
348 if not ds then
349 return { }
350 else
351 local dn
352 if block and block ~= "" then
353 dn = ds[block..":"..name] or ds[name] or ds[block] or ds.default
354 else
355 dn = ds[name] or ds.default
356 end
357 return (dn and dn[1]) or { }
358 end
359end
360
361
362
363
364local splitter = lpeg.splitat("::")
365
366function sets.get(namespace,block,name,level,default)
367
368 local kind, rest = lpegmatch(splitter,name)
369 if rest and kind == "fixed" then
370 local s = settings_to_array(rest)
371 return s[level] or s[#s] or default
372 end
373
374 local ds = setlist[namespace]
375 if not ds then
376 return default
377 end
378 local dn
379 if name and name ~= "" then
380 if block and block ~= "" then
381 dn = ds[block..":"..name] or ds[name] or ds[block] or ds.default
382 else
383 dn = ds[name] or ds.default
384 end
385 else
386 if block and block ~= "" then
387 dn = ds[block] or ds[block..":default"] or ds.default
388 else
389 dn = ds.default
390 end
391 end
392 if not dn then
393 return default
394 end
395 local dl = dn[1][level]
396 return dl or dn[2] or default
397end
398
399
400
401interfaces.implement {
402 name = "definestructureset",
403 actions = sets.define,
404 arguments = { "string", "string", "string", "string", "boolean" }
405}
406 |