summaryrefslogtreecommitdiff
path: root/scripts/context/lua/mtxrun.lua
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/context/lua/mtxrun.lua')
-rw-r--r--scripts/context/lua/mtxrun.lua665
1 files changed, 448 insertions, 217 deletions
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index d0c7469e0..a3cbb35e0 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -377,6 +377,31 @@ function string:split_settings() -- no {} handling, see l-aux for lpeg variant
end
end
+local patterns_escapes = {
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["+"] = "%+",
+ ["*"] = "%*",
+ ["%"] = "%%",
+ ["("] = "%)",
+ [")"] = "%)",
+ ["["] = "%[",
+ ["]"] = "%]",
+}
+
+
+function string:pattesc()
+ return (self:gsub(".",patterns_escapes))
+end
+
+function string:tohash()
+ local t = { }
+ for s in self:gmatch("([^, ]+)") do -- lpeg
+ t[s] = true
+ end
+ return t
+end
+
-- filename : l-lpeg.lua
-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
@@ -420,7 +445,6 @@ end
-
-- filename : l-table.lua
-- comment : split off from luat-lib
-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
@@ -502,7 +526,8 @@ end
--~ return t
--~ end
-function table.merge(t, ...)
+function table.merge(t, ...) -- first one is target
+ t = t or {}
local lst = {...}
for i=1,#lst do
for k, v in pairs(lst[i]) do
@@ -1031,6 +1056,14 @@ function table.tohash(t)
return h
end
+function table.fromhash(t)
+ local h = { }
+ for k, v in pairs(t) do -- no ipairs here
+ if v then h[#h+1] = k end
+ end
+ return h
+end
+
function table.contains(t, v)
if t then
for i=1, #t do
@@ -1062,6 +1095,22 @@ end
--~ return table.serialize(a) == table.serialize(b)
--~ end
+function table.clone(t,p) -- t is optional or nil or table
+ if not p then
+ t, p = { }, t or { }
+ elseif not t then
+ t = { }
+ end
+ setmetatable(t, { __index = function(_,key) return p[key] end })
+ return t
+end
+
+
+function table.hexed(t,seperator)
+ local tt = { }
+ for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end
+ return table.concat(tt,seperator or " ")
+end
-- filename : l-io.lua
@@ -1133,38 +1182,10 @@ function io.noflines(f)
return n
end
---~ t, f, n = os.clock(), io.open("testbed/sample-utf16-bigendian-big.txt",'rb'), 0
---~ for a in io.characters(f) do n = n + 1 end
---~ print(string.format("characters: %s, time: %s", n, os.clock()-t))
-
do
local sb = string.byte
---~ local nextchar = {
---~ [ 4] = function(f)
---~ return f:read(1), f:read(1), f:read(1), f:read(1)
---~ end,
---~ [ 2] = function(f)
---~ return f:read(1), f:read(1)
---~ end,
---~ [ 1] = function(f)
---~ return f:read(1)
---~ end,
---~ [-2] = function(f)
---~ local a = f:read(1)
---~ local b = f:read(1)
---~ return b, a
---~ end,
---~ [-4] = function(f)
---~ local a = f:read(1)
---~ local b = f:read(1)
---~ local c = f:read(1)
---~ local d = f:read(1)
---~ return d, c, b, a
---~ end
---~ }
-
local nextchar = {
[ 4] = function(f)
return f:read(1,1,1,1)
@@ -1488,18 +1509,27 @@ function os.resultof(command)
return io.popen(command,"r"):read("*all")
end
-if not os.exec then -- still not ok
- os.exec = os.execute
-end
-if not os.spawn then -- still not ok
- os.spawn = os.execute
+if not os.exec then os.exec = os.execute end
+if not os.spawn then os.spawn = os.execute end
+
+--~ os.type : windows | unix (new, we already guessed os.platform)
+--~ os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
+
+if not io.fileseparator then
+ if string.find(os.getenv("PATH"),";") then
+ io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows"
+ else
+ io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix"
+ end
end
+os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix"
+
function os.launch(str)
if os.platform == "windows" then
- os.spawn("start " .. str)
+ os.execute("start " .. str) -- os.spawn ?
else
- os.spawn(str .. " &")
+ os.execute(str .. " &") -- os.spawn ?
end
end
@@ -1514,19 +1544,15 @@ if not os.times then
-- cstime = children system time
function os.times()
return {
- utime = os.clock(), -- user
- stime = 0, -- system
- cutime = 0, -- children user
- cstime = 0, -- children system
+ utime = os.gettimeofday(), -- user
+ stime = 0, -- system
+ cutime = 0, -- children user
+ cstime = 0, -- children system
}
end
end
-if os.gettimeofday then
- os.clock = os.gettimeofday
-else
- os.gettimeofday = os.clock
-end
+os.gettimeofday = os.gettimeofday or os.clock
do
local startuptime = os.gettimeofday()
@@ -1553,11 +1579,11 @@ if not versions then versions = { } end versions['l-file'] = 1.001
if not file then file = { } end
function file.removesuffix(filename)
- return filename:gsub("%.%a+$", "")
+ return filename:gsub("%.[%a%d]+$", "")
end
function file.addsuffix(filename, suffix)
- if not filename:find("%.%a-$") then
+ if not filename:find("%.[%a%d]+$") then
return filename .. "." .. suffix
else
return filename
@@ -1565,7 +1591,11 @@ function file.addsuffix(filename, suffix)
end
function file.replacesuffix(filename, suffix)
- return (filename:gsub("%.%a+$", "." .. suffix))
+ if not filename:find("%.[%a%d]+$") then
+ return filename .. "." .. suffix
+ else
+ return (filename:gsub("%.[%a%d]+$","."..suffix))
+ end
end
function file.dirname(name)
@@ -1584,12 +1614,36 @@ function file.extname(name)
return name:match("^.+%.([^/\\]-)$") or ""
end
+function file.stripsuffix(name)
+ return (name:gsub("%.[%a%d]+$",""))
+end
+
+--~ function file.join(...)
+--~ local t = { ... }
+--~ for i=1,#t do
+--~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","")
+--~ end
+--~ return table.concat(t,"/")
+--~ end
+
+--~ print(file.join("x/","/y"))
+--~ print(file.join("http://","/y"))
+--~ print(file.join("http://a","/y"))
+--~ print(file.join("http:///a","/y"))
+--~ print(file.join("//nas-1","/y"))
+
function file.join(...)
- local t = { ... }
- for i=1,#t do
- t[i] = (t[i]:gsub("\\","/")):gsub("/+$","")
+ local pth = table.concat({...},"/")
+ pth = pth:gsub("\\","/")
+ local a, b = pth:match("^(.*://)(.*)$")
+ if a and b then
+ return a .. b:gsub("//+","/")
+ end
+ a, b = pth:match("^(//)(.*)$")
+ if a and b then
+ return a .. b:gsub("//+","/")
end
- return table.concat(t,"/")
+ return (pth:gsub("//+","/"))
end
function file.is_writable(name)
@@ -1888,6 +1942,8 @@ xml.trace_lpath = false
xml.trace_print = false
xml.trace_remap = false
+-- todo: some things per xml file, liek namespace remapping
+
--[[ldx--
<p>First a hack to enable namespace resolving. A namespace is characterized by
a <l n='url'/>. The following function associates a namespace prefix with a
@@ -2506,7 +2562,7 @@ function xml.text(root)
return (root and xml.tostring(root)) or ""
end
-function xml.content(root)
+function xml.content(root) -- bugged
return (root and root.dt and xml.tostring(root.dt)) or ""
end
@@ -2837,14 +2893,13 @@ do
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
- function xml.traverse(root,pattern,handle,reverse,index,parent,wildcard)
+ local function traverse(root,pattern,handle,reverse,index,parent,wildcard)
if not root then -- error
return false
elseif pattern == false then -- root
handle(root,root.dt,root.ri)
return false
elseif pattern == true then -- wildcard
- local traverse = xml.traverse
local rootdt = root.dt
if rootdt then
local start, stop, step = 1, #rootdt, 1
@@ -2875,7 +2930,7 @@ do
elseif command == 11 then -- parent
local ep = root.__p__ or parent
if index < #pattern then
- if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end
elseif handle(root,rootdt,k) then
return false
end
@@ -2890,12 +2945,11 @@ do
if command == 11 then -- parent
local ep = root.__p__ or parent
if index < #pattern then
- if not xml.traverse(ep,pattern,handle,reverse,index+1,root) then return false end
+ if not traverse(ep,pattern,handle,reverse,index+1,root) then return false end
elseif handle(root,rootdt,k) then
return false
end
else
- local traverse = xml.traverse
local rootdt = root.dt
local start, stop, step, n, dn = 1, #rootdt, 1, 0, 1
if command == 30 then
@@ -2989,6 +3043,7 @@ do
if index == #pattern then
if handle(root,rootdt,root.ri or k) then return false end
if wildcard and multiple then
+--~ if wildcard or multiple then
if not traverse(e,pattern,handle,reverse,index,root,true) then return false end
end
else
@@ -3049,6 +3104,8 @@ do
return true
end
+ xml.traverse = traverse
+
end
--[[ldx--
@@ -3119,7 +3176,7 @@ do
traverse(root, lpath(pattern), function(r,d,k) rt,dt,dk = r,d,k return true end, 'reverse')
return dt and dt[dk], rt, dt, dk
end
- function xml.filters.count(root, pattern,everything)
+ function xml.filters.count(root,pattern,everything)
local n = 0
traverse(root, lpath(pattern), function(r,d,t)
if everything or type(d[t]) == "table" then
@@ -3189,13 +3246,15 @@ do
local rt, dt, dk
traverse(root, lpath(pattern), function(r,d,k) rt, dt, dk = r, d, k return true end)
local ekat = (dt and dt[dk] and dt[dk].at) or (rt and rt.at)
- return (ekat and ekat[arguments]) or ""
+ return (ekat and (ekat[arguments] or ekat[arguments:gsub("^([\"\'])(.*)%1$","%2")])) or ""
end
- function xml.filters.text(root,pattern,arguments)
+ function xml.filters.text(root,pattern,arguments) -- ?? why index
local dtk, rt, dt, dk = xml.filters.index(root,pattern,arguments)
if dtk then
local dtkdt = dtk.dt
- if #dtkdt == 1 and type(dtkdt[1]) == "string" then
+ if not dtkdt then
+ return "", rt, dt, dk
+ elseif #dtkdt == 1 and type(dtkdt[1]) == "string" then
return dtkdt[1], rt, dt, dk
else
return xml.tostring(dtkdt), rt, dt, dk
@@ -3260,7 +3319,7 @@ do
</typing>
<p>Which will print all the titles in the document. The iterator variant takes
- 1.5 times the runtime of the function variant which si due to the overhead in
+ 1.5 times the runtime of the function variant which is due to the overhead in
creating the wrapper. So, instead of:</p>
<typing>
@@ -3279,6 +3338,10 @@ do
return coroutine.wrap(function() traverse(root, lpath(pattern), coroutine.yield, reverse) end)
end
+ function xml.elements_only(root,pattern,reverse)
+ return coroutine.wrap(function() traverse(root, lpath(pattern), function(r,d,k) coroutine.yield(d[k]) end, reverse) end)
+ end
+
function xml.each_element(root, pattern, handle, reverse)
local ok
traverse(root, lpath(pattern), function(r,d,k) ok = true handle(r,d,k) end, reverse)
@@ -3424,10 +3487,20 @@ do
end
end
- function xml.include(xmldata,pattern,attribute,recursive,findfile)
+ local function load_data(name) -- == io.loaddata
+ local f, data = io.open(name), ""
+ if f then
+ data = f:read("*all",'b') -- 'b' ?
+ f:close()
+ end
+ return data
+ end
+
+ function xml.include(xmldata,pattern,attribute,recursive,loaddata)
-- parse="text" (default: xml), encoding="" (todo)
- pattern = pattern or 'include'
-- attribute = attribute or 'href'
+ pattern = pattern or 'include'
+ loaddata = loaddata or load_data
local function include(r,d,k)
local ek, name = d[k], nil
if not attribute or attribute == "" then
@@ -3442,29 +3515,21 @@ do
end
end
end
- if name then
- name = (findfile and findfile(name)) or name
- if name ~= "" then
- local f = io.open(name)
- if f then
- if ek.at["parse"] == "text" then -- for the moment hard coded
- d[k] = xml.escaped(f:read("*all"))
- else
- local xi = xml.load(f)
- if recursive then
- xml.include(xi,pattern,attribute,recursive,findfile)
- end
- xml.assign(d,k,xi)
- end
- f:close()
- else
- xml.empty(d,k)
- end
- else
+ local data = (name and name ~= "" and loaddata(name)) or ""
+ if data == "" then
+ xml.empty(d,k)
+ elseif ek.at["parse"] == "text" then -- for the moment hard coded
+ d[k] = xml.escaped(data)
+ else
+ local xi = xml.convert(data)
+ if not xi then
xml.empty(d,k)
+ else
+ if recursive then
+ xml.include(xi,pattern,attribute,recursive,loaddata)
+ end
+ xml.assign(d,k,xi)
end
- else
- xml.empty(d,k)
end
end
xml.each_element(xmldata, pattern, include)
@@ -3948,19 +4013,13 @@ os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
if not io.fileseparator then
if string.find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator, os.platform = "\\", ";", "windows"
+ io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows"
else
- io.fileseparator, io.pathseparator, os.platform = "/" , ":", "unix"
+ io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix"
end
end
-if not os.platform then
- if io.pathseparator == ";" then
- os.platform = "windows"
- else
- os.platform = "unix"
- end
-end
+os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix"
-- arg normalization
--
@@ -4159,17 +4218,22 @@ input.formats ['lua'] = 'LUAINPUTS' -- new
input.suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' }
-- here we catch a few new thingies (todo: add these paths to context.tmf)
+--
+-- FONTFEATURES = .;$TEXMF/fonts/fea//
+-- FONTCIDMAPS = .;$TEXMF/fonts/cid//
-function input.checkconfigdata(instance)
+function input.checkconfigdata(instance) -- not yet ok, no time for debugging now
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- if not instance.environment[proname] and not instance.variables[proname] == "" and not instance.environment[varname] and not instance.variables[varname] == "" then
- instance.variables[varname] = default
+ local p = instance.environment[proname]
+ local v = instance.environment[varname]
+ if not ((p and p ~= "") or (v and v ~= "")) then
+ instance.variables[varname] = default -- or environment?
end
end
fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS")
- fix("FONTFEATURES", ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
- fix("FONTCIDMAPS" , ".;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
+ fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
+ fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
end
-- backward compatible ones
@@ -4270,6 +4334,11 @@ function input.reset()
end
+function input.reset_hashes(instance)
+ instance.lists = { }
+ instance.found = { }
+end
+
function input.bare_variable(str)
-- return string.gsub(string.gsub(string.gsub(str,"%s+$",""),'^"(.+)"$',"%1"),"^'(.+)'$","%1")
return (str:gsub("\s*([\"\']?)(.+)%1\s*", "%2"))
@@ -4335,7 +4404,7 @@ input.settrace(tonumber(os.getenv("MTX.INPUT.TRACE") or os.getenv("MTX_INPUT_TRA
-- loading the database files.
do
- local clock = os.clock
+ local clock = os.gettimeofday or os.clock
function input.starttiming(instance)
if instance then
@@ -4609,6 +4678,7 @@ function input.aux.extend_texmf_var(instance,specification) -- crap
instance.variables['TEXMF'] = "{" .. instance.variables['TEXMF'] .. "}"
end
input.expand_variables(instance)
+ input.reset_hashes(instance)
end
-- locators
@@ -4624,28 +4694,6 @@ function input.locatedatabase(instance,specification)
return input.methodhandler('locators', instance, specification)
end
---~ poor mans solution, from before we had lfs.isdir
---~
---~ function input.locators.tex(instance,specification)
---~ if specification and specification ~= '' then
---~ local files = {
---~ file.join(specification,'files'..input.lucsuffix),
---~ file.join(specification,'files'..input.luasuffix),
---~ file.join(specification,input.lsrname)
---~ }
---~ for _, filename in pairs(files) do
---~ local f = io.open(filename)
---~ if f then
---~ input.logger('! tex locator', specification..' found')
---~ input.aux.append_hash(instance,'file',specification,filename)
---~ f:close()
---~ return
---~ end
---~ end
---~ input.logger('? tex locator', specification..' not found')
---~ end
---~ end
-
function input.locators.tex(instance,specification)
if specification and specification ~= '' and lfs.isdir(specification) then
input.logger('! tex locator', specification..' found')
@@ -5004,8 +5052,6 @@ function input.expand_variables(instance)
for k,v in pairs(instance.expansions) do
instance.expansions[k] = v:gsub("\\", '/')
end
- -- ##########
- --~ input.splitexpansions(instance) -- better not, fuzzy
end
function input.aux.expand_vars(instance,lst) -- simple vars
@@ -5163,15 +5209,12 @@ do
end
function input.register_extra_path(instance,paths,subpaths)
+ local ep = instance.extra_paths or { }
+ local n = #ep
if paths and paths ~= "" then
- local ep = instance.extra_paths
- if not ep then
- ep = { }
- instance.extra_paths = ep
- end
- local n = #ep
- if subpath and subpaths ~= "" then
+ if subpaths and subpaths ~= "" then
for p in paths:gmatch("[^,]+") do
+ -- we gmatch each step again, not that fast, but used seldom
for s in subpaths:gmatch("[^,]+") do
local ps = p .. "/" .. s
if not done[ps] then
@@ -5188,10 +5231,24 @@ do
end
end
end
- if n < #ep then
- instance.lists = { }
+ elseif subpaths and subpaths ~= "" then
+ for i=1,n do
+ -- we gmatch each step again, not that fast, but used seldom
+ for s in subpaths:gmatch("[^,]+") do
+ local ps = ep[i] .. "/" .. s
+ if not done[ps] then
+ ep[#ep+1] = input.clean_path(ps)
+ done[ps] = true
+ end
+ end
end
end
+ if #ep > 0 then
+ instance.extra_paths = ep -- register paths
+ end
+ if #ep > n then
+ instance.lists = { } -- erase the cache
+ end
end
end
@@ -5446,7 +5503,7 @@ input.is_readable.tex = input.is_readable.file
-- name/name
function input.aux.collect_files(instance,names)
- local filelist = nil
+ local filelist = { }
for _, fname in pairs(names) do
if fname then
if input.trace > 2 then
@@ -5478,15 +5535,20 @@ function input.aux.collect_files(instance,names)
if blobfile then
if type(blobfile) == 'string' then
if not dname or blobfile:find(dname) then
- if not filelist then filelist = { } end
- -- input.logger('= collected', blobpath.." | "..blobfile.." | "..bname)
- filelist[#filelist+1] = file.join(blobpath,blobfile,bname)
+ filelist[#filelist+1] = {
+ hash.type,
+ file.join(blobpath,blobfile,bname), -- search
+ input.concatinators[hash.type](blobpath,blobfile,bname) -- result
+ }
end
else
for _, vv in pairs(blobfile) do
if not dname or vv:find(dname) then
- if not filelist then filelist = { } end
- filelist[#filelist+1] = file.join(blobpath,vv,bname)
+ filelist[#filelist+1] = {
+ hash.type,
+ file.join(blobpath,vv,bname), -- search
+ input.concatinators[hash.type](blobpath,vv,bname) -- result
+ }
end
end
end
@@ -5497,7 +5559,11 @@ function input.aux.collect_files(instance,names)
end
end
end
- return filelist
+ if #filelist > 0 then
+ return filelist
+ else
+ return nil
+ end
end
function input.suffix_of_format(str)
@@ -5516,54 +5582,30 @@ function input.suffixes_of_format(str)
end
end
---~ function input.aux.qualified_path(filename) -- make platform dependent / not good yet
---~ return
---~ filename:find("^%.+/") or
---~ filename:find("^/") or
---~ filename:find("^%a+%:") or
---~ filename:find("^%a+##")
---~ end
-
---~ function input.normalize_name(original)
---~ -- internally we use type##spec##subspec ; this hackery slightly slows down searching
---~ local str = original or ""
---~ str = str:gsub("::", "##") -- :: -> ##
---~ str = str:gsub("^(%a+)://" ,"%1##") -- zip:// -> zip##
---~ str = str:gsub("(.+)##(.+)##/(.+)","%1##%2##%3") -- ##/spec -> ##spec
---~ if (input.trace>1) and (original ~= str) then
---~ input.logger('= normalizer',original.." -> "..str)
---~ end
---~ return str
---~ end
+do
-do -- called about 700 times for an empty doc (font initializations etc)
+ -- called about 700 times for an empty doc (font initializations etc)
-- i need to weed the font files for redundant calls
local letter = lpeg.R("az","AZ")
- local separator = lpeg.P("##")
+ local separator = lpeg.P("://")
- local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator
- local normalized = lpeg.Cs(
- (letter^1*(lpeg.P("://")/"##") * (1-lpeg.P(false))^1) +
- (lpeg.P("::")/"##" + (1-separator)^1*separator*(1-separator)^1*separator*(lpeg.P("/")/"") + 1)^0
- )
+ local qualified = lpeg.P(".")^0 * lpeg.P("/") + letter*lpeg.P(":") + letter^1*separator
+ local rootbased = lpeg.P("/") + letter*lpeg.P(":")
- -- ./name ../name /name c: zip## (todo: use url internally and get rid of ##)
+ -- ./name ../name /name c: ://
function input.aux.qualified_path(filename)
return qualified:match(filename)
end
+ function input.aux.rootbased_path(filename)
+ return rootbased:match(filename)
+ end
- -- zip:// -> zip## ; :: -> ## ; aa##bb##/cc -> aa##bb##cc
function input.normalize_name(original)
- local str = normalized:match(original or "")
- if input.trace > 1 and original ~= str then
- input.logger('= normalizer',original.." -> "..str)
- end
- return str
+ return original
end
-end
--- split the next one up, better for jit
+end
function input.aux.register_in_trees(instance,name)
if not name:find("^%.") then
@@ -5571,11 +5613,13 @@ function input.aux.register_in_trees(instance,name)
end
end
+-- split the next one up, better for jit
+
function input.aux.find_file(instance,filename) -- todo : plugin (scanners, checkers etc)
local result = { }
local stamp = nil
- filename = input.normalize_name(filename)
- filename = file.collapse_path(filename:gsub("\\","/"))
+ filename = input.normalize_name(filename) -- elsewhere
+ filename = file.collapse_path(filename:gsub("\\","/")) -- elsewhere
-- speed up / beware: format problem
if instance.remember then
stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
@@ -5647,7 +5691,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
local typespec = input.variable_of_format(filetype)
local pathlist = input.expanded_path_list(instance,typespec)
if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only
+ -- no pathlist, access check only / todo == wildcard
if input.trace > 2 then
input.logger('? filename',filename)
input.logger('? filetype',filetype or '?')
@@ -5662,8 +5706,9 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
end
-- this is actually 'other text files' or 'any' or 'whatever'
local filelist = input.aux.collect_files(instance,wantedfiles)
- filename = filelist and filelist[1]
- if filename then
+ local lf = filelist and filelist[1]
+ if fl then
+ filename = fl[3]
result[#result+1] = filename
done = true
end
@@ -5673,8 +5718,8 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
local doscan, recurse
if input.trace > 2 then
input.logger('? filename',filename)
- if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end
- if filelist then input.logger('? file list',table.concat(filelist," | ")) end
+ -- if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end
+ -- if filelist then input.logger('? file list',table.concat(filelist," | ")) end
end
-- a bit messy ... esp the doscan setting here
for _, path in pairs(pathlist) do
@@ -5687,16 +5732,18 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
-- compare list entries with permitted pattern
pathname = pathname:gsub("([%-%.])","%%%1") -- this also influences
pathname = pathname:gsub("/+$", '/.*') -- later usage of pathname
- pathname = pathname:gsub("//", '/.-/')
+ pathname = pathname:gsub("//", '/.-/') -- not ok for /// but harmless
local expr = "^" .. pathname
-- input.debug('?',expr)
- for _, f in pairs(filelist) do
+ for _, fl in ipairs(filelist) do
+ local f = fl[2]
if f:find(expr) then
-- input.debug('T',' '..f)
if input.trace > 2 then
input.logger('= found in hash',f)
end
- result[#result+1] = f
+ --- todo, test for readable
+ result[#result+1] = fl[3]
input.aux.register_in_trees(instance,f) -- for tracing used files
done = true
if not instance.allresults then break end
@@ -5706,7 +5753,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
end
end
if not done and doscan then
- -- check if on disk / unchecked / does not work at all
+ -- check if on disk / unchecked / does not work at all / also zips
if input.method_is_file(pathname) then -- ?
local pname = pathname:gsub("%.%*$",'')
if not pname:find("%*") then
@@ -5783,10 +5830,7 @@ end
if not input.concatinators then input.concatinators = { } end
-function input.concatinators.tex(tag,path,name)
- return tag .. '/' .. path .. '/' .. name
-end
-
+input.concatinators.tex = file.join
input.concatinators.file = input.concatinators.tex
function input.find_files(instance,filename,filetype,mustexist)
@@ -5988,15 +6032,6 @@ function input.aux.register_file(files, name, path)
end
end
--- zip:: zip## zip://
--- zip::pathtozipfile::pathinzipfile (also: pathtozipfile/pathinzipfile)
--- file::name
--- tex::name
--- kpse::name
--- kpse::format::name
--- parent::n::name
--- parent::name (default 2)
-
if not input.finders then input.finders = { } end
if not input.openers then input.openers = { } end
if not input.loaders then input.loaders = { } end
@@ -6006,30 +6041,37 @@ input.openers.notfound = { nil }
input.loaders.notfound = { false, nil, 0 }
function input.splitmethod(filename)
- local method, specification = filename:match("^(.-)##(.+)$")
- if method and specification then
- return method, specification
+ if not filename then
+ return { } -- safeguard
+ elseif type(filename) == "table" then
+ return filename -- already split
+ elseif not filename:find("://") then
+ return { scheme="file", path = filename, original=filename } -- quick hack
else
- return 'tex', filename
+ return url.hashed(filename)
end
end
function input.method_is_file(filename)
- local method, specification = input.splitmethod(filename)
- return method == 'tex' or method == 'file'
+ return input.splitmethod(filename).scheme == 'file'
+end
+
+function table.sequenced(t,sep) -- temp here
+ local s = { }
+ for k, v in pairs(t) do
+ s[#s+1] = k .. "=" .. v
+ end
+ return table.concat(s, sep or " | ")
end
function input.methodhandler(what, instance, filename, filetype) -- ...
- local method, specification = input.splitmethod(filename)
- if method and specification then -- redundant
- if input[what][method] then
- input.logger('= handler',filename.." -> "..what.." | "..method.." | "..specification)
- return input[what][method](instance,specification,filetype)
- else
- return nil
- end
+ local specification = (type(filename) == "string" and input.splitmethod(filename)) or filename -- no or { }, let it bomb
+ local scheme = specification.scheme
+ if input[what][scheme] then
+ input.logger('= handler',specification.original .." -> " .. what .. " -> " .. table.sequenced(specification))
+ return input[what][scheme](instance,filename,filetype) -- todo: specification
else
- return input[what].tex(instance,filename,filetype)
+ return input[what].tex(instance,filename,filetype) -- todo: specification
end
end
@@ -6063,6 +6105,8 @@ function input.texdatablob(instance, filename, filetype)
return data or ""
end
+input.loadtexfile = input.texdatablob
+
function input.openfile(filename) -- brrr texmf.instance here / todo ! ! ! ! !
local fullname = input.findtexfile(texmf.instance, filename)
if fullname and (fullname ~= "") then
@@ -6641,7 +6685,7 @@ function input.aux.load_data(instance,pathname,dataname,filename)
end
end
--- we will make a better format, maybe something xml or just text
+-- we will make a better format, maybe something xml or just text or lua
input.automounted = input.automounted or { }
@@ -6879,6 +6923,191 @@ logs.set_level('error')
logs.set_method('tex')
+if not modules then modules = { } end modules ['luat-sta'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+states = states or { }
+states.data = states.data or { }
+states.hash = states.hash or { }
+states.tag = states.tag or ""
+states.filename = states.filename or ""
+
+function states.save(filename,tag)
+ tag = tag or states.tag
+ filename = file.addsuffix(filename or states.filename,'lus')
+ io.savedata(filename,
+ "-- generator : luat-sta.lua\n" ..
+ "-- state tag : " .. tag .. "\n\n" ..
+ table.serialize(states.data[tag or states.tag] or {},true)
+ )
+end
+
+function states.load(filename,tag)
+ states.filename = filename
+ states.tag = tag or "whatever"
+ states.filename = file.addsuffix(states.filename,'lus')
+ states.data[states.tag], states.hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { }
+end
+
+function states.set_by_tag(tag,key,value,default,persistent)
+ local d, h = states.data[tag], states.hash[tag]
+ if d then
+ local dkey, hkey = key, key
+ local pre, post = key:match("(.+)%.([^%.]+)$")
+ if pre and post then
+ for k in pre:gmatch("[^%.]+") do
+ local dk = d[k]
+ if not dk then
+ dk = { }
+ d[k] = dk
+ end
+ d = dk
+ end
+ dkey, hkey = post, key
+ end
+ if type(value) == nil then
+ value = value or default
+ elseif persistent then
+ value = value or d[dkey] or default
+ else
+ value = value or default
+ end
+ d[dkey], h[hkey] = value, value
+ end
+end
+
+function states.get_by_tag(tag,key,default)
+ local h = states.hash[tag]
+ if h and h[key] then
+ return h[key]
+ else
+ local d = states.data[tag]
+ if d then
+ for k in key:gmatch("[^%.]+") do
+ local dk = d[k]
+ if dk then
+ d = dk
+ else
+ return default
+ end
+ end
+ return d or default
+ end
+ end
+end
+
+function states.set(key,value,default,persistent)
+ states.set_by_tag(states.tag,key,value,default,persistent)
+end
+
+function states.get(key,default)
+ return states.get_by_tag(states.tag,key,default)
+end
+
+--~ states.data.update = {
+--~ ["version"] = {
+--~ ["major"] = 0,
+--~ ["minor"] = 1,
+--~ },
+--~ ["rsync"] = {
+--~ ["server"] = "contextgarden.net",
+--~ ["module"] = "minimals",
+--~ ["repository"] = "current",
+--~ ["flags"] = "-rpztlv --stats",
+--~ },
+--~ ["tasks"] = {
+--~ ["update"] = true,
+--~ ["make"] = true,
+--~ ["delete"] = false,
+--~ },
+--~ ["platform"] = {
+--~ ["host"] = true,
+--~ ["other"] = {
+--~ ["mswin"] = false,
+--~ ["linux"] = false,
+--~ ["linux-64"] = false,
+--~ ["osx-intel"] = false,
+--~ ["osx-ppc"] = false,
+--~ ["sun"] = false,
+--~ },
+--~ },
+--~ ["context"] = {
+--~ ["available"] = {"current", "beta", "alpha", "experimental"},
+--~ ["selected"] = "current",
+--~ },
+--~ ["formats"] = {
+--~ ["cont-en"] = true,
+--~ ["cont-nl"] = true,
+--~ ["cont-de"] = false,
+--~ ["cont-cz"] = false,
+--~ ["cont-fr"] = false,
+--~ ["cont-ro"] = false,
+--~ },
+--~ ["engine"] = {
+--~ ["pdftex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["pdftex"] = true,
+--~ },
+--~ },
+--~ ["luatex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ },
+--~ },
+--~ ["xetex"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["xetex"] = false,
+--~ },
+--~ },
+--~ ["metapost"] = {
+--~ ["install"] = true,
+--~ ["formats"] = {
+--~ ["mpost"] = true,
+--~ ["metafun"] = true,
+--~ },
+--~ },
+--~ },
+--~ ["fonts"] = {
+--~ },
+--~ ["doc"] = {
+--~ },
+--~ ["modules"] = {
+--~ ["f-urwgaramond"] = false,
+--~ ["f-urwgothic"] = false,
+--~ ["t-bnf"] = false,
+--~ ["t-chromato"] = false,
+--~ ["t-cmscbf"] = false,
+--~ ["t-cmttbf"] = false,
+--~ ["t-construction-plan"] = false,
+--~ ["t-degrade"] = false,
+--~ ["t-french"] = false,
+--~ ["t-lettrine"] = false,
+--~ ["t-lilypond"] = false,
+--~ ["t-mathsets"] = false,
+--~ ["t-tikz"] = false,
+--~ ["t-typearea"] = false,
+--~ ["t-vim"] = false,
+--~ },
+--~ }
+
+
+--~ states.save("teststate", "update")
+--~ states.load("teststate", "update")
+
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+--~ states.set_by_tag("update","rsync.server","oeps")
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+--~ states.save("teststate", "update")
+--~ states.load("teststate", "update")
+--~ print(states.get_by_tag("update","rsync.server","unknown"))
+
+
-- end library merge
own = { }
@@ -6906,6 +7135,7 @@ own.libs = { -- todo: check which ones are really needed
-- 'luat-kps.lua',
'luat-tmp.lua',
'luat-log.lua',
+ 'luat-sta.lua',
}
-- We need this hack till luatex is fixed.
@@ -7185,6 +7415,7 @@ input.runners.registered = {
if not messages then messages = { } end
messages.help = [[
+--script run an mtx script
--execute run a script or program
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)