summaryrefslogtreecommitdiff
path: root/indra/newview/scripts/lua/require/util.lua
diff options
context:
space:
mode:
authornat-goodspeed <nat@lindenlab.com>2024-08-28 10:23:53 -0400
committerGitHub <noreply@github.com>2024-08-28 10:23:53 -0400
commit6f454ad8366ed33bbe199c3fc3ed69e6d3448cec (patch)
tree05f856f85c00194c6c43ca23cacb7021a50ffa33 /indra/newview/scripts/lua/require/util.lua
parentc225b44a59ddd6b84105ace4181b3ca9f7439bfa (diff)
parent7b21acd39745d265548eeb62d687cde9febb1f7a (diff)
Merge pull request #2416 from secondlife/lua-lazymod
Allow UI to have lazily-loaded submodules.
Diffstat (limited to 'indra/newview/scripts/lua/require/util.lua')
-rw-r--r--indra/newview/scripts/lua/require/util.lua65
1 files changed, 55 insertions, 10 deletions
diff --git a/indra/newview/scripts/lua/require/util.lua b/indra/newview/scripts/lua/require/util.lua
index bfbfc8637c..40737a159a 100644
--- a/indra/newview/scripts/lua/require/util.lua
+++ b/indra/newview/scripts/lua/require/util.lua
@@ -15,16 +15,9 @@ local util = {}
-- util.classctor(MyClass, MyClass.construct)
-- return MyClass
function util.classctor(class, ctor)
- -- get the metatable for the passed class
- local mt = getmetatable(class)
- if mt == nil then
- -- if it doesn't already have a metatable, then create one
- mt = {}
- setmetatable(class, mt)
- end
- -- now that class has a metatable, set its __call method to the specified
- -- constructor method (class.new if not specified)
- mt.__call = ctor or class.new
+ -- set class's __call metamethod to the specified constructor function
+ -- (class.new if not specified)
+ util.setmetamethods{class, __call=(ctor or class.new)}
end
-- check if array-like table contains certain value
@@ -66,4 +59,56 @@ function util.equal(t1, t2)
return util.empty(temp)
end
+-- Find or create the metatable for a specified table (a new empty table if
+-- omitted), and to that metatable assign the specified keys.
+-- Setting multiple keys at once is more efficient than a function to set only
+-- one at a time, e.g. setametamethod().
+-- t = util.setmetamethods{__index=readfunc, __len=lenfunc}
+-- returns a new table with specified metamethods __index, __len
+-- util.setmetamethods{t, __call=action}
+-- finds or creates the metatable for existing table t and sets __call
+-- util.setmetamethods{table=t, __call=action}
+-- same as util.setmetamethods{t, __call=action}
+function util.setmetamethods(specs)
+ -- first determine the target table
+ assert(not (specs.table and specs[1]),
+ "Pass setmetamethods table either as positional or table=, not both")
+ local t = specs.table or specs[1] or {}
+ -- remove both ways of specifying table, leaving only the metamethods
+ specs.table = nil
+ specs[1] = nil
+ local mt = getmetatable(t)
+ if not mt then
+ -- t doesn't already have a metatable: just set specs
+ setmetatable(t, specs)
+ else
+ -- t already has a metatable: copy specs into it
+ local key, value
+ for key, value in pairs(specs) do
+ mt[key] = value
+ end
+ end
+ -- having set or enriched t's metatable, return t
+ return t
+end
+
+-- On the passed module (i.e. table), set an __index metamethod such that
+-- referencing module.submodule lazily requires(path/submodule).
+-- The loaded submodule is cached in the module table so it need not be passed
+-- to require() again.
+-- 'path', like any require() string, can be relative to LuaRequirePath.
+-- Returns the enriched module, permitting e.g.
+-- mymod = util.submoduledir({}, 'mymod')
+function util.submoduledir(module, path)
+ return util.setmetamethods{
+ module,
+ __index=function(t, key)
+ local mod = require(`{path}/{key}`)
+ -- cache the submodule
+ t[key] = mod
+ return mod
+ end
+ }
+end
+
return util