1if 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
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24local next , rawget , type , tostring , tonumber = next , rawget , type , tostring , tonumber
25local match , find , gsub = string . match , string . find , string . gsub
26local concat , sort , tohash = table . concat , table . sort , table . tohash
27local mod = math . mod
28local formatters = string . formatters
29local allocate = utilities . storage . allocate
30local settings_to_array , settings_to_set = utilities . parsers . settings_to_array , utilities . parsers . settings_to_set
31local sortedkeys , sortedhash = table . sortedkeys , table . sortedhash
32local setmetatableindex = table . setmetatableindex
33local lpegmatch = lpeg . match
34local P , S , C , Ct , Cs , R , Carg = lpeg . P , lpeg . S , lpeg . C , lpeg . Ct , lpeg . Cs , lpeg . R , lpeg . Carg
35local upper = characters . upper
36
37local report = logs . reporter ( " publications " )
38local report_cite = logs . reporter ( " publications " , " cite " )
39local report_list = logs . reporter ( " publications " , " list " )
40local report_suffix = logs . reporter ( " publications " , " suffix " )
41
42local trace = false trackers . register ( " publications " , function ( v ) trace = v end )
43local trace_cite = false trackers . register ( " publications.cite " , function ( v ) trace_cite = v end )
44local trace_missing = false trackers . register ( " publications.cite.missing " , function ( v ) trace_missing = v end )
45local trace_references = false trackers . register ( " publications.cite.references " , function ( v ) trace_references = v end )
46local trace_details = false trackers . register ( " publications.details " , function ( v ) trace_details = v end )
47local trace_suffixes = false trackers . register ( " publications.suffixes " , function ( v ) trace_suffixes = v end )
48
49publications = publications or { }
50local datasets = publications . datasets
51local writers = publications . writers
52local casters = publications . casters
53local detailed = publications . detailed
54local enhancer = publications . enhancer
55local enhancers = publications . enhancers
56
57local tracers = publications . tracers or { }
58publications . tracers = tracers
59
60local setmacro = interfaces . setmacro
61local setcounter = tex . setcounter
62local variables = interfaces . variables
63
64local v_local = variables [ " local " ]
65local v_global = variables [ " global " ]
66
67local v_force = variables . force
68local v_normal = variables . normal
69local v_reverse = variables . reverse
70local v_none = variables . none
71local v_yes = variables . yes
72local v_no = variables . no
73local v_all = variables . all
74local v_always = variables . always
75local v_text = variables . text
76local v_doublesided = variables . doublesided
77local v_default = variables . default
78local v_dataset = variables . dataset
79
80local conditionals = tex . conditionals
81
82local isdefined = tex . isdefined
83
84
85
86
87
88local manipulators = typesetters . manipulators
89local splitmanipulation = manipulators . splitspecification
90local applymanipulation = manipulators . applyspecification
91local manipulatormethods = manipulators . methods
92
93
94
95manipulatormethods . Word = converters . Word
96manipulatormethods . WORD = converters . WORD
97manipulatormethods . Words = converters . Words
98manipulatormethods . WORDS = converters . WORDS
99
100local context = context
101local commands = commands
102local implement = interfaces . implement
103
104local ctx_doifelse = commands . doifelse
105local ctx_doif = commands . doif
106local ctx_doifnot = commands . doifnot
107local ctx_gobbletwoarguments = context . gobbletwoarguments
108
109local ctx_btxhandlelistentry = context . btxhandlelistentry
110local ctx_btxhandlecombientry = context . btxhandlecombientry
111local ctx_btxchecklistentry = context . btxchecklistentry
112
113local ctx_btxsetdataset = context . btxsetdataset
114local ctx_btxsettag = context . btxsettag
115local ctx_btxsetnumber = context . btxsetnumber
116local ctx_btxsetlanguage = context . btxsetlanguage
117local ctx_btxsetcombis = context . btxsetcombis
118local ctx_btxsetcategory = context . btxsetcategory
119local ctx_btxsetfirst = context . btxsetfirst
120local ctx_btxsetsecond = context . btxsetsecond
121local ctx_btxsetsuffix = context . btxsetsuffix
122local ctx_btxsetinternal = context . btxsetinternal
123local ctx_btxsetlefttext = context . btxsetlefttext
124local ctx_btxsetrighttext = context . btxsetrighttext
125local ctx_btxsetbefore = context . btxsetbefore
126local ctx_btxsetafter = context . btxsetafter
127local ctx_btxsetbacklink = context . btxsetbacklink
128local ctx_btxsetfirstinternal = context . btxsetfirstinternal
129local ctx_btxsetlastinternal = context . btxsetlastinternal
130local ctx_btxsetauthorfield = context . btxsetauthorfield
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150local ctx_btxsetfirstpage = context . btxsetfirstpage
151local ctx_btxsetlastpage = context . btxsetlastpage
152
153local ctx_btxstartcite = context . btxstartcite
154local ctx_btxstopcite = context . btxstopcite
155local ctx_btxstartciteauthor = context . btxstartciteauthor
156local ctx_btxstopciteauthor = context . btxstopciteauthor
157local ctx_btxstartsubcite = context . btxstartsubcite
158local ctx_btxstopsubcite = context . btxstopsubcite
159local ctx_btxstartlistentry = context . btxstartlistentry
160local ctx_btxstoplistentry = context . btxstoplistentry
161local ctx_btxstartcombientry = context . btxstartcombientry
162local ctx_btxstopcombientry = context . btxstopcombientry
163
164local ctx_btxflushauthor = context . btxflushauthor
165
166local ctx_btxsetnoflistentries = context . btxsetnoflistentries
167local ctx_btxsetcurrentlistentry = context . btxsetcurrentlistentry
168local ctx_btxsetcurrentlistindex = context . btxsetcurrentlistindex
169
170local ctx_btxsetcount = context . btxsetcount
171local ctx_btxsetconcat = context . btxsetconcat
172
173local ctx_btxcitesetup = context . btxcitesetup
174local ctx_btxsubcitesetup = context . btxsubcitesetup
175local ctx_btxnumberingsetup = context . btxnumberingsetup
176local ctx_btxpagesetup = context . btxpagesetup
177local ctx_btxlistsetup = context . btxlistsetup
178
179local trialtypesetting = context . trialtypesetting
180
181languages . data = languages . data or { }
182local data = languages . data
183
184local specifications = publications . specifications
185local currentspecification = specifications [ false ]
186local ignoredfields = { }
187publications . currentspecification = currentspecification
188
189local 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
195end
196
197publications . setspecification = setspecification
198
199implement {
200 name = " btxsetspecification " ,
201 actions = setspecification ,
202 arguments = " string " ,
203}
204
205local optionalspace = lpeg . patterns . whitespace ^ 0
206local prefixsplitter = optionalspace * lpeg . splitat ( optionalspace * P ( " :: " ) * optionalspace )
207
208statistics . 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
221end )
222
223logs . 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
256end )
257
258
259
260
261local collected = allocate ( )
262local tobesaved = allocate ( )
263
264do
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
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
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
348 end
349
350 job . register ( ' publications.collected ' , tobesaved , initializer , finalizer )
351
352end
353
354
355
356
357local nofcitations = 0
358local usedentries = nil
359local citetolist = nil
360local listtocite = nil
361local listtolist = nil
362
363do
364
365 local initialize = nil
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
377
378
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
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
405 local int = tonumber ( userdata . btxint )
406 if int then
407 listtocite [ int ] = entry
408 end
409 local detail = datasets [ set ] . details [ tag ]
410
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
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
477end
478
479
480
481
482
483
484
485
486
487
488local findallused do
489
490 local reported = { }
491
492
493 findallused = function ( dataset , reference , internal , forcethem )
494 local current = datasets [ dataset ]
495 local finder = publications . finder
496 local find = finder and finder ( current , reference )
497 local tags = not find and settings_to_array ( reference )
498 local todo = { }
499 local okay = { }
500 local allused = usedentries [ dataset ] or { }
501
502 local luadata = current . luadata
503 local details = current . details
504 local ordered = current . ordered
505 if allused then
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
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
549
550 if # entry = = 1 then
551 entry = entry [ 1 ]
552 else
553
554 local done = false
555 if internal and internal > 0 then
556
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
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
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
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
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
694end
695
696local 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 " )
702end
703
704local concatstate = publications . concatstate
705
706
707
708
709
710
711local marked_todo = false
712local marked_dataset = false
713local marked_list = false
714local marked_method = false
715
716local 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 ( )
726end
727
728local 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
745 return nofcitations
746 else
747 return citation
748 end
749end
750
751local function btxflushmarked ( )
752 if marked_list and marked_todo then
753 for i = 1 , # marked_list do
754
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
766 end
767 end
768 end
769 marked_todo = false
770 marked_dataset = false
771 marked_list = false
772 marked_method = false
773end
774
775implement { name = " btxflushmarked " , actions = btxflushmarked }
776
777
778
779local function getfield ( dataset , tag , name )
780 local d = datasets [ dataset ] . luadata [ tag ]
781 return d and d [ name ]
782end
783
784local function getdetail ( dataset , tag , name )
785 local d = datasets [ dataset ] . details [ tag ]
786 return d and d [ name ]
787end
788
789local 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 ]
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 ]
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
828 end
829 end
830 end
831end
832
833local 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 ]
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 ]
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
865end
866
867local function getdirect ( dataset , data , field , catspec )
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 ]
881 if value then
882 return value
883 end
884 end
885 end
886 end
887 return fields [ field ] and data [ field ] or nil
888 end
889end
890
891local function getfuzzy ( data , field , categories )
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 ]
913 if value then
914 return value
915 end
916 end
917 end
918 end
919 return fields [ field ] and data [ field ] or nil
920 end
921end
922
923publications . getfield = getfield
924publications . getdetail = getdetail
925publications . getcasted = getcasted
926publications . getfaster = getfaster
927publications . getdirect = getdirect
928publications . getfuzzy = getfuzzy
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967local inspectors = allocate ( )
968local nofmultiple = allocate ( )
969local firstandlast = allocate ( )
970
971publications . inspectors = inspectors
972inspectors . nofmultiple = nofmultiple
973inspectors . firstandlast = firstandlast
974
975function nofmultiple . author ( d )
976 return type ( d ) = = " table " and # d or 0
977end
978
979function 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
989end
990
991function firstandlast . range ( d )
992 if type ( d ) = = " table " then
993 return d [ 1 ] , d [ 2 ]
994 end
995end
996
997firstandlast . pagenumber = firstandlast . range
998
999function 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
1009end
1010
1011function 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
1022end
1023
1024function 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
1035end
1036
1037implement {
1038 name = " btxsingularorplural " ,
1039 actions = { publications . singularorplural , ctx_doifelse } ,
1040 arguments = " 3 strings "
1041}
1042
1043implement {
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
1049implement {
1050 name = " btxfirstofrange " ,
1051 actions = { publications . firstofrange , context } ,
1052 arguments = " 3 strings "
1053}
1054
1055implement {
1056 name = " btxlastofrange " ,
1057 actions = { publications . lastofrange , context } ,
1058 arguments = " 3 strings "
1059}
1060
1061
1062
1063function publications . usedataset ( specification )
1064 specification . kind = " current "
1065 publications . load ( specification )
1066end
1067
1068implement {
1069 name = " btxusedataset " ,
1070 actions = publications . usedataset ,
1071 arguments = {
1072 {
1073 { " specification " } ,
1074 { " dataset " } ,
1075 { " filename " } ,
1076 }
1077 }
1078}
1079
1080implement {
1081 name = " convertbtxdatasettoxml " ,
1082 arguments = { " string " , true } ,
1083 actions = publications . converttoxml
1084}
1085
1086
1087
1088do
1089
1090
1091
1092 local function shortsorter ( a , b )
1093 local ay = a [ 2 ]
1094 local by = b [ 2 ]
1095 if ay ~ = by then
1096 return ay < by
1097 end
1098 local ay = a [ 3 ]
1099 local by = b [ 3 ]
1100 if ay ~ = by then
1101
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
1114
1115
1116
1117
1118 local f_short = formatters [ " %s%02i " ]
1119
1120 function publications . enhancers . suffixes ( dataset )
1121 if not dataset then
1122 return
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
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
1138 end
1139
1140 local kind = dataset . authorconversion or " name "
1141 local fields = { " author " , " editor " }
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
1154
1155 local listentry = use [ 1 ]
1156 local userdata = listentry . userdata
1157 local btxspc = userdata and userdata . btxspc
1158 if btxspc then
1159
1160
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
1169 else
1170 u = " 0 "
1171 end
1172 local year = tonumber ( entry . year ) or 9999
1173 local data = { tag , year , u , i }
1174
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
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
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
1207 local n = # tags
1208 if n = = 0 then
1209
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 )
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 " )
1257 addsuffix ( authors , " authorhash " , " authorsuffix " )
1258 end
1259
1260
1261
1262end
1263
1264implement {
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
1275function 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
1285end
1286
1287implement {
1288 name = " btxsetdataset " ,
1289 arguments = " 2 strings " ,
1290 actions = { publications . checkeddataset , context } ,
1291}
1292
1293implement {
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
1311
1312do
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
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
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 " )
1359 return false
1360 end
1361 local fields = catspec . fields
1362 if not fields then
1363 report ( " invalid category %a, %s " , category , " no fields " )
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
1386 end
1387 end
1388
1389 local function found ( dataset , tag , field , valid , fields )
1390 if valid = = true then
1391
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
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 )
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
1601end
1602
1603
1604
1605function publications . singularorplural ( singular , plural )
1606 if lastconcatsize and lastconcatsize > 1 then
1607 context ( plural )
1608 else
1609 context ( singular )
1610 end
1611end
1612
1613
1614
1615do
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 )
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 )
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
1660end
1661
1662
1663
1664local renderings = { }
1665
1666do
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
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
1697
1698 function lists . register ( dataset , tag , short )
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
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 )
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
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
1760
1761 methods [ v_force ] = function ( dataset , rendering , keyword )
1762
1763
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
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
1786
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 = { }
1799 local pages = { }
1800 local current = datasets [ dataset ]
1801 local luadata = current . luadata
1802
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
1809 local set = u . btxset or v_default
1810 if set = = dataset then
1811
1812 local tag = u . btxref
1813 if not tag then
1814
1815 elseif done [ tag ] = = section then
1816
1817 elseif doglobal and alldone [ tag ] then
1818
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
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
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 = { }
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
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 ]
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
1939 if not repeated then
1940 used [ tag ] = true
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
1961 report ( " fatal error, missing details for tag %a in dataset %a (enhanced: %s) " , tag , dataset , current . enhanced and " yes " or " no " )
1962
1963
1964
1965
1966
1967 elseif detail . parent then
1968
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
2000
2001
2002
2003 local function btxflushpages ( dataset , tag )
2004
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
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 ( " " )
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
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
2117
2118
2119
2120
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 )
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
2278
2279
2280
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
2321
2322
2323
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
2388end
2389
2390do
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 )
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 ( )
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
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
2554 local bs = b . suffix
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
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
2639
2640
2641
2642
2643
2644
2645
2646 local numberonly = R ( " 09 " ) ^ 1 / tonumber + P ( 1 ) ^ 0
2647 local f_missing = formatters [ " <%s> " ]
2648
2649
2650
2651
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 )
2676
2677 if not found or # found = = 0 then
2678
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
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
2702
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
2746 bl = bl . references . internal
2747 else
2748
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
2758
2759
2760
2761 if not getter ( entry , last , nil , specification ) then
2762 ctx_btxsetfirst ( " " )
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 ( )
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
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 )
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
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
2895
2896 do
2897
2898 local function setter ( data , dataset , tag , entry )
2899
2900 end
2901
2902 local function getter ( first , last , _ , specification )
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
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 )
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 )
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
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
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
3003
3004 end
3005
3006
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
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
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
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 " ? "
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
3117
3118 do
3119
3120
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
3127 local bs = b . authorsuffix
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
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
3166
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
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 " " )
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 " "
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 " " )
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
3254 end
3255
3256 local function authorgetter ( first , last , key , specification )
3257 ctx_btxsetauthorfield ( first . varfield or " author " )
3258 if first . type = = " author " then
3259 ctx_btxsetfirst ( currentbtxciteauthor )
3260 else
3261 ctx_btxsetfirst ( first . author )
3262 end
3263 local entries = first . entries
3264
3265
3266 if partialinteractive and not entries then
3267 entries = { first }
3268 end
3269 if entries then
3270
3271 local c = compresslist ( entries , specification )
3272 local f = function ( ) authorconcat ( c , key , specification . setup or " author " ) return true end
3273 ctx_btxsetcount ( # c )
3274 ctx_btxsetsecond ( f )
3275 elseif first then
3276
3277 local f = function ( ) authorsingle ( first , key , specification . setup or " author " ) return true end
3278 ctx_btxsetcount ( 0 )
3279 ctx_btxsetsecond ( f )
3280 end
3281 return true
3282 end
3283
3284
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 " )
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 )
3296 else
3297 ctx_btxsetfirst ( first . author )
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
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 " )
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
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 " )
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
3386end
3387
3388
3389
3390do
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
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
3461end
3462
3463
3464
3465do
3466
3467
3468
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
3490end
3491
3492do
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
3507end
3508 |