summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/context/lua/mtx-chars.lua5
-rw-r--r--scripts/context/lua/mtx-colors.lua51
-rw-r--r--scripts/context/lua/mtx-context.lua5
-rw-r--r--scripts/context/lua/mtx-fonts.lua7
-rw-r--r--scripts/context/lua/mtx-interface.lua14
-rw-r--r--scripts/context/lua/mtx-patterns.lua593
-rw-r--r--scripts/context/lua/mtx-server-ctx-fonttest.lua2
-rw-r--r--scripts/context/lua/mtx-server.lua2
-rw-r--r--scripts/context/lua/mtxrun.lua311
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua311
-rwxr-xr-xscripts/context/stubs/unix/mtxrun311
11 files changed, 1183 insertions, 429 deletions
diff --git a/scripts/context/lua/mtx-chars.lua b/scripts/context/lua/mtx-chars.lua
index 6acacfbd2..ea4a6061f 100644
--- a/scripts/context/lua/mtx-chars.lua
+++ b/scripts/context/lua/mtx-chars.lua
@@ -143,6 +143,11 @@ local banner_utf_patch = [[
\setXTXcharcodes "201C "201C "201C
\setXTXcharcodes "201D "201D "201D
+
+% patch needed for french
+
+\setXTXcharcodes "2019 "2019 "2019
+
]]
local banner_utf_names = [[
diff --git a/scripts/context/lua/mtx-colors.lua b/scripts/context/lua/mtx-colors.lua
new file mode 100644
index 000000000..a99fd7257
--- /dev/null
+++ b/scripts/context/lua/mtx-colors.lua
@@ -0,0 +1,51 @@
+if not modules then modules = { } end modules ['mtx-colors'] = {
+ version = 1.001,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: fc-cache -v en check dirs, or better is: fc-cat -v | grep Directory
+
+if not fontloader then fontloader = fontforge end
+
+dofile(resolvers.find_file("colo-icc.lua","tex"))
+
+scripts = scripts or { }
+scripts.colors = scripts.colors or { }
+
+function scripts.colors.table()
+ local files = environment.files
+ if #files > 0 then
+ for i=1,#files do
+ local profile, okay, message = colors.iccprofile(files[i])
+ if not okay then
+ logs.simple(message)
+ else
+ logs.simple(table.serialize(profile,"profile"))
+ end
+ end
+ else
+ logs.simple("no file(s) given" )
+ end
+end
+
+logs.extendbanner("ConTeXt Color Management 0.1")
+
+messages.help = [[
+--table show icc table
+
+example:
+
+mtxrun --script color --table somename
+]]
+
+--~ local track = environment.argument("track")
+--~ if track then trackers.enable(track) end
+
+if environment.argument("table") then
+ scripts.colors.table()
+else
+ logs.help(messages.help)
+end
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index 785539754..66b8a6311 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -439,14 +439,13 @@ function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,curr
f:write(format:format(...),"\n")
end
--
+ -- This might change ... we can just pass the relevant flags directly.
+ --
setalways("%% runtime options files (command line driven)")
--
setalways("\\unprotect")
--
setalways("%% feedback and basic job control")
- if type(environment.argument("track")) == "string" then
- setvalue ("track" , "\\enabletrackers[%s]")
- end
if type(environment.argument("trackers")) == "string" then
setvalue ("trackers" , "\\enabletrackers[%s]")
end
diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua
index b8bbdde5b..9e370b2d5 100644
--- a/scripts/context/lua/mtx-fonts.lua
+++ b/scripts/context/lua/mtx-fonts.lua
@@ -194,10 +194,9 @@ local function list_specifications(t,info)
fontweight(entry.fontweight),
}
end
- table.formatcolumns(s)
+ aux.formatcolumns(s)
for k=1,#s do
- local v = s[k]
- texio.write_nl(v)
+ texio.write_nl(s[k])
end
end
end
@@ -222,7 +221,7 @@ local function list_matches(t,info)
subfont(entry.subfont)
}
end
- table.formatcolumns(s)
+ aux.formatcolumns(s)
for k=1,#s do
texio.write_nl(s[k])
end
diff --git a/scripts/context/lua/mtx-interface.lua b/scripts/context/lua/mtx-interface.lua
index 34ecffab0..12a6d0e29 100644
--- a/scripts/context/lua/mtx-interface.lua
+++ b/scripts/context/lua/mtx-interface.lua
@@ -161,7 +161,7 @@ function scripts.interface.context()
local v = t[key]
local value = v[language] or v["en"]
if not value then
- logs.simple(format("warning, no value for key '%s' for language '%s'",key,language))
+ logs.simple("warning, no value for key '%s' for language '%s'",key,language)
else
local value = t[key][language] or t[key].en
texresult[#texresult+1] = format("\\setinterface%s{%s}{%s}",tag,key,value)
@@ -199,9 +199,9 @@ function scripts.interface.context()
local texfilename = format("mult-%s.tex",language)
local xmlfilename = format("keys-%s.xml",language)
io.savedata(texfilename,table.concat(texresult,"\n"))
- logs.simple(format("saving interface definitions '%s'",texfilename))
+ logs.simple("saving interface definitions '%s'",texfilename)
io.savedata(xmlfilename,table.concat(xmlresult,"\n"))
- logs.simple(format("saving interface translations '%s'",xmlfilename))
+ logs.simple("saving interface translations '%s'",xmlfilename)
if language ~= "en" and xmldata ~= "" then
local newdata = xmldata:gsub("(<cd:interface.*language=.)en(.)","%1"..language.."%2",1)
newdata = replace(newdata, 'cd:string', 'value', interface.commands, interface.elements, language)
@@ -212,7 +212,7 @@ function scripts.interface.context()
newdata = replace(newdata, 'cd:inherit', 'name', interface.commands, interface.elements, language)
local xmlfilename = format("cont-%s.xml",language)
io.savedata(xmlfilename,newdata)
- logs.simple(format("saving interface specification '%s'",xmlfilename))
+ logs.simple("saving interface specification '%s'",xmlfilename)
end
end
end
@@ -223,6 +223,8 @@ function scripts.interface.messages()
local filename = resolvers.find_file(environment.files[1] or "mult-mes.lua") or ""
if filename ~= "" then
local messages = dofile(filename)
+ logs.simple("messages for * loaded from '%s'",filename)
+ logs.simple()
for i=1,#messageinterfaces do
local interface = messageinterfaces[i]
local texresult = { }
@@ -237,7 +239,9 @@ function scripts.interface.messages()
end
end
texresult[#texresult+1] = format("%%\n\\endinput")
- io.savedata(format("mult-m%s.tex",interface),table.concat(texresult,"\n"))
+ local interfacefile = format("mult-m%s.tex",interface)
+ io.savedata(interfacefile,table.concat(texresult,"\n"))
+ logs.simple("messages for '%s' saved in '%s'",interface,interfacefile)
end
end
end
diff --git a/scripts/context/lua/mtx-patterns.lua b/scripts/context/lua/mtx-patterns.lua
index c3817e9a8..a51ca5860 100644
--- a/scripts/context/lua/mtx-patterns.lua
+++ b/scripts/context/lua/mtx-patterns.lua
@@ -6,95 +6,111 @@ if not modules then modules = { } end modules ['mtx-patterns'] = {
license = "see context related readme files"
}
-local format, find, concat = string.format, string.find, table.concat
+local format, find, concat, gsub, match, gmatch = string.format, string.find, table.concat, string.gsub, string.match, string.gmatch
+local byte, char = utf.byte, utf.char
+local addsuffix = file.addsuffix
+local lpegmatch, validutf8 = lpeg.match, lpeg.patterns.validutf8
scripts = scripts or { }
scripts.patterns = scripts.patterns or { }
+
+local permitted_characters = table.tohash {
+ 0x0009, -- tab
+ 0x0027, -- apostrofe
+ 0x02BC, -- modifier apostrofe (used in greek)
+ 0x002D, -- hyphen
+ 0x200C, -- zwnj
+ 0x2019, -- quote right
+ 0x1FBD, -- greek, but no letter: symbol modifier
+ 0x1FBF, -- greek, but no letter: symbol modifier
+}
+
+local ignored_ancient_greek = table.tohash {
+ 0x1FD3, -- greekiotadialytikatonos (also 0x0390)
+ 0x1FE3, -- greekupsilondialytikatonos (also 0x03B0)
+ 0x1FBD, -- greek, but no letter: symbol modifier
+ 0x1FBF, -- greek, but no letter: symbol modifier
+ 0x03F2, -- greeksigmalunate
+ 0x02BC, -- modifier apostrofe)
+}
+
+local ignored_french = table.tohash {
+ 0x02BC, -- modifier apostrofe
+}
+
+local replaced_whatever = {
+ [char(0x2019)] = char(0x0027)
+}
+
scripts.patterns.list = {
- -- no patterns for arabic
--- { "ar", "hyph-ar.tex", "arabic" },
- -- not supported
--- { "as", "hyph-as.tex", "assamese" },
- { "bg", "hyph-bg.tex", "bulgarian" },
- -- not supported
--- { "bn", "hyph-bn.tex", "bengali" },
- { "ca", "hyph-ca.tex", "catalan" },
- -- not supported
--- { "cop", "hyph-cop.tex", "coptic" },
- { "cs", "hyph-cs.tex", "czech" },
- { "cy", "hyph-cy.tex", "welsh" },
- { "da", "hyph-da.tex", "danish" },
- { "deo", "hyph-de-1901.tex", "german, old spelling" },
- { "de", "hyph-de-1996.tex", "german, new spelling" },
- { "??", "hyph-de-ch-1901.tex", "swiss german" },
---~ { "??", "hyph-el-monoton.tex", "" },
---~ { "??", "hyph-el-polyton.tex", "" },
- { "agr", "hyph-grc.tex", "ancient greek" },
- { "gb", "hyph-en-gb.tex", "british english" },
- { "us", "hyph-en-us.tex", "american english" },
---~ { "gr", "", "" },
- -- these patterns do not satisfy the rules of 'clean patterns'
--- { "eo", "hyph-eo.tex", "esperanto" },
- { "es", "hyph-es.tex", "spanish" },
- { "et", "hyph-et.tex", "estonian" },
- { "eu", "hyph-eu.tex", "basque" },
- -- no patterns for farsi/persian
--- { "fa", "hyph-fa.tex", "farsi" },
- { "fi", "hyph-fi.tex", "finnish" },
- { "fr", "hyph-fr.tex", "french" },
- { "??", "hyph-ga.tex", "irish" },
- { "??", "hyph-gl.tex", "galician" },
- -- not supported
--- { "gu", "hyph-gu.tex", "gujarati" },
- -- not supported
--- { "hi", "hyph-hi.tex", "hindi" },
- { "hr", "hyph-hr.tex", "croatian" },
- { "??", "hyph-hsb.tex", "upper sorbian" },
- { "hu", "hyph-hu.tex", "hungarian" },
- -- not supported
--- { "hy", "hyph-hy.tex", "armenian" },
- { "??", "hyph-ia.tex", "interlingua" },
- { "??", "hyph-id.tex", "indonesian" },
- { "is", "hyph-is.tex", "icelandic" },
- { "it", "hyph-it.tex", "italian" },
- { "??", "hyph-kmr.tex", "kurmanji" },
- -- not supported
--- { "kn", "hyph-kn.tex", "kannada" },
- { "la", "hyph-la.tex", "latin" },
- -- not supported
--- { "lo", "hyph-lo.tex", "lao" },
- { "lt", "hyph-lt.tex", "lithuanian" },
- { "??", "hyph-lv.tex", "latvian" },
- { "mn", "hyph-mn-cyrl.tex", "mongolian, cyrillic script" },
- { "nb", "hyph-nb.tex", "norwegian bokmål" },
- { "nl", "hyph-nl.tex", "dutch" },
- { "nn", "hyph-nn.tex", "norwegian nynorsk" },
- -- not supported
--- { "or", "hyph-or.tex", "oriya" },
- -- not supported
--- { "pa", "hyph-pa.tex", "panjabi" },
- -- not supported
--- { "", "hyph-.tex", "" },
- { "pl", "hyph-pl.tex", "polish" },
- { "pt", "hyph-pt.tex", "portuguese" },
- { "ro", "hyph-ro.tex", "romanian" },
- { "ru", "hyph-ru.tex", "russian" },
- -- not supported
--- { "sa", "hyph-sa.tex", "sanskrit" },
- { "sk", "hyph-sk.tex", "slovak" },
- { "sl", "hyph-sl.tex", "slovenian" },
- -- TODO: there is both Cyrillic and Latin script available
- { "sr", "hyph-sr-cyrl.tex", "serbian" },
- { "sv", "hyph-sv.tex", "swedish" },
- -- not supported
--- { "ta", "hyph-ta.tex", "tamil" },
- -- not supported
--- { "te", "hyph-te.tex", "telugu" },
- { "tk", "hyph-tk.tex", "turkmen" },
- { "tr", "hyph-tr.tex", "turkish" },
- { "uk", "hyph-uk.tex", "ukrainian" },
- { "zh", "hyph-zh-latn.tex", "zh-latn, chinese Pinyin" },
+ -- { "ar", "hyph-ar", "arabic" },
+ -- { "as", "hyph-as", "assamese" },
+ { "bg", "hyph-bg", "bulgarian" },
+ -- { "bn", "hyph-bn", "bengali" },
+ { "ca", "hyph-ca", "catalan" },
+ -- { "??", "hyph-cop", "coptic" },
+ { "cs", "hyph-cs", "czech" },
+ { "cy", "hyph-cy", "welsh" },
+ { "da", "hyph-da", "danish" },
+ { "deo", "hyph-de-1901", "german, old spelling" },
+ { "de", "hyph-de-1996", "german, new spelling" },
+ -- { "??", "hyph-de-ch-1901", "swiss german" },
+ -- { "??", "hyph-el-monoton", "greek" },
+ -- { "gr", "hyph-el-polyton", "greek" },
+ { "agr", "hyph-grc", "ancient greek", ignored_ancient_greek },
+ { "gb", "hyph-en-gb", "british english" },
+ { "us", "hyph-en-us", "american english" },
+ -- { "eo", "hyph-eo", "esperanto" },
+ { "es", "hyph-es", "spanish" },
+ { "et", "hyph-et", "estonian" },
+ { "eu", "hyph-eu", "basque" },
+ -- { "fa", "hyph-fa", "farsi" },
+ { "fi", "hyph-fi", "finnish" },
+ { "fr", "hyph-fr", "french", ignored_french },
+ -- { "??", "hyph-ga", "irish" },
+ -- { "??", "hyph-gl", "galician" },
+ -- { "gu", "hyph-gu", "gujarati" },
+ -- { "hi", "hyph-hi", "hindi" },
+ { "hr", "hyph-hr", "croatian" },
+ -- { "??", "hyph-hsb", "upper sorbian" },
+ { "hu", "hyph-hu", "hungarian" },
+ -- { "hy", "hyph-hy", "armenian" },
+ -- { "??", "hyph-ia", "interlingua" },
+ -- { "??", "hyph-id", "indonesian" },
+ { "is", "hyph-is", "icelandic" },
+ { "it", "hyph-it", "italian" },
+ -- { "??", "hyph-kmr", "kurmanji" },
+ -- { "kn", "hyph-kn", "kannada" },
+ { "la", "hyph-la", "latin" },
+ -- { "lo", "hyph-lo", "lao" },
+ { "lt", "hyph-lt", "lithuanian" },
+ { "lv", "hyph-lv", "latvian" },
+ -- { "ml", "hyph-ml", "..." },
+ { "mn", "hyph-mn-cyrl", "mongolian, cyrillic script" },
+ -- { "mr", "hyph-mr", "..." },
+ { "nb", "hyph-nb", "norwegian bokmål" },
+ { "nl", "hyph-nl", "dutch" },
+ { "nn", "hyph-nn", "norwegian nynorsk" },
+ -- { "or", "hyph-or", "oriya" },
+ -- { "pa", "hyph-pa", "panjabi" },
+ -- { "", "hyph-", "" },
+ { "pl", "hyph-pl", "polish" },
+ { "pt", "hyph-pt", "portuguese" },
+ { "ro", "hyph-ro", "romanian" },
+ { "ru", "hyph-ru", "russian" },
+ -- { "sa", "hyph-sa", "sanskrit" },
+ { "sk", "hyph-sk", "slovak" },
+ { "sl", "hyph-sl", "slovenian" },
+ { "sr", "hyph-sr-cyrl", "serbian" },
+ -- { "sr", "hyph-sr-latn", "serbian" },
+ { "sv", "hyph-sv", "swedish" },
+ -- { "ta", "hyph-ta", "tamil" },
+ -- { "te", "hyph-te", "telugu" },
+ { "tk", "hyph-tk", "turkmen" },
+ { "tr", "hyph-tr", "turkish" },
+ { "uk", "hyph-uk", "ukrainian" },
+ { "zh", "hyph-zh-latn", "zh-latn, chinese pinyin" },
}
-- stripped down from lpeg example:
@@ -105,189 +121,220 @@ function utf.check(str)
return lpeg.match(lpeg.patterns.validutf8,str)
end
-local permitted_commands = table.tohash {
- "message",
- "endinput"
-}
-
-local permitted_characters = table.tohash {
- 0x0009, -- tab
- 0x0027, -- apostrofe
- 0x002D, -- hyphen
- 0x200C, --
-}
+-- *.tex
+-- *.hyp.txt *.pat.txt *.lic.txt *.chr.txt
-function scripts.patterns.load(path,name,mnemonic,fullcheck)
+function scripts.patterns.load(path,name,mnemonic,ignored)
local fullname = file.join(path,name)
- local data = io.loaddata(fullname) or ""
- local byte, char = utf.byte, utf.char
- if data ~= "" then
- data = data:gsub("([\n\r])\\input ([^ \n\r]+)", function(previous,subname)
- local subname = file.addsuffix(subname,"tex")
- local subfull = file.join(file.dirname(fullname),subname)
- local subdata = io.loaddata(subfull) or ""
- if subdata == "" then
- if mnemonic then
- logs.simple("no subfile %s for language %s",subname,mnemonic)
- else
- logs.simple("no subfile %s",name)
+ local texfile = addsuffix(fullname,"tex")
+ local hypfile = addsuffix(fullname,"hyp.txt")
+ local patfile = addsuffix(fullname,"pat.txt")
+ local licfile = addsuffix(fullname,"lic.txt")
+ -- local chrfile = addsuffix(fullname,"chr.txt")
+ local okay = true
+ local hyphenations, patterns, comment, stripset = "", "", "", ""
+ local splitpatternsnew, splithyphenationsnew = { }, { }
+ local splitpatternsold, splithyphenationsold = { }, { }
+ local usedpatterncharacters, usedhyphenationcharacters = { }, { }
+ if lfs.isfile(patfile) then
+ logs.simple("using txt files %s.[hyp|pat|lic].txt",name)
+ comment, patterns, hyphenations = io.loaddata(licfile) or "", io.loaddata(patfile) or "", io.loaddata(hypfile) or ""
+ hypfile, patfile, licfile = hypfile, patfile, licfile
+ elseif lfs.isfile(texfile) then
+ logs.simple("using tex file %s.txt",name)
+ local data = io.loaddata(texfile) or ""
+ if data ~= "" then
+ data = gsub(data,"([\n\r])\\input ([^ \n\r]+)", function(previous,subname)
+ local subname = addsuffix(subname,"tex")
+ local subfull = file.join(file.dirname(texfile),subname)
+ local subdata = io.loaddata(subfull) or ""
+ if subdata == "" then
+ logs.simple("no subfile %s",subname)
end
- end
- return previous .. subdata
- end)
- local comment = data:match("^(.-)[\n\r]\\patterns") or ""
- local n, okay = 0, true
- local cd = characters.data
- for line in data:gmatch("[^ \n\r]+") do
- local ok = utf.check(line)
- n = n + 1
- if not ok then
- okay = false
- line = line:gsub("%%","%%%%")
- if fullcheck then
- if mnemonic then
- logs.simple("invalid utf in language %s, file %s, line %s: %s",mnemonic,name,n,line)
- else
- logs.simple("invalid utf in file %s, line %s: %s",name,n,line)
- end
- else
- if mnemonic then
- logs.simple("file %s for %s contains invalid utf",name,mnemonic)
- else
- logs.simple("file %s contains invalid utf",name)
+ return previous .. subdata
+ end)
+ data = gsub(data,"%%.-[\n\r]","")
+ data = gsub(data," *[\n\r]+","\n")
+ patterns = match(data,"\\patterns[%s]*{[%s]*(.-)[%s]*}") or ""
+ hyphenations = match(data,"\\hyphenation[%s]*{[%s]*(.-)[%s]*}") or ""
+ comment = match(data,"^(.-)[\n\r]\\patterns") or ""
+ else
+ okay = false
+ end
+ else
+ okay = false
+ end
+ if okay then
+ -- split into lines
+ local how = lpeg.patterns.whitespace^1
+ splitpatternsnew = lpeg.split(how,patterns)
+ splithyphenationsnew = lpeg.split(how,hyphenations)
+ end
+ if okay then
+ -- remove comments
+ local function check(data,splitdata,name)
+ if find(data,"%%") then
+ for i=1,#splitdata do
+ local line = splitdata[i]
+ if find(line,"%%") then
+ splitdata[i] = gsub(line,"%%.*$","")
+ logs.simple("removing comment: %s",line)
end
- break
end
end
end
- local c, h = { }, { }
- for line in data:gmatch("[^\n\r]+") do
- local txt, cmt = line:match("^(.-)%%(.*)$")
- if not txt then
- txt, cmt = line, ""
- end
- for s in txt:gmatch("\\([a-zA-Z]+)") do
- h[s] = (h[s] or 0) + 1
- end
- for s in cmt:gmatch("\\([a-zA-Z]+)") do
- c[s] = (c[s] or 0) + 1
- end
- end
- h.patterns = nil
- h.hyphenation = nil
- for k, v in next, h do
- if not permitted_commands[k] then okay = false end
- if mnemonic then
- logs.simple("command \\%s found in language %s, file %s, n=%s",k,mnemonic,name,v)
- else
- logs.simple("command \\%s found in file %s, n=%s",k,name,v)
+ check(patterns,splitpatternsnew,patfile)
+ check(hyphenations,splithyphenationsnew,hypfile)
+ end
+ if okay then
+ -- remove lines with commands
+ local function check(data,splitdata,name)
+ if find(data,"\\") then
+ for i=1,#splitdata do
+ local line = splitdata[i]
+ if find(line,"\\") then
+ splitdata[i] = ""
+ logs.simple("removing line with command: %s",line)
+ end
+ end
end
end
- if not environment.argument("fast") then
- for k, v in next, c do
- if mnemonic then
- logs.simple("command \\%s found in comment of language %s, file %s, n=%s",k,mnemonic,name,v)
- else
- logs.simple("command \\%s found in comment of file %s, n=%s",k,name,v)
+ check(patterns,splitpatternsnew,patfile)
+ check(hyphenations,splithyphenationsnew,hypfile)
+ end
+ if okay then
+ -- check for valid utf
+ local function check(data,splitdata,name)
+ for i=1,#splitdata do
+ local line = splitdata[i]
+ local ok = lpegmatch(validutf8,line)
+ if not ok then
+ splitdata[i] = ""
+ logs.simple("removing line with invalid utf: %s",line)
end
end
+ -- check for commands being used in comments
end
- data = data:gsub("%%.-[\n\r]","")
- data = data:gsub(" *[\n\r]+","\n")
- local patterns = data:match("\\patterns[%s]*{[%s]*(.-)[%s]*}") or ""
- local hyphenations = data:match("\\hyphenation[%s]*{[%s]*(.-)[%s]*}") or ""
- patterns = patterns:gsub("[ \t]+","\n")
- hyphenations = hyphenations:gsub("[ \t]+","\n")
- local p, h = { }, { }
- local pats, hyps = { } , { }
- local pused, hused = { } , { }
- local period = byte(".")
- for line in patterns:gmatch("[^ \n\r]+") do
- local ok = true
- for b in line:utfvalues() do
- if b == period then
- -- ok
- else
- local ct = cd[b].category
- if ct == "lu" or ct == "ll" then
- pused[char(b)] = true
- elseif ct == "nd" then
- -- ok
+ check(patterns,splitpatternsnew,patfile)
+ check(hyphenations,splithyphenationsnew,hypfile)
+ end
+ if okay then
+ -- remove funny lines
+ local cd = characters.data
+ local stripped = { }
+ local function check(splitdata,special,name)
+ local used = { }
+ for i=1,#splitdata do
+ local line = splitdata[i]
+ for b in line:utfvalues() do -- could be an lpeg
+ if b == special then
+ -- not registered
+ elseif permitted_characters[b] then
+ used[char(b)] = true
else
- p[b] = (p[b] or 0) + 1
- ok = false
+ local cdb = cd[b]
+ if not cdb then
+ logs.simple("no entry in chardata for character %s (0x%04X)",char(b),b)
+ else
+ local ct = cd[b].category
+ if ct == "lu" or ct == "ll" then
+ used[char(b)] = true
+ elseif ct == "nd" then
+ -- number
+ else
+ logs.simple("removing line with suspected utf character %s (0x%04X), category %s: %s",char(b),b,ct,line)
+ splitdata[i] = ""
+ break
+ end
+ end
end
end
end
- if ok then
- pats[#pats+1] = line
- end
+ return used
end
- local hyphen = byte("-")
- for line in hyphenations:gmatch("[^ \n\r]+") do
- local ok = true
- for b in line:utfvalues() do
- if b == hyphen then
- -- ok
- else
- local ct = cd[b].category
- if ct == "lu" or ct == "ll" then
- hused[char(b)] = true
+ usedpatterncharacters = check(splitpatternsnew,byte("."))
+ usedhyphenationcharacters = check(splithyphenationsnew,byte("-"))
+ for k, v in next, stripped do
+ logs.simple("entries that contain character %s (0x%04X) have been omitted",char(k),k)
+ end
+ end
+ if okay then
+ local function stripped(what,ignored)
+ -- ignored (per language)
+ local p = nil
+ if ignored then
+ for k, v in next, ignored do
+ if p then
+ p = p + lpeg.P(char(k))
else
- h[b] = (h[b] or 0) + 1
- ok = false
+ p = lpeg.P(char(k))
end
end
+ p = lpeg.P{ p + 1 * lpeg.V(1) } -- anywhere
end
- if ok then
- hyps[#hyps+1] = line
- end
- end
- local stripped = { }
- for k, v in next, p do
- if mnemonic then
- logs.simple("invalid character %s (0x%04X) in patterns of language %s, file %s, n=%s",char(k),k,mnemonic,name,v)
- else
- logs.simple("invalid character %s (0x%04X) in patterns of file %s, n=%s",char(k),k,name,v)
+ -- replaced (all languages)
+ local r = nil
+ for k, v in next, replaced_whatever do
+ if r then
+ r = r + lpeg.P(k)/v
+ else
+ r = lpeg.P(k)/v
+ end
end
- if not permitted_characters[k] then
- okay = false
- else
- stripped[k] = true
+ r = lpeg.Cs((r + 1)^0)
+ local result = { }
+ for i=1,#what do
+ local line = what[i]
+ if p and lpegmatch(p,line) then
+ logs.simple("discarding conflicting pattern: %s",line)
+ else -- we can speed this up by testing for replacements in the string
+ local l = lpegmatch(r,line)
+ if l ~= line then
+ logs.simple("sanitizing pattern: %s -> %s (for old patterns)",line,l)
+ end
+ result[#result+1] = l
+ end
end
+ return result
end
- for k, v in next, h do
- if mnemonic then
- logs.simple("invalid character %s (0x%04X) in exceptions of language %s, file %s, n=%s",char(k),k,mnemonic,name,v)
- else
- logs.simple("invalid character %s (0x%04X) in exceptions of file %s, n=%s",char(k),k,name,v)
- end
- if not permitted_characters[k] then
- okay = false
- else
- stripped[k] = true
+
+ splitpatternsold = stripped(splitpatternsnew,ignored)
+ splithyphenationsold = stripped(splithyphenationsnew,ignored)
+
+ end
+ if okay then
+ -- discarding duplicates
+ local function check(data,splitdata,name)
+ local used, collected = { }, { }
+ for i=1,#splitdata do
+ local line = splitdata[i]
+ if line == "" then
+ -- discard
+ elseif used[line] then
+ -- discard
+ logs.simple("discarding duplicate pattern: %s",line)
+ else
+ used[line] = true
+ collected[#collected+1] = line
+ end
end
+ return collected
end
- local stripset = ""
- for k, v in next, stripped do
- logs.simple("entries that contain character %s will be omitted",char(k))
- stripset = stripset .. "%" .. char(k)
- end
- return okay, pats, hyps, comment, stripset, pused, hused
- else
- if mnemonic then
- logs.simple("no file %s for language %s",fullname,mnemonic)
- else
- logs.simple("no file %s",fullname)
- end
- return false, { }, { }, "", "", { }, { }
+ splitpatternsnew = check(patterns,splitpatternsnew,patfile)
+ splithyphenationsnew = check(hyphenations,splithyphenationsnew,hypfile)
+ splitpatternsold = check(patterns,splitpatternsold,patfile)
+ splithyphenationsold = check(hyphenations,splithyphenationsold,hypfile)
+ end
+ if not okay then
+ logs.simple("no valid file %s.*",name)
end
+ return okay, splitpatternsnew, splithyphenationsnew, splitpatternsold, splithyphenationsold, comment, stripset, usedpatterncharacters, usedhyphenationcharacters
end
-function scripts.patterns.save(destination,mnemonic,name,patterns,hyphenations,comment,stripped,pused,hused)
- local nofpatterns = #patterns
- local nofhyphenations = #hyphenations
- logs.simple("language %s has %s patterns and %s exceptions",mnemonic,nofpatterns,nofhyphenations)
+function scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenationsnew,patternsold,hyphenationsold,comment,stripped,pused,hused,ignored)
+ local nofpatternsnew, nofhyphenationsnew = #patternsnew, #hyphenationsnew
+ local nofpatternsold, nofhyphenationsold = #patternsold, #hyphenationsold
+ logs.simple("language %s has %s old and %s new patterns and %s old and %s new exceptions",mnemonic,nofpatternsold,nofpatternsnew,nofhyphenationsold,nofhyphenationsnew)
if mnemonic ~= "??" then
local pu = concat(table.sortedkeys(pused), " ")
local hu = concat(table.sortedkeys(hused), " ")
@@ -318,28 +365,28 @@ function scripts.patterns.save(destination,mnemonic,name,patterns,hyphenations,c
}
local patterndata, hyphenationdata
- if nofpatterns > 0 then
+ if nofpatternsnew > 0 then
patterndata = {
- n = nofpatterns,
- data = concat(patterns," ") or nil,
+ n = nofpatternsnew,
+ data = concat(patternsnew," ") or nil,
characters = concat(table.sortedkeys(pused),""),
minhyphenmin = 1, -- determined by pattern author
minhyphenmax = 1, -- determined by pattern author
}
else
patterndata = {
- n = nofpatterns,
+ n = 0,
}
end
- if nofhyphenations > 0 then
+ if nofhyphenationsnew > 0 then
hyphenationdata = {
- n = nofhyphenations,
- data = concat(hyphenations," "),
+ n = nofhyphenationsnew,
+ data = concat(hyphenationsnew," "),
characters = concat(table.sortedkeys(hused),""),
}
else
hyphenationdata = {
- n = nofhyphenations,
+ n = 0,
}
end
local data = {
@@ -358,8 +405,8 @@ function scripts.patterns.save(destination,mnemonic,name,patterns,hyphenations,c
os.remove(luafile)
io.savedata(rmefile,format("%s\n\n%s",topline,comment))
- io.savedata(patfile,format("%s\n\n%s\n\n%% used: %s\n\n\\patterns{\n%s}",topline,banner,pu,concat(patterns,"\n")))
- io.savedata(hypfile,format("%s\n\n%s\n\n%% used: %s\n\n\\hyphenation{\n%s}",topline,banner,hu,concat(hyphenations,"\n")))
+ io.savedata(patfile,format("%s\n\n%s\n\n%% used: %s\n\n\\patterns{\n%s}",topline,banner,pu,concat(patternsold,"\n")))
+ io.savedata(hypfile,format("%s\n\n%s\n\n%% used: %s\n\n\\hyphenation{\n%s}",topline,banner,hu,concat(hyphenationsold,"\n")))
io.savedata(luafile,table.serialize(data,true))
end
end
@@ -370,22 +417,16 @@ end
function scripts.patterns.check()
local path = environment.argument("path") or "."
- local found = false
local files = environment.files
+ local only = false
if #files > 0 then
- for i=1,#files do
- local name = files[i]
- logs.simple("checking language file %s", name)
- local okay = scripts.patterns.load(path,name,nil,not environment.argument("fast"))
- if #environment.files > 1 then
- logs.simple("")
- end
- end
- else
- for k, v in next, scripts.patterns.list do
- local mnemonic, name = v[1], v[2]
+ only = table.tohash(files)
+ end
+ for k, v in next, scripts.patterns.list do
+ local mnemonic, name, ignored = v[1], v[2], v[4]
+ if not only or only[mnemonic] then
logs.simple("checking language %s, file %s", mnemonic, name)
- local okay = scripts.patterns.load(path,name,mnemonic,not environment.argument("fast"))
+ local okay = scripts.patterns.load(path,name,mnemonic,ignored)
if not okay then
logs.simple("there are errors that need to be fixed")
end
@@ -403,16 +444,23 @@ function scripts.patterns.convert()
if path == destination then
logs.simple("source path and destination path should differ (use --path and/or --destination)")
else
+ local files = environment.files
+ local only = false
+ if #files > 0 then
+ only = table.tohash(files)
+ end
for k, v in next, scripts.patterns.list do
- local mnemonic, name = v[1], v[2]
- logs.simple("converting language %s, file %s", mnemonic, name)
- local okay, patterns, hyphenations, comment, stripped, pused, hused = scripts.patterns.load(path,name,false)
- if okay then
- scripts.patterns.save(destination,mnemonic,name,patterns,hyphenations,comment,stripped,pused,hused)
- else
- logs.simple("convertion aborted due to error(s)")
+ local mnemonic, name, ignored = v[1], v[2], v[4]
+ if not only or only[mnemonic] then
+ logs.simple("converting language %s, file %s", mnemonic, name)
+ local okay, patternsnew, hyphenationsnew, patternsold, hyphenationsold, comment, stripped, pused, hused = scripts.patterns.load(path,name,mnemonic,ignored)
+ if okay then
+ scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenationsnew,patternsold,hyphenationsold,comment,stripped,pused,hused,ignored)
+ else
+ logs.simple("convertion aborted due to error(s)")
+ end
+ logs.simple("")
end
- logs.simple("")
end
end
end
@@ -425,8 +473,6 @@ messages.help = [[
--check check pattern file (or those used by context when no file given)
--path source path where hyph-foo.tex files are stored
--destination destination path
-
---fast only report filenames, no lines
]]
if environment.argument("check") then
@@ -441,6 +487,5 @@ end
-- mtxrun --script pattern --check hyph-*.tex
-- mtxrun --script pattern --check --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns
--- mtxrun --script pattern --check --fast --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns
--- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns --destination=e:/tmp/patterns
--- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/branches/luatex/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns
+-- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns
+-- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns
diff --git a/scripts/context/lua/mtx-server-ctx-fonttest.lua b/scripts/context/lua/mtx-server-ctx-fonttest.lua
index b2a993bf8..4415cbd5d 100644
--- a/scripts/context/lua/mtx-server-ctx-fonttest.lua
+++ b/scripts/context/lua/mtx-server-ctx-fonttest.lua
@@ -17,7 +17,7 @@ local format, gsub, concat, match, find = string.format, string.gsub, table.conc
local sample_line = "This is a sample line!"
local tempname = "mtx-server-ctx-fonttest-temp"
-local temppath = caches.setpath("temp","mtx-server-ctx-fonttest")
+local temppath = caches.setfirstwritablefile("temp","mtx-server-ctx-fonttest")
local basename = "mtx-server-ctx-fonttest-data.lua"
local basepath = temppath
diff --git a/scripts/context/lua/mtx-server.lua b/scripts/context/lua/mtx-server.lua
index dc0befcaa..b1d1174bb 100644
--- a/scripts/context/lua/mtx-server.lua
+++ b/scripts/context/lua/mtx-server.lua
@@ -358,4 +358,4 @@ else
end
--- mtxrun --script server --start => http://localhost:8080/mtx-server-ctx-help.lua
+-- mtxrun --script server --start => http://localhost:31415/mtx-server-ctx-startup.lua
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index ac4b0556e..68ee3d2c1 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -347,7 +347,8 @@ patterns.hexadecimal = P("0x") * R("09","AF","af")^1
patterns.lowercase = R("az")
patterns.uppercase = R("AZ")
patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = S(" ")
+patterns.space = P(" ")
+patterns.tab = P("\t")
patterns.eol = S("\n\r")
patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
patterns.newline = crlf + cr + lf
@@ -358,6 +359,9 @@ patterns.nonwhitespace = 1 - patterns.whitespace
patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
@@ -462,15 +466,36 @@ local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 6
patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+
local cache = { }
function lpeg.stripper(str)
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
end
- return s
end
function lpeg.replacer(t)
@@ -642,7 +667,7 @@ end
table.sortedkeys = sortedkeys
table.sortedhashkeys = sortedhashkeys
-function table.sortedhash(t)
+local function sortedhash(t)
local s = sortedhashkeys(t) -- maybe just sortedkeys
local n = 0
local function kv(s)
@@ -653,7 +678,8 @@ function table.sortedhash(t)
return kv, s
end
-table.sortedpairs = table.sortedhash
+table.sortedhash = sortedhash
+table.sortedpairs = sortedhash
function table.append(t, list)
for _,v in next, list do
@@ -1315,12 +1341,17 @@ function table.count(t)
return n
end
-function table.swapped(t)
- local s = { }
+function table.swapped(t,s)
+ local n = { }
+ if s then
+ for k, v in next, s do
+ n[k] = v
+ end
+ end
for k, v in next, t do
- s[v] = k
+ n[v] = k
end
- return s
+ return n
end
@@ -1340,7 +1371,7 @@ function table.hexed(t,seperator)
return concat(tt,seperator or " ")
end
-function table.reverse_hash(h)
+function table.reverse_hash(h) -- needs another name
local r = { }
for k,v in next, h do
r[v] = lower(gsub(k," ",""))
@@ -1388,10 +1419,18 @@ function table.insert_after_value(t,value,extra)
insert(t,#t+1,extra)
end
-function table.sequenced(t,sep)
+function table.sequenced(t,sep,simple) -- hash only
local s = { }
- for k, v in next, t do -- indexed?
- s[#s+1] = k .. "=" .. tostring(v)
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ s[#s+1] = k
+ elseif v and v~= "" then
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
+ else
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
end
return concat(s, sep or " | ")
end
@@ -1593,6 +1632,39 @@ function io.ask(question,default,options)
end
end
+function io.readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ if n == 1 then
+ return byte(f:read(1))
+ elseif n == 2 then
+ local a, b = byte(f:read(2),1,2)
+ return 256*a + b
+ elseif n == 4 then
+ local a, b, c, d = byte(f:read(4),1,4)
+ return 256^3 * a + 256^2 * b + 256*c + d
+ elseif n == 8 then
+ local a, b = readnumber(f,4), readnumber(f,4)
+ return 256 * b + c
+ elseif n == 12 then
+ local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
+ return 256^2 * a + 256 * b + c
+ else
+ return 0
+ end
+end
+
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ local str = gsub(f:read(n),"%z","")
+ return str
+end
+
end -- of closure
@@ -1658,6 +1730,23 @@ function number.bits(n,zero)
end
+function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+end
+
+function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+end
+
+function number.setbit(x, p)
+ return hasbit(x, p) and x or x + p
+end
+
+function number.clearbit(x, p)
+ return hasbit(x, p) and x - p or x
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3023,7 +3112,7 @@ end
utf = utf or unicode.utf8
local concat, utfchar, utfgsub = table.concat, utf.char, utf.gsub
-local char, byte, find, bytepairs = string.char, string.byte, string.find, string.bytepairs
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -3189,6 +3278,15 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
+function unicode.utfcodes(str)
+ local t = { }
+ for k,v in string.utfvalues(str) do
+ t[#t+1] = format("0x%04X",k)
+ end
+ return concat(t,separator or " ")
+end
+
+
end -- of closure
@@ -3568,14 +3666,24 @@ function aux.array_to_string(a,separator)
end
end
-function aux.settings_to_set(str,t)
+function aux.settings_to_set(str,t) -- tohash?
t = t or { }
- for s in gmatch(str,"%s*([^,]+)") do
+ for s in gmatch(str,"%s*([^, ]+)") do -- space added
t[s] = true
end
return t
end
+function aux.simple_hash_to_string(h, separator)
+ local t = { }
+ for k, v in table.sortedhash(h) do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t,separator or ",")
+end
+
local value = lbrace * lpeg.C((nobrace + nested)^0) * rbrace
local pattern = lpeg.Ct((space + value)^0)
@@ -3637,6 +3745,60 @@ end
-- as we use this a lot ...
+function aux.formatcolumns(result,between)
+ if result and #result > 0 then
+ between = between or " "
+ local widths, numbers = { }, { }
+ local first = result[1]
+ local n = #first
+ for i=1,n do
+ widths[i] = 0
+ end
+ for i=1,#result do
+ local r = result[i]
+ for j=1,n do
+ local rj = r[j]
+ local tj = type(rj)
+ if tj == "number" then
+ numbers[j] = true
+ end
+ if tj ~= "string" then
+ rj = tostring(rj)
+ r[j] = rj
+ end
+ local w = #rj
+ if w > widths[j] then
+ widths[j] = w
+ end
+ end
+ end
+ for i=1,n do
+ local w = widths[i]
+ if numbers[i] then
+ if w > 80 then
+ widths[i] = "%s" .. between
+ else
+ widths[i] = "%0" .. w .. "i" .. between
+ end
+ else
+ if w > 80 then
+ widths[i] = "%s" .. between
+ elseif w > 0 then
+ widths[i] = "%-" .. w .. "s" .. between
+ else
+ widths[i] = "%s"
+ end
+ end
+ end
+ local template = string.strip(concat(widths))
+ for i=1,#result do
+ local str = format(template,unpack(result[i]))
+ result[i] = string.strip(str)
+ end
+ end
+ return result
+end
+
end -- of closure
@@ -3843,7 +4005,7 @@ if not modules then modules = { } end modules ['trac-set'] = {
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub = string.format, string.find, string.lower, string.gsub
+local format, find, lower, gsub, simpleesc = string.format, string.find, string.lower, string.gsub, string.simpleesc
local is_boolean = string.is_boolean
setters = { }
@@ -3915,7 +4077,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,w) then
+ elseif find(name,simpleesc(w)) then
done[name] = true
for i=1,#functions do
functions[i](value)
@@ -3979,14 +4141,14 @@ end
function setters.enable(t,what)
local e = t.enable
t.enable, t.done = enable, { }
- enable(t,string.simpleesc(tostring(what)))
+ enable(t,what)
t.enable, t.done = e, { }
end
function setters.disable(t,what)
local e = t.disable
t.disable, t.done = disable, { }
- disable(t,string.simpleesc(tostring(what)))
+ disable(t,what)
t.disable, t.done = e, { }
end
@@ -4050,36 +4212,50 @@ trackers = setters.new("trackers")
directives = setters.new("directives")
experiments = setters.new("experiments")
+-- experiment
+
+if trackers and environment and environment.engineflags.trackers then
+ trackers.enable(environment.engineflags.trackers)
+end
+if directives and environment and environment.engineflags.directives then
+ directives.enable(environment.engineflags.directives)
+end
+
-- nice trick: we overload two of the directives related functions with variants that
-- do tracing (itself using a tracker) .. proof of concept
+local function report(...) -- messy .. chicken or egg
+ local p = (commands and commands.writestatus) or (logs and logs.report)
+ if p then p(...) end
+end
+
local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
-local e = directives.enable
-local d = directives.disable
+local enable = directives.enable
+local disable = directives.disable
function directives.enable(...)
- (commands.writestatus or logs.report)("directives","enabling: %s",concat({...}," "))
- e(...)
+ report("directives","enabling: %s",concat({...}," "))
+ enable(...)
end
function directives.disable(...)
- (commands.writestatus or logs.report)("directives","disabling: %s",concat({...}," "))
- d(...)
+ report("directives","disabling: %s",concat({...}," "))
+ disable(...)
end
-local e = experiments.enable
-local d = experiments.disable
+local enable = experiments.enable
+local disable = experiments.disable
function experiments.enable(...)
- (commands.writestatus or logs.report)("experiments","enabling: %s",concat({...}," "))
- e(...)
+ report("experiments","enabling: %s",concat({...}," "))
+ enable(...)
end
function experiments.disable(...)
- (commands.writestatus or logs.report)("experiments","disabling: %s",concat({...}," "))
- d(...)
+ report("experiments","disabling: %s",concat({...}," "))
+ disable(...)
end
-- a useful example
@@ -4088,6 +4264,15 @@ directives.register("system.nostatistics", function(v)
statistics.enable = not v
end)
+-- experiment
+
+if trackers and environment and environment.engineflags.trackers then
+ trackers.enable(environment.engineflags.trackers)
+end
+if directives and environment and environment.engineflags.directives then
+ directives.enable(environment.engineflags.directives)
+end
+
end -- of closure
@@ -6357,17 +6542,19 @@ apply_axis['child'] = function(list)
for l=1,#list do
local ll = list[l]
local dt = ll.dt
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- collected[#collected+1] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ if dt then -- weird that this is needed
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ collected[#collected+1] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ end
end
+ ll.en = en
end
- ll.en = en
end
return collected
end
@@ -8079,6 +8266,7 @@ local finalizers = xml.finalizers.xml
local xmlfilter = xml.filter -- we could inline this one for speed
local xmltostring = xml.tostring
local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -8356,6 +8544,19 @@ xml.all = xml.filter
xml.index = xml.position
xml.found = xml.filter
+-- a nice one:
+
+local function totable(x)
+ local t = { }
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg] = xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+
+xml.table = totable
+finalizers.table = totable
+
end -- of closure
@@ -8943,6 +9144,7 @@ formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', '
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
formats['fea'] = 'FONTFEATURES' suffixes['fea'] = { 'fea' }
formats['cid'] = 'FONTCIDMAPS' suffixes['cid'] = { 'cid', 'cidmap' }
+formats['icc'] = 'ICCPROFILES' suffixes['icc'] = { 'icc' }
formats['texmfscripts'] = 'TEXMFSCRIPTS' suffixes['texmfscripts'] = { 'rb', 'pl', 'py' }
formats['lua'] = 'LUAINPUTS' suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' }
formats['lib'] = 'CLUAINPUTS' suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' }
@@ -8958,6 +9160,7 @@ alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
+alternatives['icc profiles'] = 'icc'
--[[ldx--
<p>If you wondered about some of the previous mappings, how about
@@ -12160,6 +12363,21 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
-- helper for mtxrun
+local quote = string.quote
+
+local function primaryflags()
+ local trackers = environment.argument("trackers")
+ local directives = environment.argument("directives")
+ local flags = ""
+ if trackers and trackers ~= "" then
+ flags = flags .. "--trackers=" .. quote(trackers)
+ end
+ if directives and directives ~= "" then
+ flags = flags .. "--directives=" .. quote(directives)
+ end
+ return flags
+end
+
function environment.make_format(name)
-- change to format path (early as we need expanded paths)
local olddir = lfs.currentdir()
@@ -12220,8 +12438,7 @@ function environment.make_format(name)
return
end
-- generate format
- local q = string.quote
- local command = string.format("luatex --ini --lua=%s %s %sdump",q(usedluastub),q(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = string.format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -12260,7 +12477,7 @@ function environment.run_format(name,data,more)
logs.simple("no luc/lua with name: %s",barename)
else
local q = string.quote
- local command = string.format("luatex --fmt=%s --lua=%s %s %s",q(barename),q(luaname),q(data),more ~= "" and q(more) or "")
+ local command = string.format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index ac4b0556e..68ee3d2c1 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -347,7 +347,8 @@ patterns.hexadecimal = P("0x") * R("09","AF","af")^1
patterns.lowercase = R("az")
patterns.uppercase = R("AZ")
patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = S(" ")
+patterns.space = P(" ")
+patterns.tab = P("\t")
patterns.eol = S("\n\r")
patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
patterns.newline = crlf + cr + lf
@@ -358,6 +359,9 @@ patterns.nonwhitespace = 1 - patterns.whitespace
patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
@@ -462,15 +466,36 @@ local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 6
patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+
local cache = { }
function lpeg.stripper(str)
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
end
- return s
end
function lpeg.replacer(t)
@@ -642,7 +667,7 @@ end
table.sortedkeys = sortedkeys
table.sortedhashkeys = sortedhashkeys
-function table.sortedhash(t)
+local function sortedhash(t)
local s = sortedhashkeys(t) -- maybe just sortedkeys
local n = 0
local function kv(s)
@@ -653,7 +678,8 @@ function table.sortedhash(t)
return kv, s
end
-table.sortedpairs = table.sortedhash
+table.sortedhash = sortedhash
+table.sortedpairs = sortedhash
function table.append(t, list)
for _,v in next, list do
@@ -1315,12 +1341,17 @@ function table.count(t)
return n
end
-function table.swapped(t)
- local s = { }
+function table.swapped(t,s)
+ local n = { }
+ if s then
+ for k, v in next, s do
+ n[k] = v
+ end
+ end
for k, v in next, t do
- s[v] = k
+ n[v] = k
end
- return s
+ return n
end
@@ -1340,7 +1371,7 @@ function table.hexed(t,seperator)
return concat(tt,seperator or " ")
end
-function table.reverse_hash(h)
+function table.reverse_hash(h) -- needs another name
local r = { }
for k,v in next, h do
r[v] = lower(gsub(k," ",""))
@@ -1388,10 +1419,18 @@ function table.insert_after_value(t,value,extra)
insert(t,#t+1,extra)
end
-function table.sequenced(t,sep)
+function table.sequenced(t,sep,simple) -- hash only
local s = { }
- for k, v in next, t do -- indexed?
- s[#s+1] = k .. "=" .. tostring(v)
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ s[#s+1] = k
+ elseif v and v~= "" then
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
+ else
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
end
return concat(s, sep or " | ")
end
@@ -1593,6 +1632,39 @@ function io.ask(question,default,options)
end
end
+function io.readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ if n == 1 then
+ return byte(f:read(1))
+ elseif n == 2 then
+ local a, b = byte(f:read(2),1,2)
+ return 256*a + b
+ elseif n == 4 then
+ local a, b, c, d = byte(f:read(4),1,4)
+ return 256^3 * a + 256^2 * b + 256*c + d
+ elseif n == 8 then
+ local a, b = readnumber(f,4), readnumber(f,4)
+ return 256 * b + c
+ elseif n == 12 then
+ local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
+ return 256^2 * a + 256 * b + c
+ else
+ return 0
+ end
+end
+
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ local str = gsub(f:read(n),"%z","")
+ return str
+end
+
end -- of closure
@@ -1658,6 +1730,23 @@ function number.bits(n,zero)
end
+function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+end
+
+function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+end
+
+function number.setbit(x, p)
+ return hasbit(x, p) and x or x + p
+end
+
+function number.clearbit(x, p)
+ return hasbit(x, p) and x - p or x
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3023,7 +3112,7 @@ end
utf = utf or unicode.utf8
local concat, utfchar, utfgsub = table.concat, utf.char, utf.gsub
-local char, byte, find, bytepairs = string.char, string.byte, string.find, string.bytepairs
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -3189,6 +3278,15 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
+function unicode.utfcodes(str)
+ local t = { }
+ for k,v in string.utfvalues(str) do
+ t[#t+1] = format("0x%04X",k)
+ end
+ return concat(t,separator or " ")
+end
+
+
end -- of closure
@@ -3568,14 +3666,24 @@ function aux.array_to_string(a,separator)
end
end
-function aux.settings_to_set(str,t)
+function aux.settings_to_set(str,t) -- tohash?
t = t or { }
- for s in gmatch(str,"%s*([^,]+)") do
+ for s in gmatch(str,"%s*([^, ]+)") do -- space added
t[s] = true
end
return t
end
+function aux.simple_hash_to_string(h, separator)
+ local t = { }
+ for k, v in table.sortedhash(h) do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t,separator or ",")
+end
+
local value = lbrace * lpeg.C((nobrace + nested)^0) * rbrace
local pattern = lpeg.Ct((space + value)^0)
@@ -3637,6 +3745,60 @@ end
-- as we use this a lot ...
+function aux.formatcolumns(result,between)
+ if result and #result > 0 then
+ between = between or " "
+ local widths, numbers = { }, { }
+ local first = result[1]
+ local n = #first
+ for i=1,n do
+ widths[i] = 0
+ end
+ for i=1,#result do
+ local r = result[i]
+ for j=1,n do
+ local rj = r[j]
+ local tj = type(rj)
+ if tj == "number" then
+ numbers[j] = true
+ end
+ if tj ~= "string" then
+ rj = tostring(rj)
+ r[j] = rj
+ end
+ local w = #rj
+ if w > widths[j] then
+ widths[j] = w
+ end
+ end
+ end
+ for i=1,n do
+ local w = widths[i]
+ if numbers[i] then
+ if w > 80 then
+ widths[i] = "%s" .. between
+ else
+ widths[i] = "%0" .. w .. "i" .. between
+ end
+ else
+ if w > 80 then
+ widths[i] = "%s" .. between
+ elseif w > 0 then
+ widths[i] = "%-" .. w .. "s" .. between
+ else
+ widths[i] = "%s"
+ end
+ end
+ end
+ local template = string.strip(concat(widths))
+ for i=1,#result do
+ local str = format(template,unpack(result[i]))
+ result[i] = string.strip(str)
+ end
+ end
+ return result
+end
+
end -- of closure
@@ -3843,7 +4005,7 @@ if not modules then modules = { } end modules ['trac-set'] = {
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub = string.format, string.find, string.lower, string.gsub
+local format, find, lower, gsub, simpleesc = string.format, string.find, string.lower, string.gsub, string.simpleesc
local is_boolean = string.is_boolean
setters = { }
@@ -3915,7 +4077,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,w) then
+ elseif find(name,simpleesc(w)) then
done[name] = true
for i=1,#functions do
functions[i](value)
@@ -3979,14 +4141,14 @@ end
function setters.enable(t,what)
local e = t.enable
t.enable, t.done = enable, { }
- enable(t,string.simpleesc(tostring(what)))
+ enable(t,what)
t.enable, t.done = e, { }
end
function setters.disable(t,what)
local e = t.disable
t.disable, t.done = disable, { }
- disable(t,string.simpleesc(tostring(what)))
+ disable(t,what)
t.disable, t.done = e, { }
end
@@ -4050,36 +4212,50 @@ trackers = setters.new("trackers")
directives = setters.new("directives")
experiments = setters.new("experiments")
+-- experiment
+
+if trackers and environment and environment.engineflags.trackers then
+ trackers.enable(environment.engineflags.trackers)
+end
+if directives and environment and environment.engineflags.directives then
+ directives.enable(environment.engineflags.directives)
+end
+
-- nice trick: we overload two of the directives related functions with variants that
-- do tracing (itself using a tracker) .. proof of concept
+local function report(...) -- messy .. chicken or egg
+ local p = (commands and commands.writestatus) or (logs and logs.report)
+ if p then p(...) end
+end
+
local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
-local e = directives.enable
-local d = directives.disable
+local enable = directives.enable
+local disable = directives.disable
function directives.enable(...)
- (commands.writestatus or logs.report)("directives","enabling: %s",concat({...}," "))
- e(...)
+ report("directives","enabling: %s",concat({...}," "))
+ enable(...)
end
function directives.disable(...)
- (commands.writestatus or logs.report)("directives","disabling: %s",concat({...}," "))
- d(...)
+ report("directives","disabling: %s",concat({...}," "))
+ disable(...)
end
-local e = experiments.enable
-local d = experiments.disable
+local enable = experiments.enable
+local disable = experiments.disable
function experiments.enable(...)
- (commands.writestatus or logs.report)("experiments","enabling: %s",concat({...}," "))
- e(...)
+ report("experiments","enabling: %s",concat({...}," "))
+ enable(...)
end
function experiments.disable(...)
- (commands.writestatus or logs.report)("experiments","disabling: %s",concat({...}," "))
- d(...)
+ report("experiments","disabling: %s",concat({...}," "))
+ disable(...)
end
-- a useful example
@@ -4088,6 +4264,15 @@ directives.register("system.nostatistics", function(v)
statistics.enable = not v
end)
+-- experiment
+
+if trackers and environment and environment.engineflags.trackers then
+ trackers.enable(environment.engineflags.trackers)
+end
+if directives and environment and environment.engineflags.directives then
+ directives.enable(environment.engineflags.directives)
+end
+
end -- of closure
@@ -6357,17 +6542,19 @@ apply_axis['child'] = function(list)
for l=1,#list do
local ll = list[l]
local dt = ll.dt
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- collected[#collected+1] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ if dt then -- weird that this is needed
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ collected[#collected+1] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ end
end
+ ll.en = en
end
- ll.en = en
end
return collected
end
@@ -8079,6 +8266,7 @@ local finalizers = xml.finalizers.xml
local xmlfilter = xml.filter -- we could inline this one for speed
local xmltostring = xml.tostring
local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -8356,6 +8544,19 @@ xml.all = xml.filter
xml.index = xml.position
xml.found = xml.filter
+-- a nice one:
+
+local function totable(x)
+ local t = { }
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg] = xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+
+xml.table = totable
+finalizers.table = totable
+
end -- of closure
@@ -8943,6 +9144,7 @@ formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', '
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
formats['fea'] = 'FONTFEATURES' suffixes['fea'] = { 'fea' }
formats['cid'] = 'FONTCIDMAPS' suffixes['cid'] = { 'cid', 'cidmap' }
+formats['icc'] = 'ICCPROFILES' suffixes['icc'] = { 'icc' }
formats['texmfscripts'] = 'TEXMFSCRIPTS' suffixes['texmfscripts'] = { 'rb', 'pl', 'py' }
formats['lua'] = 'LUAINPUTS' suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' }
formats['lib'] = 'CLUAINPUTS' suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' }
@@ -8958,6 +9160,7 @@ alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
+alternatives['icc profiles'] = 'icc'
--[[ldx--
<p>If you wondered about some of the previous mappings, how about
@@ -12160,6 +12363,21 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
-- helper for mtxrun
+local quote = string.quote
+
+local function primaryflags()
+ local trackers = environment.argument("trackers")
+ local directives = environment.argument("directives")
+ local flags = ""
+ if trackers and trackers ~= "" then
+ flags = flags .. "--trackers=" .. quote(trackers)
+ end
+ if directives and directives ~= "" then
+ flags = flags .. "--directives=" .. quote(directives)
+ end
+ return flags
+end
+
function environment.make_format(name)
-- change to format path (early as we need expanded paths)
local olddir = lfs.currentdir()
@@ -12220,8 +12438,7 @@ function environment.make_format(name)
return
end
-- generate format
- local q = string.quote
- local command = string.format("luatex --ini --lua=%s %s %sdump",q(usedluastub),q(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = string.format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -12260,7 +12477,7 @@ function environment.run_format(name,data,more)
logs.simple("no luc/lua with name: %s",barename)
else
local q = string.quote
- local command = string.format("luatex --fmt=%s --lua=%s %s %s",q(barename),q(luaname),q(data),more ~= "" and q(more) or "")
+ local command = string.format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index ac4b0556e..68ee3d2c1 100755
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -347,7 +347,8 @@ patterns.hexadecimal = P("0x") * R("09","AF","af")^1
patterns.lowercase = R("az")
patterns.uppercase = R("AZ")
patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = S(" ")
+patterns.space = P(" ")
+patterns.tab = P("\t")
patterns.eol = S("\n\r")
patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
patterns.newline = crlf + cr + lf
@@ -358,6 +359,9 @@ patterns.nonwhitespace = 1 - patterns.whitespace
patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191')
patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false)
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/""
patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/""
@@ -462,15 +466,36 @@ local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 6
patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+
local cache = { }
function lpeg.stripper(str)
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
end
- return s
end
function lpeg.replacer(t)
@@ -642,7 +667,7 @@ end
table.sortedkeys = sortedkeys
table.sortedhashkeys = sortedhashkeys
-function table.sortedhash(t)
+local function sortedhash(t)
local s = sortedhashkeys(t) -- maybe just sortedkeys
local n = 0
local function kv(s)
@@ -653,7 +678,8 @@ function table.sortedhash(t)
return kv, s
end
-table.sortedpairs = table.sortedhash
+table.sortedhash = sortedhash
+table.sortedpairs = sortedhash
function table.append(t, list)
for _,v in next, list do
@@ -1315,12 +1341,17 @@ function table.count(t)
return n
end
-function table.swapped(t)
- local s = { }
+function table.swapped(t,s)
+ local n = { }
+ if s then
+ for k, v in next, s do
+ n[k] = v
+ end
+ end
for k, v in next, t do
- s[v] = k
+ n[v] = k
end
- return s
+ return n
end
@@ -1340,7 +1371,7 @@ function table.hexed(t,seperator)
return concat(tt,seperator or " ")
end
-function table.reverse_hash(h)
+function table.reverse_hash(h) -- needs another name
local r = { }
for k,v in next, h do
r[v] = lower(gsub(k," ",""))
@@ -1388,10 +1419,18 @@ function table.insert_after_value(t,value,extra)
insert(t,#t+1,extra)
end
-function table.sequenced(t,sep)
+function table.sequenced(t,sep,simple) -- hash only
local s = { }
- for k, v in next, t do -- indexed?
- s[#s+1] = k .. "=" .. tostring(v)
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ s[#s+1] = k
+ elseif v and v~= "" then
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
+ else
+ s[#s+1] = k .. "=" .. tostring(v)
+ end
end
return concat(s, sep or " | ")
end
@@ -1593,6 +1632,39 @@ function io.ask(question,default,options)
end
end
+function io.readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ if n == 1 then
+ return byte(f:read(1))
+ elseif n == 2 then
+ local a, b = byte(f:read(2),1,2)
+ return 256*a + b
+ elseif n == 4 then
+ local a, b, c, d = byte(f:read(4),1,4)
+ return 256^3 * a + 256^2 * b + 256*c + d
+ elseif n == 8 then
+ local a, b = readnumber(f,4), readnumber(f,4)
+ return 256 * b + c
+ elseif n == 12 then
+ local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
+ return 256^2 * a + 256 * b + c
+ else
+ return 0
+ end
+end
+
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n = m
+ end
+ local str = gsub(f:read(n),"%z","")
+ return str
+end
+
end -- of closure
@@ -1658,6 +1730,23 @@ function number.bits(n,zero)
end
+function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+end
+
+function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+end
+
+function number.setbit(x, p)
+ return hasbit(x, p) and x or x + p
+end
+
+function number.clearbit(x, p)
+ return hasbit(x, p) and x - p or x
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3023,7 +3112,7 @@ end
utf = utf or unicode.utf8
local concat, utfchar, utfgsub = table.concat, utf.char, utf.gsub
-local char, byte, find, bytepairs = string.char, string.byte, string.find, string.bytepairs
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -3189,6 +3278,15 @@ function unicode.utf8_to_utf16(str,littleendian)
end
end
+function unicode.utfcodes(str)
+ local t = { }
+ for k,v in string.utfvalues(str) do
+ t[#t+1] = format("0x%04X",k)
+ end
+ return concat(t,separator or " ")
+end
+
+
end -- of closure
@@ -3568,14 +3666,24 @@ function aux.array_to_string(a,separator)
end
end
-function aux.settings_to_set(str,t)
+function aux.settings_to_set(str,t) -- tohash?
t = t or { }
- for s in gmatch(str,"%s*([^,]+)") do
+ for s in gmatch(str,"%s*([^, ]+)") do -- space added
t[s] = true
end
return t
end
+function aux.simple_hash_to_string(h, separator)
+ local t = { }
+ for k, v in table.sortedhash(h) do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t,separator or ",")
+end
+
local value = lbrace * lpeg.C((nobrace + nested)^0) * rbrace
local pattern = lpeg.Ct((space + value)^0)
@@ -3637,6 +3745,60 @@ end
-- as we use this a lot ...
+function aux.formatcolumns(result,between)
+ if result and #result > 0 then
+ between = between or " "
+ local widths, numbers = { }, { }
+ local first = result[1]
+ local n = #first
+ for i=1,n do
+ widths[i] = 0
+ end
+ for i=1,#result do
+ local r = result[i]
+ for j=1,n do
+ local rj = r[j]
+ local tj = type(rj)
+ if tj == "number" then
+ numbers[j] = true
+ end
+ if tj ~= "string" then
+ rj = tostring(rj)
+ r[j] = rj
+ end
+ local w = #rj
+ if w > widths[j] then
+ widths[j] = w
+ end
+ end
+ end
+ for i=1,n do
+ local w = widths[i]
+ if numbers[i] then
+ if w > 80 then
+ widths[i] = "%s" .. between
+ else
+ widths[i] = "%0" .. w .. "i" .. between
+ end
+ else
+ if w > 80 then
+ widths[i] = "%s" .. between
+ elseif w > 0 then
+ widths[i] = "%-" .. w .. "s" .. between
+ else
+ widths[i] = "%s"
+ end
+ end
+ end
+ local template = string.strip(concat(widths))
+ for i=1,#result do
+ local str = format(template,unpack(result[i]))
+ result[i] = string.strip(str)
+ end
+ end
+ return result
+end
+
end -- of closure
@@ -3843,7 +4005,7 @@ if not modules then modules = { } end modules ['trac-set'] = {
local type, next, tostring = type, next, tostring
local concat = table.concat
-local format, find, lower, gsub = string.format, string.find, string.lower, string.gsub
+local format, find, lower, gsub, simpleesc = string.format, string.find, string.lower, string.gsub, string.simpleesc
local is_boolean = string.is_boolean
setters = { }
@@ -3915,7 +4077,7 @@ local function set(t,what,newvalue)
for name, functions in next, data do
if done[name] then
-- prevent recursion due to wildcards
- elseif find(name,w) then
+ elseif find(name,simpleesc(w)) then
done[name] = true
for i=1,#functions do
functions[i](value)
@@ -3979,14 +4141,14 @@ end
function setters.enable(t,what)
local e = t.enable
t.enable, t.done = enable, { }
- enable(t,string.simpleesc(tostring(what)))
+ enable(t,what)
t.enable, t.done = e, { }
end
function setters.disable(t,what)
local e = t.disable
t.disable, t.done = disable, { }
- disable(t,string.simpleesc(tostring(what)))
+ disable(t,what)
t.disable, t.done = e, { }
end
@@ -4050,36 +4212,50 @@ trackers = setters.new("trackers")
directives = setters.new("directives")
experiments = setters.new("experiments")
+-- experiment
+
+if trackers and environment and environment.engineflags.trackers then
+ trackers.enable(environment.engineflags.trackers)
+end
+if directives and environment and environment.engineflags.directives then
+ directives.enable(environment.engineflags.directives)
+end
+
-- nice trick: we overload two of the directives related functions with variants that
-- do tracing (itself using a tracker) .. proof of concept
+local function report(...) -- messy .. chicken or egg
+ local p = (commands and commands.writestatus) or (logs and logs.report)
+ if p then p(...) end
+end
+
local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
-local e = directives.enable
-local d = directives.disable
+local enable = directives.enable
+local disable = directives.disable
function directives.enable(...)
- (commands.writestatus or logs.report)("directives","enabling: %s",concat({...}," "))
- e(...)
+ report("directives","enabling: %s",concat({...}," "))
+ enable(...)
end
function directives.disable(...)
- (commands.writestatus or logs.report)("directives","disabling: %s",concat({...}," "))
- d(...)
+ report("directives","disabling: %s",concat({...}," "))
+ disable(...)
end
-local e = experiments.enable
-local d = experiments.disable
+local enable = experiments.enable
+local disable = experiments.disable
function experiments.enable(...)
- (commands.writestatus or logs.report)("experiments","enabling: %s",concat({...}," "))
- e(...)
+ report("experiments","enabling: %s",concat({...}," "))
+ enable(...)
end
function experiments.disable(...)
- (commands.writestatus or logs.report)("experiments","disabling: %s",concat({...}," "))
- d(...)
+ report("experiments","disabling: %s",concat({...}," "))
+ disable(...)
end
-- a useful example
@@ -4088,6 +4264,15 @@ directives.register("system.nostatistics", function(v)
statistics.enable = not v
end)
+-- experiment
+
+if trackers and environment and environment.engineflags.trackers then
+ trackers.enable(environment.engineflags.trackers)
+end
+if directives and environment and environment.engineflags.directives then
+ directives.enable(environment.engineflags.directives)
+end
+
end -- of closure
@@ -6357,17 +6542,19 @@ apply_axis['child'] = function(list)
for l=1,#list do
local ll = list[l]
local dt = ll.dt
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- collected[#collected+1] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ if dt then -- weird that this is needed
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ collected[#collected+1] = dk
+ dk.ni = k -- refresh
+ en = en + 1
+ dk.ei = en
+ end
end
+ ll.en = en
end
- ll.en = en
end
return collected
end
@@ -8079,6 +8266,7 @@ local finalizers = xml.finalizers.xml
local xmlfilter = xml.filter -- we could inline this one for speed
local xmltostring = xml.tostring
local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -8356,6 +8544,19 @@ xml.all = xml.filter
xml.index = xml.position
xml.found = xml.filter
+-- a nice one:
+
+local function totable(x)
+ local t = { }
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg] = xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+
+xml.table = totable
+finalizers.table = totable
+
end -- of closure
@@ -8943,6 +9144,7 @@ formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', '
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
formats['fea'] = 'FONTFEATURES' suffixes['fea'] = { 'fea' }
formats['cid'] = 'FONTCIDMAPS' suffixes['cid'] = { 'cid', 'cidmap' }
+formats['icc'] = 'ICCPROFILES' suffixes['icc'] = { 'icc' }
formats['texmfscripts'] = 'TEXMFSCRIPTS' suffixes['texmfscripts'] = { 'rb', 'pl', 'py' }
formats['lua'] = 'LUAINPUTS' suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' }
formats['lib'] = 'CLUAINPUTS' suffixes['lib'] = (os.libsuffix and { os.libsuffix }) or { 'dll', 'so' }
@@ -8958,6 +9160,7 @@ alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
+alternatives['icc profiles'] = 'icc'
--[[ldx--
<p>If you wondered about some of the previous mappings, how about
@@ -12160,6 +12363,21 @@ if not modules then modules = { } end modules ['luat-fmt'] = {
-- helper for mtxrun
+local quote = string.quote
+
+local function primaryflags()
+ local trackers = environment.argument("trackers")
+ local directives = environment.argument("directives")
+ local flags = ""
+ if trackers and trackers ~= "" then
+ flags = flags .. "--trackers=" .. quote(trackers)
+ end
+ if directives and directives ~= "" then
+ flags = flags .. "--directives=" .. quote(directives)
+ end
+ return flags
+end
+
function environment.make_format(name)
-- change to format path (early as we need expanded paths)
local olddir = lfs.currentdir()
@@ -12220,8 +12438,7 @@ function environment.make_format(name)
return
end
-- generate format
- local q = string.quote
- local command = string.format("luatex --ini --lua=%s %s %sdump",q(usedluastub),q(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
+ local command = string.format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quote(usedluastub),quote(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
logs.simple("running command: %s\n",command)
os.spawn(command)
-- remove related mem files
@@ -12260,7 +12477,7 @@ function environment.run_format(name,data,more)
logs.simple("no luc/lua with name: %s",barename)
else
local q = string.quote
- local command = string.format("luatex --fmt=%s --lua=%s %s %s",q(barename),q(luaname),q(data),more ~= "" and q(more) or "")
+ local command = string.format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quote(barename),quote(luaname),quote(data),more ~= "" and quote(more) or "")
logs.simple("running command: %s",command)
os.spawn(command)
end