1if not modules then modules = { } end modules ['strc-syn'] = {
2 version = 1.001,
3 comment = "companion to str-syn.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 next, type = next, type
10
11local context = context
12local implement = interfaces.implement
13
14local allocate = utilities.storage.allocate
15
16local sorters = sorters
17
18local structures = structures
19local synonyms = structures.synonyms
20local tags = structures.tags
21
22local collected = allocate()
23local tobesaved = allocate()
24
25local firstofsplit = sorters.firstofsplit
26local strip = sorters.strip
27local splitter = sorters.splitters.utf
28
29synonyms.collected = collected
30synonyms.tobesaved = tobesaved
31
32local progressions = { }
33
34local variables = interfaces.variables
35local v_all = variables.all
36local v_current = variables.current
37
38local function initializer()
39 collected = synonyms.collected
40 tobesaved = synonyms.tobesaved
41end
42
43local function finalizer()
44 for entry, data in next, tobesaved do
45 data.hash = nil
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 end
61end
62
63job.register('structures.synonyms.collected', tobesaved, initializer, finalizer)
64
65
66
67table.setmetatableindex(tobesaved,function(t,k)
68 local v = {
69 metadata = {
70 language = 'en',
71 sorted = false,
72 class = v
73 },
74 entries = {
75 },
76 hash = {
77 }
78 }
79 t[k] = v
80 return v
81end)
82
83function synonyms.define(class,kind)
84 local data = tobesaved[class]
85 data.metadata.kind = kind
86end
87
88function synonyms.register(class,kind,spec)
89 local data = tobesaved[class]
90 local hash = data.hash
91 local definition = spec.definition
92 local tag = definition.tag or ""
93 data.metadata.kind = kind
94 if not hash[tag] then
95 local entries = data.entries
96 entries[#entries+1] = spec
97 hash[tag] = spec
98 end
99end
100
101function synonyms.registerused(class,tag)
102 local data = tobesaved[class]
103 local okay = data.hash[tag]
104 if okay then
105 local definition = okay.definition
106 definition.used = true
107 definition.list = true
108 end
109end
110
111function synonyms.registershown(class,tag)
112 local data = tobesaved[class]
113 local okay = data.hash[tag]
114 if okay then
115 local definition = okay.definition
116 definition.shown = true
117 definition.list = true
118 end
119end
120
121function synonyms.isused(class,tag)
122 local data = tobesaved[class]
123 local okay = data.hash[tag]
124 return okay and okay.definition.used or false
125end
126
127function synonyms.isshown(class,tag)
128 local data = tobesaved[class]
129 local okay = data.hash[tag]
130 return okay and okay.definition.shown or false
131end
132
133local function resetused(class)
134 for tag, data in next, tobesaved[class].hash do
135 data.definition.used = nil
136 end
137end
138
139local function resetshown(class)
140 for tag, data in next, tobesaved[class].hash do
141 data.definition.shown = nil
142 end
143end
144
145local function resetlist(class)
146 for tag, data in next, tobesaved[class].hash do
147 data.definition.list = nil
148 end
149end
150
151local function resetall(class)
152 for tag, data in next, tobesaved[class].hash do
153 local definition = data.definition
154 definition.used = nil
155 definition.shown = nil
156 definition.list = nil
157 end
158end
159
160synonyms.resetused = resetused
161synonyms.resetshown = resetshown
162synonyms.resetlist = resetlist
163synonyms.resetall = resetall
164
165function synonyms.reset(class,what)
166 if what == "progress" then
167 progressions = { }
168 elseif what == "used" then
169 resetused(class)
170 elseif what == "shown" then
171 resetshown(class)
172 elseif what == "list" then
173 resetlist(class)
174 else
175 resetall(class)
176 end
177end
178
179function synonyms.synonym(class,tag)
180 local data = tobesaved[class]
181 local okay = data.hash[tag]
182 if okay then
183 local definition = okay.definition
184 definition.used = true
185 definition.list = true
186 context(definition.synonym)
187 end
188 if progressions[tag] == nil then
189 progressions[tag] = false
190 end
191end
192
193function synonyms.meaning(class,tag)
194 local data = tobesaved[class]
195 local okay = data.hash[tag]
196 if okay then
197 local definition = okay.definition
198 definition.shown = true
199 definition.list = true
200 context(definition.meaning)
201 end
202end
203
204synonyms.compare = sorters.comparers.basic
205
206function synonyms.filter(data,options)
207 local result = { }
208 local entries = data.entries
209 local criterium = options and options.criterium
210 if criterium == v_all then
211 for i=1,#entries do
212 result[i] = entries[i]
213 end
214 else
215 for i=1,#entries do
216 local entry = entries[i]
217 local definition = entry.definition
218 if definition.list then
219 local tag = definition.tag
220 local done = progressions[tag]
221 if done == false then
222 result[#result+1] = entry
223 progressions[tag] = true
224 end
225 end
226 end
227 if criterium == v_current then
228 progressions = { }
229 end
230 end
231 data.result = result
232end
233
234function synonyms.prepare(data)
235 local result = data.result
236 if result then
237 for i=1, #result do
238 local entry = result[i]
239 local definition = entry.definition
240 if definition then
241 local srt = definition.sortkey or ""
242 local tag = definition.tag or ""
243 local key = (srt ~= "" and srt) or (tag ~= "" and tag) or definition.synonym
244 if key then
245 entry.split = splitter(strip(key))
246 end
247 end
248 end
249 end
250end
251
252function synonyms.sort(data,options)
253 sorters.sort(data.result,synonyms.compare)
254 data.metadata.sorted = true
255end
256
257function synonyms.finalize(data,options)
258 local result = data.result
259 local split = { }
260 local nofsplit = 0
261 local lasttag = nil
262 local lasttag = nil
263 local nofdone = 0
264 for k=1,#result do
265 local entry = result[k]
266 local first, tag = firstofsplit(entry)
267 if tag ~= lasttag then
268
269
270
271 done = { }
272 nofdone = 0
273 nofsplit = nofsplit + 1
274 lasttag = tag
275 split[nofsplit] = { tag = tag, data = done }
276 end
277 nofdone = nofdone + 1
278 done[nofdone] = entry
279 end
280 data.result = split
281end
282
283
284
285
286local ctx_synonymentry = context.synonymentry
287
288function synonyms.flush(data,options)
289 local result = data.result
290 for i=1,#result do
291 local sublist = result[i]
292 local data = sublist.data
293 for d=1,#data do
294 local entry = data[d].definition
295 ctx_synonymentry(d,entry.tag,entry.synonym,entry.meaning or "")
296 end
297 end
298 data.result = nil
299 data.metadata.sorted = false
300end
301
302function synonyms.analyzed(class,options)
303 local data = collected[class]
304 if data and data.entries then
305 options = options or { }
306 sorters.setlanguage(options.language,options.method)
307 synonyms.filter(data,options)
308 synonyms.prepare(data,options)
309 synonyms.sort(data,options)
310 synonyms.finalize(data,options)
311 data.metadata.sorted = true
312 end
313 return data and data.metadata.sorted and data.result and next(data.result)
314end
315
316function synonyms.process(class,options)
317 if synonyms.analyzed(class,options) then
318 synonyms.flush(collected[class],options)
319 end
320end
321
322
323
324implement { name = "registerusedsynonym", actions = synonyms.registerused, arguments = "2 strings" }
325implement { name = "registershownsynonym", actions = synonyms.registershown, arguments = "2 strings" }
326implement { name = "synonymmeaning", actions = synonyms.meaning, arguments = "2 strings" }
327implement { name = "synonymname", actions = synonyms.synonym, arguments = "2 strings" }
328
329
330
331implement { name = "resetsynonyms", actions = synonyms.reset, arguments = "2 strings" }
332
333implement {
334 name = "doifelsesynonymused",
335 actions = { synonyms.isused, commands.doifelse },
336 arguments = "2 strings",
337}
338
339implement {
340 name = "doifelsesynonymshown",
341 actions = { synonyms.isshown, commands.doifelse },
342 arguments = "2 strings",
343}
344
345implement {
346 name = "registersynonym",
347 actions = synonyms.register,
348 arguments = {
349 "string",
350 "string",
351 {
352 { "metadata", {
353 { "catcodes", "integer" },
354 { "coding" },
355 { "xmlroot" }
356 }
357 },
358 {
359 "definition", {
360 { "tag" },
361 { "synonym" },
362 { "meaning" },
363 { "sortkey" },
364 { "used", "boolean" }
365 }
366 }
367 }
368 }
369}
370
371implement {
372 name = "processsynonyms",
373 actions = synonyms.process,
374 arguments = {
375 "string",
376 {
377 { "criterium" },
378 { "language" },
379 { "method" }
380 }
381 }
382}
383 |