diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/data-tre.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/data-tre.lua | 222 |
1 files changed, 190 insertions, 32 deletions
diff --git a/Master/texmf-dist/tex/context/base/data-tre.lua b/Master/texmf-dist/tex/context/base/data-tre.lua index 0a8b00d9bfb..4388731f98c 100644 --- a/Master/texmf-dist/tex/context/base/data-tre.lua +++ b/Master/texmf-dist/tex/context/base/data-tre.lua @@ -6,50 +6,89 @@ if not modules then modules = { } end modules ['data-tre'] = { license = "see context related readme files" } --- \input tree://oeps1/**/oeps.tex +-- tree://e:/temporary/mb-mp/**/drawing.jpg +-- tree://e:/temporary/mb-mp/**/Drawing.jpg +-- tree://t:./**/tufte.tex +-- tree://t:/./**/tufte.tex +-- tree://t:/**/tufte.tex +-- dirlist://e:/temporary/mb-mp/**/drawing.jpg +-- dirlist://e:/temporary/mb-mp/**/Drawing.jpg +-- dirlist://e:/temporary/mb-mp/**/just/some/place/drawing.jpg +-- dirlist://e:/temporary/mb-mp/**/images/drawing.jpg +-- dirlist://e:/temporary/mb-mp/**/images/drawing.jpg?option=fileonly +-- dirlist://///storage-2/resources/mb-mp/**/drawing.jpg +-- dirlist://e:/**/drawing.jpg -local find, gsub, format = string.find, string.gsub, string.format +local find, gsub, lower = string.find, string.gsub, string.lower +local basename, dirname, joinname = file.basename, file.dirname, file .join +local globdir, isdir, isfile = dir.glob, lfs.isdir, lfs.isfile +local P, lpegmatch = lpeg.P, lpeg.match local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) -local report_trees = logs.reporter("resolvers","trees") +local report_trees = logs.reporter("resolvers","trees") -local resolvers = resolvers +local resolvers = resolvers +local resolveprefix = resolvers.resolve +local notfound = resolvers.finders.notfound +local lookup = resolvers.get_from_content -local done, found, notfound = { }, { }, resolvers.finders.notfound +-- A tree search is rather dumb ... there is some basic caching of searched trees +-- but nothing is cached over runs ... it's also a wildcard one so we cannot use +-- the normal scanner. -function resolvers.finders.tree(specification) +local collectors = { } +local found = { } + +function resolvers.finders.tree(specification) -- to be adapted to new formats local spec = specification.filename - local fnd = found[spec] - if fnd == nil then + local okay = found[spec] + if okay == nil then if spec ~= "" then - local path, name = file.dirname(spec), file.basename(spec) - if path == "" then path = "." end - local hash = done[path] - if not hash then - local pattern = path .. "/*" -- we will use the proper splitter - hash = dir.glob(pattern) - done[path] = hash + local path = dirname(spec) + local name = basename(spec) + if path == "" then + path = "." + end + local names = collectors[path] + if not names then + local pattern = find(path,"/%*+$") and path or (path .. "/*") + names = globdir(pattern) + collectors[path] = names end local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$" - for k=1,#hash do - local v = hash[k] - if find(v,pattern) then - found[spec] = v - return v + for i=1,#names do + local fullname = names[i] + if find(fullname,pattern) then + found[spec] = fullname + return fullname + end + end + -- let's be nice: + local pattern = lower(pattern) + for i=1,#names do + local fullname = lower(names[i]) + if find(fullname,pattern) then + if isfile(fullname) then + found[spec] = fullname + return fullname + else + -- no os name mapping + break + end end end end - fnd = notfound() -- false - found[spec] = fnd + okay = notfound() -- false + found[spec] = okay end - return fnd + return okay end function resolvers.locators.tree(specification) local name = specification.filename - local realname = resolvers.resolve(name) -- no shortcut - if realname and realname ~= '' and lfs.isdir(realname) then + local realname = resolveprefix(name) -- no shortcut + if realname and realname ~= '' and isdir(realname) then if trace_locating then report_trees("locator %a found",realname) end @@ -61,15 +100,134 @@ end function resolvers.hashers.tree(specification) local name = specification.filename - if trace_locating then - report_trees("analysing %a",name) - end + -- if trace_locating then + report_trees("analyzing %a",name) + -- end resolvers.methodhandler("hashers",name) resolvers.generators.file(specification) end -resolvers.concatinators.tree = resolvers.concatinators.file -resolvers.generators.tree = resolvers.generators.file -resolvers.openers.tree = resolvers.openers.file -resolvers.loaders.tree = resolvers.loaders.file +-- This is a variation on tree lookups but this time we do cache in the given +-- root. We use a similar hasher as the resolvers because we have to deal with +-- for instance trees with 50K xml files plus a similar amount of resources to +-- deal and we don't want too much overhead. + +local collectors = { } +local splitter = lpeg.splitat("/**/") +local stripper = lpeg.replacer { [P("/") * P("*")^1 * P(-1)] = "" } + +table.setmetatableindex(collectors, function(t,k) + local rootname = lpegmatch(stripper,k) + local dataname = joinname(rootname,"dirlist") + local content = caches.loadcontent(dataname,"files",dataname) + if not content then + -- path branch usecache onlyonce tolerant + content = resolvers.scanfiles(rootname,nil,nil,false,true) -- so we accept crap + caches.savecontent(dataname,"files",content,dataname) + end + t[k] = content + return content +end) + + +local function checked(root,p,n) + if p then + if type(p) == "table" then + for i=1,#p do + local fullname = joinname(root,p[i],n) + if isfile(fullname) then -- safeguard + return fullname + end + end + else + local fullname = joinname(root,p,n) + if isfile(fullname) then -- safeguard + return fullname + end + end + end + return notfound() +end + +-- no funny characters in path but in filename permitted .. sigh + +local function resolve(specification) -- can be called directly too + local filename = specification.filename + -- inspect(specification) + if filename ~= "" then + local root, rest = lpegmatch(splitter,filename) + if root and rest then + local path, name = dirname(rest), basename(rest) + if name ~= rest then + local content = collectors[root] + local p, n = lookup(content,name) + if not p then + return notfound() + end + local pattern = ".*/" .. path .. "$" + local istable = type(p) == "table" + if istable then + for i=1,#p do + local pi = p[i] + if pi == path or find(pi,pattern) then + local fullname = joinname(root,pi,n) + if isfile(fullname) then -- safeguard + return fullname + end + end + end + elseif p == path or find(p,pattern) then + local fullname = joinname(root,p,n) + if isfile(fullname) then -- safeguard + return fullname + end + end + local queries = specification.queries + if queries and queries.option == "fileonly" then + return checked(root,p,n) + else + return notfound() + end + end + end + local path, name = dirname(filename), basename(filename) + local root = lpegmatch(stripper,path) + local content = collectors[path] + local p, n = lookup(content,name) + if p then + return checked(root,p,n) + end + end + return notfound() +end + +resolvers.finders .dirlist = resolve +resolvers.locators .dirlist = resolvers.locators .tree +resolvers.hashers .dirlist = resolvers.hashers .tree +resolvers.generators.dirlist = resolvers.generators.file +resolvers.openers .dirlist = resolvers.openers .file +resolvers.loaders .dirlist = resolvers.loaders .file + +function resolvers.finders.dirfile(specification) + local queries = specification.queries + if queries then + queries.option = "fileonly" + else + specification.queries = { option = "fileonly" } + end + return resolve(specification) +end + +resolvers.locators .dirfile = resolvers.locators .dirlist +resolvers.hashers .dirfile = resolvers.hashers .dirlist +resolvers.generators.dirfile = resolvers.generators.dirlist +resolvers.openers .dirfile = resolvers.openers .dirlist +resolvers.loaders .dirfile = resolvers.loaders .dirlist + +-- local locate = collectors[ [[E:\temporary\mb-mp]] ] +-- local locate = collectors( [[\\storage-2\resources\mb-mp]] ) + +-- print(resolvers.findtexfile("tree://e:/temporary/mb-mp/**/VB_wmf_03_vw_01d_ant.jpg")) +-- print(resolvers.findtexfile("tree://t:/**/tufte.tex")) +-- print(resolvers.findtexfile("dirlist://e:/temporary/mb-mp/**/VB_wmf_03_vw_01d_ant.jpg")) |