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