summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/publ-aut.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/publ-aut.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/publ-aut.lua576
1 files changed, 412 insertions, 164 deletions
diff --git a/Master/texmf-dist/tex/context/base/publ-aut.lua b/Master/texmf-dist/tex/context/base/publ-aut.lua
index 820ac78ff3b..4ab8dd4bc93 100644
--- a/Master/texmf-dist/tex/context/base/publ-aut.lua
+++ b/Master/texmf-dist/tex/context/base/publ-aut.lua
@@ -16,9 +16,10 @@ local lpeg = lpeg
local type, next, tostring = type, next, tostring
local concat = table.concat
local utfchar = utf.char
+local utfsub = utf.sub
local formatters = string.formatters
-local P, C, V, Cs, Ct, Cg, Cf, Cc = lpeg.P, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Ct, lpeg.Cg, lpeg.Cf, lpeg.Cc
+local P, S, C, V, Cs, Ct, Cg, Cf, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Ct, lpeg.Cg, lpeg.Cf, lpeg.Cc
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local context = context
@@ -36,7 +37,10 @@ local allocate = utilities.storage.allocate
local chardata = characters.data
+local trace_hashing = false trackers.register("publications.authorhash", function(v) trace_hashing = v end)
+
local report = logs.reporter("publications","authors")
+local report_cite = logs.reporter("publications","cite")
-- local function makesplitter(separator)
-- return Ct { "start",
@@ -99,7 +103,7 @@ end
-- local cleaner = Cs( ( P("{}")/"" + P(1) )^1 )
-local cache = { } -- 33% reuse on tugboat.bib
+local cache = allocate() -- 33% reuse on tugboat.bib
local nofhits = 0
local nofused = 0
@@ -115,6 +119,144 @@ local function makeinitials(firstnames)
end
end
+local authormap = allocate()
+publications.authormap = authormap
+
+local function splitauthor(author)
+ local detail = cache[author]
+ if detail then
+ return detail
+ end
+ local remapped = authormap[author]
+ if remapped then
+ report("remapping %a to %a",author,remapped)
+ local detail = cache[remapped]
+ if detail then
+ cache[author] = detail
+ return detail
+ end
+ end
+ local author = remapped or author
+ local firstnames, vons, surnames, initials, juniors, options
+ local split = lpegmatch(commasplitter,author)
+ local n = #split
+ detail = {
+ original = author,
+ snippets = n,
+ }
+ if n == 1 then
+ -- {First Middle von Last}
+ local words = lpegmatch(spacesplitter,author)
+ firstnames, vons, surnames = { }, { }, { }
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ break
+ else
+ vons[#vons+1], i = w, i + 1
+ end
+ end
+ if i <= n then
+ while i <= n do
+ surnames[#surnames+1], i = words[i], i + 1
+ end
+ elseif #vons == 0 then
+ surnames[1] = firstnames[#firstnames]
+ firstnames[#firstnames] = nil
+ else
+ -- mess
+ end
+ if #surnames == 0 then
+ -- safeguard
+ firstnames = { }
+ vons = { }
+ surnames = { author }
+ else
+ initials = makeinitials(firstnames)
+ end
+ elseif n == 2 then
+ -- {Last, First}
+ -- {von Last, First}
+ firstnames, vons, surnames = { }, { }, { }
+ local words = lpegmatch(spacesplitter,split[1])
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ break
+ else
+ vons[#vons+1], i = w, i + 1
+ end
+ end
+ while i <= n do
+ surnames[#surnames+1], i = words[i], i + 1
+ end
+ --
+ local words = lpegmatch(spacesplitter,split[2])
+ local i, n = 1, #words
+ while i <= n do
+ local w = words[i]
+ if is_upper(w) then
+ firstnames[#firstnames+1], i = w, i + 1
+ else
+ break
+ end
+ end
+ while i <= n do
+ vons[#vons+1], i = words[i], i + 1
+ end
+ if surnames and firstnames and #surnames == 0 then
+ -- safeguard
+ surnames[1] = firstnames[#firstnames]
+ firstnames[#firstnames] = nil
+ end
+ initials = makeinitials(firstnames)
+ elseif n == 3 then
+ -- {von Last, First, Jr}
+ surnames = lpegmatch(spacesplitter,split[1])
+ juniors = lpegmatch(spacesplitter,split[2])
+ firstnames = lpegmatch(spacesplitter,split[3])
+ initials = makeinitials(firstnames)
+ elseif n == 4 then
+ -- {Von, Last, First, Jr}
+ vons = lpegmatch(spacesplitter,split[1])
+ surnames = lpegmatch(spacesplitter,split[2])
+ juniors = lpegmatch(spacesplitter,split[3])
+ firstnames = lpegmatch(spacesplitter,split[4])
+ initials = makeinitials(firstnames)
+ elseif n >= 5 then
+ -- {Von, Last, First, Jr, F.}
+ -- {Von, Last, First, Jr, Fr., options}
+ vons = lpegmatch(spacesplitter,split[1])
+ surnames = lpegmatch(spacesplitter,split[2])
+ juniors = lpegmatch(spacesplitter,split[3])
+ firstnames = lpegmatch(spacesplitter,split[4])
+ initials = lpegmatch(spacesplitter,split[5])
+ options = split[6]
+ if options then
+ options = lpegmatch(optionsplitter,options)
+ end
+ end
+ if firstnames and #firstnames > 0 then detail.firstnames = firstnames end
+ if vons and #vons > 0 then detail.vons = vons end
+ if surnames and #surnames > 0 then detail.surnames = surnames end
+ if initials and #initials > 0 then detail.initials = initials end
+ if juniors and #juniors > 0 then detail.juniors = juniors end
+ if options and next(options) then detail.options = options end
+ cache[author] = detail
+ nofhits = nofhits + 1
+ return detail
+end
+
local function splitauthorstring(str)
if str then
-- str = lpegmatch(cleaner,str)
@@ -122,144 +264,32 @@ local function splitauthorstring(str)
return
end
nofused = nofused + 1
+
+ local remapped = authormap[str]
+ if remapped then
+ local detail = cache[remapped]
+ if detail then
+ cache[str] = detail
+ return { detail }
+ end
+ end
+
local authors = cache[str]
if authors then
- -- hit 1
- -- print("hit 1",author,nofhits,nofused,math.round(100*nofhits/nofused))
return { authors } -- we assume one author
end
+
+
local authors = lpegmatch(andsplitter,str)
for i=1,#authors do
- local author = authors[i]
- local detail = cache[author]
- if detail then
- -- hit 2
- -- print("hit 2",author,nofhits,nofused,math.round(100*nofhits/nofused))
- end
- if not detail then
- local firstnames, vons, surnames, initials, juniors, options
- local split = lpegmatch(commasplitter,author)
- local n = #split
- detail = {
- original = author,
- snippets = n,
- }
- if n == 1 then
- -- {First Middle von Last}
- local words = lpegmatch(spacesplitter,author)
- firstnames, vons, surnames = { }, { }, { }
- local i, n = 1, #words
- while i <= n do
- local w = words[i]
- if is_upper(w) then
- firstnames[#firstnames+1], i = w, i + 1
- else
- break
- end
- end
- while i <= n do
- local w = words[i]
- if is_upper(w) then
- break
- else
- vons[#vons+1], i = w, i + 1
- end
- end
- if i <= n then
- while i <= n do
- surnames[#surnames+1], i = words[i], i + 1
- end
- elseif #vons == 0 then
- surnames[1] = firstnames[#firstnames]
- firstnames[#firstnames] = nil
- else
- -- mess
- end
- if #surnames == 0 then
- -- safeguard
- firstnames = { }
- vons = { }
- surnames = { author }
- else
- initials = makeinitials(firstnames)
- end
- elseif n == 2 then
- -- {Last, First}
- -- {von Last, First}
- firstnames, vons, surnames = { }, { }, { }
- local words = lpegmatch(spacesplitter,split[1])
- local i, n = 1, #words
- while i <= n do
- local w = words[i]
- if is_upper(w) then
- break
- else
- vons[#vons+1], i = w, i + 1
- end
- end
- while i <= n do
- surnames[#surnames+1], i = words[i], i + 1
- end
- --
- local words = lpegmatch(spacesplitter,split[2])
- local i, n = 1, #words
- while i <= n do
- local w = words[i]
- if is_upper(w) then
- firstnames[#firstnames+1], i = w, i + 1
- else
- break
- end
- end
- while i <= n do
- vons[#vons+1], i = words[i], i + 1
- end
- if surnames and firstnames and #surnames == 0 then
- -- safeguard
- surnames[1] = firstnames[#firstnames]
- firstnames[#firstnames] = nil
- end
- initials = makeinitials(firstnames)
- elseif n == 3 then
- -- {von Last, First, Jr}
- surnames = lpegmatch(spacesplitter,split[1])
- juniors = lpegmatch(spacesplitter,split[2])
- firstnames = lpegmatch(spacesplitter,split[3])
- initials = makeinitials(firstnames)
- elseif n == 4 then
- -- {Von, Last, First, Jr}
- vons = lpegmatch(spacesplitter,split[1])
- surnames = lpegmatch(spacesplitter,split[2])
- juniors = lpegmatch(spacesplitter,split[3])
- firstnames = lpegmatch(spacesplitter,split[4])
- initials = makeinitials(firstnames)
- elseif n >= 5 then
- -- {Von, Last, First, Jr, F.}
- -- {Von, Last, First, Jr, Fr., options}
- vons = lpegmatch(spacesplitter,split[1])
- surnames = lpegmatch(spacesplitter,split[2])
- juniors = lpegmatch(spacesplitter,split[3])
- firstnames = lpegmatch(spacesplitter,split[4])
- initials = lpegmatch(spacesplitter,split[5])
- options = split[6]
- if options then
- options = lpegmatch(optionsplitter,options)
- end
- end
- if firstnames and #firstnames > 0 then detail.firstnames = firstnames end
- if vons and #vons > 0 then detail.vons = vons end
- if surnames and #surnames > 0 then detail.surnames = surnames end
- if initials and #initials > 0 then detail.initials = initials end
- if juniors and #juniors > 0 then detail.juniors = juniors end
- if options and next(options) then detail.options = options end
- cache[author] = detail
- nofhits = nofhits + 1
- end
- authors[i] = detail
+ authors[i] = splitauthor(authors[i])
end
return authors
end
+publications.splitoneauthor = splitauthor
+publications.splitauthor = splitauthorstring
+
local function the_initials(initials,symbol,connector)
if not symbol then
symbol = "."
@@ -323,8 +353,8 @@ local function value(i,field)
end
end
-implement { name = "btxcurrentfirstnames", arguments = "integer", actions = function(i) local v = value(i,"initials") if v then context(concat(the_initials(v,currentauthorsymbol))) end end }
-implement { name = "btxcurrentinitials", arguments = "integer", actions = function(i) local v = value(i,"firstnames") if v then context(concat(v," ")) end end }
+implement { name = "btxcurrentfirstnames", arguments = "integer", actions = function(i) local v = value(i,"firstnames") if v then context(concat(v," ")) end end }
+implement { name = "btxcurrentinitials", arguments = "integer", actions = function(i) local v = value(i,"initials") if v then context(concat(the_initials(v,currentauthorsymbol))) end end }
implement { name = "btxcurrentjuniors", arguments = "integer", actions = function(i) local v = value(i,"juniors") if v then context(concat(v," ")) end end }
implement { name = "btxcurrentsurnames", arguments = "integer", actions = function(i) local v = value(i,"surnames") if v then context(concat(v," ")) end end }
implement { name = "btxcurrentvons", arguments = "integer", actions = function(i) local v = value(i,"vons") if v then context(concat(v," ")) end end }
@@ -476,7 +506,12 @@ local collapsers = allocate { }
publications.authorcollapsers = collapsers
-local function default(author)
+local function default(author) -- one author
+ local hash = author.hash
+ if hash then
+ return hash
+ end
+ local original = author.original
local vons = author.vons
local surnames = author.surnames
local initials = author.initials
@@ -485,26 +520,211 @@ local function default(author)
local result = { }
local nofresult = 0
if vons and #vons > 0 then
- nofresult = nofresult + 1 ; result[nofresult] = concat(vons," ")
+ for j=1,#vons do
+ nofresult = nofresult + 1
+ result[nofresult] = vons[j]
+ end
end
if surnames and #surnames > 0 then
- nofresult = nofresult + 1 ; result[nofresult] = concat(surnames," ")
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
end
if initials and #initials > 0 then
- nofresult = nofresult + 1 ; result[nofresult] = concat(the_initials(initials)," ")
+ initials = the_initials(initials)
+ for j=1,#initials do
+ nofresult = nofresult + 1
+ result[nofresult] = initials[j]
+ end
end
if firstnames and #firstnames > 0 then
- nofresult = nofresult + 1 ; result[nofresult] = concat(firstnames," ")
+ for j=1,#firstnames do
+ nofresult = nofresult + 1
+ result[nofresult] = firstnames[j]
+ end
end
if juniors and #juniors > 0 then
- nofresult = nofresult + 1 ; result[nofresult] = concat(juniors," ")
+ for j=1,#juniors do
+ nofresult = nofresult + 1
+ result[nofresult] = juniors[j]
+ end
+ end
+ local hash = concat(result," ")
+ if trace_hashing then
+ report("hash: %s -> %s",original,hash)
+ end
+ author.hash = hash
+ return hash
+end
+
+local authorhashers = { }
+publications.authorhashers = authorhashers
+
+-- todo: some hashing
+
+local function name(authors)
+ local n = #authors
+ if n == 0 then
+ return ""
+ end
+ local result = { }
+ local nofresult = 0
+ for i=1,n do
+ local author = authors[i]
+ local surnames = author.surnames
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ end
+ return concat(result," ")
+end
+
+table.setmetatableindex(authorhashers,function(t,k)
+ t[k] = name
+ return name
+end)
+
+authorhashers.normal = function(authors)
+ local n = #authors
+ if n == 0 then
+ return ""
+ end
+ local result = { }
+ local nofresult = 0
+ for i=1,n do
+ local author = authors[i]
+ local vons = author.vons
+ local surnames = author.surnames
+ local firstnames = author.firstnames
+ local juniors = author.juniors
+ if vons and #vons > 0 then
+ for j=1,#vons do
+ nofresult = nofresult + 1
+ result[nofresult] = vons[j]
+ end
+ end
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ if firstnames and #firstnames > 0 then
+ for j=1,#firstnames do
+ nofresult = nofresult + 1
+ result[nofresult] = firstnames[j]
+ end
+ end
+ if juniors and #juniors > 0 then
+ for j=1,#juniors do
+ nofresult = nofresult + 1
+ result[nofresult] = juniors[j]
+ end
+ end
+ end
+ return concat(result," ")
+end
+
+authorhashers.normalshort = function(authors)
+ local n = #authors
+ if n == 0 then
+ return ""
+ end
+ local result = { }
+ local nofresult = 0
+ for i=1,n do
+ local author = authors[i]
+ local vons = author.vons
+ local surnames = author.surnames
+ local initials = author.initials
+ local juniors = author.juniors
+ if vons and #vons > 0 then
+ for j=1,#vons do
+ nofresult = nofresult + 1
+ result[nofresult] = vons[j]
+ end
+ end
+ if surnames and #surnames > 0 then
+ for j=1,#surnames do
+ nofresult = nofresult + 1
+ result[nofresult] = surnames[j]
+ end
+ end
+ if initials and #initials > 0 then
+ initials = the_initials(initials)
+ for j=1,#initials do
+ nofresult = nofresult + 1
+ result[nofresult] = initials[j]
+ end
+ end
+ if juniors and #juniors > 0 then
+ for j=1,#juniors do
+ nofresult = nofresult + 1
+ result[nofresult] = juniors[j]
+ end
+ end
end
return concat(result," ")
end
+authorhashers.normalinverted = authorhashers.normal
+authorhashers.invertedshort = authorhashers.normalshort
+
+local p_clean = Cs ( (
+ P("\\btxcmd") / "" -- better keep the argument
+ + S("`~!@#$%^&*()_-+={}[]:;\"\'<>,.?/|\\") / ""
+ + lpeg.patterns.utf8character
+ )^1)
+
+authorhashers.short = function(authors)
+ -- a short is a real dumb hardcodes kind of tag and we only support
+ -- this one because some users might expect it, not because it makes
+ -- sense
+ local n = #authors
+ if n == 0 then
+ return "unk"
+ elseif n == 1 then
+ local surnames = authors[1].surnames
+ if not surnames or #surnames == 0 then
+ return "err"
+ else
+ local s = surnames[1]
+ local c = lpegmatch(p_clean,s)
+ if s ~= c then
+ report_cite("name %a cleaned to %a for short construction",s,c)
+ end
+ return utfsub(c,1,3)
+ end
+ else
+ local t = { }
+ for i=1,n do
+ if i > 3 then
+ t[#t+1] = "+" -- indeed
+ break
+ end
+ local surnames = authors[i].surnames
+ if not surnames or #surnames == 0 then
+ t[#t+1] = "?"
+ else
+ local s = surnames[1]
+ local c = lpegmatch(p_clean,s)
+ if s ~= c then
+ report_cite("name %a cleaned to %a for short construction",s,c)
+ end
+ t[#t+1] = utfsub(c,1,1)
+ end
+ end
+ return concat(t)
+ end
+end
+
collapsers.default = default
-local function writer(key,snippets)
+local function authorwriter(key,index)
if not key then
return ""
end
@@ -514,8 +734,16 @@ local function writer(key,snippets)
local n = #key
if n == 0 then
return ""
+ end
+ if index then
+ if not key[index] then
+ return ""
+ end
elseif n == 1 then
- local author = key[1]
+ index = 1
+ end
+ if index then
+ local author = key[index]
local options = author.options
if options then
for option in next, options do
@@ -525,32 +753,43 @@ local function writer(key,snippets)
end
end
end
- return default(author)
- else
- local t = { }
- local s = 0
- for i=1,n do
- local author = key[i]
- local options = author.options
- s = s + 1
- if options then
- local done = false
- for option in next, options do
- local collapse = collapsers[option]
- if collapse then
- t[s] = collapse(author)
- done = true
- end
- end
- if not done then
- t[s] = default(author)
+ local hash = default(author)
+ -- if trace_hashing then
+ -- report("hash: %s",hash)
+ -- end
+ return hash
+ end
+ local t = { }
+ local s = 0
+ for i=1,n do
+ local author = key[i]
+ local options = author.options
+ s = s + 1
+ if options then
+ local done = false
+ for option in next, options do
+ local collapse = collapsers[option]
+ if collapse then
+ t[s] = collapse(author)
+ done = true
end
- else
+ end
+ if not done then
t[s] = default(author)
end
+ else
+ t[s] = default(author)
end
- return concat(t," & ")
end
+ local hash = concat(t," & ")
+ -- if trace_hashing then
+ -- report("hash: %s",hash)
+ -- end
+ return hash
+end
+
+local function writer(key)
+ return authorwriter(key) -- discard extra arguments in the caller
end
publications.writers .author = writer
@@ -573,13 +812,22 @@ publications.sortmethods.authoryear = {
{ field = "key", default = "", unknown = "" },
{ field = "author", default = "", unknown = "" },
{ field = "year", default = "9998", unknown = "9999" },
- { field = "suffix", default = " ", unknown = " " },
+ -- { field = "suffix", default = " ", unknown = " " },
{ field = "month", default = "13", unknown = "14" },
{ field = "day", default = "32", unknown = "33" },
{ field = "journal", default = "", unknown = "" },
{ field = "volume", default = "", unknown = "" },
- { field = "number", default = "", unknown = "" },
- { field = "title", default = "", unknown = "" },
+ -- { field = "number", default = "", unknown = "" },
{ field = "pages", default = "", unknown = "" },
+ { field = "title", default = "", unknown = "" },
+ { field = "index", default = "", unknown = "" },
},
}
+
+implement {
+ name = "btxremapauthor",
+ arguments = { "string", "string" },
+ actions = function(k,v)
+ publications.authormap[k] = v
+ end
+}