publ-ini.lua /size: 119 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
publ-ini
'
]
=
{
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
-- bah .. this 200 locals limit again ... so we need to split it as adding more
10
-- do ... ends makes it messier
11 12
-- plug the list sorted in the list mechanism (specification.sortorder)
13 14
-- If we define two datasets with the same bib file we can consider
15
-- sharing the data but that means that we need to have a parent which
16
-- in turn makes things messy if we start manipulating entries in
17
-- different ways (future) .. not worth the trouble as we will seldom
18
-- load big bib files many times and even then ... fonts are larger.
19 20
-- A potential optimization is to work with current_dataset, current_tag when
21
-- fetching fields but the code become real messy that way (many currents). The
22
-- gain is not that large anyway because not much publication stuff is flushed.
23 24
local
next
,
rawget
,
type
,
tostring
,
tonumber
=
next
,
rawget
,
type
,
tostring
,
tonumber
25
local
match
,
find
,
gsub
=
string
.
match
,
string
.
find
,
string
.
gsub
26
local
concat
,
sort
,
tohash
=
table
.
concat
,
table
.
sort
,
table
.
tohash
27
local
mod
=
math
.
mod
28
local
formatters
=
string
.
formatters
29
local
allocate
=
utilities
.
storage
.
allocate
30
local
settings_to_array
,
settings_to_set
=
utilities
.
parsers
.
settings_to_array
,
utilities
.
parsers
.
settings_to_set
31
local
sortedkeys
,
sortedhash
=
table
.
sortedkeys
,
table
.
sortedhash
32
local
setmetatableindex
=
table
.
setmetatableindex
33
local
lpegmatch
=
lpeg
.
match
34
local
P
,
S
,
C
,
Ct
,
Cs
,
R
,
Carg
=
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
C
,
lpeg
.
Ct
,
lpeg
.
Cs
,
lpeg
.
R
,
lpeg
.
Carg
35
local
upper
=
characters
.
upper
36 37
local
report
=
logs
.
reporter
(
"
publications
"
)
38
local
report_cite
=
logs
.
reporter
(
"
publications
"
,
"
cite
"
)
39
local
report_list
=
logs
.
reporter
(
"
publications
"
,
"
list
"
)
40
local
report_suffix
=
logs
.
reporter
(
"
publications
"
,
"
suffix
"
)
41 42
local
trace
=
false
trackers
.
register
(
"
publications
"
,
function
(
v
)
trace
=
v
end
)
43
local
trace_cite
=
false
trackers
.
register
(
"
publications.cite
"
,
function
(
v
)
trace_cite
=
v
end
)
44
local
trace_missing
=
false
trackers
.
register
(
"
publications.cite.missing
"
,
function
(
v
)
trace_missing
=
v
end
)
45
local
trace_references
=
false
trackers
.
register
(
"
publications.cite.references
"
,
function
(
v
)
trace_references
=
v
end
)
46
local
trace_details
=
false
trackers
.
register
(
"
publications.details
"
,
function
(
v
)
trace_details
=
v
end
)
47
local
trace_suffixes
=
false
trackers
.
register
(
"
publications.suffixes
"
,
function
(
v
)
trace_suffixes
=
v
end
)
48 49
publications
=
publications
or
{
}
50
local
datasets
=
publications
.
datasets
51
local
writers
=
publications
.
writers
52
local
casters
=
publications
.
casters
53
local
detailed
=
publications
.
detailed
54
local
enhancer
=
publications
.
enhancer
55
local
enhancers
=
publications
.
enhancers
56 57
local
tracers
=
publications
.
tracers
or
{
}
58
publications
.
tracers
=
tracers
59 60
local
setmacro
=
interfaces
.
setmacro
-- todo
61
local
setcounter
=
tex
.
setcounter
-- todo
62
local
variables
=
interfaces
.
variables
63 64
local
v_local
=
variables
[
"
local
"
]
65
local
v_global
=
variables
[
"
global
"
]
66 67
local
v_force
=
variables
.
force
68
local
v_normal
=
variables
.
normal
69
local
v_reverse
=
variables
.
reverse
70
local
v_none
=
variables
.
none
71
local
v_yes
=
variables
.
yes
72
local
v_no
=
variables
.
no
73
local
v_all
=
variables
.
all
74
local
v_always
=
variables
.
always
75
local
v_text
=
variables
.
text
76
local
v_doublesided
=
variables
.
doublesided
77
local
v_default
=
variables
.
default
78
local
v_dataset
=
variables
.
dataset
79 80
local
conditionals
=
tex
.
conditionals
81 82
local
isdefined
=
tex
.
isdefined
83 84
----- basicsorter = sorters.basicsorter -- (a,b)
85
----- sortstripper = sorters.strip
86
----- sortsplitter = sorters.splitters.utf
87 88
local
manipulators
=
typesetters
.
manipulators
89
local
splitmanipulation
=
manipulators
.
splitspecification
90
local
applymanipulation
=
manipulators
.
applyspecification
91
local
manipulatormethods
=
manipulators
.
methods
92 93
-- this might move elsewhere
94 95
manipulatormethods
.
Word
=
converters
.
Word
96
manipulatormethods
.
WORD
=
converters
.
WORD
97
manipulatormethods
.
Words
=
converters
.
Words
98
manipulatormethods
.
WORDS
=
converters
.
WORDS
99 100
local
context
=
context
101
local
commands
=
commands
102
local
implement
=
interfaces
.
implement
103 104
local
ctx_doifelse
=
commands
.
doifelse
105
local
ctx_doif
=
commands
.
doif
106
local
ctx_doifnot
=
commands
.
doifnot
107
local
ctx_gobbletwoarguments
=
context
.
gobbletwoarguments
108 109
local
ctx_btxhandlelistentry
=
context
.
btxhandlelistentry
110
local
ctx_btxhandlecombientry
=
context
.
btxhandlecombientry
111
local
ctx_btxchecklistentry
=
context
.
btxchecklistentry
112 113
local
ctx_btxsetdataset
=
context
.
btxsetdataset
114
local
ctx_btxsettag
=
context
.
btxsettag
115
local
ctx_btxsetnumber
=
context
.
btxsetnumber
116
local
ctx_btxsetlanguage
=
context
.
btxsetlanguage
117
local
ctx_btxsetcombis
=
context
.
btxsetcombis
118
local
ctx_btxsetcategory
=
context
.
btxsetcategory
119
local
ctx_btxsetfirst
=
context
.
btxsetfirst
120
local
ctx_btxsetsecond
=
context
.
btxsetsecond
121
local
ctx_btxsetsuffix
=
context
.
btxsetsuffix
122
local
ctx_btxsetinternal
=
context
.
btxsetinternal
123
local
ctx_btxsetlefttext
=
context
.
btxsetlefttext
124
local
ctx_btxsetrighttext
=
context
.
btxsetrighttext
125
local
ctx_btxsetbefore
=
context
.
btxsetbefore
126
local
ctx_btxsetafter
=
context
.
btxsetafter
127
local
ctx_btxsetbacklink
=
context
.
btxsetbacklink
128
local
ctx_btxsetfirstinternal
=
context
.
btxsetfirstinternal
129
local
ctx_btxsetlastinternal
=
context
.
btxsetlastinternal
130
local
ctx_btxsetauthorfield
=
context
.
btxsetauthorfield
131 132
-- local ctx_btxsetdataset = function(s) setmacro("currentbtxdataset", s) end -- context.btxsetdataset
133
-- local ctx_btxsettag = function(s) setmacro("currentbtxtag", s) end -- context.btxsettag
134
-- local ctx_btxsetnumber = function(s) setmacro("currentbtxnumber", s) end -- context.btxsetnumber
135
-- local ctx_btxsetlanguage = function(s) setmacro("currentbtxlanguage", s) end -- context.btxsetlanguage
136
-- local ctx_btxsetcombis = function(s) setmacro("currentbtxcombis", s) end -- context.btxsetcombis
137
-- local ctx_btxsetcategory = function(s) setmacro("currentbtxcategory", s) end -- context.btxsetcategory
138
-- local ctx_btxsetfirst = function(s) setmacro("currentbtxfirst", s) end -- context.btxsetfirst
139
-- local ctx_btxsetsecond = function(s) setmacro("currentbtxsecond", s) end -- context.btxsetsecond
140
-- local ctx_btxsetsuffix = function(s) setmacro("currentbtxsuffix", s) end -- context.btxsetsuffix
141
-- local ctx_btxsetinternal = function(s) setmacro("currentbtxinternal", s) end -- context.btxsetinternal
142
-- local ctx_btxsetlefttext = function(s) setmacro("currentbtxlefttext", s) end -- context.btxsetlefttext
143
-- local ctx_btxsetrighttext = function(s) setmacro("currentbtxrighttext", s) end -- context.btxsetrighttext
144
-- local ctx_btxsetbefore = function(s) setmacro("currentbtxbefore", s) end -- context.btxsetbefore
145
-- local ctx_btxsetafter = function(s) setmacro("currentbtxafter", s) end -- context.btxsetafter
146
-- local ctx_btxsetbacklink = function(s) setmacro("currentbtxbacklink", s) end -- context.btxsetbacklink
147
-- local ctx_btxsetfirstinternal = function(s) setmacro("currentbtxfirstinternal", s) end -- context.btxsetfirstinternal
148
-- local ctx_btxsetlastinternal = function(s) setmacro("currentbtxlastinternal", s) end -- context.btxsetlastinternal
149 150
local
ctx_btxsetfirstpage
=
context
.
btxsetfirstpage
151
local
ctx_btxsetlastpage
=
context
.
btxsetlastpage
152 153
local
ctx_btxstartcite
=
context
.
btxstartcite
154
local
ctx_btxstopcite
=
context
.
btxstopcite
155
local
ctx_btxstartciteauthor
=
context
.
btxstartciteauthor
156
local
ctx_btxstopciteauthor
=
context
.
btxstopciteauthor
157
local
ctx_btxstartsubcite
=
context
.
btxstartsubcite
158
local
ctx_btxstopsubcite
=
context
.
btxstopsubcite
159
local
ctx_btxstartlistentry
=
context
.
btxstartlistentry
160
local
ctx_btxstoplistentry
=
context
.
btxstoplistentry
161
local
ctx_btxstartcombientry
=
context
.
btxstartcombientry
162
local
ctx_btxstopcombientry
=
context
.
btxstopcombientry
163 164
local
ctx_btxflushauthor
=
context
.
btxflushauthor
165 166
local
ctx_btxsetnoflistentries
=
context
.
btxsetnoflistentries
167
local
ctx_btxsetcurrentlistentry
=
context
.
btxsetcurrentlistentry
168
local
ctx_btxsetcurrentlistindex
=
context
.
btxsetcurrentlistindex
169 170
local
ctx_btxsetcount
=
context
.
btxsetcount
171
local
ctx_btxsetconcat
=
context
.
btxsetconcat
172 173
local
ctx_btxcitesetup
=
context
.
btxcitesetup
174
local
ctx_btxsubcitesetup
=
context
.
btxsubcitesetup
175
local
ctx_btxnumberingsetup
=
context
.
btxnumberingsetup
176
local
ctx_btxpagesetup
=
context
.
btxpagesetup
177
local
ctx_btxlistsetup
=
context
.
btxlistsetup
178 179
local
trialtypesetting
=
context
.
trialtypesetting
180 181
languages
.
data
=
languages
.
data
or
{
}
182
local
data
=
languages
.
data
183 184
local
specifications
=
publications
.
specifications
185
local
currentspecification
=
specifications
[
false
]
186
local
ignoredfields
=
{
}
187
publications
.
currentspecification
=
currentspecification
188 189
local
function
setspecification
(
name
)
190
currentspecification
=
specifications
[
name
]
191
if
trace
then
192
report
(
"
setting specification %a
"
,
type
(
name
)
=
=
"
string
"
and
name
or
"
anything
"
)
193
end
194
publications
.
currentspecification
=
currentspecification
195
end
196 197
publications
.
setspecification
=
setspecification
198 199
implement
{
200
name
=
"
btxsetspecification
"
,
201
actions
=
setspecification
,
202
arguments
=
"
string
"
,
203
}
204 205
local
optionalspace
=
lpeg
.
patterns
.
whitespace
^
0
206
local
prefixsplitter
=
optionalspace
*
lpeg
.
splitat
(
optionalspace
*
P
(
"
::
"
)
*
optionalspace
)
207 208
statistics
.
register
(
"
publications load time
"
,
function
(
)
209
local
publicationsstats
=
publications
.
statistics
210
local
nofbytes
=
publicationsstats
.
nofbytes
211
if
nofbytes
>
0
then
212
return
string
.
format
(
"
%s seconds, %s bytes, %s definitions, %s shortcuts
"
,
213
statistics
.
elapsedtime
(
publications
)
,
214
nofbytes
,
215
publicationsstats
.
nofdefinitions
or
0
,
216
publicationsstats
.
nofshortcuts
or
0
217
)
218
else
219
return
nil
220
end
221
end
)
222 223
logs
.
registerfinalactions
(
function
(
)
224
local
done
=
false
225
local
unknown
=
false
226
for
name
,
dataset
in
sortedhash
(
datasets
)
do
227
for
command
,
n
in
sortedhash
(
dataset
.
commands
)
do
228
if
not
done
then
229
logs
.
startfilelogging
(
report
,
"
used btx commands
"
)
230
done
=
true
231
end
232
if
isdefined
(
command
)
then
233
report
(
"
%-20s %-20s % 5i %s
"
,
name
,
command
,
n
,
"
known
"
)
234
elseif
isdefined
(
upper
(
command
)
)
then
235
report
(
"
%-20s %-20s % 5i %s
"
,
name
,
command
,
n
,
"
KNOWN
"
)
236
else
237
report
(
"
%-20s %-20s % 5i %s
"
,
name
,
command
,
n
,
"
unknown
"
)
238
unknown
=
true
239
end
240
end
241
end
242
if
done
then
243
logs
.
stopfilelogging
(
)
244
end
245
if
unknown
and
logs
.
loggingerrors
(
)
then
246
logs
.
starterrorlogging
(
report
,
"
unknown btx commands
"
)
247
for
name
,
dataset
in
sortedhash
(
datasets
)
do
248
for
command
,
n
in
sortedhash
(
dataset
.
commands
)
do
249
if
not
isdefined
(
command
)
and
not
isdefined
(
upper
(
command
)
)
then
250
report
(
"
%-20s %-20s % 5i %s
"
,
name
,
command
,
n
,
"
unknown
"
)
251
end
252
end
253
end
254
logs
.
stoperrorlogging
(
)
255
end
256
end
)
257 258
-- multipass, we need to sort because hashing is random per run and not per
259
-- version (not the best changed feature of lua)
260 261
local
collected
=
allocate
(
)
262
local
tobesaved
=
allocate
(
)
263 264
do
265 266
local
function
serialize
(
t
)
267
local
f_key_table
=
formatters
[
"
[%q] = {
"
]
268
local
f_key_string
=
formatters
[
"
%s = %q,
"
]
269
local
r
=
{
"
return {
"
}
270
local
m
=
1
271
for
tag
,
entry
in
sortedhash
(
t
)
do
272
m
=
m
+
1
273
r
[
m
]
=
f_key_table
(
tag
)
274
local
s
=
sortedkeys
(
entry
)
275
for
i
=
1
,
#
s
do
276
local
k
=
s
[
i
]
277
m
=
m
+
1
278
r
[
m
]
=
f_key_string
(
k
,
entry
[
k
]
)
279
end
280
m
=
m
+
1
281
r
[
m
]
=
"
},
"
282
end
283
r
[
m
]
=
"
}
"
284
return
concat
(
r
,
"
\n
"
)
285
end
286 287
local
function
finalizer
(
)
288
local
prefix
=
tex
.
jobname
-- or environment.jobname
289
local
setnames
=
sortedkeys
(
datasets
)
290
for
i
=
1
,
#
setnames
do
291
local
name
=
setnames
[
i
]
292
local
dataset
=
datasets
[
name
]
293
local
userdata
=
dataset
.
userdata
294
local
checksum
=
nil
295
local
username
=
file
.
addsuffix
(
file
.
robustname
(
formatters
[
"
%s-btx-%s
"
]
(
prefix
,
name
)
)
,
"
lua
"
)
296
if
userdata
and
next
(
userdata
)
then
297
if
job
.
passes
.
first
then
298
local
newdata
=
serialize
(
userdata
)
299
checksum
=
md5
.
HEX
(
newdata
)
300
io
.
savedata
(
username
,
newdata
)
301
end
302
else
303
os
.
remove
(
username
)
304
username
=
nil
305
end
306
local
loaded
=
dataset
.
loaded
307
local
sources
=
dataset
.
sources
308
local
used
=
{
}
309
for
i
=
1
,
#
sources
do
310
local
source
=
sources
[
i
]
311
-- if loaded[source.filename] ~= "previous" then -- needs checking
312
if
loaded
[
source
.
filename
]
~
=
"
previous
"
or
loaded
[
source
.
filename
]
=
=
"
current
"
then
313
used
[
#
used
+
1
]
=
source
314
end
315
end
316
tobesaved
[
name
]
=
{
317
usersource
=
{
318
filename
=
username
,
319
checksum
=
checksum
,
320
}
,
321
datasources
=
used
,
322
}
323
end
324
end
325 326
local
function
initializer
(
)
327
statistics
.
starttiming
(
publications
)
328
for
name
,
state
in
sortedhash
(
collected
)
do
329
local
dataset
=
datasets
[
name
]
330
local
datasources
=
state
.
datasources
331
local
usersource
=
state
.
usersource
332
if
datasources
then
333
for
i
=
1
,
#
datasources
do
334
local
filename
=
datasources
[
i
]
.
filename
335
publications
.
load
{
336
dataset
=
dataset
,
337
filename
=
filename
,
338
kind
=
"
previous
"
339
}
340
end
341
end
342
if
usersource
then
343
dataset
.
userdata
=
table
.
load
(
usersource
.
filename
)
or
{
}
344
end
345
end
346
statistics
.
stoptiming
(
publications
)
347
function
initializer
(
)
end
-- will go, for now, runtime loaded
348
end
349 350
job
.
register
(
'
publications.collected
'
,
tobesaved
,
initializer
,
finalizer
)
351 352
end
353 354
-- we want to minimize references as there can be many (at least
355
-- when testing)
356 357
local
nofcitations
=
0
358
local
usedentries
=
nil
359
local
citetolist
=
nil
360
local
listtocite
=
nil
361
local
listtolist
=
nil
362 363
do
364 365
local
initialize
=
nil
-- we delay
366 367
initialize
=
function
(
t
)
368
usedentries
=
allocate
{
}
369
citetolist
=
allocate
{
}
370
listtocite
=
allocate
{
}
371
listtolist
=
allocate
{
}
372
local
names
=
{
}
373
local
p_collect
=
(
C
(
R
(
"
09
"
)
^
1
)
*
Carg
(
1
)
/
function
(
s
,
entry
)
listtocite
[
tonumber
(
s
)
]
=
entry
end
+
P
(
1
)
)
^
0
374
local
nofunique
=
0
375
local
nofreused
=
0
376
-- local internals = references.sortedinternals -- todo: when we need it more than once
377
-- for i=1,#internals do -- but currently we don't do this when not
378
-- local entry = internals[i] -- needed anyway so ...
379
local
internals
=
structures
.
references
.
internals
380
for
i
,
entry
in
sortedhash
(
internals
)
do
381
local
metadata
=
entry
.
metadata
382
if
metadata
then
383
local
kind
=
metadata
.
kind
384
if
kind
=
=
"
full
"
then
385
-- reference (in list)
386
local
userdata
=
entry
.
userdata
387
if
userdata
then
388
local
tag
=
userdata
.
btxref
389
if
tag
then
390
local
set
=
userdata
.
btxset
or
v_default
391
local
s
=
usedentries
[
set
]
392
if
s
then
393
local
u
=
s
[
tag
]
394
if
u
then
395
u
[
#
u
+
1
]
=
entry
396
else
397
s
[
tag
]
=
{
entry
}
398
end
399
nofreused
=
nofreused
+
1
400
else
401
usedentries
[
set
]
=
{
[
tag
]
=
{
entry
}
}
402
nofunique
=
nofunique
+
1
403
end
404
-- alternative: collect prev in group
405
local
int
=
tonumber
(
userdata
.
btxint
)
406
if
int
then
407
listtocite
[
int
]
=
entry
408
end
409
local
detail
=
datasets
[
set
]
.
details
[
tag
]
410
-- todo: these have to be pluggable
411
if
detail
then
412
local
author
=
detail
.
author
413
if
author
then
414
for
i
=
1
,
#
author
do
415
local
a
=
author
[
i
]
416
local
s
=
a
.
surnames
417
if
s
then
418
local
c
=
concat
(
s
,
"
+
"
)
419
local
n
=
names
[
c
]
420
if
n
then
421
n
[
#
n
+
1
]
=
a
422
break
423
else
424
names
[
c
]
=
{
a
}
425
end
426
end
427
end
428
end
429
end
430
end
431
end
432
elseif
kind
=
=
"
btx
"
then
433
-- list entry (each cite)
434
local
userdata
=
entry
.
userdata
435
if
userdata
then
436
local
int
=
tonumber
(
userdata
.
btxint
)
437
if
int
then
438
citetolist
[
int
]
=
entry
439
end
440
end
441
end
442
end
443
end
444
for
k
,
v
in
sortedhash
(
names
)
do
445
local
n
=
#
v
446
if
n
>
1
then
447
local
original
=
v
[
1
]
.
original
448
for
i
=
2
,
n
do
449
if
original
~
=
v
[
i
]
.
original
then
450
report
(
"
potential clash in name %a
"
,
k
)
451
for
i
=
1
,
n
do
452
v
[
i
]
.
state
=
1
453
end
454
break
455
end
456
end
457
end
458
end
459
if
trace_details
then
460
report
(
"
%s unique references, %s reused entries
"
,
nofunique
,
nofreused
)
461
end
462
initialize
=
nil
463
end
464 465
usedentries
=
setmetatableindex
(
function
(
_
,
k
)
if
initialize
then
initialize
(
)
end
return
usedentries
[
k
]
end
)
466
citetolist
=
setmetatableindex
(
function
(
_
,
k
)
if
initialize
then
initialize
(
)
end
return
citetolist
[
k
]
end
)
467
listtocite
=
setmetatableindex
(
function
(
_
,
k
)
if
initialize
then
initialize
(
)
end
return
listtocite
[
k
]
end
)
468
listtolist
=
setmetatableindex
(
function
(
_
,
k
)
if
initialize
then
initialize
(
)
end
return
listtolist
[
k
]
end
)
469 470
function
publications
.
usedentries
(
)
471
if
initialize
then
472
initialize
(
)
473
end
474
return
usedentries
475
end
476 477
end
478 479
-- match:
480
--
481
-- [current|previous|following] section
482
-- [current|previous|following] block
483
-- [current|previous|following] component
484
--
485
-- by prefix
486
-- by dataset
487 488
local
findallused
do
489 490
local
reported
=
{
}
491
----- finder = publications.finder
492 493
findallused
=
function
(
dataset
,
reference
,
internal
,
forcethem
)
494
local
current
=
datasets
[
dataset
]
495
local
finder
=
publications
.
finder
-- for the moment, not yet in all betas
496
local
find
=
finder
and
finder
(
current
,
reference
)
497
local
tags
=
not
find
and
settings_to_array
(
reference
)
498
local
todo
=
{
}
499
local
okay
=
{
}
-- only if mark
500
local
allused
=
usedentries
[
dataset
]
or
{
}
501
-- local allused = usedentries[dataset] -- only test
502
local
luadata
=
current
.
luadata
503
local
details
=
current
.
details
504
local
ordered
=
current
.
ordered
505
if
allused
then
-- always true
506
local
registered
=
{
}
507
local
function
register
(
tag
)
508
local
entry
=
forcethem
and
luadata
[
tag
]
509
if
entry
then
510
if
registered
[
tag
]
then
511
if
trace_cite
then
512
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
already cited (1)
"
)
513
end
514
return
515
elseif
trace_cite
then
516
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
okay
"
)
517
end
518
okay
[
#
okay
+
1
]
=
entry
519
-- todo[tag] = true
520
registered
[
tag
]
=
true
521
return
tag
522
end
523
entry
=
allused
[
tag
]
524
if
trace_cite
then
525
report_cite
(
"
dataset: %s, tag: %s, used: % t
"
,
dataset
,
tag
,
table
.
sortedkeys
(
allused
)
)
526
end
527
if
not
entry
then
528
local
parent
=
details
[
tag
]
.
parent
529
if
parent
then
530
entry
=
allused
[
parent
]
531
end
532
if
entry
then
533
report
(
"
using reference of parent %a for %a
"
,
parent
,
tag
)
534
tag
=
parent
535
elseif
trace_cite
then
536
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
not used
"
)
537
end
538
elseif
trace_cite
then
539
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
used
"
)
540
end
541
if
registered
[
tag
]
then
542
if
trace_cite
then
543
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
already cited (2)
"
)
544
end
545
return
546
end
547
if
entry
then
548
-- only once in a list but at some point we can have more (if we
549
-- decide to duplicate)
550
if
#
entry
=
=
1
then
551
entry
=
entry
[
1
]
552
else
553
-- same block and section
554
local
done
=
false
555
if
internal
and
internal
>
0
then
556
-- first following in list
557
for
i
=
1
,
#
entry
do
558
local
e
=
entry
[
i
]
559
if
e
.
references
.
internal
>
internal
then
560
done
=
e
561
break
562
end
563
end
564
if
not
done
then
565
-- last preceding in list
566
for
i
=
1
,
#
entry
do
567
local
e
=
entry
[
i
]
568
if
e
.
references
.
internal
<
internal
then
569
done
=
e
570
else
571
break
572
end
573
end
574
end
575
end
576
if
done
then
577
entry
=
done
578
else
579
entry
=
entry
[
1
]
580
end
581
end
582
if
not
entry
then
583
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
no entry (1)
"
)
584
elseif
trace_cite
then
585
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
new entry
"
)
586
end
587
okay
[
#
okay
+
1
]
=
entry
588
elseif
not
entry
then
589
if
trace_cite
then
590
report_cite
(
"
dataset: %s, tag: %s, state: %s
"
,
dataset
,
tag
,
"
no entry (2)
"
)
591
end
592
-- okay[#okay+1] = luadata[tag]
593
end
594
todo
[
tag
]
=
true
595
registered
[
tag
]
=
true
596
return
tag
597
end
598
if
reference
=
=
"
*
"
then
599
tags
=
{
}
600
for
i
=
1
,
#
ordered
do
601
local
tag
=
ordered
[
i
]
.
tag
602
tag
=
register
(
tag
)
603
tags
[
#
tags
+
1
]
=
tag
604
end
605
elseif
find
then
606
tags
=
{
}
607
for
i
=
1
,
#
ordered
do
608
local
entry
=
ordered
[
i
]
609
if
find
(
entry
)
then
610
local
tag
=
entry
.
tag
611
tag
=
register
(
tag
)
612
tags
[
#
tags
+
1
]
=
tag
613
end
614
end
615
if
#
tags
=
=
0
and
not
reported
[
reference
]
then
616
tags
[
1
]
=
reference
617
reported
[
reference
]
=
true
618
end
619
else
620
for
i
=
1
,
#
tags
do
621
local
tag
=
tags
[
i
]
622
if
luadata
[
tag
]
then
623
tag
=
register
(
tag
)
624
tags
[
i
]
=
tag
625
elseif
not
reported
[
tag
]
then
626
reported
[
tag
]
=
true
627
report_cite
(
"
non-existent entry %a in %a
"
,
tag
,
dataset
)
628
end
629
end
630
end
631
elseif
find
then
632
tags
=
{
}
633
for
i
=
1
,
#
ordered
do
634
local
entry
=
ordered
[
i
]
635
if
find
(
entry
)
then
636
local
tag
=
entry
.
tag
637
local
parent
=
details
[
tag
]
.
parent
638
if
parent
then
639
tag
=
parent
640
end
641
tags
[
#
tags
+
1
]
=
tag
642
todo
[
tag
]
=
true
643
-- okay[#okay+1] = entry -- only test
644
end
645
end
646
if
#
tags
=
=
0
and
not
reported
[
reference
]
then
647
tags
[
1
]
=
reference
648
reported
[
reference
]
=
true
649
end
650
else
651
for
i
=
1
,
#
tags
do
652
local
tag
=
tags
[
i
]
653
local
parent
=
details
[
tag
]
.
parent
654
if
parent
then
655
tag
=
parent
656
tags
[
i
]
=
tag
657
end
658
local
entry
=
luadata
[
tag
]
659
if
entry
then
660
todo
[
tag
]
=
true
661
-- okay[#okay+1] = entry -- only test
662
elseif
not
reported
[
tag
]
then
663
reported
[
tag
]
=
true
664
report_cite
(
"
non-existent entry %a in %a
"
,
tag
,
dataset
)
665
end
666
end
667
end
668
return
okay
,
todo
,
tags
669
end
670 671
local
firstoftwoarguments
=
context
.
firstoftwoarguments
672
local
secondoftwoarguments
=
context
.
secondoftwoarguments
673 674
implement
{
675
name
=
"
btxdoifelsematches
"
,
676
arguments
=
"
3 strings
"
,
677
actions
=
function
(
dataset
,
tag
,
expression
)
678
local
find
=
publications
.
finder
(
dataset
,
expression
)
679
local
okay
=
false
680
if
find
then
681
local
d
=
datasets
[
dataset
]
682
if
d
then
683
local
e
=
d
.
luadata
[
tag
]
684
if
e
and
find
(
e
)
then
685
firstoftwoarguments
(
)
686
return
687
end
688
end
689
end
690
secondoftwoarguments
(
)
691
end
692
}
693 694
end
695 696
local
function
unknowncite
(
reference
)
697
ctx_btxsettag
(
reference
)
698
if
trace_details
then
699
report
(
"
expanding %a cite setup %a
"
,
"
unknown
"
,
"
unknown
"
)
700
end
701
ctx_btxcitesetup
(
"
unknown
"
)
702
end
703 704
local
concatstate
=
publications
.
concatstate
705 706
-- hidden : mark for list, don't show in text
707
-- list : mark for list, show in text only when in list
708
-- text : not to list, show in text
709
-- always : mark for list, show in text
710 711
local
marked_todo
=
false
-- keeps track or not yet flushed
712
local
marked_dataset
=
false
713
local
marked_list
=
false
-- the sequential list (we flush in order, not by unordered hash)
714
local
marked_method
=
false
715 716
local
function
marknocite
(
dataset
,
tag
,
nofcitations
,
setup
)
717
ctx_btxstartcite
(
)
718
ctx_btxsetdataset
(
dataset
)
719
ctx_btxsettag
(
tag
)
720
ctx_btxsetbacklink
(
nofcitations
)
721
if
trace_details
then
722
report
(
"
expanding cite setup %a
"
,
setup
)
723
end
724
ctx_btxcitesetup
(
setup
)
725
ctx_btxstopcite
(
)
726
end
727 728
local
function
markcite
(
dataset
,
tag
,
flush
)
729
if
not
marked_todo
then
730
return
0
731
end
732
local
citation
=
marked_todo
[
tag
]
733
if
not
citation
then
734
return
0
735
end
736
if
citation
=
=
true
then
737
nofcitations
=
nofcitations
+
1
738
if
trace_cite
then
739
report_cite
(
"
mark, dataset: %s, tag: %s, number: %s, state: %s
"
,
dataset
,
tag
,
nofcitations
,
"
cited
"
)
740
end
741
if
flush
then
742
marknocite
(
dataset
,
tag
,
nofcitations
,
"
nocite
"
)
743
end
744
marked_todo
[
tag
]
=
nofcitations
-- signal that it's marked
745
return
nofcitations
746
else
747
return
citation
748
end
749
end
750 751
local
function
btxflushmarked
(
)
752
if
marked_list
and
marked_todo
then
753
for
i
=
1
,
#
marked_list
do
754
-- keep order
755
local
tag
=
marked_list
[
i
]
756
local
tbm
=
marked_todo
[
tag
]
757
if
tbm
=
=
true
or
not
tbm
then
758
nofcitations
=
nofcitations
+
1
759
local
setup
=
(
tbm
or
marked_method
=
=
v_always
)
and
"
nocite
"
or
"
invalid
"
760
marknocite
(
marked_dataset
,
tag
,
nofcitations
,
setup
)
761
if
trace_cite
then
762
report_cite
(
"
mark, dataset: %s, tag: %s, number: %s, setup: %s
"
,
marked_dataset
,
tag
,
nofcitations
,
setup
)
763
end
764
else
765
-- a number signaling being marked
766
end
767
end
768
end
769
marked_todo
=
false
770
marked_dataset
=
false
771
marked_list
=
false
772
marked_method
=
false
773
end
774 775
implement
{
name
=
"
btxflushmarked
"
,
actions
=
btxflushmarked
}
776 777
-- basic access
778 779
local
function
getfield
(
dataset
,
tag
,
name
)
-- for the moment quick and dirty
780
local
d
=
datasets
[
dataset
]
.
luadata
[
tag
]
781
return
d
and
d
[
name
]
782
end
783 784
local
function
getdetail
(
dataset
,
tag
,
name
)
-- for the moment quick and dirty
785
local
d
=
datasets
[
dataset
]
.
details
[
tag
]
786
return
d
and
d
[
name
]
787
end
788 789
local
function
getcasted
(
dataset
,
tag
,
field
,
specification
)
790
local
current
=
datasets
[
dataset
]
791
if
current
then
792
local
data
=
current
.
luadata
[
tag
]
793
if
data
then
794
local
category
=
data
.
category
795
if
not
specification
then
796
specification
=
currentspecification
797
end
798
local
catspec
=
specification
.
categories
[
category
]
799
if
not
catspec
then
800
return
false
801
end
802
local
fields
=
catspec
.
fields
803
if
fields
then
804
local
sets
=
catspec
.
sets
805
if
sets
then
806
local
set
=
sets
[
field
]
807
if
set
then
808
for
i
=
1
,
#
set
do
809
local
field
=
set
[
i
]
810
local
value
=
fields
[
field
]
and
data
[
field
]
-- redundant check
811
if
value
then
812
local
kind
=
specification
.
types
[
field
]
813
return
detailed
[
kind
]
[
value
]
,
field
,
kind
814
end
815
end
816
end
817
end
818
local
value
=
fields
[
field
]
and
data
[
field
]
-- redundant check
819
if
value
then
820
local
kind
=
specification
.
types
[
field
]
821
return
detailed
[
kind
]
[
value
]
,
field
,
kind
822
end
823
end
824
local
data
=
current
.
details
[
tag
]
825
if
data
then
826
local
kind
=
specification
.
types
[
field
]
827
return
data
[
field
]
,
field
,
kind
-- no check
828
end
829
end
830
end
831
end
832 833
local
function
getfaster
(
current
,
data
,
details
,
field
,
categories
,
types
)
834
local
category
=
data
.
category
835
local
catspec
=
categories
[
category
]
836
if
not
catspec
then
837
return
false
838
end
839
local
fields
=
catspec
.
fields
840
if
fields
then
841
local
sets
=
catspec
.
sets
842
if
sets
then
843
local
set
=
sets
[
field
]
844
if
set
then
845
for
i
=
1
,
#
set
do
846
local
field
=
set
[
i
]
847
local
value
=
fields
[
field
]
and
data
[
field
]
-- redundant check
848
if
value
then
849
local
kind
=
types
[
field
]
850
return
detailed
[
kind
]
[
value
]
,
field
,
kind
851
end
852
end
853
end
854
end
855
local
value
=
fields
[
field
]
and
data
[
field
]
-- redundant check
856
if
value
then
857
local
kind
=
types
[
field
]
858
return
detailed
[
kind
]
[
value
]
859
end
860
end
861
if
details
then
862
local
kind
=
types
[
field
]
863
return
details
[
field
]
864
end
865
end
866 867
local
function
getdirect
(
dataset
,
data
,
field
,
catspec
)
-- no field check, no dataset check
868
local
catspec
=
(
catspec
or
currentspecification
)
.
categories
[
data
.
category
]
869
if
not
catspec
then
870
return
false
871
end
872
local
fields
=
catspec
.
fields
873
if
fields
then
874
local
sets
=
catspec
.
sets
875
if
sets
then
876
local
set
=
sets
[
field
]
877
if
set
then
878
for
i
=
1
,
#
set
do
879
local
field
=
set
[
i
]
880
local
value
=
fields
[
field
]
and
data
[
field
]
-- redundant check
881
if
value
then
882
return
value
883
end
884
end
885
end
886
end
887
return
fields
[
field
]
and
data
[
field
]
or
nil
-- redundant check
888
end
889
end
890 891
local
function
getfuzzy
(
data
,
field
,
categories
)
-- no field check, no dataset check
892
local
catspec
893
if
categories
then
894
local
category
=
data
.
category
895
if
category
then
896
catspec
=
categories
[
data
.
category
]
897
end
898
end
899
if
not
field
then
900
return
901
elseif
not
catspec
then
902
return
data
[
field
]
903
end
904
local
fields
=
catspec
.
fields
905
if
fields
then
906
local
sets
=
catspec
.
sets
907
if
sets
then
908
local
set
=
sets
[
field
]
909
if
set
then
910
for
i
=
1
,
#
set
do
911
local
field
=
set
[
i
]
912
local
value
=
fields
[
field
]
and
data
[
field
]
-- redundant check
913
if
value
then
914
return
value
915
end
916
end
917
end
918
end
919
return
fields
[
field
]
and
data
[
field
]
or
nil
-- redundant check
920
end
921
end
922 923
publications
.
getfield
=
getfield
924
publications
.
getdetail
=
getdetail
925
publications
.
getcasted
=
getcasted
926
publications
.
getfaster
=
getfaster
927
publications
.
getdirect
=
getdirect
928
publications
.
getfuzzy
=
getfuzzy
929 930
-- this needs to be checked: a specific type should have a checker
931 932
-- author pagenumber keyword url
933 934
-- function commands.btxsingularorplural(dataset,tag,name)
935
-- local d = getcasted(dataset,tag,name)
936
-- if type(d) == "table" then
937
-- d = #d <= 1
938
-- else
939
-- d = true
940
-- end
941
-- ctx_doifelse(d)
942
-- end
943 944
-- function commands.oneorrange(dataset,tag,name)
945
-- local d = datasets[dataset].luadata[tag] -- details ?
946
-- if d then
947
-- d = d[name]
948
-- end
949
-- if type(d) == "string" then
950
-- d = find(d,"%-")
951
-- else
952
-- d = false
953
-- end
954
-- ctx_doifelse(not d) -- so singular is default
955
-- end
956 957
-- function commands.firstofrange(dataset,tag,name)
958
-- local d = datasets[dataset].luadata[tag] -- details ?
959
-- if d then
960
-- d = d[name]
961
-- end
962
-- if type(d) == "string" then
963
-- context(match(d,"([^%-]+)"))
964
-- end
965
-- end
966 967
local
inspectors
=
allocate
(
)
968
local
nofmultiple
=
allocate
(
)
969
local
firstandlast
=
allocate
(
)
970 971
publications
.
inspectors
=
inspectors
972
inspectors
.
nofmultiple
=
nofmultiple
973
inspectors
.
firstandlast
=
firstandlast
974 975
function
nofmultiple
.
author
(
d
)
976
return
type
(
d
)
=
=
"
table
"
and
#
d
or
0
977
end
978 979
function
publications
.
singularorplural
(
dataset
,
tag
,
name
)
980
local
data
,
field
,
kind
=
getcasted
(
dataset
,
tag
,
name
)
981
if
data
then
982
local
test
=
nofmultiple
[
kind
]
983
if
test
then
984
local
n
=
test
(
data
)
985
return
not
n
or
n
<
2
986
end
987
end
988
return
true
989
end
990 991
function
firstandlast
.
range
(
d
)
992
if
type
(
d
)
=
=
"
table
"
then
993
return
d
[
1
]
,
d
[
2
]
994
end
995
end
996 997
firstandlast
.
pagenumber
=
firstandlast
.
range
998 999
function
publications
.
oneorrange
(
dataset
,
tag
,
name
)
1000
local
data
,
field
,
kind
=
getcasted
(
dataset
,
tag
,
name
)
1001
if
data
then
1002
local
test
=
firstandlast
[
kind
]
1003
if
test
then
1004
local
first
,
last
=
test
(
data
)
1005
return
not
(
first
and
last
)
1006
end
1007
end
1008
return
nil
-- nothing at all
1009
end
1010 1011
function
publications
.
firstofrange
(
dataset
,
tag
,
name
)
1012
local
data
,
field
,
kind
=
getcasted
(
dataset
,
tag
,
name
)
1013
if
data
then
1014
local
test
=
firstandlast
[
kind
]
1015
if
test
then
1016
local
first
=
test
(
data
)
1017
if
first
then
1018
return
first
1019
end
1020
end
1021
end
1022
end
1023 1024
function
publications
.
lastofrange
(
dataset
,
tag
,
name
)
1025
local
data
,
field
,
kind
=
getcasted
(
dataset
,
tag
,
name
)
1026
if
data
then
1027
local
test
=
firstandlast
[
kind
]
1028
if
test
then
1029
local
first
,
last
=
test
(
data
)
1030
if
last
then
1031
return
last
1032
end
1033
end
1034
end
1035
end
1036 1037
implement
{
1038
name
=
"
btxsingularorplural
"
,
1039
actions
=
{
publications
.
singularorplural
,
ctx_doifelse
}
,
1040
arguments
=
"
3 strings
"
1041
}
1042 1043
implement
{
1044
name
=
"
btxoneorrange
"
,
1045
actions
=
{
publications
.
oneorrange
,
function
(
b
)
if
b
=
=
nil
then
ctx_gobbletwoarguments
(
)
else
ctx_doifelse
(
b
)
end
end
}
,
1046
arguments
=
"
3 strings
"
1047
}
1048 1049
implement
{
1050
name
=
"
btxfirstofrange
"
,
1051
actions
=
{
publications
.
firstofrange
,
context
}
,
1052
arguments
=
"
3 strings
"
1053
}
1054 1055
implement
{
1056
name
=
"
btxlastofrange
"
,
1057
actions
=
{
publications
.
lastofrange
,
context
}
,
1058
arguments
=
"
3 strings
"
1059
}
1060 1061
-- basic loading
1062 1063
function
publications
.
usedataset
(
specification
)
1064
specification
.
kind
=
"
current
"
1065
publications
.
load
(
specification
)
1066
end
1067 1068
implement
{
1069
name
=
"
btxusedataset
"
,
1070
actions
=
publications
.
usedataset
,
1071
arguments
=
{
1072
{
1073
{
"
specification
"
}
,
1074
{
"
dataset
"
}
,
1075
{
"
filename
"
}
,
1076
}
1077
}
1078
}
1079 1080
implement
{
1081
name
=
"
convertbtxdatasettoxml
"
,
1082
arguments
=
{
"
string
"
,
true
}
,
1083
actions
=
publications
.
converttoxml
1084
}
1085 1086
-- enhancing
1087 1088
do
1089 1090
-- maybe not redo when already done
1091 1092
local
function
shortsorter
(
a
,
b
)
1093
local
ay
=
a
[
2
]
-- year
1094
local
by
=
b
[
2
]
-- year
1095
if
ay
~
=
by
then
1096
return
ay
<
by
1097
end
1098
local
ay
=
a
[
3
]
-- suffix
1099
local
by
=
b
[
3
]
-- suffix
1100
if
ay
~
=
by
then
1101
-- bah, bah, bah
1102
local
an
=
tonumber
(
ay
)
1103
local
bn
=
tonumber
(
by
)
1104
if
an
and
bn
then
1105
return
an
<
bn
1106
else
1107
return
ay
<
by
1108
end
1109
end
1110
return
a
[
4
]
<
b
[
4
]
1111
end
1112 1113
-- We could avoid loops by combining enhancers but that makes it only
1114
-- more messy and for documents that use publications the few extra milli
1115
-- seconds are irrelevant (there is for sure more to gain by proper coding
1116
-- of the source and or style).
1117 1118
local
f_short
=
formatters
[
"
%s%02i
"
]
1119 1120
function
publications
.
enhancers
.
suffixes
(
dataset
)
1121
if
not
dataset
then
1122
return
-- bad news
1123
else
1124
report
(
"
analyzing previous publication run for %a
"
,
dataset
.
name
)
1125
end
1126
dataset
.
suffixed
=
true
1127
--
1128
local
used
=
usedentries
[
dataset
.
name
]
1129
if
not
used
then
1130
return
-- probably a first run
1131
end
1132
local
luadata
=
dataset
.
luadata
1133
local
details
=
dataset
.
details
1134
local
ordered
=
dataset
.
ordered
1135
if
not
luadata
or
not
details
or
not
ordered
then
1136
report
(
"
nothing to be analyzed in %a
"
,
dataset
.
name
)
1137
return
-- also bad news
1138
end
1139
-- we have two suffixes: author (dependent of type) and short
1140
local
kind
=
dataset
.
authorconversion
or
"
name
"
1141
local
fields
=
{
"
author
"
,
"
editor
"
}
-- will be entry in data definition
1142
local
shorts
=
{
}
1143
local
authors
=
{
}
1144
local
hasher
=
publications
.
authorhashers
[
kind
]
1145
local
shorter
=
publications
.
authorhashers
.
short
1146
for
i
=
1
,
#
ordered
do
1147
local
entry
=
ordered
[
i
]
1148
if
entry
then
1149
local
tag
=
entry
.
tag
1150
if
tag
then
1151
local
use
=
used
[
tag
]
1152
if
use
then
1153
-- use is a table of used list entries (so there can be more) and we just look at
1154
-- the first one for btx properties
1155
local
listentry
=
use
[
1
]
1156
local
userdata
=
listentry
.
userdata
1157
local
btxspc
=
userdata
and
userdata
.
btxspc
1158
if
btxspc
then
1159
-- we could act on the 3rd arg returned by getcasted but in general any string will do
1160
-- so we deal with it in the author hashers ... maybe some day ...
1161
local
done
=
false
1162
for
i
=
1
,
#
fields
do
1163
local
field
=
fields
[
i
]
1164
local
author
=
getcasted
(
dataset
,
tag
,
field
,
specifications
[
btxspc
]
)
1165
local
kind
=
type
(
author
)
1166
if
kind
=
=
"
table
"
or
kind
=
=
"
string
"
then
1167
if
u
then
1168
u
=
listentry
.
entries
.
text
-- hm
1169
else
1170
u
=
"
0
"
1171
end
1172
local
year
=
tonumber
(
entry
.
year
)
or
9999
1173
local
data
=
{
tag
,
year
,
u
,
i
}
1174
-- authors
1175
local
hash
=
hasher
(
author
)
1176
local
found
=
authors
[
hash
]
1177
if
not
found
then
1178
authors
[
hash
]
=
{
data
}
1179
else
1180
found
[
#
found
+
1
]
=
data
1181
end
1182
-- shorts
1183
local
hash
=
shorter
(
author
)
1184
local
short
=
f_short
(
hash
,
mod
(
year
,
100
)
)
1185
local
found
=
shorts
[
short
]
1186
if
not
found
then
1187
shorts
[
short
]
=
{
data
}
1188
else
1189
found
[
#
found
+
1
]
=
data
1190
end
1191
done
=
true
1192
break
1193
end
1194
end
1195
if
not
done
then
1196
report
(
"
unable to create short for %a, needs one of [%,t]
"
,
tag
,
fields
)
1197
end
1198
else
1199
--- no spec so let's forget about it
1200
end
1201
end
1202
end
1203
end
1204
end
1205
local
function
addsuffix
(
hashed
,
key
,
suffixkey
)
1206
for
hash
,
tags
in
sortedhash
(
hashed
)
do
-- ordered ?
1207
local
n
=
#
tags
1208
if
n
=
=
0
then
1209
-- skip
1210
elseif
n
=
=
1
then
1211
local
tagdata
=
tags
[
1
]
1212
local
tag
=
tagdata
[
1
]
1213
local
detail
=
details
[
tag
]
1214
local
entry
=
luadata
[
tag
]
1215
local
year
=
entry
.
year
1216
detail
[
key
]
=
hash
1217
elseif
n
>
1
then
1218
sort
(
tags
,
shortsorter
)
-- or take first -- todo: proper utf sorter
1219
local
lastyear
=
nil
1220
local
suffix
=
nil
1221
local
previous
=
nil
1222
for
i
=
1
,
n
do
1223
local
tagdata
=
tags
[
i
]
1224
local
tag
=
tagdata
[
1
]
1225
local
detail
=
details
[
tag
]
1226
local
entry
=
luadata
[
tag
]
1227
local
year
=
entry
.
year
1228
detail
[
key
]
=
hash
1229
if
not
year
or
year
~
=
lastyear
then
1230
lastyear
=
year
1231
suffix
=
1
1232
else
1233
if
previous
and
suffix
=
=
1
then
1234
previous
[
suffixkey
]
=
suffix
1235
end
1236
suffix
=
suffix
+
1
1237
detail
[
suffixkey
]
=
suffix
1238
end
1239
previous
=
detail
1240
end
1241
end
1242
if
trace_suffixes
then
1243
for
i
=
1
,
n
do
1244
local
tag
=
tags
[
i
]
[
1
]
1245
local
year
=
luadata
[
tag
]
.
year
1246
local
suffix
=
details
[
tag
]
.
suffix
1247
if
suffix
then
1248
report_suffix
(
"
%s: tag %a, hash %a, year %a, suffix %a
"
,
key
,
tag
,
hash
,
year
or
'
'
,
suffix
or
'
'
)
1249
else
1250
report_suffix
(
"
%s: tag %a, hash %a, year %a
"
,
key
,
tag
,
hash
,
year
or
'
'
)
1251
end
1252
end
1253
end
1254
end
1255
end
1256
addsuffix
(
shorts
,
"
shorthash
"
,
"
shortsuffix
"
)
-- todo: shorthash
1257
addsuffix
(
authors
,
"
authorhash
"
,
"
authorsuffix
"
)
1258
end
1259 1260
-- utilities.sequencers.appendaction(enhancer,"system","publications.enhancers.suffixes")
1261 1262
end
1263 1264
implement
{
1265
name
=
"
btxaddentry
"
,
1266
arguments
=
"
3 strings
"
,
1267
actions
=
function
(
name
,
settings
,
content
)
1268
local
dataset
=
datasets
[
name
]
1269
if
dataset
then
1270
publications
.
addtexentry
(
dataset
,
settings
,
content
)
1271
end
1272
end
,
1273
}
1274 1275
function
publications
.
checkeddataset
(
name
,
default
)
1276
local
dataset
=
rawget
(
datasets
,
name
)
1277
if
dataset
then
1278
return
name
1279
elseif
default
and
default
~
=
"
"
then
1280
return
default
1281
else
1282
report
(
"
unknown dataset %a, forcing %a
"
,
name
,
v_default
)
1283
return
v_default
1284
end
1285
end
1286 1287
implement
{
1288
name
=
"
btxsetdataset
"
,
1289
arguments
=
"
2 strings
"
,
1290
actions
=
{
publications
.
checkeddataset
,
context
}
,
1291
}
1292 1293
implement
{
1294
name
=
"
btxsetentry
"
,
1295
arguments
=
"
2 strings
"
,
1296
actions
=
function
(
name
,
tag
)
1297
local
dataset
=
rawget
(
datasets
,
name
)
1298
if
dataset
then
1299
if
dataset
.
luadata
[
tag
]
then
1300
context
(
tag
)
1301
else
1302
report
(
"
unknown tag %a in dataset %a
"
,
tag
,
name
)
1303
end
1304
else
1305
report
(
"
unknown dataset %a
"
,
name
)
1306
end
1307
end
,
1308
}
1309 1310
-- rendering of fields
1311 1312
do
1313 1314
local
typesetters
=
{
}
1315
publications
.
typesetters
=
typesetters
1316 1317
local
function
defaulttypesetter
(
field
,
value
,
manipulator
)
1318
if
value
and
value
~
=
"
"
then
1319
value
=
tostring
(
value
)
1320
context
(
manipulator
and
applymanipulation
(
manipulator
,
value
)
or
value
)
1321
end
1322
end
1323 1324
setmetatableindex
(
typesetters
,
function
(
t
,
k
)
1325
local
v
=
defaulttypesetter
1326
t
[
k
]
=
v
1327
return
v
1328
end
)
1329 1330
function
typesetters
.
string
(
field
,
value
,
manipulator
)
1331
if
value
and
value
~
=
"
"
then
1332
context
(
manipulator
and
applymanipulation
(
manipulator
,
value
)
or
value
)
1333
end
1334
end
1335 1336
function
typesetters
.
author
(
field
,
value
,
manipulator
)
1337
ctx_btxflushauthor
(
field
)
1338
end
1339 1340
-- function typesetters.url(field,value,manipulator)
1341
-- ....
1342
-- end
1343 1344
-- if there is no specification then we're in trouble but there is
1345
-- always a default anyway
1346
--
1347
-- there's also always a fields table but it can be empty due to
1348
-- lack of specifications
1349
--
1350
-- then there can be cases where we have no specification for instance
1351
-- when we have a special kind of database
1352 1353
local
splitter
=
lpeg
.
splitat
(
"
:
"
)
1354 1355
local
function
permitted
(
category
,
field
)
1356
local
catspec
=
currentspecification
.
categories
[
category
]
1357
if
not
catspec
then
1358
report
(
"
invalid category %a, %s
"
,
category
,
"
no specification
"
)
-- can't happen
1359
return
false
1360
end
1361
local
fields
=
catspec
.
fields
1362
if
not
fields
then
1363
report
(
"
invalid category %a, %s
"
,
category
,
"
no fields
"
)
-- can't happen
1364
return
false
1365
end
1366
if
ignoredfields
and
ignoredfields
[
field
]
then
1367
return
false
1368
end
1369
local
virtualfields
=
currentspecification
.
virtualfields
1370
if
virtualfields
and
virtualfields
[
field
]
then
1371
return
true
1372
end
1373
local
sets
=
catspec
.
sets
1374
if
sets
then
1375
local
set
=
sets
[
field
]
1376
if
set
then
1377
return
set
1378
end
1379
end
1380
if
fields
[
field
]
then
1381
return
true
1382
end
1383
local
f
,
l
=
lpegmatch
(
splitter
,
field
)
1384
if
f
and
l
and
fields
[
f
]
then
1385
return
true
-- language specific one
1386
end
1387
end
1388 1389
local
function
found
(
dataset
,
tag
,
field
,
valid
,
fields
)
1390
if
valid
=
=
true
then
1391
-- local fields = dataset.luadata[tag]
1392
local
okay
=
fields
[
field
]
1393
if
okay
then
1394
return
field
,
okay
1395
end
1396
local
details
=
dataset
.
details
[
tag
]
1397
local
value
=
details
[
field
]
1398
if
value
then
1399
return
field
,
value
1400
end
1401
elseif
valid
then
1402
-- local fields = dataset.luadata[tag]
1403
for
i
=
1
,
#
valid
do
1404
local
field
=
valid
[
i
]
1405
local
value
=
fields
[
field
]
1406
if
value
then
1407
return
field
,
value
1408
end
1409
end
1410
local
details
=
dataset
.
details
[
tag
]
1411
for
i
=
1
,
#
valid
do
1412
local
value
=
details
[
field
]
1413
if
value
then
1414
return
field
,
value
1415
end
1416
end
1417
end
1418
end
1419 1420
local
function
get
(
dataset
,
tag
,
field
,
what
,
check
,
catspec
)
-- somewhat more extensive
1421
local
current
=
rawget
(
datasets
,
dataset
)
1422
if
current
then
1423
local
data
=
current
.
luadata
[
tag
]
1424
if
data
then
1425
local
category
=
data
.
category
1426
local
catspec
=
(
catspec
or
currentspecification
)
.
categories
[
category
]
1427
if
not
catspec
then
1428
return
false
1429
end
1430
local
fields
=
catspec
.
fields
1431
if
fields
then
1432
local
sets
=
catspec
.
sets
1433
if
sets
then
1434
local
set
=
sets
[
field
]
1435
if
set
then
1436
if
check
then
1437
for
i
=
1
,
#
set
do
1438
local
field
=
set
[
i
]
1439
local
kind
=
(
not
check
or
data
[
field
]
)
and
fields
[
field
]
1440
if
kind
then
1441
return
what
and
kind
or
field
1442
end
1443
end
1444
elseif
what
then
1445
local
t
=
{
}
1446
for
i
=
1
,
#
set
do
1447
t
[
i
]
=
fields
[
set
[
i
]
]
or
"
unknown
"
1448
end
1449
return
concat
(
t
,
"
,
"
)
1450
else
1451
return
concat
(
set
,
"
,
"
)
1452
end
1453
end
1454
end
1455
local
kind
=
(
not
check
or
data
[
field
]
)
and
fields
[
field
]
1456
if
kind
then
1457
return
what
and
kind
or
field
1458
end
1459
end
1460
end
1461
end
1462
return
"
"
1463
end
1464 1465
publications
.
permitted
=
permitted
1466
publications
.
found
=
found
1467
publications
.
get
=
get
1468 1469
local
function
btxflush
(
name
,
tag
,
field
)
1470
local
dataset
=
rawget
(
datasets
,
name
)
1471
if
dataset
then
1472
local
fields
=
dataset
.
luadata
[
tag
]
1473
if
fields
then
1474
local
manipulator
,
field
=
splitmanipulation
(
field
)
1475
local
category
=
fields
.
category
1476
local
valid
=
permitted
(
category
,
field
)
1477
if
valid
then
1478
local
name
,
value
=
found
(
dataset
,
tag
,
field
,
valid
,
fields
)
1479
if
value
then
1480
typesetters
[
currentspecification
.
types
[
name
]
]
(
field
,
value
,
manipulator
)
1481
elseif
trace_details
then
1482
report
(
"
%s %s %a in category %a for tag %a in dataset %a
"
,
"
unknown
"
,
"
entry
"
,
field
,
category
,
tag
,
name
)
1483
end
1484
elseif
trace_details
then
1485
report
(
"
%s %s %a in category %a for tag %a in dataset %a
"
,
"
invalid
"
,
"
entry
"
,
field
,
category
,
tag
,
name
)
1486
end
1487
else
1488
report
(
"
unknown tag %a in dataset %a
"
,
tag
,
name
)
1489
end
1490
else
1491
report
(
"
unknown dataset %a
"
,
name
)
1492
end
1493
end
1494 1495
local
function
btxfield
(
name
,
tag
,
field
)
1496
local
dataset
=
rawget
(
datasets
,
name
)
1497
if
dataset
then
1498
local
fields
=
dataset
.
luadata
[
tag
]
1499
if
fields
then
1500
local
category
=
fields
.
category
1501
local
manipulator
,
field
=
splitmanipulation
(
field
)
1502
if
permitted
(
category
,
field
)
then
1503
local
value
=
fields
[
field
]
1504
if
value
then
1505
typesetters
[
currentspecification
.
types
[
field
]
]
(
field
,
value
,
manipulator
)
1506
elseif
trace_details
then
1507
report
(
"
%s %s %a in category %a for tag %a in dataset %a
"
,
"
unknown
"
,
"
field
"
,
field
,
category
,
tag
,
name
)
1508
end
1509
elseif
trace_details
then
1510
report
(
"
%s %s %a in category %a for tag %a in dataset %a
"
,
"
invalid
"
,
"
field
"
,
field
,
category
,
tag
,
name
)
1511
end
1512
else
1513
report
(
"
unknown tag %a in dataset %a
"
,
tag
,
name
)
1514
end
1515
else
1516
report
(
"
unknown dataset %a
"
,
name
)
1517
end
1518
end
1519 1520
local
function
btxdetail
(
name
,
tag
,
field
)
1521
local
dataset
=
rawget
(
datasets
,
name
)
1522
if
dataset
then
1523
local
fields
=
dataset
.
luadata
[
tag
]
1524
if
fields
then
1525
local
details
=
dataset
.
details
[
tag
]
1526
if
details
then
1527
local
category
=
fields
.
category
1528
local
manipulator
,
field
=
splitmanipulation
(
field
)
1529
if
permitted
(
category
,
field
)
then
1530
local
value
=
details
[
field
]
1531
if
value
then
1532
typesetters
[
currentspecification
.
types
[
field
]
]
(
field
,
value
,
manipulator
)
1533
elseif
trace_details
then
1534
report
(
"
%s %s %a in category %a for tag %a in dataset %a
"
,
"
unknown
"
,
"
detail
"
,
field
,
category
,
tag
,
name
)
1535
end
1536
elseif
trace_details
then
1537
report
(
"
%s %s %a in category %a for tag %a in dataset %a
"
,
"
invalid
"
,
"
detail
"
,
field
,
category
,
tag
,
name
)
1538
end
1539
else
1540
report
(
"
no details for tag %a in dataset %a
"
,
tag
,
name
)
1541
end
1542
else
1543
report
(
"
unknown tag %a in dataset %a
"
,
tag
,
name
)
1544
end
1545
else
1546
report
(
"
unknown dataset %a
"
,
name
)
1547
end
1548
end
1549 1550
local
function
btxdirect
(
name
,
tag
,
field
)
1551
local
dataset
=
rawget
(
datasets
,
name
)
1552
if
dataset
then
1553
local
fields
=
dataset
.
luadata
[
tag
]
1554
if
fields
then
1555
local
manipulator
,
field
=
splitmanipulation
(
field
)
1556
local
value
=
fields
[
field
]
1557
if
value
then
1558
context
(
typesetters
.
default
(
field
,
value
,
manipulator
)
)
1559
elseif
trace_details
then
1560
report
(
"
field %a of tag %a in dataset %a has no value
"
,
field
,
tag
,
name
)
1561
end
1562
else
1563
report
(
"
unknown tag %a in dataset %a
"
,
tag
,
name
)
1564
end
1565
else
1566
report
(
"
unknown dataset %a
"
,
name
)
1567
end
1568
end
1569 1570
local
function
okay
(
name
,
tag
,
field
)
1571
local
dataset
=
rawget
(
datasets
,
name
)
1572
if
dataset
then
1573
local
fields
=
dataset
.
luadata
[
tag
]
1574
if
fields
then
1575
local
category
=
fields
.
category
1576
local
valid
=
permitted
(
category
,
field
)
1577
if
valid
then
1578
local
value
,
field
=
found
(
dataset
,
tag
,
field
,
valid
,
fields
)
1579
return
value
and
value
~
=
"
"
1580
end
1581
end
1582
end
1583
end
1584 1585
publications
.
okay
=
okay
1586 1587
implement
{
name
=
"
btxfield
"
,
actions
=
btxfield
,
arguments
=
"
3 strings
"
}
1588
implement
{
name
=
"
btxdetail
"
,
actions
=
btxdetail
,
arguments
=
"
3 strings
"
}
1589
implement
{
name
=
"
btxflush
"
,
actions
=
btxflush
,
arguments
=
"
3 strings
"
}
1590
implement
{
name
=
"
btxdirect
"
,
actions
=
btxdirect
,
arguments
=
"
3 strings
"
}
1591 1592
implement
{
name
=
"
btxfieldname
"
,
actions
=
{
get
,
context
}
,
arguments
=
{
"
string
"
,
"
string
"
,
"
string
"
,
false
,
false
}
}
1593
implement
{
name
=
"
btxfieldtype
"
,
actions
=
{
get
,
context
}
,
arguments
=
{
"
string
"
,
"
string
"
,
"
string
"
,
true
,
false
}
}
1594
implement
{
name
=
"
btxfoundname
"
,
actions
=
{
get
,
context
}
,
arguments
=
{
"
string
"
,
"
string
"
,
"
string
"
,
false
,
true
}
}
1595
implement
{
name
=
"
btxfoundtype
"
,
actions
=
{
get
,
context
}
,
arguments
=
{
"
string
"
,
"
string
"
,
"
string
"
,
true
,
true
}
}
1596 1597
implement
{
name
=
"
btxdoifelse
"
,
actions
=
{
okay
,
ctx_doifelse
}
,
arguments
=
"
3 strings
"
}
1598
implement
{
name
=
"
btxdoif
"
,
actions
=
{
okay
,
ctx_doif
}
,
arguments
=
"
3 strings
"
}
1599
implement
{
name
=
"
btxdoifnot
"
,
actions
=
{
okay
,
ctx_doifnot
}
,
arguments
=
"
3 strings
"
}
1600 1601
end
1602 1603
-- -- alternative approach: keep data at the tex end
1604 1605
function
publications
.
singularorplural
(
singular
,
plural
)
1606
if
lastconcatsize
and
lastconcatsize
>
1
then
1607
context
(
plural
)
1608
else
1609
context
(
singular
)
1610
end
1611
end
1612 1613
-- loading
1614 1615
do
1616 1617
local
patterns
=
{
1618
CONTEXTLMTXMODE
>
0
and
"
symb-imp-%s.mklx
"
or
"
"
,
1619
CONTEXTLMTXMODE
>
0
and
"
symb-imp-%s.mkxl
"
or
"
"
,
1620
"
publ-imp-%s.mkvi
"
,
1621
"
publ-imp-%s.mkiv
"
,
1622
"
publ-imp-%s.tex
"
,
1623
}
1624 1625
local
function
failure
(
name
)
1626
report
(
"
unknown library %a
"
,
name
)
1627
end
1628 1629
local
function
action
(
name
,
foundname
)
1630
context
.
loadfoundpublicationfile
(
name
,
foundname
)
1631
end
1632 1633
function
publications
.
loaddefinitionfile
(
name
)
-- a more specific name
1634
resolvers
.
uselibrary
{
1635
name
=
gsub
(
name
,
"
^publ%-
"
,
"
"
)
,
1636
patterns
=
patterns
,
1637
action
=
action
,
1638
failure
=
failure
,
1639
onlyonce
=
true
,
1640
}
1641
end
1642 1643
local
patterns
=
{
1644
"
publ-imp-%s.lua
"
,
1645
}
1646 1647
function
publications
.
loadreplacementfile
(
name
)
-- a more specific name
1648
resolvers
.
uselibrary
{
1649
name
=
gsub
(
name
,
"
^publ%-
"
,
"
"
)
,
1650
patterns
=
patterns
,
1651
action
=
publications
.
loaders
.
registercleaner
,
1652
failure
=
failure
,
1653
onlyonce
=
true
,
1654
}
1655
end
1656 1657
implement
{
name
=
"
btxloaddefinitionfile
"
,
actions
=
publications
.
loaddefinitionfile
,
arguments
=
"
string
"
}
1658
implement
{
name
=
"
btxloadreplacementfile
"
,
actions
=
publications
.
loadreplacementfile
,
arguments
=
"
string
"
}
1659 1660
end
1661 1662
-- lists
1663 1664
local
renderings
=
{
}
--- per dataset
1665 1666
do
1667 1668
publications
.
lists
=
publications
.
lists
or
{
}
1669
local
lists
=
publications
.
lists
1670 1671
local
context
=
context
1672
local
structures
=
structures
1673 1674
local
references
=
structures
.
references
1675
local
sections
=
structures
.
sections
1676 1677
-- per rendering
1678 1679
setmetatableindex
(
renderings
,
function
(
t
,
k
)
1680
local
v
=
{
1681
list
=
{
}
,
1682
done
=
{
}
,
1683
alldone
=
{
}
,
1684
used
=
{
}
,
1685
registered
=
{
}
,
1686
ordered
=
{
}
,
1687
shorts
=
{
}
,
1688
method
=
v_none
,
1689
texts
=
setmetatableindex
(
"
table
"
)
,
1690
currentindex
=
0
,
1691
}
1692
t
[
k
]
=
v
1693
return
v
1694
end
)
1695 1696
-- helper
1697 1698
function
lists
.
register
(
dataset
,
tag
,
short
)
-- needs checking now that we split
1699
local
r
=
renderings
[
dataset
]
1700
if
not
short
or
short
=
=
"
"
then
1701
short
=
tag
1702
end
1703
if
trace
then
1704
report
(
"
registering publication entry %a with shortcut %a
"
,
tag
,
short
)
1705
end
1706
local
top
=
#
r
.
registered
+
1
1707
-- do we really need these
1708
r
.
registered
[
top
]
=
tag
1709
r
.
ordered
[
tag
]
=
top
1710
r
.
shorts
[
tag
]
=
short
1711
end
1712 1713
function
lists
.
nofregistered
(
dataset
)
1714
return
#
renderings
[
dataset
]
.
registered
1715
end
1716 1717
local
function
validkeyword
(
dataset
,
tag
,
keyword
,
specification
)
-- todo: pass specification
1718
local
kw
=
getcasted
(
dataset
,
tag
,
"
keywords
"
,
specification
)
1719
if
kw
then
1720
for
i
=
1
,
#
kw
do
1721
if
keyword
[
kw
[
i
]
]
then
1722
return
true
1723
end
1724
end
1725
end
1726
end
1727 1728
local
function
registerpage
(
pages
,
tag
,
result
,
listindex
)
1729
local
p
=
pages
[
tag
]
1730
local
r
=
result
[
listindex
]
.
references
1731
if
p
then
1732
local
last
=
p
[
#
p
]
[
2
]
1733
local
real
=
last
.
realpage
1734
if
real
~
=
r
.
realpage
then
1735
p
[
#
p
+
1
]
=
{
listindex
,
r
}
1736
end
1737
else
1738
pages
[
tag
]
=
{
{
listindex
,
r
}
}
1739
end
1740
end
1741 1742
-- tag | listindex | reference | userdata | dataindex
1743 1744
local
methods
=
{
}
1745
lists
.
methods
=
methods
1746 1747
methods
[
v_dataset
]
=
function
(
dataset
,
rendering
,
keyword
)
1748
local
current
=
datasets
[
dataset
]
1749
local
luadata
=
current
.
luadata
1750
local
list
=
rendering
.
list
1751
for
tag
,
data
in
sortedhash
(
luadata
)
do
1752
if
not
keyword
or
validkeyword
(
dataset
,
tag
,
keyword
)
then
1753
local
index
=
data
.
index
or
0
1754
list
[
#
list
+
1
]
=
{
tag
,
index
,
0
,
false
,
index
}
1755
end
1756
end
1757
end
1758 1759
-- todo: names = { "btx" }
1760 1761
methods
[
v_force
]
=
function
(
dataset
,
rendering
,
keyword
)
1762
-- only for checking, can have duplicates, todo: collapse page numbers, although
1763
-- we then also needs deferred writes
1764
local
result
=
structures
.
lists
.
filter
(
rendering
.
specifications
)
or
{
}
1765
local
list
=
rendering
.
list
1766
local
current
=
datasets
[
dataset
]
1767
local
luadata
=
current
.
luadata
1768
for
listindex
=
1
,
#
result
do
1769
local
r
=
result
[
listindex
]
1770
local
u
=
r
.
userdata
-- better check on metadata.kind == "btx"
1771
if
u
then
1772
local
set
=
u
.
btxset
or
v_default
1773
if
set
=
=
dataset
then
1774
local
tag
=
u
.
btxref
1775
if
tag
and
(
not
keyword
or
validkeyword
(
dataset
,
tag
,
keyword
)
)
then
1776
local
data
=
luadata
[
tag
]
1777
list
[
#
list
+
1
]
=
{
tag
,
listindex
,
0
,
u
,
data
and
data
.
index
or
0
}
1778
end
1779
end
1780
end
1781
end
1782
lists
.
result
=
result
1783
end
1784 1785
-- local : if tag and done[tag] ~= section then ...
1786
-- global : if tag and not alldone[tag] and done[tag] ~= section then ...
1787 1788
methods
[
v_local
]
=
function
(
dataset
,
rendering
,
keyword
)
1789
local
result
=
structures
.
lists
.
filter
(
rendering
.
specifications
)
or
{
}
1790
local
section
=
sections
.
currentid
(
)
1791
local
list
=
rendering
.
list
1792
local
repeated
=
rendering
.
repeated
=
=
v_yes
1793
local
r_done
=
rendering
.
done
1794
local
r_alldone
=
rendering
.
alldone
1795
local
done
=
repeated
and
{
}
or
r_done
1796
local
alldone
=
repeated
and
{
}
or
r_alldone
1797
local
doglobal
=
rendering
.
method
=
=
v_global
1798
local
traced
=
{
}
-- todo: only if interactive (backlinks) or when tracing
1799
local
pages
=
{
}
1800
local
current
=
datasets
[
dataset
]
1801
local
luadata
=
current
.
luadata
1802
-- handy for tracing :
1803
rendering
.
result
=
result
1804
--
1805
for
listindex
=
1
,
#
result
do
1806
local
r
=
result
[
listindex
]
1807
local
u
=
r
.
userdata
1808
if
u
then
-- better check on metadata.kind == "btx"
1809
local
set
=
u
.
btxset
or
v_default
1810
if
set
=
=
dataset
then
1811
-- inspect(structures.references.internals[tonumber(u.btxint)])
1812
local
tag
=
u
.
btxref
1813
if
not
tag
then
1814
-- problem
1815
elseif
done
[
tag
]
=
=
section
then
-- a bit messy for global and all and so
1816
-- skip
1817
elseif
doglobal
and
alldone
[
tag
]
then
1818
-- skip
1819
elseif
not
keyword
or
validkeyword
(
dataset
,
tag
,
keyword
)
then
1820
if
traced
then
1821
local
l
=
traced
[
tag
]
1822
if
l
then
1823
l
[
#
l
+
1
]
=
u
.
btxint
-- tonumber ?
1824
else
1825
local
data
=
luadata
[
tag
]
1826
local
l
=
{
tag
,
listindex
,
0
,
u
,
data
and
data
.
index
or
0
}
1827
list
[
#
list
+
1
]
=
l
1828
traced
[
tag
]
=
l
1829
end
1830
else
1831
done
[
tag
]
=
section
1832
alldone
[
tag
]
=
true
1833
local
data
=
luadata
[
tag
]
1834
list
[
#
list
+
1
]
=
{
tag
,
listindex
,
0
,
u
,
data
and
data
.
index
or
0
}
1835
end
1836
end
1837
if
tag
then
1838
registerpage
(
pages
,
tag
,
result
,
listindex
)
1839
end
1840
end
1841
end
1842
end
1843
if
traced
then
1844
for
tag
in
next
,
traced
do
1845
done
[
tag
]
=
section
1846
alldone
[
tag
]
=
true
1847
end
1848
end
1849
lists
.
result
=
result
1850
structures
.
lists
.
result
=
result
1851
rendering
.
pages
=
pages
-- or list.pages
1852
end
1853 1854
methods
[
v_global
]
=
methods
[
v_local
]
1855 1856
function
lists
.
collectentries
(
specification
)
1857
local
dataset
=
specification
.
dataset
1858
if
not
dataset
then
1859
return
1860
end
1861
local
rendering
=
renderings
[
dataset
]
1862
if
not
rendering
then
1863
return
1864
end
1865
local
method
=
specification
.
method
or
v_none
1866
local
ignored
=
specification
.
ignored
or
"
"
1867
local
filter
=
specification
.
filter
or
"
"
1868
rendering
.
method
=
method
1869
rendering
.
ignored
=
ignored
~
=
"
"
and
settings_to_set
(
ignored
)
or
nil
1870
rendering
.
list
=
{
}
1871
rendering
.
done
=
{
}
1872
rendering
.
sorttype
=
specification
.
sorttype
or
v_default
1873
rendering
.
criterium
=
specification
.
criterium
or
v_none
1874
rendering
.
repeated
=
specification
.
repeated
or
v_no
1875
rendering
.
group
=
specification
.
group
or
"
"
1876
rendering
.
specifications
=
specification
1877
local
filtermethod
=
methods
[
method
]
1878
if
not
filtermethod
then
1879
report_list
(
"
invalid method %a
"
,
method
or
"
"
)
1880
return
1881
end
1882
report_list
(
"
collecting entries using method %a and sort order %a
"
,
method
,
rendering
.
sorttype
)
1883
lists
.
result
=
{
}
-- kind of reset
1884
local
keyword
=
specification
.
keyword
1885
if
keyword
and
keyword
~
=
"
"
then
1886
keyword
=
settings_to_set
(
keyword
)
1887
else
1888
keyword
=
nil
1889
end
1890
filtermethod
(
dataset
,
rendering
,
keyword
)
1891
local
list
=
rendering
.
list
1892
if
list
and
filter
~
=
"
"
then
1893
local
find
=
publications
.
finder
(
dataset
,
filter
)
1894
if
find
then
1895
local
luadata
=
datasets
[
dataset
]
.
luadata
1896
local
matched
=
0
1897
for
i
=
1
,
#
list
do
1898
local
found
=
list
[
i
]
1899
local
entry
=
luadata
[
found
[
1
]
]
1900
if
find
(
entry
)
then
1901
matched
=
matched
+
1
1902
list
[
matched
]
=
found
1903
end
1904
end
1905
for
i
=
#
list
,
matched
+
1
,
-1
do
1906
list
[
i
]
=
nil
1907
end
1908
end
1909
end
1910
ctx_btxsetnoflistentries
(
list
and
#
list
or
0
)
1911
end
1912 1913
-- for determining width
1914 1915
local
groups
=
setmetatableindex
(
"
number
"
)
1916 1917
function
lists
.
prepareentries
(
dataset
)
1918
local
rendering
=
renderings
[
dataset
]
1919
local
list
=
rendering
.
list
1920
local
used
=
rendering
.
used
1921
local
forceall
=
rendering
.
criterium
=
=
v_all
1922
local
repeated
=
rendering
.
repeated
=
=
v_yes
1923
local
sorttype
=
rendering
.
sorttype
or
v_default
1924
local
group
=
rendering
.
group
or
"
"
1925
local
sorter
=
lists
.
sorters
[
sorttype
]
1926
local
current
=
datasets
[
dataset
]
1927
local
luadata
=
current
.
luadata
1928
local
details
=
current
.
details
1929
local
newlist
=
{
}
1930
local
lastreferencenumber
=
groups
[
group
]
-- current.lastreferencenumber or 0
1931
for
i
=
1
,
#
list
do
1932
local
li
=
list
[
i
]
1933
local
tag
=
li
[
1
]
1934
local
entry
=
luadata
[
tag
]
1935
if
entry
then
1936
if
forceall
or
repeated
or
not
used
[
tag
]
then
1937
newlist
[
#
newlist
+
1
]
=
li
1938
-- already here:
1939
if
not
repeated
then
1940
used
[
tag
]
=
true
-- beware we keep the old state (one can always use criterium=all)
1941
end
1942
end
1943
end
1944
end
1945
if
type
(
sorter
)
=
=
"
function
"
then
1946
list
=
sorter
(
dataset
,
rendering
,
newlist
,
sorttype
)
or
newlist
1947
else
1948
list
=
newlist
1949
end
1950
local
newlist
=
{
}
1951
local
tagtolistindex
=
{
}
1952
rendering
.
tagtolistindex
=
tagtolistindex
1953
for
i
=
1
,
#
list
do
1954
local
li
=
list
[
i
]
1955
local
tag
=
li
[
1
]
1956
local
entry
=
luadata
[
tag
]
1957
if
entry
then
1958
local
detail
=
details
[
tag
]
1959
if
not
detail
then
1960
-- fatal error
1961
report
(
"
fatal error, missing details for tag %a in dataset %a (enhanced: %s)
"
,
tag
,
dataset
,
current
.
enhanced
and
"
yes
"
or
"
no
"
)
1962
-- lastreferencenumber = lastreferencenumber + 1
1963
-- details[tag] = { referencenumber = lastreferencenumber }
1964
-- li[3] = lastreferencenumber
1965
-- tagtolistindex[tag] = i
1966
-- newlist[#newlist+1] = li
1967
elseif
detail
.
parent
then
1968
-- skip this one
1969
else
1970
local
referencenumber
=
detail
.
referencenumber
1971
if
not
referencenumber
then
1972
lastreferencenumber
=
lastreferencenumber
+
1
1973
referencenumber
=
lastreferencenumber
1974
detail
.
referencenumber
=
lastreferencenumber
1975
end
1976
li
[
3
]
=
referencenumber
1977
tagtolistindex
[
tag
]
=
i
1978
newlist
[
#
newlist
+
1
]
=
li
1979
end
1980
end
1981
end
1982
groups
[
group
]
=
lastreferencenumber
1983
rendering
.
list
=
newlist
1984
end
1985 1986
function
lists
.
fetchentries
(
dataset
)
1987
local
rendering
=
renderings
[
dataset
]
1988
local
list
=
rendering
.
list
1989
if
list
then
1990
for
i
=
1
,
#
list
do
1991
local
li
=
list
[
i
]
1992
ctx_btxsettag
(
li
[
1
]
)
1993
ctx_btxsetnumber
(
li
[
3
]
)
1994
ctx_btxchecklistentry
(
)
1995
end
1996
end
1997
end
1998 1999
-- for rendering
2000 2001
-- setspecification
2002 2003
local
function
btxflushpages
(
dataset
,
tag
)
2004
-- todo: interaction
2005
local
rendering
=
renderings
[
dataset
]
2006
local
pages
=
rendering
.
pages
2007
if
not
pages
then
2008
return
2009
else
2010
pages
=
pages
[
tag
]
2011
end
2012
if
not
pages
then
2013
return
2014
end
2015
local
nofpages
=
#
pages
2016
if
nofpages
=
=
0
then
2017
return
2018
end
2019
local
first_p
=
nil
2020
local
first_r
=
nil
2021
local
last_p
=
nil
2022
local
last_r
=
nil
2023
local
ranges
=
{
}
2024
local
nofdone
=
0
2025
local
function
flush
(
)
2026
if
last_r
and
first_r
~
=
last_r
then
2027
ranges
[
#
ranges
+
1
]
=
{
first_p
,
last_p
}
2028
else
2029
ranges
[
#
ranges
+
1
]
=
{
first_p
}
2030
end
2031
end
2032
for
i
=
1
,
nofpages
do
2033
local
next_p
=
pages
[
i
]
2034
local
next_r
=
next_p
[
2
]
.
realpage
2035
if
not
first_r
then
2036
first_p
=
next_p
2037
first_r
=
next_r
2038
elseif
last_r
+
1
=
=
next_r
then
2039
-- continue
2040
elseif
first_r
then
2041
flush
(
)
2042
first_p
=
next_p
2043
first_r
=
next_r
2044
end
2045
last_p
=
next_p
2046
last_r
=
next_r
2047
end
2048
if
first_r
then
2049
flush
(
)
2050
end
2051
local
nofranges
=
#
ranges
2052
for
i
=
1
,
nofranges
do
2053
local
r
=
ranges
[
i
]
2054
ctx_btxsetconcat
(
concatstate
(
i
,
nofranges
)
)
2055
local
first
=
r
[
1
]
2056
local
last
=
r
[
2
]
2057
ctx_btxsetfirstinternal
(
first
[
2
]
.
internal
)
2058
ctx_btxsetfirstpage
(
first
[
1
]
)
2059
if
last
then
2060
ctx_btxsetlastinternal
(
last
[
2
]
.
internal
)
2061
ctx_btxsetlastpage
(
last
[
1
]
)
2062
end
2063
if
trace_details
then
2064
report
(
"
expanding page setup
"
)
2065
end
2066
ctx_btxpagesetup
(
"
"
)
-- nothing yet
2067
end
2068
end
2069 2070
implement
{
2071
name
=
"
btxflushpages
"
,
2072
arguments
=
"
2 strings
"
,
2073
actions
=
btxflushpages
,
2074
}
2075 2076
local
function
identical
(
a
,
b
)
2077
local
na
=
#
a
2078
local
nb
=
#
b
2079
if
na
~
=
nb
then
2080
return
false
2081
end
2082
if
na
>
0
then
2083
for
i
=
1
,
na
do
2084
if
not
identical
(
a
[
i
]
,
b
[
i
]
)
then
2085
return
false
2086
end
2087
end
2088
return
true
2089
end
2090
local
ha
=
a
.
hash
2091
local
hb
=
b
.
hash
2092
if
ha
then
2093
return
ha
=
=
hb
2094
end
2095
for
k
,
v
in
next
,
a
do
2096
if
k
=
=
"
original
"
or
k
=
=
"
snippets
"
then
2097
-- skip diagnostic info
2098
elseif
v
~
=
b
[
k
]
then
2099
return
false
2100
end
2101
end
2102
return
true
2103
end
2104 2105
function
lists
.
sameasprevious
(
dataset
,
i
,
name
,
order
,
method
)
2106
local
rendering
=
renderings
[
dataset
]
2107
local
list
=
rendering
.
list
2108
local
n
=
tonumber
(
i
)
2109
if
n
and
n
>
1
and
n
<
=
#
list
then
2110
local
luadata
=
datasets
[
dataset
]
.
luadata
2111
local
p_index
=
list
[
n
-1
]
[
1
]
2112
local
c_index
=
list
[
n
]
[
1
]
2113
local
previous
=
getdirect
(
dataset
,
luadata
[
p_index
]
,
name
)
2114
local
current
=
getdirect
(
dataset
,
luadata
[
c_index
]
,
name
)
2115 2116
-- authors are a special case
2117 2118
-- if not order then
2119
-- order = gettexcounter("c_btx_list_reference")
2120
-- end
2121
if
order
and
order
>
0
and
(
method
=
=
v_always
or
method
=
=
v_doublesided
)
then
2122
local
clist
=
listtolist
[
order
]
2123
local
plist
=
listtolist
[
order
-1
]
2124
if
clist
and
plist
then
2125
local
crealpage
=
clist
.
references
.
realpage
2126
local
prealpage
=
plist
.
references
.
realpage
2127
if
crealpage
~
=
prealpage
then
2128
if
method
=
=
v_always
or
not
conditionals
.
layoutisdoublesided
then
2129
if
trace_details
then
2130
report
(
"
previous %a, current %a, different page
"
,
previous
,
current
)
2131
end
2132
return
false
2133
elseif
crealpage
%
2
=
=
0
then
2134
if
trace_details
then
2135
report
(
"
previous %a, current %a, different page
"
,
previous
,
current
)
2136
end
2137
return
false
2138
end
2139
end
2140
end
2141
end
2142
local
sameentry
=
false
2143
if
current
and
current
=
=
previous
then
2144
sameentry
=
true
2145
else
2146
local
p_casted
=
getcasted
(
dataset
,
p_index
,
name
)
2147
local
c_casted
=
getcasted
(
dataset
,
c_index
,
name
)
2148
if
c_casted
and
c_casted
=
=
p_casted
then
2149
sameentry
=
true
2150
elseif
type
(
c_casted
)
=
=
"
table
"
and
type
(
p_casted
)
=
=
"
table
"
then
2151
sameentry
=
identical
(
c_casted
,
p_casted
)
2152
end
2153
end
2154
if
trace_details
then
2155
if
sameentry
then
2156
report
(
"
previous %a, current %a, same entry
"
,
previous
,
current
)
2157
else
2158
report
(
"
previous %a, current %a, different entry
"
,
previous
,
current
)
2159
end
2160
end
2161
return
sameentry
2162
else
2163
return
false
2164
end
2165
end
2166 2167
function
lists
.
combiinlist
(
dataset
,
tag
)
2168
local
rendering
=
renderings
[
dataset
]
2169
local
list
=
rendering
.
list
2170
local
toindex
=
rendering
.
tagtolistindex
2171
return
toindex
and
toindex
[
tag
]
2172
end
2173 2174
function
lists
.
flushcombi
(
dataset
,
tag
)
2175
local
rendering
=
renderings
[
dataset
]
2176
local
list
=
rendering
.
list
2177
local
toindex
=
rendering
.
tagtolistindex
2178
local
listindex
=
toindex
and
toindex
[
tag
]
2179
if
listindex
then
2180
local
li
=
list
[
listindex
]
2181
if
li
then
2182
local
data
=
datasets
[
dataset
]
2183
local
luadata
=
data
.
luadata
2184
local
details
=
data
.
details
2185
local
tag
=
li
[
1
]
2186
local
listindex
=
li
[
2
]
2187
local
n
=
li
[
3
]
2188
local
entry
=
luadata
[
tag
]
2189
local
detail
=
details
[
tag
]
2190
ctx_btxstartcombientry
(
)
2191
ctx_btxsetcurrentlistindex
(
listindex
)
2192
ctx_btxsetcategory
(
entry
.
category
or
"
unknown
"
)
2193
ctx_btxsettag
(
tag
)
2194
ctx_btxsetnumber
(
n
)
2195
local
language
=
entry
.
language
2196
if
language
then
2197
ctx_btxsetlanguage
(
language
)
2198
end
2199
local
authorsuffix
=
detail
.
authorsuffix
2200
if
authorsuffix
then
2201
ctx_btxsetsuffix
(
authorsuffix
)
2202
end
2203
ctx_btxhandlecombientry
(
)
2204
ctx_btxstopcombientry
(
)
2205
end
2206
end
2207
end
2208 2209
function
lists
.
flushtag
(
dataset
,
i
)
2210
local
li
=
renderings
[
dataset
]
.
list
[
i
]
2211
ctx_btxsettag
(
li
and
li
[
1
]
or
"
"
)
2212
end
2213 2214
function
lists
.
flushentry
(
dataset
,
i
)
2215
local
rendering
=
renderings
[
dataset
]
2216
local
list
=
rendering
.
list
2217
local
li
=
list
[
i
]
2218
if
li
then
2219
local
data
=
datasets
[
dataset
]
2220
local
luadata
=
data
.
luadata
2221
local
details
=
data
.
details
2222
local
tag
=
li
[
1
]
2223
local
listindex
=
li
[
2
]
2224
local
n
=
li
[
3
]
2225
local
entry
=
luadata
[
tag
]
2226
local
detail
=
details
[
tag
]
2227
--
2228
ctx_btxstartlistentry
(
)
2229
ctx_btxsetcurrentlistentry
(
i
)
-- redundant
2230
ctx_btxsetcurrentlistindex
(
listindex
or
0
)
2231
local
children
=
detail
.
children
2232
local
language
=
entry
.
language
2233
if
children
then
2234
ctx_btxsetcombis
(
concat
(
children
,
"
,
"
)
)
2235
end
2236
ctx_btxsetcategory
(
entry
.
category
or
"
unknown
"
)
2237
ctx_btxsettag
(
tag
)
2238
ctx_btxsetnumber
(
n
)
2239
--
2240
local
citation
=
citetolist
[
n
]
2241
if
citation
then
2242
local
references
=
citation
.
references
2243
if
references
then
2244
local
internal
=
references
.
internal
2245
if
internal
and
internal
>
0
then
2246
ctx_btxsetinternal
(
internal
)
2247
end
2248
end
2249
end
2250
--
2251
if
language
then
2252
ctx_btxsetlanguage
(
language
)
2253
end
2254
local
userdata
=
li
[
4
]
2255
if
userdata
then
2256
local
b
=
userdata
.
btxbtx
2257
local
a
=
userdata
.
btxatx
2258
if
b
then
2259
ctx_btxsetbefore
(
b
)
2260
end
2261
if
a
then
2262
ctx_btxsetafter
(
a
)
2263
end
2264
local
bl
=
userdata
.
btxint
2265
if
bl
and
bl
~
=
"
"
then
2266
ctx_btxsetbacklink
(
bl
)
2267
end
2268
end
2269
local
authorsuffix
=
detail
.
authorsuffix
2270
if
authorsuffix
then
2271
ctx_btxsetsuffix
(
authorsuffix
)
2272
end
2273
rendering
.
userdata
=
userdata
2274
ctx_btxhandlelistentry
(
)
2275
ctx_btxstoplistentry
(
)
2276
--
2277
-- context(function()
2278
-- -- wrapup
2279
-- rendering.ignoredfields = nil
2280
-- end)
2281
end
2282
end
2283 2284
local
function
getuserdata
(
dataset
,
key
)
2285
local
rendering
=
renderings
[
dataset
]
2286
if
rendering
then
2287
local
userdata
=
rendering
.
userdata
2288
if
userdata
then
2289
local
value
=
userdata
[
key
]
2290
if
value
and
value
~
=
"
"
then
2291
return
value
2292
end
2293
end
2294
end
2295
end
2296 2297
lists
.
uservariable
=
getuserdata
2298 2299
function
lists
.
filterall
(
dataset
)
2300
local
r
=
renderings
[
dataset
]
2301
local
list
=
r
.
list
2302
local
registered
=
r
.
registered
2303
for
i
=
1
,
#
registered
do
2304
list
[
i
]
=
{
registered
[
i
]
,
i
,
0
,
false
,
false
}
2305
end
2306
end
2307 2308
implement
{
2309
name
=
"
btxuservariable
"
,
2310
arguments
=
"
2 strings
"
,
2311
actions
=
{
getuserdata
,
context
}
,
2312
}
2313 2314
implement
{
2315
name
=
"
btxdoifelseuservariable
"
,
2316
arguments
=
"
2 strings
"
,
2317
actions
=
{
getuserdata
,
ctx_doifelse
}
,
2318
}
2319 2320
-- implement {
2321
-- name = "btxresolvelistreference",
2322
-- arguments = "2 strings",
2323
-- actions = lists.resolve,
2324
-- }
2325 2326
implement
{
2327
name
=
"
btxcollectlistentries
"
,
2328
actions
=
lists
.
collectentries
,
2329
arguments
=
{
2330
{
2331
{
"
names
"
}
,
2332
{
"
criterium
"
}
,
2333
{
"
reference
"
}
,
2334
{
"
method
"
}
,
2335
{
"
dataset
"
}
,
2336
{
"
keyword
"
}
,
2337
{
"
sorttype
"
}
,
2338
{
"
repeated
"
}
,
2339
{
"
ignored
"
}
,
2340
{
"
group
"
}
,
2341
{
"
filter
"
}
,
2342
}
2343
}
2344
}
2345 2346
implement
{
2347
name
=
"
btxpreparelistentries
"
,
2348
arguments
=
"
string
"
,
2349
actions
=
lists
.
prepareentries
,
2350
}
2351 2352
implement
{
2353
name
=
"
btxfetchlistentries
"
,
2354
arguments
=
"
string
"
,
2355
actions
=
lists
.
fetchentries
,
2356
}
2357 2358
implement
{
2359
name
=
"
btxflushlistentry
"
,
2360
arguments
=
{
"
string
"
,
"
integer
"
}
,
2361
actions
=
lists
.
flushentry
,
2362
}
2363 2364
implement
{
2365
name
=
"
btxflushlisttag
"
,
2366
arguments
=
{
"
string
"
,
"
integer
"
}
,
2367
actions
=
lists
.
flushtag
,
2368
}
2369 2370
implement
{
2371
name
=
"
btxflushlistcombi
"
,
2372
arguments
=
"
2 strings
"
,
2373
actions
=
lists
.
flushcombi
,
2374
}
2375 2376
implement
{
2377
name
=
"
btxdoifelsesameasprevious
"
,
2378
actions
=
{
lists
.
sameasprevious
,
ctx_doifelse
}
,
2379
arguments
=
{
"
string
"
,
"
integer
"
,
"
string
"
,
"
integer
"
,
"
string
"
}
2380
}
2381 2382
implement
{
2383
name
=
"
btxdoifelsecombiinlist
"
,
2384
arguments
=
"
2 strings
"
,
2385
actions
=
{
lists
.
combiinlist
,
ctx_doifelse
}
,
2386
}
2387 2388
end
2389 2390
do
2391 2392
local
citevariants
=
{
}
2393
publications
.
citevariants
=
citevariants
2394 2395
local
function
btxvalidcitevariant
(
dataset
,
variant
)
2396
local
citevariant
=
rawget
(
citevariants
,
variant
)
2397
if
citevariant
then
2398
return
citevariant
2399
end
2400
local
s
=
datasets
[
dataset
]
2401
if
s
then
2402
s
=
s
.
specifications
2403
end
2404
if
s
then
2405
for
k
,
v
in
sortedhash
(
s
)
do
2406
s
=
k
2407
break
2408
end
2409
end
2410
if
s
then
2411
s
=
specifications
[
s
]
2412
end
2413
if
s
then
2414
s
=
s
.
types
2415
end
2416
if
s
then
2417
variant
=
s
[
variant
]
2418
if
variant
then
2419
citevariant
=
rawget
(
citevariants
,
variant
)
2420
end
2421
if
citevariant
then
2422
return
citevariant
2423
end
2424
end
2425
return
citevariants
.
default
2426
end
2427 2428
local
function
btxhandlecite
(
specification
)
2429
local
dataset
=
specification
.
dataset
or
v_default
2430
local
reference
=
specification
.
reference
2431
local
variant
=
specification
.
variant
2432
--
2433
if
not
variant
or
variant
=
=
"
"
then
2434
variant
=
"
default
"
2435
end
2436
if
not
reference
or
reference
=
=
"
"
then
2437
return
2438
end
2439
--
2440
local
data
=
datasets
[
dataset
]
2441
if
not
data
.
suffixed
then
2442
data
.
authorconversion
=
specification
.
authorconversion
2443
publications
.
enhancers
.
suffixes
(
data
)
2444
end
2445
--
2446
specification
.
variant
=
variant
2447
specification
.
compress
=
specification
.
compress
2448
specification
.
markentry
=
specification
.
markentry
~
=
false
2449
--
2450
if
specification
.
sorttype
=
=
v_yes
then
2451
specification
.
sorttype
=
v_normal
2452
end
2453
--
2454
local
prefix
,
rest
=
lpegmatch
(
prefixsplitter
,
reference
)
2455
if
prefix
and
rest
then
2456
dataset
=
prefix
2457
specification
.
dataset
=
prefix
2458
specification
.
reference
=
rest
2459
end
2460
--
2461
if
trace_cite
then
2462
report_cite
(
"
inject, dataset: %s, tag: %s, variant: %s, compressed
"
,
2463
specification
.
dataset
or
"
-
"
,
2464
specification
.
reference
,
2465
specification
.
variant
2466
)
2467
end
2468
--
2469
ctx_btxsetdataset
(
dataset
)
2470
--
2471
local
citevariant
=
btxvalidcitevariant
(
dataset
,
variant
)
2472
--
2473
citevariant
(
specification
)
-- we always fall back on default
2474
end
2475 2476
local
function
btxhandlenocite
(
specification
)
2477
if
trialtypesetting
(
)
then
2478
return
2479
end
2480
local
dataset
=
specification
.
dataset
or
v_default
2481
local
reference
=
specification
.
reference
2482
if
not
reference
or
reference
=
=
"
"
then
2483
return
2484
end
2485
--
2486
local
method
=
specification
.
method
2487
local
internal
=
specification
.
internal
or
"
"
2488
--
2489
local
prefix
,
rest
=
lpegmatch
(
prefixsplitter
,
reference
)
2490
if
rest
then
2491
dataset
=
prefix
2492
reference
=
rest
2493
end
2494
--
2495
if
trace_cite
then
2496
report_cite
(
"
mark, dataset: %s, tags: %s
"
,
dataset
or
"
-
"
,
reference
)
2497
end
2498
--
2499
local
reference
=
publications
.
parenttag
(
dataset
,
reference
)
2500
--
2501
local
found
,
todo
,
list
=
findallused
(
dataset
,
reference
,
internal
)
2502
--
2503
if
todo
then
2504
marked_todo
=
todo
2505
marked_dataset
=
dataset
2506
marked_list
=
list
2507
marked_method
=
method
2508
btxflushmarked
(
)
-- here (could also be done in caller)
2509
else
2510
marked_todo
=
false
2511
end
2512
end
2513 2514
implement
{
2515
name
=
"
btxhandlecite
"
,
2516
actions
=
btxhandlecite
,
2517
arguments
=
{
2518
{
2519
{
"
dataset
"
}
,
2520
{
"
reference
"
}
,
2521
{
"
method
"
}
,
2522
{
"
variant
"
}
,
2523
{
"
sorttype
"
}
,
2524
{
"
compress
"
}
,
2525
{
"
authorconversion
"
}
,
2526
{
"
author
"
}
,
2527
{
"
lefttext
"
}
,
2528
{
"
righttext
"
}
,
2529
{
"
before
"
}
,
2530
{
"
after
"
}
,
2531
}
2532
}
2533
}
2534 2535
implement
{
2536
name
=
"
btxhandlenocite
"
,
2537
actions
=
btxhandlenocite
,
2538
arguments
=
{
2539
{
2540
{
"
dataset
"
}
,
2541
{
"
reference
"
}
,
2542
{
"
method
"
}
,
2543
}
2544
}
2545
}
2546 2547
-- sorter
2548 2549
local
keysorter
=
function
(
a
,
b
)
2550
local
ak
=
a
.
sortkey
2551
local
bk
=
b
.
sortkey
2552
if
ak
=
=
bk
then
2553
local
as
=
a
.
suffix
-- numeric
2554
local
bs
=
b
.
suffix
-- numeric
2555
if
as
and
bs
then
2556
return
(
as
or
0
)
<
(
bs
or
0
)
2557
else
2558
return
false
2559
end
2560
else
2561
return
ak
<
bk
2562
end
2563
end
2564 2565
local
revsorter
=
function
(
a
,
b
)
2566
return
keysorter
(
b
,
a
)
2567
end
2568 2569
local
function
compresslist
(
source
,
specification
)
2570
if
specification
.
sorttype
=
=
v_normal
then
2571
sort
(
source
,
keysorter
)
2572
elseif
specification
.
sorttype
=
=
v_reverse
then
2573
sort
(
source
,
revsorter
)
2574
end
2575
if
specification
and
specification
.
compress
=
=
v_yes
and
specification
.
numeric
then
2576
local
first
,
last
,
firstr
,
lastr
2577
local
target
,
noftarget
,
tags
=
{
}
,
0
,
{
}
2578
local
oldvalue
=
nil
2579
local
function
flushrange
(
)
2580
noftarget
=
noftarget
+
1
2581
if
last
>
first
+
1
then
2582
target
[
noftarget
]
=
{
2583
first
=
firstr
,
2584
last
=
lastr
,
2585
tags
=
tags
,
2586
}
2587
else
2588
target
[
noftarget
]
=
firstr
2589
if
last
>
first
then
2590
noftarget
=
noftarget
+
1
2591
target
[
noftarget
]
=
lastr
2592
end
2593
end
2594
tags
=
{
}
2595
end
2596
for
i
=
1
,
#
source
do
2597
local
entry
=
source
[
i
]
2598
local
current
=
entry
.
sortkey
-- so we need a sortkey !
2599
if
type
(
current
)
=
=
"
number
"
then
2600
if
entry
.
suffix
then
2601
if
not
first
then
2602
first
,
last
,
firstr
,
lastr
=
current
,
current
,
entry
,
entry
2603
else
2604
flushrange
(
)
2605
first
,
last
,
firstr
,
lastr
=
current
,
current
,
entry
,
entry
2606
end
2607
else
2608
if
not
first
then
2609
first
,
last
,
firstr
,
lastr
=
current
,
current
,
entry
,
entry
2610
elseif
current
=
=
last
+
1
then
2611
last
,
lastr
=
current
,
entry
2612
else
2613
flushrange
(
)
2614
first
,
last
,
firstr
,
lastr
=
current
,
current
,
entry
,
entry
2615
end
2616
end
2617
tags
[
#
tags
+
1
]
=
entry
.
tag
2618
end
2619
end
2620
if
first
and
last
then
2621
flushrange
(
)
2622
end
2623
return
target
2624
else
2625
local
target
,
noftarget
=
{
}
,
0
2626
for
i
=
1
,
#
source
do
2627
local
entry
=
source
[
i
]
2628
noftarget
=
noftarget
+
1
2629
target
[
noftarget
]
=
{
2630
first
=
entry
,
2631
tags
=
{
entry
.
tag
}
,
2632
}
2633
end
2634
return
target
2635
end
2636
end
2637 2638
-- local source = {
2639
-- { tag = "one", internal = 1, value = "foo", page = 1 },
2640
-- { tag = "two", internal = 2, value = "bar", page = 2 },
2641
-- { tag = "three", internal = 3, value = "gnu", page = 3 },
2642
-- }
2643
--
2644
-- local target = compresslist(source)
2645 2646
local
numberonly
=
R
(
"
09
"
)
^
1
/
tonumber
+
P
(
1
)
^
0
2647
local
f_missing
=
formatters
[
"
<%s>
"
]
2648 2649
-- maybe also sparse (e.g. pages)
2650 2651
-- a bit redundant access to datasets
2652 2653
local
function
processcite
(
presets
,
specification
)
2654
--
2655
if
specification
then
2656
setmetatableindex
(
specification
,
presets
)
2657
else
2658
specification
=
presets
2659
end
2660
--
2661
local
dataset
=
specification
.
dataset
2662
local
reference
=
specification
.
reference
2663
local
internal
=
specification
.
internal
2664
local
setup
=
specification
.
variant
2665
local
compress
=
specification
.
compress
2666
local
sorttype
=
specification
.
sorttype
2667
local
getter
=
specification
.
getter
2668
local
setter
=
specification
.
setter
2669
local
compressor
=
specification
.
compressor
2670
local
method
=
specification
.
method
2671
local
varfield
=
specification
.
varfield
2672
--
2673
local
reference
=
publications
.
parenttag
(
dataset
,
reference
)
2674
--
2675
local
found
,
todo
,
list
=
findallused
(
dataset
,
reference
,
internal
,
method
=
=
v_text
or
method
=
=
v_always
)
-- also when not in list
2676
--
2677
if
not
found
or
#
found
=
=
0
then
2678
-- if not list or #list == 0 then
2679
report
(
"
no entry %a found in dataset %a
"
,
reference
,
dataset
)
2680
elseif
not
setup
then
2681
report
(
"
invalid reference for %a
"
,
reference
)
2682
else
2683
if
trace_cite
then
2684
report
(
"
processing reference %a
"
,
reference
)
2685
end
2686
local
source
=
{
}
2687
local
luadata
=
datasets
[
dataset
]
.
luadata
2688
for
i
=
1
,
#
found
do
2689
local
entry
=
found
[
i
]
2690
local
userdata
=
entry
.
userdata
2691
local
references
=
entry
.
references
2692
local
tag
=
userdata
and
userdata
.
btxref
or
entry
.
tag
-- no need for userdata
2693
if
tag
then
2694
local
ldata
=
luadata
[
tag
]
2695
local
data
=
{
2696
internal
=
references
and
references
.
internal
,
2697
language
=
ldata
.
language
,
2698
dataset
=
dataset
,
2699
tag
=
tag
,
2700
varfield
=
varfield
,
2701
-- combis = entry.userdata.btxcom,
2702
-- luadata = ldata,
2703
}
2704
setter
(
data
,
dataset
,
tag
,
entry
)
2705
if
type
(
data
)
=
=
"
table
"
then
2706
source
[
#
source
+
1
]
=
data
2707
else
2708
report
(
"
error in cite rendering %a
"
,
setup
or
"
?
"
)
2709
end
2710
end
2711
end
2712 2713
local
lefttext
=
specification
.
lefttext
2714
local
righttext
=
specification
.
righttext
2715
local
before
=
specification
.
before
2716
local
after
=
specification
.
after
2717 2718
if
lefttext
and
lefttext
~
=
"
"
then
lefttext
=
settings_to_array
(
lefttext
)
end
2719
if
righttext
and
righttext
~
=
"
"
then
righttext
=
settings_to_array
(
righttext
)
end
2720
if
before
and
before
~
=
"
"
then
before
=
settings_to_array
(
before
)
end
2721
if
after
and
after
~
=
"
"
then
after
=
settings_to_array
(
after
)
end
2722 2723
local
function
flush
(
i
,
n
,
entry
,
last
)
2724
local
tag
=
entry
.
tag
2725
local
currentcitation
=
markcite
(
dataset
,
tag
)
2726
--
2727
ctx_btxstartcite
(
)
2728
ctx_btxsettag
(
tag
)
2729
ctx_btxsetcategory
(
entry
.
category
or
"
unknown
"
)
2730
--
2731
local
language
=
entry
.
language
2732
if
language
then
2733
ctx_btxsetlanguage
(
language
)
2734
end
2735
--
2736
if
lefttext
then
local
text
=
lefttext
[
i
]
;
if
text
and
text
~
=
"
"
then
ctx_btxsetlefttext
(
text
)
end
end
2737
if
righttext
then
local
text
=
righttext
[
i
]
;
if
text
and
text
~
=
"
"
then
ctx_btxsetrighttext
(
text
)
end
end
2738
if
before
then
local
text
=
before
[
i
]
;
if
text
and
text
~
=
"
"
then
ctx_btxsetbefore
(
text
)
end
end
2739
if
after
then
local
text
=
after
[
i
]
;
if
text
and
text
~
=
"
"
then
ctx_btxsetafter
(
text
)
end
end
2740
--
2741
if
method
~
=
v_text
then
2742
ctx_btxsetbacklink
(
currentcitation
)
2743
local
bl
=
listtocite
[
currentcitation
]
2744
if
bl
then
2745
-- we refer to a coming list entry
2746
bl
=
bl
.
references
.
internal
2747
else
2748
-- we refer to a previous list entry
2749
bl
=
entry
.
internal
2750
end
2751
ctx_btxsetinternal
(
bl
and
bl
>
0
and
bl
or
"
"
)
2752
end
2753
local
language
=
entry
.
language
2754
if
language
then
2755
ctx_btxsetlanguage
(
language
)
2756
end
2757
-- local combis = entry.combis
2758
-- if combis then
2759
-- ctx_btxsetcombis(combis)
2760
-- end
2761
if
not
getter
(
entry
,
last
,
nil
,
specification
)
then
2762
ctx_btxsetfirst
(
"
"
)
-- (f_missing(tag))
2763
end
2764
ctx_btxsetconcat
(
concatstate
(
i
,
n
)
)
2765
if
trace_details
then
2766
report
(
"
expanding cite setup %a
"
,
setup
)
2767
end
2768
ctx_btxcitesetup
(
setup
)
2769
ctx_btxstopcite
(
)
2770
end
2771
if
sorttype
=
=
v_normal
or
sorttype
=
=
v_reverse
then
2772
local
target
=
(
compressor
or
compresslist
)
(
source
,
specification
)
2773
local
nofcollected
=
#
target
2774
if
nofcollected
=
=
0
then
2775
local
nofcollected
=
#
source
2776
if
nofcollected
=
=
0
then
2777
unknowncite
(
reference
)
2778
else
2779
for
i
=
1
,
nofcollected
do
2780
flush
(
i
,
nofcollected
,
source
[
i
]
)
2781
end
2782
end
2783
else
2784
for
i
=
1
,
nofcollected
do
2785
local
entry
=
target
[
i
]
2786
local
first
=
entry
.
first
2787
if
first
then
2788
flush
(
i
,
nofcollected
,
first
,
entry
.
last
)
2789
else
2790
flush
(
i
,
nofcollected
,
entry
)
2791
end
2792
end
2793
end
2794
else
2795
local
nofcollected
=
#
source
2796
if
nofcollected
=
=
0
then
2797
unknowncite
(
reference
)
2798
else
2799
for
i
=
1
,
nofcollected
do
2800
flush
(
i
,
nofcollected
,
source
[
i
]
)
2801
end
2802
end
2803
end
2804
end
2805
if
trialtypesetting
(
)
then
2806
marked_todo
=
false
2807
elseif
method
~
=
v_text
then
2808
marked_todo
=
todo
2809
marked_dataset
=
dataset
2810
marked_list
=
list
2811
marked_method
=
method
2812
btxflushmarked
(
)
-- here (could also be done in caller)
2813
else
2814
marked_todo
=
false
2815
end
2816
end
2817 2818
--
2819 2820
local
function
simplegetter
(
first
,
last
,
field
,
specification
)
2821
local
value
=
first
[
field
]
2822
if
value
then
2823
if
type
(
value
)
=
=
"
string
"
then
2824
ctx_btxsetfirst
(
value
)
2825
if
last
then
2826
ctx_btxsetsecond
(
last
[
field
]
)
2827
end
2828
return
true
2829
else
2830
report
(
"
missing data type definition for %a
"
,
field
)
2831
end
2832
end
2833
end
2834 2835
local
setters
=
setmetatableindex
(
{
}
,
function
(
t
,
k
)
2836
local
v
=
function
(
data
,
dataset
,
tag
,
entry
)
2837
local
value
=
getcasted
(
dataset
,
tag
,
k
)
2838
data
.
value
=
value
-- not really needed
2839
data
[
k
]
=
value
2840
data
.
sortkey
=
value
2841
data
.
sortfld
=
k
2842
end
2843
t
[
k
]
=
v
2844
return
v
2845
end
)
2846 2847
local
getters
=
setmetatableindex
(
{
}
,
function
(
t
,
k
)
2848
local
v
=
function
(
first
,
last
,
_
,
specification
)
2849
return
simplegetter
(
first
,
last
,
k
,
specification
)
-- maybe _ or k
2850
end
2851
t
[
k
]
=
v
2852
return
v
2853
end
)
2854 2855
setmetatableindex
(
citevariants
,
function
(
t
,
k
)
2856
local
p
=
defaultvariant
or
"
default
"
2857
local
v
=
rawget
(
t
,
p
)
2858
report_cite
(
"
variant %a falls back on %a setter and getter with setup %a
"
,
k
,
p
,
k
)
2859
t
[
k
]
=
v
2860
return
v
2861
end
)
2862 2863
function
citevariants
.
default
(
presets
)
2864
local
variant
=
presets
.
variant
2865
processcite
(
presets
,
{
2866
setup
=
variant
,
2867
setter
=
setters
[
variant
]
,
2868
getter
=
getters
[
variant
]
,
2869
}
)
2870
end
2871 2872
-- category
2873 2874
do
2875 2876
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
2877
data
.
category
=
getfield
(
dataset
,
tag
,
"
category
"
)
2878
end
2879 2880
local
function
getter
(
first
,
last
,
_
,
specification
)
2881
return
simplegetter
(
first
,
last
,
"
category
"
,
specification
)
2882
end
2883 2884
function
citevariants
.
category
(
presets
)
2885
processcite
(
presets
,
{
2886
setter
=
setter
,
2887
getter
=
getter
,
2888
}
)
2889
end
2890 2891
end
2892 2893 2894
-- entry (we could provide a generic one)
2895 2896
do
2897 2898
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
2899
-- nothing
2900
end
2901 2902
local
function
getter
(
first
,
last
,
_
,
specification
)
-- last not used
2903
ctx_btxsetfirst
(
first
.
tag
)
2904
end
2905 2906
function
citevariants
.
entry
(
presets
)
2907
processcite
(
presets
,
{
2908
compress
=
false
,
2909
setter
=
setter
,
2910
getter
=
getter
,
2911
}
)
2912
end
2913 2914
end
2915 2916
-- short
2917 2918
do
2919 2920
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
2921
local
short
=
getdetail
(
dataset
,
tag
,
"
shorthash
"
)
2922
local
suffix
=
getdetail
(
dataset
,
tag
,
"
shortsuffix
"
)
2923
data
.
short
=
short
2924
data
.
sortkey
=
short
2925
data
.
suffix
=
suffix
2926
end
2927 2928
local
function
getter
(
first
,
last
,
_
,
specification
)
-- last not used
2929
local
short
=
first
.
short
2930
if
short
then
2931
local
suffix
=
first
.
suffix
2932
ctx_btxsetfirst
(
short
)
2933
if
suffix
then
2934
ctx_btxsetsuffix
(
suffix
)
-- watch out: third
2935
end
2936
return
true
2937
end
2938
end
2939 2940
function
citevariants
.
short
(
presets
)
2941
processcite
(
presets
,
{
2942
setter
=
setter
,
2943
getter
=
getter
,
2944
}
)
2945
end
2946 2947
end
2948 2949
-- pages (no compress)
2950 2951
do
2952 2953
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
2954
data
.
pages
=
getcasted
(
dataset
,
tag
,
"
pages
"
)
2955
end
2956 2957
local
function
getter
(
first
,
last
,
_
,
specification
)
2958
local
pages
=
first
.
pages
2959
if
pages
then
2960
if
type
(
pages
)
=
=
"
table
"
then
2961
ctx_btxsetfirst
(
pages
[
1
]
)
2962
ctx_btxsetsecond
(
pages
[
2
]
)
2963
else
2964
ctx_btxsetfirst
(
pages
)
2965
end
2966
return
true
2967
end
2968
end
2969 2970
function
citevariants
.
page
(
presets
)
2971
processcite
(
presets
,
{
2972
setter
=
setter
,
2973
getter
=
getter
,
2974
}
)
2975
end
2976 2977
end
2978 2979
-- num
2980 2981
do
2982 2983
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
2984
local
entries
=
entry
.
entries
2985
local
text
=
entries
and
entries
.
text
or
"
?
"
2986
data
.
num
=
text
2987
data
.
sortkey
=
tonumber
(
text
)
or
text
2988
end
2989 2990
local
function
getter
(
first
,
last
,
tag
,
specification
)
2991
return
simplegetter
(
first
,
last
,
"
num
"
,
specification
)
2992
end
2993 2994
function
citevariants
.
num
(
presets
)
2995
processcite
(
presets
,
{
2996
numeric
=
true
,
2997
setter
=
setter
,
2998
getter
=
getter
,
2999
}
)
3000
end
3001 3002
citevariants
.
textnum
=
citevariants
.
num
-- should not be needed
3003 3004
end
3005 3006
-- year
3007 3008
do
3009 3010
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3011
local
year
=
getfield
(
dataset
,
tag
,
"
year
"
)
3012
local
suffix
=
getdetail
(
dataset
,
tag
,
"
authorsuffix
"
)
3013
data
.
year
=
year
3014
data
.
suffix
=
suffix
3015
data
.
sortkey
=
tonumber
(
year
)
or
9999
3016
end
3017 3018
local
function
getter
(
first
,
last
,
_
,
specification
)
3019
return
simplegetter
(
first
,
last
,
"
year
"
,
specification
)
3020
end
3021 3022
function
citevariants
.
year
(
presets
)
3023
processcite
(
presets
,
{
3024
numeric
=
true
,
3025
setter
=
setter
,
3026
getter
=
getter
,
3027
}
)
3028
end
3029 3030
end
3031 3032
-- index
3033 3034
do
3035 3036
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3037
local
index
=
getfield
(
dataset
,
tag
,
"
index
"
)
3038
data
.
index
=
index
3039
data
.
sortkey
=
index
3040
end
3041 3042
local
function
getter
(
first
,
last
,
_
,
specification
)
3043
return
simplegetter
(
first
,
last
,
"
index
"
,
specification
)
3044
end
3045 3046
function
citevariants
.
index
(
presets
)
3047
processcite
(
presets
,
{
3048
setter
=
setter
,
3049
getter
=
getter
,
3050
numeric
=
true
,
3051
}
)
3052
end
3053 3054
end
3055 3056
-- tag
3057 3058
do
3059 3060
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3061
data
.
tag
=
tag
3062
data
.
sortkey
=
tag
3063
end
3064 3065
local
function
getter
(
first
,
last
,
_
,
specification
)
3066
return
simplegetter
(
first
,
last
,
"
tag
"
,
specification
)
3067
end
3068 3069
function
citevariants
.
tag
(
presets
)
3070
return
processcite
(
presets
,
{
3071
setter
=
setter
,
3072
getter
=
getter
,
3073
}
)
3074
end
3075 3076
end
3077 3078
-- keyword
3079 3080
do
3081 3082
local
function
listof
(
list
)
3083
local
size
=
type
(
list
)
=
=
"
table
"
and
#
list
or
0
3084
if
size
>
0
then
3085
return
function
(
)
3086
for
i
=
1
,
size
do
3087
ctx_btxsetfirst
(
list
[
i
]
)
3088
ctx_btxsetconcat
(
concatstate
(
i
,
size
)
)
3089
ctx_btxcitesetup
(
"
listelement
"
)
3090
end
3091
return
true
3092
end
3093
else
3094
return
"
?
"
-- unknown
3095
end
3096
end
3097 3098
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3099
data
.
keywords
=
getcasted
(
dataset
,
tag
,
"
keywords
"
)
3100
end
3101 3102
local
function
getter
(
first
,
last
,
_
,
specification
)
3103
context
(
listof
(
first
.
keywords
)
)
3104
end
3105 3106
function
citevariants
.
keywords
(
presets
)
3107
return
processcite
(
presets
,
{
3108
variant
=
"
keywords
"
,
3109
setter
=
setter
,
3110
getter
=
getter
,
3111
}
)
3112
end
3113 3114
end
3115 3116
-- authors
3117 3118
do
3119 3120
-- is this good enough?
3121 3122
local
keysorter
=
function
(
a
,
b
)
3123
local
ak
=
a
.
authorhash
3124
local
bk
=
b
.
authorhash
3125
if
ak
=
=
bk
then
3126
local
as
=
a
.
authorsuffix
-- numeric
3127
local
bs
=
b
.
authorsuffix
-- numeric
3128
if
as
and
bs
then
3129
return
(
as
or
0
)
<
(
bs
or
0
)
3130
else
3131
return
false
3132
end
3133
elseif
ak
and
bk
then
3134
return
ak
<
bk
3135
else
3136
return
false
3137
end
3138
end
3139 3140
local
revsorter
=
function
(
a
,
b
)
3141
return
keysorter
(
b
,
a
)
3142
end
3143 3144
local
function
authorcompressor
(
found
,
specification
)
3145
-- HERE
3146
if
specification
.
sorttype
=
=
v_normal
then
3147
sort
(
found
,
keysorter
)
3148
elseif
specification
.
sorttype
=
=
v_reverse
then
3149
sort
(
found
,
revsorter
)
3150
end
3151
local
result
=
{
}
3152
local
entries
=
{
}
3153
for
i
=
1
,
#
found
do
3154
local
entry
=
found
[
i
]
3155
local
author
=
entry
.
authorhash
3156
if
author
then
3157
local
aentries
=
entries
[
author
]
3158
if
aentries
then
3159
aentries
[
#
aentries
+
1
]
=
entry
3160
else
3161
entries
[
author
]
=
{
entry
}
3162
end
3163
end
3164
end
3165
-- beware: we use tables as hash so we get a cycle when inspecting (unless we start
3166
-- hashing with strings)
3167
for
i
=
1
,
#
found
do
3168
local
entry
=
found
[
i
]
3169
local
author
=
entry
.
authorhash
3170
if
author
then
3171
local
aentries
=
entries
[
author
]
3172
if
not
aentries
then
3173
result
[
#
result
+
1
]
=
entry
3174
elseif
aentries
=
=
true
then
3175
-- already done
3176
else
3177
result
[
#
result
+
1
]
=
entry
3178
entry
.
entries
=
aentries
3179
entries
[
author
]
=
true
3180
end
3181
end
3182
end
3183
return
result
3184
end
3185 3186
local
function
authorconcat
(
target
,
key
,
setup
)
3187
ctx_btxstartsubcite
(
setup
)
3188
local
nofcollected
=
#
target
3189
if
nofcollected
=
=
0
then
3190
unknowncite
(
tag
)
3191
else
3192
for
i
=
1
,
nofcollected
do
3193
local
entry
=
target
[
i
]
3194
local
first
=
entry
.
first
3195
local
tag
=
entry
.
tag
3196
local
currentcitation
=
markcite
(
entry
.
dataset
,
tag
)
3197
ctx_btxstartciteauthor
(
)
3198
ctx_btxsettag
(
tag
)
3199
ctx_btxsetbacklink
(
currentcitation
)
3200
local
bl
=
listtocite
[
currentcitation
]
3201
ctx_btxsetinternal
(
bl
and
bl
.
references
.
internal
or
"
"
)
3202
if
first
then
3203
ctx_btxsetfirst
(
first
[
key
]
or
"
"
)
-- f_missing(first.tag))
3204
local
suffix
=
entry
.
suffix
3205
local
last
=
entry
.
last
3206
local
value
=
last
and
last
[
key
]
3207
if
value
then
3208
ctx_btxsetsecond
(
value
)
3209
end
3210
if
suffix
then
3211
ctx_btxsetsuffix
(
suffix
)
3212
end
3213
else
3214
local
suffix
=
entry
.
suffix
3215
local
value
=
entry
[
key
]
or
"
"
-- f_missing(tag)
3216
ctx_btxsetfirst
(
value
)
3217
if
suffix
then
3218
ctx_btxsetsuffix
(
suffix
)
3219
end
3220
end
3221
ctx_btxsetconcat
(
concatstate
(
i
,
nofcollected
)
)
3222
if
trace_details
then
3223
report
(
"
expanding %a cite setup %a
"
,
"
multiple author
"
,
setup
)
3224
end
3225
ctx_btxsubcitesetup
(
setup
)
3226
ctx_btxstopciteauthor
(
)
3227
end
3228
end
3229
ctx_btxstopsubcite
(
)
3230
end
3231 3232
local
function
authorsingle
(
entry
,
key
,
setup
)
3233
ctx_btxstartsubcite
(
setup
)
3234
ctx_btxstartciteauthor
(
)
3235
local
tag
=
entry
.
tag
3236
ctx_btxsettag
(
tag
)
3237
ctx_btxsetfirst
(
entry
[
key
]
or
"
"
)
-- f_missing(tag)
3238
if
suffix
then
3239
ctx_btxsetsuffix
(
entry
.
suffix
)
3240
end
3241
if
trace_details
then
3242
report
(
"
expanding %a cite setup %a
"
,
"
single author
"
,
setup
)
3243
end
3244
ctx_btxcitesetup
(
setup
)
3245
ctx_btxstopciteauthor
(
)
3246
ctx_btxstopsubcite
(
)
3247
end
3248 3249
local
partialinteractive
=
false
3250 3251
local
currentbtxciteauthor
=
function
(
)
3252
context
.
currentbtxciteauthorbyfield
(
)
3253
return
true
-- needed?
3254
end
3255 3256
local
function
authorgetter
(
first
,
last
,
key
,
specification
)
-- only first
3257
ctx_btxsetauthorfield
(
first
.
varfield
or
"
author
"
)
3258
if
first
.
type
=
=
"
author
"
then
3259
ctx_btxsetfirst
(
currentbtxciteauthor
)
-- formatter (much slower)
3260
else
3261
ctx_btxsetfirst
(
first
.
author
)
-- unformatted
3262
end
3263
local
entries
=
first
.
entries
3264
-- alternatively we can use a concat with one ... so that we can only make the
3265
-- year interactive, as with the concat
3266
if
partialinteractive
and
not
entries
then
3267
entries
=
{
first
}
3268
end
3269
if
entries
then
3270
-- happens with year
3271
local
c
=
compresslist
(
entries
,
specification
)
3272
local
f
=
function
(
)
authorconcat
(
c
,
key
,
specification
.
setup
or
"
author
"
)
return
true
end
-- indeed return true?
3273
ctx_btxsetcount
(
#
c
)
3274
ctx_btxsetsecond
(
f
)
3275
elseif
first
then
3276
-- happens with num
3277
local
f
=
function
(
)
authorsingle
(
first
,
key
,
specification
.
setup
or
"
author
"
)
return
true
end
-- indeed return true?
3278
ctx_btxsetcount
(
0
)
3279
ctx_btxsetsecond
(
f
)
3280
end
3281
return
true
3282
end
3283 3284
-- author (the varfield hack is for editor and translator i.e author type)
3285 3286
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3287
data
.
author
,
data
.
field
,
data
.
type
=
getcasted
(
dataset
,
tag
,
data
.
varfield
or
"
author
"
)
3288
data
.
sortkey
=
text
and
lpegmatch
(
numberonly
,
text
)
3289
data
.
authorhash
=
getdetail
(
dataset
,
tag
,
"
authorhash
"
)
-- todo let getcasted return
3290
end
3291 3292
local
function
getter
(
first
,
last
,
_
,
specification
)
3293
ctx_btxsetauthorfield
(
specification
.
varfield
or
"
author
"
)
3294
if
first
.
type
=
=
"
author
"
then
3295
ctx_btxsetfirst
(
currentbtxciteauthor
)
-- formatter (much slower)
3296
else
3297
ctx_btxsetfirst
(
first
.
author
)
-- unformatted
3298
end
3299
return
true
3300
end
3301 3302
function
citevariants
.
author
(
presets
)
3303
processcite
(
presets
,
{
3304
variant
=
"
author
"
,
3305
setup
=
"
author
"
,
3306
setter
=
setter
,
3307
getter
=
getter
,
3308
varfield
=
presets
.
variant
or
"
author
"
,
3309
compressor
=
authorcompressor
,
3310
}
)
3311
end
3312 3313
-- authornum
3314 3315
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3316
local
entries
=
entry
.
entries
3317
local
text
=
entries
and
entries
.
text
or
"
?
"
3318
data
.
author
,
data
.
field
,
data
.
type
=
getcasted
(
dataset
,
tag
,
"
author
"
)
3319
data
.
authorhash
=
getdetail
(
dataset
,
tag
,
"
authorhash
"
)
-- todo let getcasted return
3320
data
.
num
=
text
3321
data
.
sortkey
=
text
and
lpegmatch
(
numberonly
,
text
)
3322
end
3323 3324
local
function
getter
(
first
,
last
,
_
,
specification
)
3325
authorgetter
(
first
,
last
,
"
num
"
,
specification
)
3326
return
true
3327
end
3328 3329
function
citevariants
.
authornum
(
presets
)
3330
processcite
(
presets
,
{
3331
variant
=
"
authornum
"
,
3332
setup
=
"
author:num
"
,
3333
numeric
=
true
,
3334
setter
=
setter
,
3335
getter
=
getter
,
3336
compressor
=
authorcompressor
,
3337
}
)
3338
end
3339 3340
-- authoryear | authoryears
3341 3342
local
function
setter
(
data
,
dataset
,
tag
,
entry
)
3343
data
.
author
,
data
.
field
,
data
.
type
=
getcasted
(
dataset
,
tag
,
"
author
"
)
3344
data
.
authorhash
=
getdetail
(
dataset
,
tag
,
"
authorhash
"
)
-- todo let getcasted return
3345
local
year
=
getfield
(
dataset
,
tag
,
"
year
"
)
3346
local
suffix
=
getdetail
(
dataset
,
tag
,
"
authorsuffix
"
)
3347
data
.
year
=
year
3348
data
.
suffix
=
suffix
3349
data
.
sortkey
=
tonumber
(
year
)
or
9999
3350
end
3351 3352
local
function
getter
(
first
,
last
,
_
,
specification
)
3353
authorgetter
(
first
,
last
,
"
year
"
,
specification
)
3354
return
true
3355
end
3356 3357
function
citevariants
.
authoryear
(
presets
)
3358
processcite
(
presets
,
{
3359
variant
=
"
authoryear
"
,
3360
setup
=
"
author:year
"
,
3361
numeric
=
true
,
3362
setter
=
setter
,
3363
getter
=
getter
,
3364
compressor
=
authorcompressor
,
3365
}
)
3366
end
3367 3368
local
function
getter
(
first
,
last
,
_
,
specification
)
3369
authorgetter
(
first
,
last
,
"
year
"
,
specification
)
3370
return
true
3371
end
3372 3373
function
citevariants
.
authoryears
(
presets
)
3374
processcite
(
presets
,
{
3375
variant
=
"
authoryears
"
,
3376
setup
=
"
author:years
"
,
3377
numeric
=
true
,
3378
setter
=
setter
,
3379
getter
=
getter
,
3380
compressor
=
authorcompressor
,
3381
}
)
3382
end
3383 3384
end
3385 3386
end
3387 3388
-- List variants
3389 3390
do
3391 3392
local
listvariants
=
{
}
3393
publications
.
listvariants
=
listvariants
3394 3395
local
function
btxlistvariant
(
dataset
,
block
,
tag
,
variant
,
listindex
)
3396
local
action
=
listvariants
[
variant
]
or
listvariants
.
default
3397
if
action
then
3398
listindex
=
tonumber
(
listindex
)
3399
if
listindex
then
3400
action
(
dataset
,
block
,
tag
,
variant
,
listindex
)
3401
end
3402
end
3403
end
3404 3405
implement
{
3406
name
=
"
btxlistvariant
"
,
3407
arguments
=
"
5 strings
"
,
3408
actions
=
btxlistvariant
,
3409
}
3410 3411
function
listvariants
.
default
(
dataset
,
block
,
tag
,
variant
)
3412
ctx_btxsetfirst
(
"
?
"
)
3413
if
trace_details
then
3414
report
(
"
expanding %a list setup %a
"
,
"
default
"
,
variant
)
3415
end
3416
ctx_btxnumberingsetup
(
"
default
"
)
3417
end
3418 3419
function
listvariants
.
num
(
dataset
,
block
,
tag
,
variant
,
listindex
)
3420
ctx_btxsetfirst
(
listindex
)
3421
if
trace_details
then
3422
report
(
"
expanding %a list setup %a
"
,
"
num
"
,
variant
)
3423
end
3424
ctx_btxnumberingsetup
(
variant
or
"
num
"
)
3425
end
3426 3427
-- listvariants[v_yes] = listvariants.num
3428 3429
function
listvariants
.
index
(
dataset
,
block
,
tag
,
variant
,
listindex
)
3430
local
index
=
getdetail
(
dataset
,
tag
,
"
index
"
)
3431
ctx_btxsetfirst
(
index
or
"
?
"
)
3432
if
trace_details
then
3433
report
(
"
expanding %a list setup %a
"
,
"
index
"
,
variant
)
3434
end
3435
ctx_btxnumberingsetup
(
variant
or
"
index
"
)
3436
end
3437 3438
function
listvariants
.
tag
(
dataset
,
block
,
tag
,
variant
,
listindex
)
3439
ctx_btxsetfirst
(
tag
)
3440
if
trace_details
then
3441
report
(
"
expanding %a list setup %a
"
,
"
tag
"
,
variant
)
3442
end
3443
ctx_btxnumberingsetup
(
variant
or
"
tag
"
)
3444
end
3445 3446
function
listvariants
.
short
(
dataset
,
block
,
tag
,
variant
,
listindex
)
3447
local
short
=
getdetail
(
dataset
,
tag
,
"
shorthash
"
)
3448
local
suffix
=
getdetail
(
dataset
,
tag
,
"
shortsuffix
"
)
3449
if
short
then
3450
ctx_btxsetfirst
(
short
)
3451
end
3452
if
suffix
then
3453
ctx_btxsetsuffix
(
suffix
)
3454
end
3455
if
trace_details
then
3456
report
(
"
expanding %a list setup %a
"
,
"
short
"
,
variant
)
3457
end
3458
ctx_btxnumberingsetup
(
variant
or
"
short
"
)
3459
end
3460 3461
end
3462 3463
-- a helper
3464 3465
do
3466 3467
-- local context = context
3468
-- local lpegmatch = lpeg.match
3469
local
splitter
=
lpeg
.
tsplitat
(
"
:
"
)
3470 3471
implement
{
3472
name
=
"
checkinterfacechain
"
,
3473
arguments
=
"
2 strings
"
,
3474
actions
=
function
(
str
,
command
)
3475
local
chain
=
lpegmatch
(
splitter
,
str
)
3476
if
#
chain
>
0
then
3477
local
command
=
context
[
command
]
3478
local
parent
=
"
"
3479
local
child
=
chain
[
1
]
3480
command
(
child
,
parent
)
3481
for
i
=
2
,
#
chain
do
3482
parent
=
child
3483
child
=
child
.
.
"
:
"
.
.
chain
[
i
]
3484
command
(
child
,
parent
)
3485
end
3486
end
3487
end
3488
}
3489 3490
end
3491 3492
do
3493 3494
local
btxstring
=
"
"
3495 3496
implement
{
3497
name
=
"
btxcmdstring
"
,
3498
actions
=
function
(
)
if
btxstring
~
=
"
"
then
context
(
btxstring
)
end
end
,
3499
}
3500 3501
function
publications
.
prerollcmdstring
(
str
)
3502
btxstring
=
str
or
"
"
3503
tex
.
runtoks
(
"
t_btx_cmd
"
)
3504
return
nodes
.
toutf
(
tex
.
getbox
(
"
b_btx_cmd
"
)
.
list
)
or
str
3505
end
3506 3507
end
3508