if not modules then modules = { } end modules ['data-tre'] = { version = 1.001, comment = "companion to luat-lib.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- 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, 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 resolvers = resolvers local resolveprefix = resolvers.resolve local notfound = resolvers.finders.notfound local lookup = resolvers.get_from_content -- 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. local collectors = { } local found = { } function resolvers.finders.tree(specification) -- to be adapted to new formats local spec = specification.filename local okay = found[spec] if okay == nil then if spec ~= "" then 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 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 okay = notfound() -- false found[spec] = okay end return okay end function resolvers.locators.tree(specification) local name = specification.filename 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 resolvers.appendhash('tree',name,false) -- don't cache elseif trace_locating then report_trees("locator %a not found",name) end end function resolvers.hashers.tree(specification) local name = specification.filename if trace_locating then report_trees("analyzing %a",name) end resolvers.methodhandler("hashers",name) resolvers.generators.file(specification) end -- 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"))