publ-sor.lua /size: 11 Kb    last modification: 2020-07-01 14:35
1
if
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
-- if needed we can optimize this one: chekc if it's detail or something else
10
-- and use direct access, but in practice it's fast enough
11 12
local
type
=
type
13
local
concat
=
table
.
concat
14
local
formatters
=
string
.
formatters
15
local
compare
=
sorters
.
comparers
.
basic
-- (a,b)
16
local
sort
=
table
.
sort
17 18
local
toarray
=
utilities
.
parsers
.
settings_to_array
19
local
utfchar
=
utf
.
char
20 21
local
publications
=
publications
22
local
writers
=
publications
.
writers
23 24
local
variables
=
interfaces
.
variables
25
local
v_short
=
variables
.
short
26
local
v_default
=
variables
.
default
27
local
v_reference
=
variables
.
reference
28
local
v_dataset
=
variables
.
dataset
29
local
v_list
=
variables
.
list
30
local
v_index
=
variables
.
index
31
local
v_cite
=
variables
.
cite
32
local
v_used
=
variables
.
used
33 34
local
report
=
logs
.
reporter
(
"
publications
"
,
"
sorters
"
)
35 36
local
trace_sorters
=
false
trackers
.
register
(
"
publications.sorters
"
,
function
(
v
)
trace_sorters
=
v
end
)
37 38
-- authors(s) | year | journal | title | pages
39 40
local
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 103
local
f_getter
=
formatters
[
"
splitted[strip(getter(current,entry,detail,%q,categories,types) or %q)], -- %s
"
]
104
local
f_writer
=
formatters
[
"
splitted[strip(writer_%s(getter(current,entry,detail,%q,categories,types) or %q,snippets))], -- %s
"
]
105
local
f_helper
=
formatters
[
"
local writer_%s = writers[%q] -- %s: %s
"
]
106
local
f_value
=
formatters
[
"
splitted[%q], -- %s
"
]
107
local
s_index
=
"
splitted[index], -- the order in the list, always added
"
108 109
-- there is no need to cache this in specification
110 111
local
sharedmethods
=
{
}
112
publications
.
sortmethods
=
sharedmethods
113 114
local
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
-- print(code)
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
-- sorters.setlanguage(options.language,options.method)
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 233
end
234 235
-- tag | listindex | reference | userdata | dataindex
236 237
-- short : short + tag index
238
-- dataset : index + tag
239
-- list : list + index
240
-- reference : tag + index
241
-- used : reference + dataset
242
-- authoryear : complex sort
243 244
local
sorters
=
{
}
245 246
sorters
[
v_short
]
=
function
(
dataset
,
rendering
,
list
)
-- should we store it
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
-- assumes ascii shorts ... no utf yet
257
return
shorta
<
shortb
258
end
259
-- fall back on tag order
260
return
taga
<
tagb
261
end
262
-- fall back on dataset order
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
)
272
end
273 274
sorters
[
v_dataset
]
=
function
(
dataset
,
rendering
,
list
)
-- dataset index
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
)
291
end
292 293
sorters
[
v_list
]
=
function
(
dataset
,
rendering
,
list
)
-- list index (normally redundant)
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
)
310
end
311 312
sorters
[
v_reference
]
=
function
(
dataset
,
rendering
,
list
)
-- tag
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
)
329
end
330 331
sorters
[
v_used
]
=
function
(
dataset
,
rendering
,
list
)
-- tag
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
)
348
end
349 350
sorters
[
v_default
]
=
sorters
[
v_list
]
351
sorters
[
"
"
]
=
sorters
[
v_list
]
352
sorters
[
v_cite
]
=
sorters
[
v_list
]
353
sorters
[
v_index
]
=
sorters
[
v_dataset
]
354 355
local
function
anything
(
dataset
,
rendering
,
list
,
sorttype
)
356
local
valid
=
sortsequence
(
dataset
,
list
,
sorttype
)
-- field order
357
if
valid
and
#
valid
>
0
then
358
-- hm, we have a complication here because a sortsequence doesn't know if there's a field
359
-- so there is no real catch possible here .., anyway, we add a index as last entry when no
360
-- one is set so that should be good enough (needs testing)
361
for
i
=
1
,
#
valid
do
362
local
v
=
valid
[
i
]
363
valid
[
i
]
=
list
[
v
.
index
]
364
end
365
return
valid
366
end
367
end
368 369
table
.
setmetatableindex
(
sorters
,
function
(
t
,
k
)
return
anything
end
)
370 371
publications
.
lists
.
sorters
=
sorters
372 373
-- publications.sortmethods.key = {
374
-- sequence = {
375
-- { field = "key", default = "", unknown = "" },
376
-- { field = "index", default = "", unknown = "" },
377
-- },
378
-- }
379