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