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 function initializer()
33 collected = synonyms.collected
34 tobesaved = synonyms.tobesaved
35end
36
37local function finalizer()
38 for entry, data in next, tobesaved do
39 data.hash = nil
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 end
55end
56
57job.register('structures.synonyms.collected', tobesaved, initializer, finalizer)
58
59
60
61table.setmetatableindex(tobesaved,function(t,k)
62 local v = {
63 metadata = {
64 language = 'en',
65 sorted = false,
66 class = v
67 },
68 entries = {
69 },
70 hash = {
71 }
72 }
73 t[k] = v
74 return v
75end)
76
77function synonyms.define(class,kind)
78 local data = tobesaved[class]
79 data.metadata.kind = kind
80end
81
82function synonyms.register(class,kind,spec)
83 local data = tobesaved[class]
84 local hash = data.hash
85 local definition = spec.definition
86 local tag = definition.tag or ""
87 data.metadata.kind = kind
88 if not hash[tag] then
89
90
91
92
93
94
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
133function synonyms.resetused(class)
134 for tag, data in next, tobesaved[class].hash do
135
136 data.definition.used = nil
137 end
138end
139
140function synonyms.resetshown(class)
141 for tag, data in next, tobesaved[class].hash do
142
143 data.definition.shown = nil
144 end
145end
146
147function synonyms.synonym(class,tag)
148 local data = tobesaved[class]
149 local okay = data.hash[tag]
150 if okay then
151 local definition = okay.definition
152 definition.used = true
153 definition.list = true
154 context(definition.synonym)
155 end
156end
157
158function synonyms.meaning(class,tag)
159 local data = tobesaved[class]
160 local okay = data.hash[tag]
161 if okay then
162 local definition = okay.definition
163 definition.shown = true
164 definition.list = true
165 context(definition.meaning)
166 end
167end
168
169synonyms.compare = sorters.comparers.basic
170
171function synonyms.filter(data,options)
172 local result = { }
173 local entries = data.entries
174 local all = options and options.criterium == interfaces.variables.all
175 if all then
176 for i=1,#entries do
177 result[i] = entries[i]
178 end
179 else
180 for i=1,#entries do
181 local entry = entries[i]
182 local definition = entry.definition
183 if definition.list then
184 result[#result+1] = entry
185 end
186 end
187 end
188 data.result = result
189end
190
191function synonyms.prepare(data)
192 local result = data.result
193 if result then
194 for i=1, #result do
195 local entry = result[i]
196 local definition = entry.definition
197 if definition then
198 local srt = definition.sortkey or ""
199 local tag = definition.tag or ""
200 local key = (srt ~= "" and srt) or (tag ~= "" and tag) or definition.synonym
201 if key then
202 entry.split = splitter(strip(key))
203 end
204 end
205 end
206 end
207end
208
209function synonyms.sort(data,options)
210 sorters.sort(data.result,synonyms.compare)
211 data.metadata.sorted = true
212end
213
214function synonyms.finalize(data,options)
215 local result = data.result
216 local split = { }
217 local nofsplit = 0
218 local lasttag = nil
219 local lasttag = nil
220 local nofdone = 0
221 for k=1,#result do
222 local entry = result[k]
223 local first, tag = firstofsplit(entry)
224 if tag ~= lasttag then
225
226
227
228 done = { }
229 nofdone = 0
230 nofsplit = nofsplit + 1
231 lasttag = tag
232 split[nofsplit] = { tag = tag, data = done }
233 end
234 nofdone = nofdone + 1
235 done[nofdone] = entry
236 end
237 data.result = split
238end
239
240
241
242
243local ctx_synonymentry = context.synonymentry
244
245function synonyms.flush(data,options)
246 local result = data.result
247 for i=1,#result do
248 local sublist = result[i]
249 local data = sublist.data
250 for d=1,#data do
251 local entry = data[d].definition
252 ctx_synonymentry(d,entry.tag,entry.synonym,entry.meaning or "")
253 end
254 end
255 data.result = nil
256 data.metadata.sorted = false
257end
258
259function synonyms.analyzed(class,options)
260 local data = collected[class]
261 if data and data.entries then
262 options = options or { }
263 sorters.setlanguage(options.language,options.method)
264 synonyms.filter(data,options)
265 synonyms.prepare(data,options)
266 synonyms.sort(data,options)
267 synonyms.finalize(data,options)
268 data.metadata.sorted = true
269 end
270 return data and data.metadata.sorted and data.result and next(data.result)
271end
272
273function synonyms.process(class,options)
274 if synonyms.analyzed(class,options) then
275 synonyms.flush(collected[class],options)
276 end
277end
278
279
280
281implement { name = "registerusedsynonym", actions = synonyms.registerused, arguments = "2 strings" }
282implement { name = "registershownsynonym", actions = synonyms.registershown, arguments = "2 strings" }
283implement { name = "synonymmeaning", actions = synonyms.meaning, arguments = "2 strings" }
284implement { name = "synonymname", actions = synonyms.synonym, arguments = "2 strings" }
285implement { name = "resetusedsynonyms", actions = synonyms.resetused, arguments = "string" }
286implement { name = "resetshownsynonyms", actions = synonyms.resetshown, arguments = "string" }
287
288implement {
289 name = "doifelsesynonymused",
290 actions = { synonyms.isused, commands.doifelse },
291 arguments = "2 strings",
292}
293
294implement {
295 name = "doifelsesynonymshown",
296 actions = { synonyms.isshown, commands.doifelse },
297 arguments = "2 strings",
298}
299
300implement {
301 name = "registersynonym",
302 actions = synonyms.register,
303 arguments = {
304 "string",
305 "string",
306 {
307 { "metadata", {
308 { "catcodes", "integer" },
309 { "coding" },
310 { "xmlroot" }
311 }
312 },
313 {
314 "definition", {
315 { "tag" },
316 { "synonym" },
317 { "meaning" },
318 { "sortkey" },
319 { "used", "boolean" }
320 }
321 }
322 }
323 }
324}
325
326implement {
327 name = "processsynonyms",
328 actions = synonyms.process,
329 arguments = {
330 "string",
331 {
332 { "criterium" },
333 { "language" },
334 { "method" }
335 }
336 }
337}
338 |