diff options
author | Karl Berry <karl@freefriends.org> | 2018-12-03 22:49:28 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-12-03 22:49:28 +0000 |
commit | 510cc1b8395f714ec6c1b7299cf73371563b1a16 (patch) | |
tree | ef1d3f055e87db8e906501a88ca550b861ac22e2 /Master/texmf-dist/tex/lualatex | |
parent | f855360800d3dd036378f102ca41cf5fa3e87db1 (diff) |
xindex (2dec18)
git-svn-id: svn://tug.org/texlive/trunk@49312 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/lualatex')
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-DIN2.lua | 102 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-HAdW.lua | 231 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-base.lua | 222 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-cfg-common.lua | 29 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-cfg.lua | 89 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-dtk.lua | 157 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-lapp.lua | 325 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-lib.lua | 908 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex-pretty.lua | 254 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/xindex/xindex.sty | 76 |
10 files changed, 2393 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-DIN2.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-DIN2.lua new file mode 100644 index 00000000000..58c33a5e2b8 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-DIN2.lua @@ -0,0 +1,102 @@ +----------------------------------------------------------------------- +-- FILE: xindex-cfg.lua +-- DESCRIPTION: configuration file for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- + +if not modules then modules = { } end modules ['xindex-cfg'] = { + version = 0.05, + comment = "configuration to xindex.lua", + author = "Herbert Voss", + copyright = "Herbert Voss", + license = "LPPL 1.3" +} + +escape_chars = { -- by default " is the escape char + {'""', "\\escapedquote", "\"{}" }, + {'"@', "\\escapedat", "@" }, + {'"|', "\\escapedvert", "|" }, + {'"!', "\\escapedexcl", "!" } +} + +itemPageDelimiter = "," -- Hello, 14 +compressPages = true -- something like 12--15, instaead of 12,13,14,15. the |( ... |) syntax is still valid +fCompress = true -- 3f -> page 3, 4 and 3ff -> page 3, 4, 5 +minCompress = 3 -- 14--17 or +numericPage = true -- for non numerical pagenumbers, like "VI-17" +sublabels = {"", "-\\,", "--\\,", "---\\,"} -- for the (sub(sub(sub-items first one is for item +pageNoPrefixDel = "" -- a delimiter for page numbers like "VI-17" +indexOpening = "" -- commands after \begin{theindex} + + +--[[ + Each character's position in this array-like table determines its 'priority'. + Several characters in the same slot have the same 'priority'. +]] +alphabet_lower = { -- for sorting + { ' ' }, -- only for internal tests + { 'a', 'á', 'à', 'å', 'æ', }, + { 'ae', 'ä'}, + { 'b' }, + { 'c', 'ç' }, + { 'd' }, + { 'e', 'é', 'è', 'ë' }, + { 'f' }, + { 'g' }, + { 'h' }, + { 'i', 'í', 'ì', 'ï' }, + { 'j' }, + { 'k' }, + { 'l' }, + { 'm' }, + { 'n', 'ñ' }, + { 'o', 'ó', 'ò', 'ø', 'œ'}, + { 'oe', 'ö' }, + { 'p' }, + { 'q' }, + { 'r' }, + { 's', 'š', 'ß' }, + { 't' }, + { 'u', 'ú', 'ù' }, + { 'ue', 'ü' }, + { 'v' }, + { 'w' }, + { 'x' }, + { 'y', 'ý', 'ÿ' }, + { 'z', 'ž' } +} +alphabet_upper = { -- for sorting + { ' ' }, + { 'A', 'Á', 'À', 'Å', 'Æ'}, + { 'AE', 'Ä'}, + { 'B' }, + { 'C', 'Ç' }, + { 'D' }, + { 'E', 'È', 'È', 'Ë' }, + { 'F' }, + { 'G' }, + { 'H' }, + { 'I', 'Í', 'Ì', 'Ï' }, + { 'J' }, + { 'K' }, + { 'L' }, + { 'M' }, + { 'N', 'Ñ' }, + { 'O', 'Ó', 'Ò', 'Ø','Œ' }, + { 'OE', 'Ö' }, + { 'P' }, + { 'Q' }, + { 'R' }, + { 'S', 'Š' }, + { 'T' }, + { 'U', 'Ú', 'Ù' }, + { 'UE', 'Ü' }, + { 'V' }, + { 'W' }, + { 'X' }, + { 'Y', 'Ý', 'Ÿ' }, + { 'Z', 'Ž' } +} + diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-HAdW.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-HAdW.lua new file mode 100644 index 00000000000..a45bd744332 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-HAdW.lua @@ -0,0 +1,231 @@ +----------------------------------------------------------------------- +-- FILE: xindex-HAdW.lua +-- DESCRIPTION: configuration file for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- +-- +-- configuration for index files of the Heidelberger Akademie der Wissenschaften + +if not modules then modules = { } end modules ['xindex-HAdW'] = { + version = 0.05, + comment = "configuration to xindex.lua", + author = "Herbert Voss", + copyright = "Herbert Voss", + license = "LPPL 1.3" +} + +--local version = "0.01" + +itemPageDelimiter = "," -- Hello, 14 +compressPages = true -- something like 12--15, instaead of 12,13,14,15. the |( ... |) syntax is still valid +fCompress = true -- 3f -> page 3, 4 and 3ff -> page 3, 4, 5 +minCompress = 3 -- 14--17 or +numericPage = false -- for non numerical pagenumbers, like "VI-17" +sublabels = {"", "-\\,", "--\\,", "---\\,"} -- for the (sub(sub(sub-items first one is for item +pageNoPrefixDel = "" -- a delimiter for page numbers like "VI-17" +indexOpening = "" -- commands after \begin{theindex} + + + +--[[ + Each character's position in this array-like table determines its 'priority'. + Several characters in the same slot have the same 'priority'. +]] +alphabet_lower = { -- for sorting + { ' ' }, -- only for internal tests + { 'a', 'á', 'à', 'ä'}, + { 'b' }, + { 'c' }, + { 'd' }, + { 'e', 'é', 'è', 'ë' }, + { 'f' }, + { 'g' }, + { 'h' }, + { 'i', 'í', 'ì', 'ï' }, + { 'j' }, + { 'k' }, + { 'l' }, + { 'm' }, + { 'n', 'ñ' }, + { 'o', 'ó', 'ò', 'ö' }, + { 'p' }, + { 'q' }, + { 'r' }, + { 's' }, + { 't' }, + { 'u', 'ú', 'ù', 'ü' }, + { 'v' }, + { 'w' }, + { 'x' }, + { 'y' }, + { 'z' } +} +alphabet_upper = { -- for sorting + { ' ' }, + { 'A', 'Á', 'À', 'Ä'}, + { 'B' }, + { 'C' }, + { 'D' }, + { 'E', 'È', 'È', 'ë' }, + { 'F' }, + { 'G' }, + { 'H' }, + { 'I', 'Í', 'Ì', 'ï' }, + { 'J' }, + { 'K' }, + { 'L' }, + { 'M' }, + { 'N', 'Ñ' }, + { 'O', 'Ó', 'Ò', 'Ö' }, + { 'P' }, + { 'Q' }, + { 'R' }, + { 'S' }, + { 'T' }, + { 'U', 'Ú', 'Ù', 'Ü' }, + { 'V' }, + { 'W' }, + { 'X' }, + { 'Y' }, + { 'Z' } +} + + +--\indexentry{Ackers, Carolus}{VII/1-715} +--\indexentry{Bremen!Adalbert I. von, Erzbischof}{VII/2/1-948} +--\indexentry{Bremen!Adalbert I. von, Erzbischof}{VII/1-50} + +function specialCompressPageList(pages) + if (#pages <= 1) or (pages[1]["number"] == "") then + pages[1]["number"] = pages[1]["number"]:gsub('-',' ') + return pages + end -- only one pageno +--[[ +modify pagelist +sortPages = {{ origin = { number=VII/1-715, special="" }, + sort = 07/1-00715 }, + {...} + } +]] + local sortPages = {} + local roman + local volume + local page + local i + for i=1,#pages do + roman = string.gsub(pages[i]["number"],'%U*','') -- only uppercase to catch VII123f (folium pages) + roman = string.format("%03d",tonumber(romanToNumber(roman))) + volume = string.gsub(pages[i]["number"],'%a*','') + if volume then volume = volume:gsub('-%d*','') end + page = string.gsub(pages[i]["number"],'.*-','') + page = string.format("%5s",page) +--print(roman..volume.." "..page) + sortPages[#sortPages+1] = { + origin = pages[i], + sort = roman..volume.." "..page } -- no minus between Roman/Volume and first page + end +-- sort the page list + table.sort(sortPages, function(a,b) return a["sort"] < b["sort"] end ) + local Pages = {} + for i=1,#sortPages do -- use the sorted origin table + Pages[#Pages+1] = sortPages[i]["origin"] + end +-- writeLog(1,print(getRawPagesP(Pages)),2) +-- test if two or more pages in the list + if #Pages == 2 then -- only two pages + local page1 = string.gsub(Pages[1]["number"],'%A*','') -- get prefix1 + local page2 = string.gsub(Pages[2]["number"],'%A*','') -- ger prefix2 + if page1 == page2 then -- same prefix + page1 = string.gsub(Pages[1]["number"],'.*-','') -- get page1 + page2 = string.gsub(Pages[2]["number"],'.*-','') -- get page2 + if (page2-page1) == 1 then -- pagediff = 1 + Pages[1]["number"] = Pages[1]["number"].."f" + Pages[2] = nil -- remove second page + return Pages + else -- page difference > 1 + pages[1]["number"] = pages[1]["number"]:gsub('-',' ') + Pages[2]["number"] = string.gsub(Pages[2]["number"],'.*-','') -- use only number -> same prefix + return Pages -- Pages[1] is the same + end + else + pages[1]["number"] = pages[1]["number"]:gsub('-',' ') + pages[2]["number"] = pages[2]["number"]:gsub('-',' ') + return Pages -- different prefix -> simple return of the two pages + end + else -- more than two pages + local prefixList = {} + local lastPrefix = "" + local currentPrefix + for i=1,#Pages do -- create the list of different prefixes, eg {VI, VI/2/1, VI/2/2} + currentPrefix, j = string.gsub(Pages[i]["number"],'-.*','') + if currentPrefix ~= lastPrefix then + prefixList[#prefixList+1] = currentPrefix + lastPrefix = currentPrefix + end + end + pages = {} + for j = 1,#prefixList do + lastPrefix = prefixList[j] + i = 1 + local subPageList = {} + while (i <= #Pages) do + currentPrefix, _ = string.gsub(Pages[i]["number"],'-.*','') + if (lastPrefix == currentPrefix) then + subPageList[#subPageList+1] = { number = string.gsub(Pages[i]["number"],'.*-',''), special = Pages[i]["special"] } + end + i = i +1 + end + sortPages = compressPageList(subPageList) + -- no minus between Roman/Volume and first page + pages[#pages+1] = { number = lastPrefix.." "..sortPages[1]["number"], special = sortPages[1]["special"] } + for i=2,#sortPages do + pages[#pages+1] = sortPages[i] + end + end + return pages + end +end + +function replaceRoman(r) + local i = romanToNumber(r) + if i then return "//"..string.format("%03d",i).."//" + else return r + end +end + +function SORTprehook(data) -- replace roman with algebraic, eg Karl IX -> Karl // 9// +-- writeLog(1,require 'xindex-pretty'.dump(data),0) -- only for internal dump + local entry + local elements = {} + for i=1,#data do + entry = data[i]["Entry"] + elements = entry:split() + local number = romanToNumber(elements[#elements]) + if number then + local strNr = string.format("%03d",tostring(number)) + elements[#elements] = "//"..strNr.."//" + entry = "" + for j=1,#elements do entry=entry.." "..elements[j] end + else + entry:gsub("!(.-)%p",replaceRoman) + end + data[i]["Entry"] = entry + end + return data +end + +function SORTposthook(data) -- the other way round as prehook + local entry + local elements = {} + for i=1,#data do + entry = data[i]["Entry"] + if entry:find("//") then + data[i]["Entry"] = entry:gsub("//(.-)//",numberToRoman) + end + end + return data +end + + diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-base.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-base.lua new file mode 100644 index 00000000000..e8ba4a4b827 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-base.lua @@ -0,0 +1,222 @@ +----------------------------------------------------------------------- +-- FILE: xindex-base.lua +-- DESCRIPTION: base file for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- + +local info = { version = 0.05} + +-- check config +if pageNoPrefixDel ~= "" then +-- numericPage = false + pageNoPrefixPattern = "^.*"..pageNoPrefixDel +end + +writeLog(2,"Read Data from file "..inFile.." ... \n",0) +local lines = read_lines_from(inFile) +writeLog(2,#lines.." lines of data read\n",0) + +if vlevel > 1 then + writeLog(1,"--------------- Input data -----------------\n",2) + for _,l in pairs(lines) do writeLog(1,l.."\n",2) end + writeLog(1,"--------------- end Input data -----------------\n",2) +end + +local Index = {} -- Entry = "Seitenzahl(en)" +local pages = {} +local noEntryfound +local noPagefound + +hyperpage, lines = checkHyperpage(lines) -- hyperref used? +if hyperpage then writeLog(1,"We have hyperpages ... \n",1) end + +--for _,l in pairs(lines) do print (l) end + +writeLog(1,"Change escape chars with macros ... \n",0) +for k,v in pairs(lines) do + if not commandEntry(v) then + for i, str0 in ipairs(escape_chars) do + v = v:gsub(str0[1],str0[2]) + end + if k < #lines then + if commandEntry(lines[k+1]) then -- is the next line not a \indexentry ? + Index = getEntryAndPage(v,lines[k+1],Index)-- read two lines + else + Index = getEntryAndPage(v,"",Index)-- current line + end + else + Index = getEntryAndPage(v,"",Index)-- current line + end + end +end + +writeLog(1,"... done\n",0) +writeLog(1,"------------------ Start list after getEntryAndPage() ------------------------\n,",2) +printList(Index,2) +writeLog(1,"\n------------------ end list after getEntryAndPage() ------------------------\n",2) +writeLog(2,"Sorting entries: for LARGE idx files it can take some minutes ... \n",0) + +if SORTprehook then Index = SORTprehook(Index) end +k = 0 +table.sort(Index,UTFCompare) +if SORTposthook then Index = SORTposthook(Index) end + +writeLog(1,"------------------ Start list after table.sort(Index,UTFCompare)------------\n",2) +printList(Index,2) +writeLog(1,require 'xindex-pretty'.dump(Index),3) -- only for internal dump +writeLog(1,"\n------------------ end list after table.sort(Index,UTFCompare)------------\n",2) + +writeLog(1,"\n",0) +writeLog(2,"\ncheck for |(...|) \n",0) +writeLog(1,"------------------ Start list before checkParenthesis(Index)------------\n",2) +writeLog(1,require 'xindex-pretty'.dump(Index),3) -- only for internal dump +--for i=1,#Index do print(Index[i]["Entry"],Index[i]["pages"][1]["number"],Index[i]["pages"][1]["special"]) end + +Index = checkParenthesis(Index) + +writeLog(1,"\n",0) + +--for i=1,#Index do print(Index[i]["Entry"],Index[i]["pages"][1]["number"],Index[i]["pages"][1]["special"]) end +writeLog(1,require 'xindex-pretty'.dump(Index),3) -- only for internal dump +printList(Index,2) +writeLog(1,"------------------ End list after checkParenthesis(Index) ------------\n",2) +writeLog(2,"done\n",0) + + + +writeLog(2,"Replace @-operator ...\n",0) +writeLog(1,"------------------ Start list before compressEntryList(Index)------------\n",1) +writeLog(1,require 'xindex-pretty'.dump(Index),3) -- only for internal dump + +local NewIndex = {} +NewIndex = compressEntryList(Index) -- replaces also foo@bar -> bar + +-- for i=1,#NewIndex do print(NewIndex[i]["Entry"],NewIndex[i]["pages"][1]["number"],NewIndex[i]["pages"][1]["special"]) end +writeLog(1,require 'xindex-pretty'.dump(NewIndex),3) -- only for internal dump +printList(NewIndex,2) +writeLog(1,"------------------ End list after compressEntryList(Index)------------\n",1) +writeLog(2,"done\n",0) + +-- output the .ind-list +--[[ +for i, str0 in ipairs(escape_chars) do + outFile:write("\\def"..str0[2].."{"..str0[3].."}\n") +end +]] -- no more needed, we redo the setting + + +outFile:write("\n") +outFile:write("\\begin{theindex}\n") + +if indexOpening ~= "" then -- commands after \begin{theindex} + outFile:write(indexOpening) +end + +local entry +local firstCLine = true +local firstNLine = true +local firstSLine = true +local firstChar +local symbols = true +local numbers = false +local letters = false +local charType +local currentChar +local currentCharType = 0 -- assume Symbol; 1 number; 2 letter +local oldChar = "" +local excl = 0 -- number of ! symbols in one entry +local lastItems = {"","",""} + +writeLog(2,"Start writing .ind file ... \n",0) + +-- first the special cases for symbols and numbers: + +writeLog(1,"---------- Start list to write the ind file --------------\n",1) +writeLog(1,require 'xindex-pretty'.dump(NewIndex),3) -- only for internal dump +for k=1,#NewIndex do +-- require 'xindex-pretty'.dump(NewIndex[k]) -- only for internal dump + if NewIndex[k]["Entry"] then + local v = NewIndex[k] + writeLog(1," NewIndex[k]: "..v["Entry"].."\n",2) + writeLog(1,require 'xindex-pretty'.dump(v),3) -- only for internal dump + entry = v["Entry"] + writeLog(1,"\nBase start: "..entry.."\n",2) +-- local c = utf.sub(v["sortChar"],1,1) +-- if utf8.codepoint(c) < 12288 then -- Japanese starts at hex 3000 +-- firstChar = v["sortChar"] +-- else + firstChar = utf.sub(v["sortChar"],1,1) -- catch a translatet Ö->OE +-- end + currentChar = firstChar + charType = getCharType(firstChar) + if charType == 0 then + numbers = false + symbols = true + end + if charType == 1 then + numbers = true + symbols = false + end + if charType > 1 then + numbers = false + symbols = false + letters = true + end + if symbols then + writeLog(1,"We have symbols to print ...\n",3) + if firstSLine then + firstSLine = false + if not no_headings then + outFile:write("\\textbf{"..index_header[1].."}\n\\nopagebreak[4]\n") + end + end + if specialItemOutput then + lastItems = specialItemOutput(lastItems, v, hyperpage) + else + lastItems = itemOutput(lastItems, v, hyperpage) + end + else + writeLog(1,"We have no symbols to print ...\n",3) + end + if numbers then + writeLog(1,"We have numbers to print ...\n",3) + if firstNLine then + firstNLine = false + outFile:write("\n\\indexspace\n") + if not no_headings then + outFile:write("\\textbf{"..index_header[2].."}\n\\nopagebreak[4]\n") + end + end + if specialItemOutput then + lastItems = specialItemOutput(lastItems, v, hyperpage) + else + lastItems = itemOutput(lastItems, v, hyperpage) + end + else + writeLog(1,"We have no numbers to print ...\n",3) + end + if letters then + writeLog(1,"We have letters to print ...\n",3) + if (currentChar ~= oldChar) and (charType == 2) then + outFile:write("\n\\indexspace\n") + if not no_headings then + outFile:write("\\textbf{"..currentChar.."}\n\\nopagebreak[4]\n") + end + oldChar = currentChar + end + if specialItemOutput then + lastItems = specialItemOutput(lastItems, v, hyperpage) + else + lastItems = itemOutput(lastItems, v, hyperpage) + end + end + if v["Macro"] then outFile:write(v["Macro"].."\n") end + end +end +outFile:write("\\end{theindex}\n") +outFile:close() + +writeLog(2,"\ndone! closing program\n",0) + diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-cfg-common.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-cfg-common.lua new file mode 100644 index 00000000000..8237dd5022e --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-cfg-common.lua @@ -0,0 +1,29 @@ +----------------------------------------------------------------------- +-- FILE: xindex-cfg-common.lua +-- DESCRIPTION: configuration file for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- + +if not modules then modules = { } end modules ['xindex-cfg-common'] = { + version = 0.05, + comment = "configuration to xindex.lua", + author = "Herbert Voss", + copyright = "Herbert Voss", + license = "LPPL 1.3" +} + +indexheader = { + de = {"Symbole", "Zahlen"}, + en = {"Symbols", "Numbers"}, + fr = {"Symboles","Chiffre"}, + jp = {"シンボル","番号"}, +} + +folium = { + de = {"f", "ff"}, + en = {"f", "ff"}, + fr = {"\\,sq","\\,sqq"}, +} + diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-cfg.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-cfg.lua new file mode 100644 index 00000000000..f4d726bd039 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-cfg.lua @@ -0,0 +1,89 @@ +----------------------------------------------------------------------- +-- FILE: xindex-cfg.lua +-- DESCRIPTION: configuration file for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- + +if not modules then modules = { } end modules ['xindex-cfg'] = { + version = 0.05, + comment = "main configuration to xindex.lua", + author = "Herbert Voss", + copyright = "Herbert Voss", + license = "LPPL 1.3" +} + +itemPageDelimiter = "," -- Hello, 14 +compressPages = true -- something like 12--15, instaead of 12,13,14,15. the |( ... |) syntax is still valid +fCompress = true -- 3f -> page 3, 4 and 3ff -> page 3, 4, 5 +minCompress = 3 -- 14--17 or +numericPage = true -- for non numerical pagenumbers, like "VI-17" +sublabels = {"", "-\\,", "--\\,", "---\\,"} -- for the (sub(sub(sub-items first one is for item +pageNoPrefixDel = "" -- a delimiter for page numbers like "VI-17" -- not used !!! +indexOpening = "" -- commands after \begin{theindex} + + +--[[ + Each character's position in this array-like table determines its 'priority'. + Several characters in the same slot have the same 'priority'. +]] +alphabet_lower = { -- for sorting + { ' ' }, -- only for internal tests + { 'a', 'á', 'à', 'ä', 'å', 'æ', }, + { 'b' }, + { 'c', 'ç' }, + { 'd' }, + { 'e', 'é', 'è', 'ë' }, + { 'f' }, + { 'g' }, + { 'h' }, + { 'i', 'í', 'ì', 'ï' }, + { 'j' }, + { 'k' }, + { 'l' }, + { 'm' }, + { 'n', 'ñ' }, + { 'o', 'ó', 'ò', 'ö', 'ø', 'œ'}, + { 'p' }, + { 'q' }, + { 'r' }, + { 's', 'š', 'ß' }, + { 't' }, + { 'u', 'ú', 'ù', 'ü' }, + { 'v' }, + { 'w' }, + { 'x' }, + { 'y', 'ý', 'ÿ' }, + { 'z', 'ž' } +} +alphabet_upper = { -- for sorting + { ' ' }, + { 'A', 'Á', 'À', 'Ä', 'Å', 'Æ'}, + { 'B' }, + { 'C', 'Ç' }, + { 'D' }, + { 'E', 'È', 'È', 'Ë' }, + { 'F' }, + { 'G' }, + { 'H' }, + { 'I', 'Í', 'Ì', 'Ï' }, + { 'J' }, + { 'K' }, + { 'L' }, + { 'M' }, + { 'N', 'Ñ' }, + { 'O', 'Ó', 'Ò', 'Ö', 'Ø','Œ' }, + { 'P' }, + { 'Q' }, + { 'R' }, + { 'S', 'Š' }, + { 'T' }, + { 'U', 'Ú', 'Ù', 'Ü' }, + { 'V' }, + { 'W' }, + { 'X' }, + { 'Y', 'Ý', 'Ÿ' }, + { 'Z', 'Ž' } +} + diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-dtk.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-dtk.lua new file mode 100644 index 00000000000..0104f37cece --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-dtk.lua @@ -0,0 +1,157 @@ +----------------------------------------------------------------------- +-- FILE: xindex-cfg.lua +-- DESCRIPTION: configuration file for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- + +if not modules then modules = { } end modules ['xindex-cfg'] = { + version = 0.05, + comment = "DTK configuration to xindex.lua", + author = "Herbert Voss", + copyright = "Herbert Voss", + license = "LPPL 1.3" +} + +itemPageDelimiter = "" -- Hello, 14 +compressPages = true -- something like 12--15, instaead of 12,13,14,15. the |( ... |) syntax is still valid +fCompress = true -- 3f -> page 3, 4 and 3ff -> page 3, 4, 5 +minCompress = 3 -- 14--17 or +numericPage = true -- for non numerical pagenumbers, like "VI-17" +sublabels = {"","","",""} -- for the sub(sub(sub-items +pageNoPrefixDel = "" -- a delimiter for page numbers like "VI-17" -- not used !!! +indexOpening = "" --[[\providecommand*\lettergroupDefault[1]{} +\providecommand*\lettergroup[1]{% + \par\textbf{#1}\par + \nopagebreak + } +]] + + +--[[ + Each character's position in this array-like table determines its 'priority'. + Several characters in the same slot have the same 'priority'. +]] +alphabet_lower = { -- for sorting + { ' ' }, -- only for internal tests + { 'a', 'á', 'à', 'ä'}, + { 'b' }, + { 'c' }, + { 'd' }, + { 'e', 'é', 'è', 'ë' }, + { 'f' }, + { 'g' }, + { 'h' }, + { 'i', 'í', 'ì', 'ï' }, + { 'j' }, + { 'k' }, + { 'l' }, + { 'm' }, + { 'n', 'ñ' }, + { 'o', 'ó', 'ò', 'ö' }, + { 'p' }, + { 'q' }, + { 'r' }, + { 's' }, + { 't' }, + { 'u', 'ú', 'ù', 'ü' }, + { 'v' }, + { 'w' }, + { 'x' }, + { 'y' }, + { 'z' } +} +alphabet_upper = { -- for sorting + { ' ' }, + { 'A', 'Á', 'À', 'Ä'}, + { 'B' }, + { 'C' }, + { 'D' }, + { 'E', 'È', 'È', 'ë' }, + { 'F' }, + { 'G' }, + { 'H' }, + { 'I', 'Í', 'Ì', 'ï' }, + { 'J' }, + { 'K' }, + { 'L' }, + { 'M' }, + { 'N', 'Ñ' }, + { 'O', 'Ó', 'Ò', 'Ö' }, + { 'P' }, + { 'Q' }, + { 'R' }, + { 'S' }, + { 'T' }, + { 'U', 'Ú', 'Ù', 'Ü' }, + { 'V' }, + { 'W' }, + { 'X' }, + { 'Y' }, + { 'Z' } +} + + +function specialGetPageList(v,hyperpage) + local Pages = {} + if v["pages"] then + table.sort(v["pages"],pageCompare)-- nur nötig, da User manuell eine Zeile einfügen kann + if specialCompressPageList then + Pages = specialCompressPageList(v["pages"]) + else + Pages = compressPageList(v["pages"]) + end + local pageNo + if hyperpage then + if string.find(v["pages"][1]["special"],"hyperindexformat") then + pageNo = v["pages"][1]["special"].."{"..checkFF(Pages[1]["number"].."}") + else + pageNo = "\\hyperpage{"..checkFF(Pages[1]["number"]).."}" + end + for i=2,#Pages do + if string.find(v["pages"][i]["special"],"hyperindexformat") then + pageNo = pageNo..", "..v["pages"][i]["special"].."{"..checkFF(Pages[i]["number"].."}") + else + pageNo = pageNo..", \\hyperpage{"..checkFF(Pages[i]["number"]).."}" + end +-- Pages[i] = nil + end + else + if args_v then print("getPageList: "..tostring(Pages[1]["special"])..tostring(Pages[1]["number"])) end + if (Pages[1]["special"] == nil) or (Pages[1]["number"] == nil) then return "" end + if #Pages == 1 then + return "\\relax "..Pages[1]["number"].."\\@nil" + else + pageNo = "\\relax "..Pages[1]["number"] + for i=2,#Pages do + if Pages[i]["number"] then + pageNo = pageNo..", "..Pages[i]["number"] + Pages[i] = {} + end + end + pageNo = pageNo.."\\@nil" -- add \@nil + end + return pageNo + end + else + return "" + end +end + +function specialItemOutput(last, v, hyperpage) + local lastItems = last + local currentItems = {} + local Entry = v["Entry"] + local name = getItem(Entry,0) + local adress = getItem(Entry,1) + outFile:write(" \\item "..name..itemPageDelimiter.."\n") + str = " \\subitem "..itemPageDelimiter.." "..adress..getPageList(v,hyperpage).."\n" + for i, str0 in ipairs(escape_chars) do -- undo the escape char setting + str = str:gsub(str0[2],str0[3]) + end + outFile:write(str) + return last +end + + diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-lapp.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-lapp.lua new file mode 100644 index 00000000000..d0e01e634e6 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-lapp.lua @@ -0,0 +1,325 @@ +-- lapp.lua +-- Simple command-line parsing using human-readable specification +----------------------------- +--~ -- args.lua +--~ local args = require ('lapp') [[ +--~ Testing parameter handling +--~ -p Plain flag (defaults to false) +--~ -q,--quiet Plain flag with GNU-style optional long name +--~ -o (string) Required string option +--~ -n (number) Required number option +--~ -s (default 1.0) Option that takes a number, but will default +--~ <start> (number) Required number argument +--~ <input> (default stdin) A parameter which is an input file +--~ <output> (default stdout) One that is an output file +--~ ]] +--~ for k,v in pairs(args) do +--~ print(k,v) +--~ end +------------------------------- +--~ > args -pq -o help -n 2 2.3 +--~ input file (781C1B78) +--~ p true +--~ s 1 +--~ output file (781C1B98) +--~ quiet true +--~ start 2.3 +--~ o help +--~ n 2 +-------------------------------- +if not modules then modules = { } end modules ['xindex-lapp'] = { + version = 0.05, + comment = "read parameter for xindex.lua", + author = "Steve Donovan", + copyright = "Steve Donovan", + license = "MIT" +} + + +lapp = {} + +local append = table.insert +local usage +local open_files = {} +local parms = {} +local aliases = {} +local parmlist = {} + +local filetypes = { + stdin = {io.stdin,'file-in'}, stdout = {io.stdout,'file-out'}, + stderr = {io.stderr,'file-out'} +} + +local function quit(msg,no_usage) + if msg then + io.stderr:write(msg..'\n\n') + end + if not no_usage then + io.stderr:write(usage) + end + os.exit(1); +end + +local function error(msg,no_usage) + quit(arg[0]:gsub('.+[\\/]','')..':'..msg,no_usage) +end + +local function ltrim(line) + return line:gsub('^%s*','') +end + +local function rtrim(line) + return line:gsub('%s*$','') +end + +local function trim(s) + return ltrim(rtrim(s)) +end + +local function open (file,opt) + local val,err = io.open(file,opt) + if not val then error(err,true) end + append(open_files,val) + return val +end + +local function xassert(condn,msg) + if not condn then + error(msg) + end +end + +local function range_check(x,min,max,parm) + xassert(min <= x and max >= x,parm..' out of range') +end + +local function xtonumber(s) + local val = tonumber(s) + if not val then error("unable to convert to number: "..s) end + return val +end + +local function is_filetype(type) + return type == 'file-in' or type == 'file-out' +end + +local types = {} + +local function convert_parameter(ps,val) + if ps.converter then + val = ps.converter(val) + end + if ps.type == 'number' then + val = xtonumber(val) + elseif is_filetype(ps.type) then + val = open(val,(ps.type == 'file-in' and 'r') or 'w' ) + elseif ps.type == 'boolean' then + val = true + end + if ps.constraint then + ps.constraint(val) + end + return val +end + +function lapp.add_type (name,converter,constraint) + types[name] = {converter=converter,constraint=constraint} +end + +local function force_short(short) + xassert(#short==1,short..": short parameters should be one character") +end + +function process_options_string(str) + local res = {} + local varargs + + local function check_varargs(s) + local res,cnt = s:gsub('%.%.%.$','') + varargs = cnt > 0 + return res + end + + local function set_result(ps,parm,val) + if not ps.varargs then + res[parm] = val + else + if not res[parm] then + res[parm] = { val } + else + append(res[parm],val) + end + end + end + + usage = str + + for line in str:gmatch('([^\n]*)\n') do + local optspec,optparm,i1,i2,defval,vtype,constraint + line = ltrim(line) + -- flags: either -<short> or -<short>,<long> + i1,i2,optspec = line:find('^%-(%S+)') + if i1 then + optspec = check_varargs(optspec) + local short,long = optspec:match('([^,]+),(.+)') + if short then + optparm = long:sub(3) + aliases[short] = optparm + force_short(short) + else + optparm = optspec + force_short(optparm) + end + else -- is it <parameter_name>? + i1,i2,optparm = line:find('(%b<>)') + if i1 then + -- so <input file...> becomes input_file ... + optparm = check_varargs(optparm:sub(2,-2)):gsub('%A','_') + append(parmlist,optparm) + end + end + if i1 then -- this is not a pure doc line + local last_i2 = i2 + local sval + line = ltrim(line:sub(i2+1)) + -- do we have (default <val>) or (<type>)? + i1,i2,typespec = line:find('^%s*(%b())') + if i1 then + typespec = trim(typespec:sub(2,-2)) -- trim the parens and any space + sval = typespec:match('default%s+(.+)') + if sval then + local val = tonumber(sval) + if val then -- we have a number! + defval = val + vtype = 'number' + elseif filetypes[sval] then + local ft = filetypes[sval] + defval = ft[1] + vtype = ft[2] + else + defval = sval + vtype = 'string' + end + else + local min,max = typespec:match '([^%.]+)%.%.(.+)' + if min then -- it's (min..max) + vtype = 'number' + min = xtonumber(min) + max = xtonumber(max) + constraint = function(x) + range_check(x,min,max,optparm) + end + else -- () just contains type of required parameter + vtype = typespec + end + end + else -- must be a plain flag, no extra parameter required + defval = false + vtype = 'boolean' + end + local ps = { + type = vtype, + defval = defval, + required = defval == nil, + comment = line:sub((i2 or last_i2)+1) or optparm, + constraint = constraint, + varargs = varargs + } + if types[vtype] then + local converter = types[vtype].converter + if type(converter) == 'string' then + ps.type = converter + else + ps.converter = converter + end + ps.constraint = types[vtype].constraint + end + parms[optparm] = ps + end + end + -- cool, we have our parms, let's parse the command line args + local iparm = 1 + local iextra = 1 + local i = 1 + local parm,ps,val + while i <= #arg do + -- look for a flag, -<short flags> or --<long flag> + local i1,i2,dash,parmstr = arg[i]:find('^(%-+)(%a.*)') + if i1 then -- we have a flag + if #dash == 2 then -- long option + parm = parmstr + else -- short option + if #parmstr == 1 then + parm = parmstr + else -- multiple flags after a '-',? + parm = parmstr:sub(1,1) + if parmstr:find('^%a%d+') then + -- a short option followed by a digit? (exception for AW ;)) + -- push ahead into the arg array + table.insert(arg,i+1,parmstr:sub(2)) + else + -- push multiple flags into the arg array! + for k = 2,#parmstr do + table.insert(arg,i+k-1,'-'..parmstr:sub(k,k)) + end + end + end + end + if parm == 'h' or parm == 'help' then + quit() + end + if aliases[parm] then parm = aliases[parm] end + ps = parms[parm] + if not ps then error("unrecognized parameter: "..parm) end + if ps.type ~= 'boolean' then -- we need a value! This should follow + val = arg[i+1] + i = i + 1 + xassert(val,parm.." was expecting a value") + end + else -- a parameter + parm = parmlist[iparm] + if not parm then + -- extra unnamed parameters are indexed starting at 1 + parm = iextra + iextra = iextra + 1 + ps = { type = 'string' } + else + ps = parms[parm] + end + if not ps.varargs then + iparm = iparm + 1 + end + val = arg[i] + end + ps.used = true + val = convert_parameter(ps,val) + set_result(ps,parm,val) + if is_filetype(ps.type) then + set_result(ps,parm..'_name',arg[i]) + end + if lapp.callback then + lapp.callback(parm,arg[i],res) + end + i = i + 1 + end + -- check unused parms, set defaults and check if any required parameters were missed + for parm,ps in pairs(parms) do + if not ps.used then + if ps.required then error("missing required parameter: "..parm) end + set_result(ps,parm,ps.defval) + end + end + return res +end + +setmetatable(lapp, { + __call = function(tbl,str) return process_options_string(str) end, + __index = { + open = open, + quit = quit, + error = error, + assert = xassert, + } +}) + +return lapp diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-lib.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-lib.lua new file mode 100644 index 00000000000..f570771776d --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-lib.lua @@ -0,0 +1,908 @@ +----------------------------------------------------------------------- +-- FILE: xindex-lib.lua +-- DESCRIPTION: library for xindex.lua +-- REQUIREMENTS: +-- AUTHOR: Herbert Voß +-- LICENSE: LPPL1.3 +----------------------------------------------------------------------- + +if not modules then modules = { } end modules ['xindex-lib'] = { + version = 0.05, + comment = "main library to xindex.lua", + author = "Herbert Voss", + copyright = "Herbert Voss", + license = "LPPL 1.3" +} + +local escapechar1 = "\"" +local escapechar2 = "\"\"" +local Letters = "ÄÖÜäöüabcdefghijklmnopqrstuvwxyzßABCDEFGHIJKLMNOPQRSTUVWXYZ" +local Digits = "0123456789" + +-- Looks up the character `character´ in the alphabet and returns its 'normalization' for sorting +local function get_normalized_char( CharList, character ) + for i, alphabet_entry in ipairs(CharList) do + for _, alphabet_char in ipairs(alphabet_entry) do + if character == alphabet_char then + return alphabet_entry[1] + end + end + end + return character +end + +function Lower(strOrig) -- return UTF string.lower + local str = "" + for i=1, utf.len(strOrig) do + local c = utf.sub(strOrig,i,i) + if c == "Ä" then str = str.."ä" + elseif c == "Ö" then str = str.."ö" + elseif c == "Ü" then str = str.."ü" + else str = str..utf.lower(c) + end + end + return str +end + +function NormalizedLower(strOrig) -- return normalized UTF string.lower (ä -> a) + local str = "" + for i=1, utf.len(strOrig) do + local c = get_normalized_char(alphabet_lower,utf.sub(strOrig,i,i)) + str = str..string.lower(c) + end + return str +end + +function NormalizedUpper(strOrig) -- return normalized UTF string.upper (ä -> A) + local str = "" + for i=1, utf.len(strOrig) do + local c = get_normalized_char(alphabet_lower,utf.sub(strOrig,i,i)) + str = str..string.upper(c) + end + strOrig = str + str = "" + for i=1, utf.len(strOrig) do + local c = get_normalized_char(alphabet_upper,utf.sub(strOrig,i,i)) + str = str..string.upper(c) + end + return str +end + +function checkVert(str) -- get the | part + local vert = string.find(str,"|",1,true) + if (vert) then + vertStr = string.sub(str,vert+1) + str = string.sub(str,1,vert-1) + return (vertStr) + else + return ("") + end +end + +function checkEntry(str) -- get the index entry name + local at=string.find(str,"@") + local excl=string.find(str,"!") + if (excl and at) then + if (at < excl) then + return string.sub(str,1,at-1) + else + return string.sub(str,1,excl-1) + end + elseif (excl) then + return string.sub(str,1,excl-1) + elseif (at) then + return string.sub(str,1,at-1) + else + return (str) + end +end + +function replaceAt(str) -- return "bar" from "foo@bar" +-- return str:gsub('[^!|@%s]+@', '') + return str:gsub('[^!|@]+@', '') +end + +function dofile(filename) + local file = kpse.find_file(filename) + local f = assert(loadfile(file)) + return f() +end + +-- see if the file exists +function file_exists(file) +local f = io.open(file, "rb") +if f then f:close() end +return f ~= nil +end + +-- get all lines from a file, returns an empty +-- list/table if the file does not exist +function read_lines_from(infile) + if not file_exists(infile) then return {} end + local lines = {} + local str + local c + for line in io.lines(infile) do + if line ~= "" then + if string.find(line,'\\indexentry',1,true) then + str = line:gsub('^\\%a+%s*{','{') -- remove "\\indexentry " + writeLog(1,"read_lines: str="..str.." ("..utf.sub(str,2,2)..")\n",2) + if getCharType(utf.sub(str,2,2)) == 0 then -- we have a symbol + lines[#lines + 1] = str:gsub('^{*','{ ') -- add a space before the symbol + else + lines[#lines + 1] = str + end + else + lines[#lines + 1] = "\\MACRO<<< "..line -- allow macros between entries + end + end + end + return lines +end + +function array_concat(...) + local t = {} + for n = 1,select("#",...) do + local arg = select(n,...) + if type(arg)=="table" then + for _,v in ipairs(arg) do + t[#t+1] = v + end + else + t[#t+1] = arg + end + end + return t +end + +function findSequences(a) -- look for 1,2,3,4, ... + local b = {} + local firstPage = a[1] -- first page in the sequence + for i=2,#a do -- next page until end of page list + if a[i]-a[i-1] > 1 then -- not next page + lastPage = a[i-1] -- new start for a sequence search + if lastPage - firstPage >= minCompress then -- sequence found + b[#b+1]= tostring(firstPage).."--"..tostring(lastPage) + else + b[#b+1]= firstPage + if (firstPage ~= lastPage) then b[#b+1]= lastPage end + end + firstPage=a[i] + end + end + if a[#a] - firstPage > 2 then -- test file end + b[#b+1]= tostring(firstPage).."--"..tostring(a[#a]) + else + b[#b+1]= firstPage + if (firstPage ~= a[#a]) then b[#b+1]= a[#a] end + end + return (b) +end + + +function deleteOpenClose(v) -- remove |( and/or |) + res, _ = string.gsub(v:gsub('\\[()]%s*$', ''), '\\[()]%s*', ' \\') + return res +end + +-- "\) " -> "" +-- "\)foo" -> \foo + +function checkParenthesis(Entries) -- search for |( ... |) entries + local paraOpen + local paraClose + local firstPage = 0 + local lastPage + local newEntries = {} + for k,v in pairs(Entries) do + if (k % 50) == 0 then writeLog(1,".",1) end + if v["Entry"] then + v["Entry"] = replaceAt(v["Entry"]) -- foo@bar!baz@foobar -> bar!foobar + CurrentEntry = v["Entry"] + paraOpen = v["pages"][1]["special"]:find("\\(",1,true) + paraClose = v["pages"][1]["special"]:find("\\)",1,true) + if paraOpen then + firstPage = v["pages"][1]["number"] + elseif paraClose then + lastPage = v["pages"][1]["number"] + newEntries[#newEntries+1] = { Entry = v["Entry"], + pages = {{ number = firstPage.."--"..lastPage, + special = deleteOpenClose(v["pages"][1]["special"])}}, + sortChar= v["sortChar"], + Macro = v["Macro"] + } + firstPage = 0 + elseif ((firstPage == 0) and not paraClose) then + newEntries[#newEntries+1] = v -- same Entry with greater page or new entry + end + end + end + return newEntries +end + +function replaceVerticalChar(v) +-- res, _ = string.gsub(v:gsub('|[()]$', ''), '|[()]?', ' \\') +-- return res + if not v:match('|') then + return v,"" + else + return v:gsub('|.*',''), v:match('|.*'):gsub('|','\\'):gsub("%s+", "") -- part before, part after | without spaces + end +end + +function getEntryAndPage(w, nextW, EntryList) +-- \indexentry{Aachen, Johann von}{VII/1-215} +-- \indexentry {Document@\idxtextClasses !IEEEtran@{\sfffffamily IEEEtran}}{185} +-- if indexEntry(w) then + local macro = nil + if string.find(nextW,"\\MACRO<<< ") then + macro = string.gsub(nextW,'\\MACRO<<<','') + end + local entry, pageNo = w:match('{(.*)}%s*{(.*)}') +-- if numericPage then +-- if tonumber(pageNo) then -- check for roman numbering +-- pageNo = tonumber(pageNo) +-- end +-- end + local IndexString, Special = replaceVerticalChar(entry) + EntryList[#EntryList+1] = { + Entry = IndexString, -- the index item foo@bar + pages = {{ + number = pageNo, + special = Special }}, -- the page number(s) and the part after | + sortChar= NormalizedUpper(utf.sub(IndexString,1,1)), -- :byte(), -- Initial for later output + Macro = macro + } + if args_v then + if Special == "" then Special = "-" end + writeLog(1,"getEntryAndPage: "..tostring(IndexString,pageNo,Special,utf.sub(IndexString,1,1),macro).."\n",2) + end + return EntryList +end + +function compressEntryList(EntryList) +-- require 'xindex-pretty'.dump(EntryList) -- only for internal dump + local newList = {} + newList[1] = EntryList[1] -- at least one entry + local nPages = 1 + for k=2,#EntryList do + if EntryList[k] then -- exists? + local vEntry = EntryList[k]["Entry"] + local last = EntryList[k-1] -- complete data + if (getSortString(last["Entry"]) == getSortString(vEntry)) then -- Entry exists -> add page +-- require 'xindex-pretty'.dump(EntryList) -- only for internal dump +-- require 'xindex-pretty'.dump(newList) -- only for internal dump + if (newList[#newList]["pages"][nPages]["number"] ~= EntryList[k]["pages"][1]["number"]) -- different pages or special? + or (newList[#newList]["pages"][nPages]["special"] ~= EntryList[k]["pages"][1]["special"]) then + newList[#newList]["pages"][nPages+1] = EntryList[k]["pages"][1] + nPages = nPages + 1 +-- require 'xindex-pretty'.dump(newList) -- only for internal dump + else + -- gleiche Entries, gleiche Seiten, gleiche specials -> nichts tun + end + else -- not the same entry +-- require 'xindex-pretty'.dump(newList) -- only for internal dump + newList[#newList]["pages"] = deletePageDups(newList[#newList]["pages"]) + newList[#newList+1] = EntryList[k] + nPages = 1 + end + end + end + -- last data line + newList[#newList]["pages"] = deletePageDups(newList[#newList]["pages"]) +-- require 'xindex-pretty'.dump(newList) -- only for internal dump + return newList +end + +--[[ example entry +EntryList[2] = { + Entry = "Johann", -- the index item foo@bar + pages = { -- the page number(s) and the part after | + { number = 111, + special = '\\emph' }, + { number = 11, + special = "\\textit"} + }, + sortChar= "", -- Initial for later output + Macro = "" +} +]] + + +function deletePageDups(pages) + if #pages == 1 then return pages end + local newPages = {pages[1]} + local notfound + for i=2,#pages do + notfound = true + for j=1,#newPages do + if (pages[i]["number"] == newPages[j]["number"]) and (pages[i]["special"] == newPages[j]["special"]) then + notfound = false + break + end + end + if notfound then + newPages[#newPages+1] = pages[i] + end + end + return newPages +end + + +function compressPageList(pages) -- called with (v["pages"]) + writeLog(1,"compressPageList: we have "..#pages.." pages for this entry",2) +-- require 'xindex-pretty'.dump(pages) -- only for internal dump + pages = deletePageDups(pages) -- delete duplicate page numners with same special + local str + if #pages == 1 then -- only one pageno + return pages + end -- only one pageno + if #pages == 2 then -- only two pages + if tonumber(pages[1]["number"]) and tonumber(pages[2]["number"]) then + if ((tonumber(pages[2]["number"]) - tonumber(pages[1]["number"])) == 1) and + (pages[1]["special"] == pages[2]["special"]) then + pages[1]["number"] = pages[1]["number"].."f" + pages[2] = nil +-- elseif (pages[1]["number"] == pages[2]["number"]) and +-- (pages[1]["special"] == pages[2]["special"]) then +-- pages[2] = nil + end + end + return pages + end + -- we have at least three pages + pages[#pages+1] = {number = 9999999, special = ""} -- dummy to sort the last real page number correct + local startIndex + local newPages = {} -- { pages[1], pages[2], ... } + local series = {} -- { pages[1], pages[2], ... } + if tonumber(pages[1]["number"]) then -- if a number we start with seconf page + newPages = {} + series = {pages[1]} + startIndex = 2 + else -- if not a number we start with third page + newPages = {pages[1]} + series = {pages[2]} + startIndex = 3 + end +if args_v then print ("compressPageList: more than two pages for the entry") end + for i=startIndex,#pages do + if tonumber(pages[i-1]["number"]) and tonumber(pages[i]["number"]) then -- de we have something like 17--31 in the current list + if ((tonumber(pages[i]["number"])-tonumber(pages[i-1]["number"])) == 1) and + (pages[i]["special"] == pages[i-1]["special"]) then -- something like 12, 13 with identical |\special + series[#series+1] = pages[i]-- page difference is 1, add page to series + elseif (#series == 1) then -- no -f page -> only one page -> output + newPages[#newPages+1] = series[1] + series = {pages[i]} + elseif (#series > minCompress) then -- we found series od f pages like 11, 12, 13, 14 + -- the sequenz gets the special from the first page + newPages[#newPages+1] = { number = series[1]["number"].."--"..series[#series]["number"], special = series[1]["special"]} -- first..last + series = {pages[i]} + else -- series < minCompress + if fCompress then + if #series == 2 then -- two pages -> 3f + writeLog(1,"compressPageList: Two consecutive pages for this entry",2) + if series[1]["special"] == series[2]["special"] then + newPages[#newPages+1] = { number = series[1]["number"]..page_folium[1], special = series[1]["special"] } + else + newPages[#newPages+1] = series[1] -- different |\special -> no compress to -f + newPages[#newPages+1] = series[2] + end + else -- must be #series=3 + if (series[1]["special"] == series[2]["special"]) and (series[2]["special"] == series[3]["special"]) then + newPages[#newPages+1] = { number = series[1]["number"]..page_folium[2], special = series[1]["special"] } -- three pages + elseif (series[1]["special"] == series[2]["special"]) then + newPages[#newPages+1] = { number = series[1]["number"]..page_folium[1], special = series[1]["special"] } -- three pages + newPages[#newPages+1] = series[3] + elseif (series[2]["special"] == series[3]["special"]) then + newPages[#newPages+1] = series[1] + newPages[#newPages+1] = { number = series[2]["number"]..page_folium[1], special = series[2]["special"] } -- three pages + else -- all different specials + newPages[#newPages+1] = series[1] + newPages[#newPages+1] = series[2] + newPages[#newPages+1] = series[3] + end + end + else + for i=1,#series do + newPages[#newPages+1] = series[i] + end + end + series = {pages[i]} + end + else -- current or forgoing page is not a number, we simply add it + if tonumber(pages[i]["number"]) then -- p[i-1] is non numeric p[i] is ok and not last no + series = {pages[i]} + else -- current page is non numeric + if (#series > minCompress) then -- we found a page series + newPages[#newPages+1] = { number = series[1]["number"].."--"..series[#series]["number"], -- first..last + special =series[1]["special"] } + series = {pages[i]} + else -- series < minCompress + for i=1,#series do + newPages[#newPages+1] = series[i] + end + series = {pages[i]} + end + end + end + end +-- require 'xindex-pretty'.dump(newPages) + return newPages +end + + +-- 2 letter +-- 1 digit +-- 0 symbol + +UTFdatafile = kpse.find_file("unicode-category.lua") +local category_data = dofile(UTFdatafile) +local floor = math.floor + +local function binary_range_search(code_point, ranges) + local low, mid, high + low, high = 1, #ranges + while low <= high do + mid = floor((low + high) / 2) + local range = ranges[mid] + if code_point < range[1] then + high = mid - 1 + elseif code_point <= range[2] then + return range, mid + else + low = mid + 1 + end + end + return nil, mid +end + +function get_category(code_point) + if category_data.singles[code_point] then + return category_data.singles[code_point] + else + local range = binary_range_search(code_point, category_data.ranges) + return range and range[3] or "Cn" + end +end + +function getCharType(c) +-- print ("getCharType c="..c..": codepoint="..utf8.codepoint(c)) + local category = get_category(utf8.codepoint(c)) +-- print ("getCharType: "..category) + if category == "Nd" then return 1 + elseif category:sub(1, 1) == "L" then return 2 + else return 0 + end +end + +--print(get_category(utf8.codepoint('ö'))) +--print(category_to_number(get_category(utf8.codepoint('ö')))) + +function getCharTypeOld(c) -- in case of Lua < 5.3 (has no utf support) + if utf.find(Letters,c,1,true) then return 2 + elseif utf.find(Digits,c,1,true) then return 1 + else return 0 + end +end + +-- string.gsub('{Entry}{page}', '{[^{}]*}$', '') -> {Entry} +-- str = "\indexentry {foo}{bar}" +-- first, second = str:match('{([^}]*)}%s*{([^}]*)}') -> foo, bar + +function UTFCompare(a,b) +-- a, b are something like \indexentry{foo}{bar} + writeLog(1,"UTFCompare: "..a["Entry"]..", "..a["pages"][1]["number"].." - "..b["Entry"]..", "..b["pages"][1]["number"],2) + k = k + 1 + if (k % 50) == 0 then writeLog(1,".",1) end + local A,B,Apage,Bpage + if numericPage then + if tonumber(a["pages"][1]["number"]) then + Apage = string.format("%09d",a["pages"][1]["number"]) + else + Apage = string.format("%09d",romanToNumber(a["pages"][1]["number"])) + end + if tonumber(b["pages"][1]["number"]) then + Bpage = string.format("%09d",b["pages"][1]["number"]) + else + Bpage = string.format("%09d",romanToNumber(b["pages"][1]["number"])) + end + else + Apage = string.format("%09s",a["pages"][1]["number"]) + Bpage = string.format("%09s",b["pages"][1]["number"]) + end + A = NormalizedUpper(getSortString(a["Entry"].." "..Apage..a["pages"][1]["special"]):gsub('!',' ')) + B = NormalizedUpper(getSortString(b["Entry"].." "..Bpage..b["pages"][1]["special"]):gsub('!',' ')) +-- print(A,B) +--[[ + if A == B then -- same entry, use also page number + Apage = string.format("%09s",a["pages"][1]["number"]) + Bpage = string.format("%09s",b["pages"][1]["number"]) + A = string.format("%-90s",A)..Apage + B = string.format("%-90s",B)..Bpage + end + if numericPage then + if tonumber(a["pages"][1]["number"]) then + Apage = string.format("%09d",a["pages"][1]["number"]) + else + Apage = string.format("%09d",romanToNumber(a["pages"][1]["number"])) + end + if tonumber(b["pages"][1]["number"]) then + Bpage = string.format("%09d",b["pages"][1]["number"]) + else + Bpage = string.format("%09d",romanToNumber(b["pages"][1]["number"])) + end + else + Apage = string.format("%09s",a["pages"][1]["number"]) + Bpage = string.format("%09s",b["pages"][1]["number"]) + end + A = string.format("%-90s",A)..Apage + B = string.format("%-90s",B)..Bpage +]] + return A < B +end + +function pageCompare(a,b) -- a = {{number=...,special=..},{...,...}} +-- a["number"], b["number"] are something like "3" or "VI-17" or "9--31" + writeLog(1,"pageCompare: "..a["number"].." "..b["number"].."\n",2) + if (a["number"] == nil) or (b["number"] == nil) then return true end -- should be no nil here + local a0 = a["number"] -- can be numeric or alphanumeric + local b0 = b["number"] +-- if pageNoPrefixDel ~= "" then ---- not active +-- A = (a0:gsub(pageNoPrefixPattern,'')) +-- B = (b0:gsub(pageNoPrefixPattern,'')) +-- a0 = tonumber(A) or romanToNumber(A) +-- b0 = tonumber(B) or romanToNumber(B) +-- else + if numericPage then + if (type(a0) == "number") and (type(b0) == "number") then return a0 < b0 end + if romanToNumber(a0) and (type(b0) == "number") then return true end -- ii < 2 + if (type(a0) == "number") and romanToNumber(b0) then return false end -- ii > 2 + if romanToNumber(a0) and romanToNumber(b0) then return a0 < b0 end -- ii < iii + -- now we have some special page numbers + A = tostring(a0) + B = tostring(b0) + A1 = A:find("--",1,true) or A:find("f",1,true) -- sequence or folio pages + B1 = B:find("--",1,true) or B:find("f",1,true) + if A1 then a0 = tonumber(A:sub(1,A1-1)) end + if B1 then b0 = tonumber(B:sub(1,B1-1)) end + return tonumber(a0) < tonumber(b0) -- numeric + else + return a0 < b0 -- alphanumeric (strings) + end +end + +function checkFF(p) + if not p then return p end + local P = tostring(p) + if P:find("ff") then + return P:gsub('%a+','').."\\nohyperpage{"..page_folium[2].."}" + elseif P:find("f") then + return P:gsub('%a+','').."\\nohyperpage{"..page_folium[1].."}" + else + return P + end +end + +function getRawPages(v) + writeLog(1,"getRawPages, Entry: "..v["Entry"]..", page: "..tostring(v["pages"][1]["number"]),2) + if v then + local str = tostring(v["pages"][1]["number"]).."("..tostring(v["pages"][1]["special"])..")" + for i=2,#v["pages"] do + if v["pages"] then + str = str..", "..tostring(v["pages"][i]["number"]).."("..tostring(v["pages"][i]["special"])..")" + end + end + return str + else + return "v->nil" + end +end + +function getRawPagesP(p) -- does the same but uses table pages + if p then + local str = tostring(p[1]["number"]).."("..tostring(p[1]["special"])..")" + for i=2,#p do + if p then + str = str..", "..tostring(p[i]["number"]).."("..tostring(p[i]["special"])..")" + end + end + return str + else + return "pages->nil" + end +end + + +function getPageList(v,hyperpage) + if specialGetPageList then + local pageNo = specialGetPageList(v,hyperpage) + return pageNo + end + local Pages = {} + if v["pages"] then + table.sort(v["pages"],pageCompare)-- nur nötig, da User manuell eine Zeile einfügen kann + if specialCompressPageList then + Pages = specialCompressPageList(v["pages"]) + else + Pages = compressPageList(v["pages"]) + end +-- require 'xindex-pretty'.dump(Pages) -- only for internal dump + local pageNo +--[[ +\indexentry{Auto|hyperindexformat{\textbf}}{1} +-> \item Auto, \hyperindexformat{\textbf}{1} + + add for example \hyperpage{5\nohyperpage{f}} , same for ff + + \item foo, \hyperpage{1\nohyperpage{f}}, + \hyperpage{4\nohyperpage{ff}}, \hyperpage{8} + +]] + if hyperpage then + if string.find(v["pages"][1]["special"],"hyperindexformat") then + pageNo = v["pages"][1]["special"].."{"..checkFF(Pages[1]["number"].."}") + else + pageNo = "\\hyperpage{"..checkFF(Pages[1]["number"]).."}" + end + for i=2,#Pages do + if string.find(v["pages"][i]["special"],"hyperindexformat") then + pageNo = pageNo..", "..v["pages"][i]["special"].."{"..checkFF(Pages[i]["number"].."}") + else + pageNo = pageNo..", \\hyperpage{"..checkFF(Pages[i]["number"]).."}" + end +-- Pages[i] = nil + end + else + writeLog(1,"getPageList: "..tostring(Pages[1]["special"]).."{"..tostring(Pages[1]["number"]).."}\n",2) + if (Pages[1]["special"] == nil) or (Pages[1]["number"] == nil) then return "" end + pageNo = Pages[1]["special"].."{"..Pages[1]["number"].."}" + for i=2,#Pages do + if Pages[i]["number"] then + pageNo = pageNo..", "..Pages[i]["special"].."{"..Pages[i]["number"].."}" + Pages[i] = {} + end + end + end + return pageNo + else + return "" + end +end + + +function getPathFileExt(str) + local filepath = str:match("(.*[/\\])") + local filename = str:match("^.+/(.+)$") + local fileext = str:match("^.+(%..+)$") + return filepath,filename,fileext +end + +function printList(Index,level) + for k,v in pairs(Index) do + if v["Entry"] then + local sortChar = v["sortChar"] + if v["Entry"] and v["Macro"] then + writeLog(1,"Entry: "..v["Entry"].."; Pages: "..getRawPages(v).."Special: "..v["pages"][1]["special"].."; Type: "..sortChar.."; Macro: "..v["Macro"].."\n",level) + else + writeLog(1,"Entry: "..v["Entry"].."; Pages: "..getRawPages(v).."Special: "..v["pages"][1]["special"].."; Type: "..sortChar.."; Macro: nil".."\n",level) + end + end + end +end + +function getItem(str,n) + if n >= 0 then + local item = (str:gsub("!.*", "%0!") + :gsub("[^!]*!", "", n) + :match("^([^!]*)!") ) + writeLog(1,"getItem ("..str..", "..n..") = "..item.."\n",2) + return item + end +end + +local romanMap = { + I = 1, + V = 5, + X = 10, + L = 50, + C = 100, + D = 500, + M = 1000, +} + +local numbers = { 1, 5, 10, 50, 100, 500, 1000 } +local romanchars = { "I", "V", "X", "L", "C", "D", "M" } +local RomanNumerals = { } + +function numberToRoman(s) + --s = tostring(s) + s = tonumber(s) + if not s or s ~= s then error"Unable to convert to number" end + if s == math.huge then error"Unable to convert infinity" end + s = math.floor(s) + if s <= 0 then return s end + local ret = "" + for i = #numbers, 1, -1 do + local num = numbers[i] + while s - num >= 0 and s > 0 do + ret = ret .. romanchars[i] + s = s - num + end + for j = 1, i - 1 do + local n2 = numbers[j] + if s - (num - n2) >= 0 and s < num and s > 0 and num - n2 ~= n2 then + ret = ret .. romanchars[j] .. romanchars[i] + s = s - (num - n2) + break + end + end + end + return ret +end + +function romanToNumber(s) +-- if args_v then print("romanToNumber: "..tostring(s)) end +-- if not s then return end + s = s:upper() + local ret = 0 + local i = 1 + while i <= s:len() do + local c = s:sub(i, i) + if c ~= " " then -- allow spaces + local m = romanMap[c] + if not m then return nil end --error("Unknown Roman Numeral '" .. c .. "'") + local next = s:sub(i + 1, i + 1) + local nextm = romanMap[next] + if next and nextm then + if nextm > m then + ret = ret + (nextm - m) + i = i + 1 + else + ret = ret + m + end + else + ret = ret + m + end + end + i = i + 1 + end + return ret +end + +function commandEntry(line) + return string.find(line,"\\MACRO<<<",1,true) +end + +function checkHyperpage(lines) + local hyperpage = false + for i=1,#lines do + if string.find(lines[i],'hyperpage}') then + hyperpage = true + break + end + end + if hyperpage then + for i=1,#lines do + lines[i] = string.gsub(lines[i],'|?hyperpage}{','}{') + end + return true, lines + else + return false, lines + end + return +end + +function itemOutput(last, v, hyperpage) + local lastItems = last + local currentItems = {} + local Entry = v["Entry"] +-- require 'xindex-pretty'.dump(v) -- only for internal dump + local str + local excl = select(2,string.gsub(Entry,"!","!")) -- Number of ! + writeLog(1,"itemOutput(): We have entry "..Entry.."\n",2) + writeLog(1,"itemOutput(): The entry has "..excl.." Exclamation characters\n",2) + if excl == 0 then + str = " \\item "..Entry..itemPageDelimiter.." "..getPageList(v,hyperpage).."\n" + for i, str0 in ipairs(escape_chars) do -- undo the escape char setting + str = str:gsub(str0[2],str0[3]) + end + outFile:write(str) +-- lastItems[1] = Entry + else + for i = 1,excl+1 do + currentItems[i] = getItem(Entry,i-1) -- 0 ! 1 ! 2 ! ... + local item = "item" + if (currentItems[i] ~= lastItems[i]) then + writeLog(1,"itemOutput: currentItems[i]: "..tostring(currentItems[i]).."~= lastItems[i]: "..tostring(lastItems[i]).."\n",2) + local space = " " + for j = 2,i do + item = "sub"..item -- get the sub...subitem + space = space.." " + end + if not sublabels[i] then sublabels[i] = "---" end -- only three levels are predefined + writeLog(1,"itemOutput: currentItems[i]: "..currentItems[i].."; item: "..item.."\n",2) + if (i == 1) and (item == "item") then + str = space.."\\"..item.." "..sublabels[i]..currentItems[i].."\n" + else + str = space.."\\"..item.." "..sublabels[i]..currentItems[i]..itemPageDelimiter.." "..getPageList(v,hyperpage).."\n" + end + for i, str0 in ipairs(escape_chars) do -- undo the escape char setting + str = string.gsub(str,str0[2],str0[3]) + end + outFile:write(str) + lastItems[i] = currentItems[i] + else + writeLog(1,"itemOutput: currentItems[i]: "..currentItems[i].."= lastItems[i]: "..lastItems[i].."\n",2) + end + end + end + return lastItems +end + +-- \item Bugenhagen, {VII/1-16}, {166}, {17}, {215}, {222f}, {226}, {237f}, {248}, {258f}, {263}, {269}, {316f}, {321}, {361}, {365f}, {368}, {385}, {431}, {57}, {65}, {68}, {71}, {714}, {728}, {73f}, {748}, {75}, {79}, {81}, {85}, {90f}, {VII/2/1-1013}, {1015}, {1049}, {1085}, {1088}, {1097--1100}, {1110}, {1114}, {1120}, {1126}, {1148}, {1175}, {1234}, {1236ff}, {761}, {782}, {785}, {799}, {803--811}, {813f}, {818}, {822f}, {829}, {832--835}, {839f}, {848f}, {851}, {857--862}, {864f}, {867--871}, {873}, {875}, {877}, {880}, {882}, {884}, {961}, {973}, {IX-277} +-- \subitem -\,Johannes, {VII/1-16}, {166}, {17}, {215}, {222f}, {226}, {237f}, {248}, {258f}, {263}, {269}, {316f}, {321}, {361}, {365f}, {368}, {385}, {431}, {57}, {65}, {68}, {71}, {714}, {728}, {73f}, {748}, {75}, {79}, {81}, {85}, {90f}, {VII/2/1-1013}, {1015}, {1049}, {1085}, {1088}, {1097--1100}, {1110}, {1114}, {1120}, {1126}, {1148}, {1175}, {1234}, {1236ff}, {761}, {782}, {785}, {799}, {803--811}, {813f}, {818}, {822f}, {829}, {832--835}, {839f}, {848f}, {851}, {857--862}, {864f}, {867--871}, {873}, {875}, {877}, {880}, {882}, {884}, {961}, {973}, {IX-277} + +local match = function(expr) + local C, Ct, S = lpeg.C, lpeg.Ct, lpeg.S + local sep = S("@!|") + local str = C((1 - sep)^0) + local prefix = function(prefix) + return function(match) + return prefix .. match + end + end + local idx = str * ( "@" * str / prefix("@") + + "!" * str / prefix("!") + + "|" * str / prefix("|"))^0 + return Ct(idx):match(expr) +end + +function getSortString(Entry) + local t = match(Entry) +-- require 'xindex-pretty'.dump(t) -- only for internal dump + local data = t[1] + local c = utf.sub(data,1,1) + if getCharType(c) == 0 then + data = " "..data + end + for i = 2,#t do + if not (t[i]:sub(1,1) == "@") then -- and not (t[i]:sub(1,1) == "|") then + data = data..t[i] + end + end + return data +end + +function writeLog(i, str, level) -- mode i 0->console; 1->logfile: 2->both + if not_quiet then + if level <= vlevel then + if (i ~= 1) or (i < 0) then io.write(tostring(str)) end + if i > 0 then logFile:write(tostring(str)) end + end + else + if level < 0 then + io.write(tostring(str)) + elseif level == 0 then + logFile:write(tostring(str)) + end + end +end + +function string:split() + local sep, fields = " ", {} + local pattern = string.format("([^%s]+)", sep) + self:gsub(pattern, function(c) fields[#fields+1] = c end) + return fields +end + + + +--\indexentry{hello@foo!world@foo!bar|bar}{60} + + +--[[ +\indexentry {Schrift!Höhe}{64} +\indexentry {Schrift!Breite}{64} +\indexentry {Schrift!Tiefe}{64} + +]]
\ No newline at end of file diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex-pretty.lua b/Master/texmf-dist/tex/lualatex/xindex/xindex-pretty.lua new file mode 100644 index 00000000000..290c30d1c96 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex-pretty.lua @@ -0,0 +1,254 @@ +--- Pretty-printing Lua tables. +-- based on Steve Donovans Penlight package +-- Also provides a sandboxed Lua table reader and +-- a function to present large numbers in human-friendly format. +-- + +if not modules then modules = { } end modules ['xindex-pretty'] = { + version = 0.05, + comment = "dump a Lua table for debugging", + author = "Steve Donovan", + copyright = "Steve Donovan", + license = "MIT" +} + +local append = table.insert +local concat = table.concat +local mfloor, mhuge = math.floor, math.huge +local mtype = math.type + +local original_tostring = tostring + +--- Utility function that finds any patterns that match a long string's an open or close. +-- Note that having this function use the least number of equal signs that is possible is a harder algorithm to come up with. +-- Right now, it simply returns the greatest number of them found. +-- @param s The string +-- @return 'nil' if not found. If found, the maximum number of equal signs found within all matches. +local function has_lquote(s) + local lstring_pat = '([%[%]])(=*)%1' + local equals, new_equals, _ + local finish = 1 + repeat + _, finish, _, new_equals = s:find(lstring_pat, finish) + if new_equals then + equals = max(equals or 0, #new_equals) + end + until not new_equals + + return equals +end + +--- Quote the given string and preserve any control or escape characters, such that reloading the string in Lua returns the same result. +-- @param s The string to be quoted. +-- @return The quoted string. + +function quote_string(s) +-- assert_string(1,s) + -- Find out if there are any embedded long-quote sequences that may cause issues. + -- This is important when strings are embedded within strings, like when serializing. + -- Append a closing bracket to catch unfinished long-quote sequences at the end of the string. + local equal_signs = has_lquote(s .. "]") + + -- Note that strings containing "\r" can't be quoted using long brackets + -- as Lua lexer converts all newlines to "\n" within long strings. + if (s:find("\n") or equal_signs) and not s:find("\r") then + -- If there is an embedded sequence that matches a long quote, then + -- find the one with the maximum number of = signs and add one to that number. + equal_signs = ("="):rep((equal_signs or -1) + 1) + -- Long strings strip out leading newline. We want to retain that, when quoting. + if s:find("^\n") then s = "\n" .. s end + local lbracket, rbracket = + "[" .. equal_signs .. "[", + "]" .. equal_signs .. "]" + s = lbracket .. s .. rbracket + else + -- Escape funny stuff. Lua 5.1 does not handle "\r" correctly. + s = ("%q"):format(s):gsub("\r", "\\r") + end + return s +end + +-- Patch tostring to format numbers with better precision +-- and to produce cross-platform results for +-- infinite values and NaN. +local function tostring(value) + if type(value) ~= "number" then + return original_tostring(value) + elseif value ~= value then + return "NaN" + elseif value == mhuge then + return "Inf" + elseif value == -mhuge then + return "-Inf" + elseif (_VERSION ~= "Lua 5.3" or mtype(value) == "integer") and mfloor(value) == value then + return ("%d"):format(value) + else + local res = ("%.14g"):format(value) + if _VERSION == "Lua 5.3" and mtype(value) == "float" and not res:find("%.") then + -- Number is internally a float but looks like an integer. + -- Insert ".0" after first run of digits. + res = res:gsub("%d+", "%0.0", 1) + end + return res + end +end + +local pretty = {} + +local function quote_if_necessary (v) + if not v then return '' + else + --AAS + if v:find ' ' then v = quote_string(v) end + end + return v +end + +local keywords + +local function is_identifier (s) + return type(s) == 'string' and s:find('^[%a_][%w_]*$') and not keywords[s] +end + +local function quote (s) + if type(s) == 'table' then + return pretty.write(s,'') + else + --AAS + return quote_string(s)-- ('%q'):format(tostring(s)) + end +end + +local function index (numkey,key) + --AAS + if not numkey then + key = quote(key) + key = key:find("^%[") and (" " .. key .. " ") or key + end + return '['..key..']' +end + +--- Create a string representation of a Lua table. +-- This function never fails, but may complain by returning an +-- extra value. Normally puts out one item per line, using +-- the provided indent; set the second parameter to an empty string +-- if you want output on one line. +-- @tab tbl Table to serialize to a string. +-- @string[opt] space The indent to use. +-- Defaults to two spaces; pass an empty string for no indentation. +-- @bool[opt] not_clever Pass `true` for plain output, e.g `{['key']=1}`. +-- Defaults to `false`. +-- @return a string +-- @return an optional error message + +function pretty.dump (tbl,space,not_clever) + if type(tbl) ~= 'table' then + local res = tostring(tbl) + if type(tbl) == 'string' then return quote(tbl) end + return res, 'not a table' + end + if not keywords then + keywords = { + ["and"] = true, ["break"] = true, ["do"] = true, + ["else"] = true, ["elseif"] = true, ["end"] = true, + ["false"] = true, ["for"] = true, ["function"] = true, + ["if"] = true, ["in"] = true, ["local"] = true, ["nil"] = true, + ["not"] = true, ["or"] = true, ["repeat"] = true, + ["return"] = true, ["then"] = true, ["true"] = true, + ["until"] = true, ["while"] = true + } + end + local set = ' = ' + if space == '' then set = '=' end + space = space or ' ' + local lines = {} + local line = '' + local tables = {} + + + local function put(s) + if #s > 0 then + line = line..s + end + end + + local function putln (s) + if #line > 0 then + line = line..s + append(lines,line) + line = '' + else + append(lines,s) + end + end + + local function eat_last_comma () + local n = #lines + local lastch = lines[n]:sub(-1,-1) + if lastch == ',' then + lines[n] = lines[n]:sub(1,-2) + end + end + + local writeit + writeit = function (t,oldindent,indent) + local tp = type(t) + if tp ~= 'string' and tp ~= 'table' then + putln(quote_if_necessary(tostring(t))..',') + elseif tp == 'string' then + -- if t:find('\n') then + -- putln('[[\n'..t..']],') + -- else + -- putln(quote(t)..',') + -- end + --AAS + putln(quote_string(t) ..",") + elseif tp == 'table' then + if tables[t] then + putln('<cycle>,') + return + end + tables[t] = true + local newindent = indent..space + putln('{') + local used = {} + if not not_clever then + for i,val in ipairs(t) do + put(indent) + writeit(val,indent,newindent) + used[i] = true + end + end + for key,val in pairs(t) do + local tkey = type(key) + local numkey = tkey == 'number' + if not_clever then + key = tostring(key) + put(indent..index(numkey,key)..set) + writeit(val,indent,newindent) + else + if not numkey or not used[key] then -- non-array indices + if tkey ~= 'string' then + key = tostring(key) + end + if numkey or not is_identifier(key) then + key = index(numkey,key) + end + put(indent..key..set) + writeit(val,indent,newindent) + end + end + end + tables[t] = nil + eat_last_comma() + putln(oldindent..'},') + else + putln(tostring(t)..',') + end + end + writeit(tbl,'',space) + eat_last_comma() + return concat(lines,#space > 0 and '\n' or '') +end + +return pretty diff --git a/Master/texmf-dist/tex/lualatex/xindex/xindex.sty b/Master/texmf-dist/tex/lualatex/xindex/xindex.sty new file mode 100644 index 00000000000..58afc99c20d --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/xindex/xindex.sty @@ -0,0 +1,76 @@ +%% This is file `xindex.sty', +%% +%% Copyright (C) 2018 +%% Herbert Voss +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +% +% $Id: xindex.sty 836 2018-11-11 20:22:56Z herbert $ +% +% ------------------------------------- +\ProvidesPackage{xindex}[2018/11/11 v. 0.02 write into an idx file (hv)] +% +\RequirePackage{xkeyval} + +\newif\if@@imakeidx \@@imakeidxfalse + +\DeclareOptionX{imakeidx}{\@@imakeidxtrue} +\DeclareOptionX*{\PassOptionsToPackage\CurrentOption{imakeidx}} +\ProcessOptionsX\relax + +\@ifpackageloaded{imakeidx}{}{% imakeidx already loaded?? if not then define ... + \newif\ifimki@startedidx + \newif\ifimki@splitindex +} + +\if@@imakeidx + \typeout{xindex: Using package imakeidx}% + \RequirePackage{imakeidx} + \def\imki@progdefault{xindex} + \def\imki@program{xindex} +% + \def\imki@@startidxsplit#1{% + \if@filesw + \def\index{\@bsphack + \@ifnextchar [{\@index}{\@index[\imki@jobname]}} + \expandafter\newwrite\csname #1@idxfile\endcsname + \immediate\openout \csname #1@idxfile\endcsname #1.idx\relax + \def\writeidx##1{\write\expandafter\csname #1@idxfile\endcsname{\noexpand##1}}% + \typeout{Writing index file #1.idx}% + \fi + } + \global\imki@startedidxfalse + \def\imki@@startidxunique#1{% + \if@filesw + \ifimki@startedidx\else + \newwrite\@indexfile + \immediate\openout\@indexfile\imki@jobname.idx% + \def\writeidx##1{\write\@indexfile{\noexpand##1}}% + \global\imki@startedidxtrue + \fi + \def\index{\@bsphack + \@ifnextchar [{\@index}{\@index[\imki@jobname]}} + \expandafter\let\csname #1@idxfile\endcsname\@empty + \typeout{Started index file #1}% + \fi + } +% + \ifimki@splitindex + \let\imki@startidx\imki@@startidxunique + \else + \let\imki@startidx\imki@@startidxsplit + \fi +\else + \typeout{xindex: Using package makeidx}% + \RequirePackage{makeidx} + \def\writeidx#1{\write\@indexfile{\noexpand#1}} +\fi + +\endinput + |