libs-ini.lmt /size: 6438 b    last modification: 2024-01-16 10:22
1if not modules then modules = { } end modules ['libs-ini'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- This is a loader for optional libraries in luametatex with context lmtx. It's
10-- kind of experimental. We also use a different locator than in mkiv because we
11-- don't support loading lua libraries and swiglibs any more. Of course one can try
12-- the regular lua loaders but we just assume that a user then knows what (s)he is
13-- doing. At some point this variant will divert more from the original loader
14-- file 'libs-ini.lua'.
15
16local type, unpack = type, unpack
17local find = string.find
18
19-- here we implement the resolver
20
21local nameonly      = file.nameonly
22local joinfile      = file.join
23local addsuffix     = file.addsuffix
24local qualifiedpath = file.is_qualified_path
25
26local isfile        = lfs.isfile
27
28local findfile      = resolvers.findfile
29local expandpaths   = resolvers.expandedpathlistfromvariable
30
31local report        = logs.reporter("resolvers","libraries")
32local trace         = false
33local silent        = false
34
35trackers.register("resolvers.lib",        function(v) trace  = v end)
36trackers.register("resolvers.lib.silent", function(v) silent = v end)
37
38local function findlib(required) -- todo: cache
39    local suffix = os.libsuffix or "so"
40    if not qualifiedpath(required) then
41        local list = directives.value("system.librarynames" )
42        local only = nameonly(required)
43        if type(list) == "table" then
44            list = list[only]
45            if type(list) ~= "table" then
46                list = { only }
47            end
48        else
49            list = { only }
50        end
51        if trace then
52            report("using lookup list for library %a: % | t",only,list)
53        end
54        for i=1,#list do
55            local name  = list[i]
56            local found = findfile(name,"lib")
57            if not found or found == "" then
58                found = findfile(addsuffix(name,suffix),"lib")
59            end
60            if found and found ~= "" then
61                if trace then
62                    report("library %a resolved via %a path to %a",name,"tds lib",found)
63                end
64                return found
65            end
66        end
67        if expandpaths then
68            local list = expandpaths("PATH")
69            local base = addsuffix(only,suffix)
70            for i=1,#list do
71                local full  = joinfile(list[i],base)
72                local found = isfile(full) and full
73                if found and found ~= "" then
74                    if trace then
75                        report("library %a resolved via %a path to %a",full,"system",found)
76                    end
77                    return found
78                end
79            end
80        end
81    elseif isfile(addsuffix(required,suffix)) then
82        if trace then
83            report("library with qualified name %a %sfound",required,"")
84        end
85        return required
86    else
87        if trace then
88            report("library with qualified name %a %sfound",required,"not ")
89        end
90    end
91    return false
92end
93
94local foundlibraries = table.setmetatableindex(function(t,k)
95    local v = findlib(k)
96    t[k] = v
97    return v
98end)
99
100function resolvers.findlib(required)
101    return foundlibraries[required]
102end
103
104-- here we implement the loader
105
106local libraries     = { }
107resolvers.libraries = libraries
108
109local report        = logs.reporter("optional")
110
111if optional then optional.loaded = { } end
112
113function libraries.validoptional(name)
114    local thelib = optional and optional[name]
115    if not thelib then
116        -- forget about it, no message here
117    elseif thelib.initialize then
118        return thelib
119    else
120        report("invalid optional library %a",libname)
121    end
122end
123
124function libraries.optionalloaded(name,libnames)
125    local thelib = optional and optional[name]
126    if not thelib then
127        report("no optional %a library found",name)
128    else
129        local thelib_initialize = thelib.initialize
130        if not thelib_initialize then
131            report("invalid optional library %a",name)
132        else
133            if type(libnames) == "string" then
134                libnames = { libnames }
135            end
136            if type(libnames) == "table" then
137                for i=1,#libnames do
138                    local libname  = libnames[i]
139                    local filename = foundlibraries[libname]
140                    if filename and filename ~= "" then
141                        libnames[i] = filename
142                    else
143                        report("unable to locate library %a",libname)
144                        return
145                    end
146                end
147                local initialized = thelib_initialize(unpack(libnames))
148                if not initialized then
149                    report("unable to initialize library '% + t'",libnames)
150                elseif not silent then
151                    report("using library '% + t'",libnames)
152                end
153                return initialized
154            end
155        end
156    end
157end
158
159-- local patterns = {
160--     "libs-imp-%s.mkxl",
161--     "libs-imp-%s.mklx",
162-- }
163--
164-- local function action(name,foundname)
165--     -- could be one command
166--     context.startreadingfile()
167--     context.input(foundname)
168--     context.stopreadingfile()
169-- end
170--
171-- interfaces.implement {
172--     name      = "uselibrary",
173--     arguments = "string"
174--     actions   = function(name)
175--         resolvers.uselibrary {
176--             category = "color definition",
177--             name     = name,
178--             patterns = patterns,
179--             action   = action,
180--             onlyonce = true,
181--         }
182--     end
183-- }
184
185-- We overload the standard 'require' function. Because we're in LuaMetaTeX we are
186-- more likely to find 'lmt' files when we deal with the TeX and MetaPost part but
187-- user files likely have the 'lua' suffix.
188
189do
190
191    local dofile       = dofile
192    local savedrequire = require
193
194    function require(name,version)
195        if find(name,"%.lua$") or find(name,"%.lmt$") then
196            local m = dofile(findfile(name))
197            if m then
198                package.loaded[name] = m
199                return m
200            end
201        else
202            return savedrequire(name)
203        end
204    end
205
206end
207