summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/data-tre.lua
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
commit8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch)
tree94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/mkiv/data-tre.lua
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/mkiv/data-tre.lua')
-rw-r--r--tex/context/base/mkiv/data-tre.lua233
1 files changed, 233 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/data-tre.lua b/tex/context/base/mkiv/data-tre.lua
new file mode 100644
index 000000000..4388731f9
--- /dev/null
+++ b/tex/context/base/mkiv/data-tre.lua
@@ -0,0 +1,233 @@
+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"))