summaryrefslogtreecommitdiff
path: root/tex/context/base/data-tre.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/data-tre.lua')
-rw-r--r--tex/context/base/data-tre.lua222
1 files changed, 190 insertions, 32 deletions
diff --git a/tex/context/base/data-tre.lua b/tex/context/base/data-tre.lua
index 0a8b00d9b..4388731f9 100644
--- a/tex/context/base/data-tre.lua
+++ b/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"))