1if not modules then modules = { } end modules ['mult-ini'] = {
2 version = 1.001,
3 comment = "companion to mult-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
9local format, gmatch, match, find, sub = string.format, string.gmatch, string.match, string.find, string.sub
10local lpegmatch = lpeg.match
11local serialize, concat = table.serialize, table.concat
12local rawget, type, tonumber, next = rawget, type, tonumber, next
13
14local context = context
15local commands = commands
16local implement = interfaces.implement
17
18local allocate = utilities.storage.allocate
19local mark = utilities.storage.mark
20local contextsprint = context.sprint
21local setmetatableindex = table.setmetatableindex
22local formatters = string.formatters
23
24
25local vrbcatcodes <const> = catcodes.numbers.vrbcatcodes
26
27local report_interface = logs.reporter("interface","initialization")
28
29interfaces = interfaces or { }
30interfaces.constants = mark(interfaces.constants or { })
31interfaces.variables = mark(interfaces.variables or { })
32interfaces.elements = mark(interfaces.elements or { })
33interfaces.formats = mark(interfaces.formats or { })
34interfaces.translations = mark(interfaces.translations or { })
35interfaces.setupstrings = mark(interfaces.setupstrings or { })
36interfaces.corenamespaces = mark(interfaces.corenamespaces or { })
37interfaces.usednamespaces = mark(interfaces.usednamespaces or { })
38
39local registerstorage = storage.register
40local sharedstorage = storage.shared
41
42local constants = interfaces.constants
43local variables = interfaces.variables
44local elements = interfaces.elements
45local formats = interfaces.formats
46local translations = interfaces.translations
47local setupstrings = interfaces.setupstrings
48local corenamespaces = interfaces.corenamespaces
49local usednamespaces = interfaces.usednamespaces
50local reporters = { }
51
52local setmacro = tokens.setters.macro
53
54registerstorage("interfaces/constants", constants, "interfaces.constants")
55registerstorage("interfaces/variables", variables, "interfaces.variables")
56registerstorage("interfaces/elements", elements, "interfaces.elements")
57registerstorage("interfaces/formats", formats, "interfaces.formats")
58registerstorage("interfaces/translations", translations, "interfaces.translations")
59registerstorage("interfaces/setupstrings", setupstrings, "interfaces.setupstrings")
60registerstorage("interfaces/corenamespaces", corenamespaces, "interfaces.corenamespaces")
61registerstorage("interfaces/usednamespaces", usednamespaces, "interfaces.usednamespaces")
62
63interfaces.interfaces = {
64 "cs", "de", "en", "fr", "it", "nl", "ro", "pe",
65}
66
67sharedstorage.currentinterface = sharedstorage.currentinterface or "en"
68sharedstorage.currentresponse = sharedstorage.currentresponse or "en"
69
70local currentinterface = sharedstorage.currentinterface
71local currentresponse = sharedstorage.currentresponse
72
73interfaces.currentinterface = currentinterface
74interfaces.currentresponse = currentresponse
75
76local complete = allocate()
77interfaces.complete = complete
78
79local function resolve(t,k)
80 report_interface("loading interface definitions from 'mult-def.lua'")
81 complete = dofile(resolvers.findfile("mult-def.lua"))
82 report_interface("loading interface messages from 'mult-mes.lua'")
83 complete.messages = dofile(resolvers.findfile("mult-mes.lua"))
84 interfaces.complete = complete
85 return rawget(complete,k)
86end
87
88setmetatableindex(complete, resolve)
89
90local function valueiskey(t,k)
91 t[k] = k
92 return k
93end
94
95setmetatableindex(variables, valueiskey)
96setmetatableindex(constants, valueiskey)
97setmetatableindex(elements, valueiskey)
98setmetatableindex(formats, valueiskey)
99setmetatableindex(translations, valueiskey)
100setmetatableindex(setupstrings, valueiskey)
101
102function interfaces.registernamespace(n,namespace)
103 corenamespaces[n] = namespace
104 usednamespaces[namespace] = n
105end
106
107function interfaces.getnamespace(n)
108 return usednamespaces[n] .. ">"
109end
110
111if documentdata then
112
113 local prefix, getmacro
114
115 function documentdata.variable(name)
116 if not prefix then
117 prefix = usednamespaces.variables .. ">document:"
118 end
119 if not getmacro then
120 getmacro = tokens.getters.macro
121 end
122 return getmacro(prefix..name)
123 end
124
125end
126
127local function resolve(t,k)
128 local v = logs.reporter(k)
129 t[k] = v
130 return v
131end
132
133setmetatableindex(reporters,resolve)
134
135for category, _ in next, translations do
136
137
138
139
140 local r = reporters[category]
141end
142
143
144
145local function add(target,tag,values)
146 local t = target[tag]
147 if not f then
148 target[tag] = values
149 else
150 for k, v in next, values do
151 if f[k] then
152
153 else
154 f[k] = v
155 end
156 end
157 end
158end
159
160function interfaces.settranslation(tag,values)
161 add(translations,tag,values)
162end
163
164function interfaces.setformat(tag,values)
165 add(formats,tag,values)
166end
167
168local function getsetupstring(tag)
169 return setupstrings[tag] or tag
170end
171
172interfaces.getsetupstring = getsetupstring
173
174
175
176local replacer = lpeg.replacer { { "--", "%%a" } }
177
178local function fulltag(category,tag)
179 return formatters["%s:%s"](category,lpegmatch(replacer,tag))
180end
181
182function interfaces.setmessages(category,str)
183 for tag, message in gmatch(str,"(%S+) *: *(.-) *[\n\r]") do
184 if tag == "title" then
185 translations[tag] = translations[tag] or tag
186 else
187 formats[fulltag(category,tag)] = lpegmatch(replacer,message)
188 end
189 end
190end
191
192function interfaces.setmessage(category,tag,message)
193 formats[fulltag(category,tag)] = lpegmatch(replacer,message)
194end
195
196function interfaces.getmessage(category,tag,default)
197 return formats[fulltag(category,tag)] or default or "unknown message"
198end
199
200function interfaces.doifelsemessage(category,tag)
201 return rawget(formats,fulltag(category,tag))
202end
203
204local splitter = lpeg.splitat(",")
205
206function interfaces.showmessage(category,tag,arguments)
207 local r = reporters[category]
208 local f = formats[fulltag(category,tag)]
209 local t = type(arguments)
210 if t == "string" and #arguments > 0 then
211 r(f,lpegmatch(splitter,arguments))
212 elseif t == "table" then
213 r(f,unpack(arguments))
214 elseif arguments then
215 r(f,arguments)
216 else
217 r(f)
218 end
219end
220
221
222
223function interfaces.setvariable(variable,given)
224 variables[given] = variable
225end
226
227function interfaces.setconstant(constant,given)
228 constants[given] = constant
229end
230
231function interfaces.setelement(element,given)
232 elements[given] = element
233end
234
235
236
237logs.setmessenger(context.verbatim.ctxreport)
238
239interfaces.cachedsetups = interfaces.cachedsetups or { }
240interfaces.hashedsetups = interfaces.hashedsetups or { }
241
242local cachedsetups = interfaces.cachedsetups
243local hashedsetups = interfaces.hashedsetups
244
245storage.register("interfaces/cachedsetups", cachedsetups, "interfaces.cachedsetups")
246storage.register("interfaces/hashedsetups", hashedsetups, "interfaces.hashedsetups")
247
248function interfaces.cachesetup(t)
249 local hash = serialize(t)
250 local done = hashedsetups[hash]
251 if done then
252 return cachedsetups[done]
253 else
254 done = #cachedsetups + 1
255 cachedsetups[done] = t
256 hashedsetups[hash] = done
257 return t
258 end
259end
260
261function interfaces.interfacedcommand(name)
262 local command = complete.commands[name]
263 return command and command[currentinterface] or name
264end
265
266
267
268function interfaces.writestatus(category,message)
269 reporters[category](message)
270end
271
272function interfaces.message(str)
273 texio.write(str)
274end
275
276implement { name = "registernamespace", actions = interfaces.registernamespace, arguments = { "integer", "string" } }
277implement { name = "setinterfaceconstant", actions = interfaces.setconstant, arguments = "2 strings" }
278implement { name = "setinterfacevariable", actions = interfaces.setvariable, arguments = "2 strings" }
279implement { name = "setinterfaceelement", actions = interfaces.setelement, arguments = "2 strings" }
280implement { name = "setinterfacemessage", actions = interfaces.setmessage, arguments = "3 strings" }
281implement { name = "setinterfacemessages", actions = interfaces.setmessages, arguments = "2 strings" }
282
283implement {
284 name = "showmessage",
285 public = true,
286 protected = true,
287 arguments = "3 arguments" ,
288 actions = interfaces.showmessage,
289}
290
291implement {
292 name = "doifelsemessage",
293 public = true,
294 protected = true,
295 arguments = "2 arguments",
296 actions = { interfaces.doifelsemessage, commands.doifelse },
297}
298
299implement {
300 name = "getmessage",
301 public = true,
302 protected = true,
303 arguments = "3 arguments",
304 actions = function(...)
305 setmacro("currentmessagetext", interfaces.getmessage(...))
306 end,
307}
308
309implement {
310 name = "writestatus",
311 overload = true,
312 public = true,
313 protected = true,
314 arguments = "2 arguments",
315 actions = interfaces.writestatus,
316}
317
318implement {
319 name = "message",
320 overload = true,
321 public = true,
322 protected = true,
323 arguments = "string",
324 actions = interfaces.message,
325}
326
327local function gss(s)
328 contextsprint(vrbcatcodes,getsetupstring(s))
329end
330
331implement {
332 name = "getsetupstring",
333 public = true,
334
335 arguments = "string",
336 actions = gss,
337}
338
339implement {
340 name = "rawsetupstring",
341 public = true,
342 arguments = "string",
343 actions = gss,
344}
345
346local function showassignerror(namespace,key,line)
347
348
349 local ns, instance = match(namespace,"^(.-)>(%a*)")
350 if ns then
351 namespace = corenamespaces[tonumber(ns,16)] or ns
352 end
353
354 if instance and instance ~= "" then
355 context.writestatus("setup",formatters["error in line %a, namespace %a, instance %a, key %a"](line,namespace,instance,key))
356 else
357 context.writestatus("setup",formatters["error in line %a, namespace %a, key %a"](line,namespace,key))
358 end
359
360end
361
362implement {
363 name = "showassignerror",
364 actions = showassignerror,
365 arguments = { "string", "string", "integer" },
366}
367
368
369
370local settings_to_hash = utilities.parsers.settings_to_hash
371
372local makesparse = function(t)
373 for k, v in next, t do
374 if not v or v == "" then
375 t[k] = nil
376 end
377 end
378 return t
379end
380
381function interfaces.checkedspecification(specification)
382 local kind = type(specification)
383 if kind == "table" then
384 return makesparse(specification)
385 elseif kind == "string" and specification ~= "" then
386 return makesparse(settings_to_hash(specification))
387 else
388 return { }
389 end
390end
391 |