1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
if not modules then modules = { } end modules ['data-met'] = {
version = 1.100,
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"
}
local find, format = string.find, string.format
local sequenced = table.sequenced
local addurlscheme, urlhashed = url.addscheme, url.hashed
local getcurrentdir = lfs.currentdir
local trace_locating = false
local trace_methods = false
trackers.register("resolvers.locating", function(v) trace_methods = v end)
trackers.register("resolvers.methods", function(v) trace_methods = v end)
--~ trace_methods = true
local report_methods = logs.reporter("resolvers","methods")
local allocate = utilities.storage.allocate
local resolvers = resolvers
local registered = { }
local function splitmethod(filename) -- todo: filetype in specification
if not filename then
return { scheme = "unknown", original = filename }
end
if type(filename) == "table" then
return filename -- already split
end
filename = file.collapsepath(filename,".") -- hm, we should keep ./ in some cases
-- filename = gsub(filename,"^%./",getcurrentdir().."/") -- we will merge dir.expandname and collapse some day
if not find(filename,"://") then
return { scheme = "file", path = filename, original = filename, filename = filename }
end
local specification = url.hashed(filename)
if not specification.scheme or specification.scheme == "" then
return { scheme = "file", path = filename, original = filename, filename = filename }
else
return specification
end
end
resolvers.splitmethod = splitmethod -- bad name but ok
-- the second argument is always analyzed (saves time later on) and the original
-- gets passed as original but also as argument
local function methodhandler(what,first,...) -- filename can be nil or false
local method = registered[what]
if method then
local how, namespace = method.how, method.namespace
if how == "uri" or how == "url" then
local specification = splitmethod(first)
local scheme = specification.scheme
local resolver = namespace and namespace[scheme]
if resolver then
if trace_methods then
report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
end
return resolver(specification,...)
else
resolver = namespace.default or namespace.file
if resolver then
if trace_methods then
report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
end
return resolver(specification,...)
elseif trace_methods then
report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
end
end
elseif how == "tag" then
local resolver = namespace and namespace[first]
if resolver then
if trace_methods then
report_methods("resolving, method %a, how %a, tag %a",what,how,first)
end
return resolver(...)
else
resolver = namespace.default or namespace.file
if resolver then
if trace_methods then
report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
end
return resolver(...)
elseif trace_methods then
report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
end
end
end
else
report_methods("resolving, invalid method %a")
end
end
resolvers.methodhandler = methodhandler
function resolvers.registermethod(name,namespace,how)
registered[name] = { how = how or "tag", namespace = namespace }
namespace["byscheme"] = function(scheme,filename,...)
if scheme == "file" then
return methodhandler(name,filename,...)
else
return methodhandler(name,addurlscheme(filename,scheme),...)
end
end
end
local concatinators = allocate { notfound = file.join } -- concatinate paths
local locators = allocate { notfound = function() end } -- locate databases
local hashers = allocate { notfound = function() end } -- load databases
local generators = allocate { notfound = function() end } -- generate databases
resolvers.concatinators = concatinators
resolvers.locators = locators
resolvers.hashers = hashers
resolvers.generators = generators
local registermethod = resolvers.registermethod
registermethod("concatinators",concatinators,"tag")
registermethod("locators", locators, "uri")
registermethod("hashers", hashers, "uri")
registermethod("generators", generators, "uri")
|