1if not modules then modules = { } end modules [ ' publ-sor ' ] = {
2 version = 1 . 001 ,
3 comment = " this module part of publication support " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9
10
11
12local type = type
13local concat = table . concat
14local formatters = string . formatters
15local compare = sorters . comparers . basic
16local sort = table . sort
17
18local toarray = utilities . parsers . settings_to_array
19local utfchar = utf . char
20
21local publications = publications
22local writers = publications . writers
23
24local variables = interfaces . variables
25local v_short = variables . short
26local v_default = variables . default
27local v_reference = variables . reference
28local v_dataset = variables . dataset
29local v_list = variables . list
30local v_index = variables . index
31local v_cite = variables . cite
32local v_used = variables . used
33
34local report = logs . reporter ( " publications " , " sorters " )
35
36local trace_sorters = false trackers . register ( " publications.sorters " , function ( v ) trace_sorters = v end )
37
38
39
40local template = [[
41local type, tostring = type, tostring
42
43local writers = publications.writers
44local datasets = publications.datasets
45local getter = publications.getfaster -- (current,data,details,field,categories,types)
46local strip = sorters.strip
47local splitter = sorters.splitters.utf
48
49local function newsplitter(splitter)
50 return table.setmetatableindex({},function(t,k) -- could be done in the sorter but seldom that many shared
51 local v = splitter(k,true) -- in other cases
52 t[k] = v
53 return v
54 end)
55end
56
57return function(dataset,list,method) -- indexer
58 local current = datasets[dataset]
59 local luadata = current.luadata
60 local details = current.details
61 local specification = publications.currentspecification
62 local categories = specification.categories
63 local types = specification.types
64 local splitted = newsplitter(splitter) -- saves mem
65 local snippets = { } -- saves mem
66 local result = { }
67
68%helpers%
69
70 for i=1,#list do
71 -- either { tag, tag, ... } or { { tag, index }, { tag, index } }
72 local li = list[i]
73 local tag = type(li) == "string" and li or li[1]
74 local index = tostring(i)
75 local entry = luadata[tag]
76 if entry then
77 -- maybe optional: if entry.key then push the keygetter
78 -- in slot 1 and ignore (e.g. author)
79 local detail = details[tag]
80 result[i] = {
81 index = i,
82 split = {
83
84%getters%
85
86 },
87 }
88 else
89 result[i] = {
90 index = i,
91 split = {
92
93%unknowns%
94
95 },
96 }
97 end
98 end
99 return result
100end
101 ]]
102
103local f_getter = formatters [ " splitted[strip(getter(current,entry,detail,%q,categories,types) or %q)], -- %s " ]
104local f_writer = formatters [ " splitted[strip(writer_%s(getter(current,entry,detail,%q,categories,types) or %q,snippets))], -- %s " ]
105local f_helper = formatters [ " local writer_%s = writers[%q] -- %s: %s " ]
106local f_value = formatters [ " splitted[%q], -- %s " ]
107local s_index = " splitted[index], -- the order in the list, always added "
108
109
110
111local sharedmethods = { }
112publications . sortmethods = sharedmethods
113
114local function sortsequence ( dataset , list , sorttype )
115
116 if not list or # list = = 0 then
117 return
118 end
119
120 local specification = publications . currentspecification
121 local types = specification . types
122 local sortmethods = specification . sortmethods
123 local method = sortmethods and sortmethods [ sorttype ] or sharedmethods [ sorttype ]
124 local sequence = method and method . sequence
125
126 local s_default = " <before end> "
127 local s_unknown = " <at the end> "
128
129 local c_default = utfchar ( 0xFFFE )
130 local c_unknown = utfchar ( 0xFFFF )
131
132 if not sequence and type ( sorttype ) = = " string " then
133 local list = toarray ( sorttype )
134 if # list > 0 then
135 local indexdone = false
136 sequence = { }
137 for i = 1 , # list do
138 local entry = toarray ( list [ i ] )
139 local field = entry [ 1 ]
140 local default = entry [ 2 ]
141 local unknown = entry [ 3 ] or default
142 sequence [ i ] = {
143 field = field ,
144 default = default = = s_default and c_default or default or c_default ,
145 unknown = unknown = = s_unknown and c_unknown or unknown or c_unknown ,
146 }
147 if field = = " index " then
148 indexdone = true
149 end
150 end
151 if not indexdone then
152 sequence [ # sequence + 1 ] = {
153 field = " index " ,
154 default = 0 ,
155 unknown = 0 ,
156 }
157 end
158 end
159 if trace_sorters then
160 report ( " creating sequence from method %a " , sorttype )
161 end
162 end
163
164 if sequence then
165
166 local getters = { }
167 local unknowns = { }
168 local helpers = { }
169
170 if trace_sorters then
171 report ( " initializing method %a " , sorttype )
172 end
173
174 for i = 1 , # sequence do
175 local step = sequence [ i ]
176 local field = step . field or " ? "
177 local default = step . default or c_default
178 local unknown = step . unknown or c_unknown
179 local fldtype = types [ field ]
180 local fldwriter = step . writer or fldtype
181 local writer = fldwriter and writers [ fldwriter ]
182
183 if trace_sorters then
184 report ( " % 3i : field %a, type %a, default %a, unknown %a " , i , field , fldtype ,
185 default = = c_default and s_default or default ,
186 unknown = = c_unknown and s_unknown or unknown
187 )
188 end
189
190 if writer then
191 local h = # helpers + 1
192 getters [ i ] = f_writer ( h , field , default , field )
193 helpers [ h ] = f_helper ( h , fldwriter , field , fldtype )
194 else
195 getters [ i ] = f_getter ( field , default , field )
196 end
197 unknowns [ i ] = f_value ( unknown , field )
198 end
199
200 unknowns [ # unknowns + 1 ] = s_index
201 getters [ # getters + 1 ] = s_index
202
203 local code = utilities . templates . replace ( template , {
204 helpers = concat ( helpers , " \n " ) ,
205 getters = concat ( getters , " \n " ) ,
206 unknowns = concat ( unknowns , " \n " ) ,
207 } )
208
209
210
211 local action , error = loadstring ( code )
212 if type ( action ) = = " function " then
213 action = action ( )
214 else
215 report ( " error when compiling sort method %a: %s " , sorttype , error or " unknown " )
216 end
217 if type ( action ) = = " function " then
218 local valid = action ( dataset , list , method )
219 if valid and # valid > 0 then
220
221 sorters . sort ( valid , compare )
222 return valid
223 else
224 report ( " error when applying sort method %a " , sorttype )
225 end
226 else
227 report ( " error in sort method %a " , sorttype )
228 end
229 else
230 report ( " invalid sort method %a " , sorttype )
231 end
232
233end
234
235
236
237
238
239
240
241
242
243
244local sorters = { }
245
246sorters [ v_short ] = function ( dataset , rendering , list )
247 local shorts = rendering . shorts
248 local function compare ( a , b )
249 if a and b then
250 local taga = a [ 1 ]
251 local tagb = b [ 1 ]
252 if taga and tagb then
253 local shorta = shorts [ taga ]
254 local shortb = shorts [ tagb ]
255 if shorta and shortb then
256
257 return shorta < shortb
258 end
259
260 return taga < tagb
261 end
262
263 local indexa = a [ 5 ]
264 local indexb = b [ 5 ]
265 if indexa and indexb then
266 return indexa < indexb
267 end
268 end
269 return false
270 end
271 sort ( list , compare )
272end
273
274sorters [ v_dataset ] = function ( dataset , rendering , list )
275 local function compare ( a , b )
276 if a and b then
277 local indexa = a [ 5 ]
278 local indexb = b [ 5 ]
279 if indexa and indexb then
280 return indexa < indexb
281 end
282 local taga = a [ 1 ]
283 local tagb = b [ 1 ]
284 if taga and tagb then
285 return taga < tagb
286 end
287 end
288 return false
289 end
290 sort ( list , compare )
291end
292
293sorters [ v_list ] = function ( dataset , rendering , list )
294 local function compare ( a , b )
295 if a and b then
296 local lista = a [ 2 ]
297 local listb = b [ 2 ]
298 if lista and listb then
299 return lista < listb
300 end
301 local indexa = a [ 5 ]
302 local indexb = b [ 5 ]
303 if indexa and indexb then
304 return indexa < indexb
305 end
306 end
307 return false
308 end
309 sort ( list , compare )
310end
311
312sorters [ v_reference ] = function ( dataset , rendering , list )
313 local function compare ( a , b )
314 if a and b then
315 local taga = a [ 1 ]
316 local tagb = b [ 1 ]
317 if taga and tagb then
318 return taga < tagb
319 end
320 local indexa = a [ 5 ]
321 local indexb = b [ 5 ]
322 if indexa and indexb then
323 return indexa < indexb
324 end
325 end
326 return false
327 end
328 sort ( list , compare )
329end
330
331sorters [ v_used ] = function ( dataset , rendering , list )
332 local function compare ( a , b )
333 if a and b then
334 local referencea = a [ 2 ]
335 local referenceb = b [ 2 ]
336 if referencea and referenceb then
337 return referencea < referenceb
338 end
339 local indexa = a [ 5 ]
340 local indexb = b [ 5 ]
341 if indexa and indexb then
342 return indexa < indexb
343 end
344 end
345 return false
346 end
347 sort ( list , compare )
348end
349
350sorters [ v_default ] = sorters [ v_list ]
351sorters [ " " ] = sorters [ v_list ]
352sorters [ v_cite ] = sorters [ v_list ]
353sorters [ v_index ] = sorters [ v_dataset ]
354
355local function anything ( dataset , rendering , list , sorttype )
356 local valid = sortsequence ( dataset , list , sorttype )
357 if valid and # valid > 0 then
358
359
360
361 for i = 1 , # valid do
362 local v = valid [ i ]
363 valid [ i ] = list [ v . index ]
364 end
365 return valid
366 end
367end
368
369table . setmetatableindex ( sorters , function ( t , k ) return anything end )
370
371publications . lists . sorters = sorters
372
373
374
375
376
377
378
379 |