Module:Buffer: Difference between revisions
From Zoophilia Wiki
Jump to navigationJump to search
meta>Codehydro (move out to meta) |
meta>Codehydro (many many new features) |
||
Line 1: | Line 1: | ||
return setmetatable({ | return setmetatable({[type] = function(v) | ||
if v and v~=true then--reject nil/boolean; faster than 2 type() comparisons | |||
if v and v ~= true then | local str = tostring(v) | ||
if str~=v and str=='table' then return table.concat(v) end | |||
return str~='' and str or nil | |||
end | |||
end, | |||
[select] = function(n, ...) | |||
local seps, meta = {select(2, ...)} | |||
if type(seps[#seps])=='table' then | |||
meta = rawset(table.remove(seps), '__index', function(t, i) return meta[1] end) | |||
setmetatable(seps, meta) | |||
end | end | ||
return ..., seps | |||
end, | end, | ||
__index = { | __index = { | ||
_ = function(self, v) | _ = function(self, v, ...) | ||
local | local at, raw = ... | ||
if | if select('#', ...)==1 and at==not not at then raw, at = at end | ||
table. | if raw then self[rawset] = math.huge else v = getmetatable(self)[type](v) end | ||
if v or raw then | |||
if at then | |||
at = math.max(1, (tostring(at)==at or at < 1) and #self + at or at) | |||
if at > #self + 1 then self[rawset] = self[rawset] and math.max(at, self[rawset]) or at end | |||
end | |||
self.last_concat = table.insert(self, select(at and 1 or 2, at, v)) | |||
end | |||
return self | |||
end, | |||
_nil = function(self, at, v2) | |||
if v2~=true and v2~=false then--faster than type(v2) ~= 'boolean' | |||
self[rawset] = math.huge | |||
at = math.max(1, at and (tostring(at)==at or at < 1) and #self + at or at or #self) | |||
if v2 then self[at] = v2 else table.remove(self, at) end | |||
end | end | ||
return self | return self | ||
end, | end, | ||
_all = function(self, t, valKey) | |||
for k, v in getmetatable(self).__pairs(t) do self:_mix(v) end | |||
if valKey then | |||
for k, v in getmetatable(self).__pairs(t, false) do | |||
if tonumber(v)==v then self:_(k, v) end | |||
end | |||
end | |||
return self | |||
end, | end, | ||
_out = function( | _mix = function(self, v, a) return v and ((type(v)~='table' or getmetatable(v)) and self._ or self._all)(self, v, a) or self end,--internal helper, do not list in doc | ||
local parent = | _str = function(self, ...) return getmetatable(self).__tostring(self, ...) end, | ||
if outs and outs | _in = function (self, ...) return rawset(getmetatable(self)(...), next, self) end,--Module:Buffer objects use [next] rather than 'parent' to avoid traversal by mw.html.allDone() | ||
_out = function(self, ...) | |||
if self[next] then | |||
outs = parent and parent:_( | local n, parent = select('#', ...), self[next] | ||
if n > 1 then | |||
return | local k, outs, seps = 1, getmetatable(self)[select](n, ...) | ||
while outs > 0 do | |||
parent:_(self(seps[k])) | |||
self, parent, k = parent, parent[next], k + 1 | |||
outs = parent and outs - 1 or 0 | |||
end | |||
else return parent:_(self(...)) end | |||
end | |||
return self[next] or self | |||
end, | |||
_c = function(self, clear, copy) | |||
assert(type(clear)=='table', copy and | |||
"Buffer:_c(clear, copy) only accepts tables for arg 'clear'." | |||
or "Two possible causes: 1) Called Buffer:_c(clear, copy) without colon, or 2) Type of 'clear' is not 'table'." | |||
) | |||
for k in next, clear do clear[k] = nil end | |||
local meta, copyMeta, copyType = getmetatable(self) | |||
if copy then | |||
if type(copy)=='table' then | |||
for k, v in next, copy do clear[k] = type(v)=='table' and mw.clone(v) or v end | |||
clear[rawset] = clear[rawset] or math.huge | |||
copyMeta = getmetatable(copy) | |||
if copyMeta then | |||
if not buffHTMLmeta then meta():_inHTML() end | |||
if copyMeta==buffHTMLmeta[mw.html] then | |||
copyMeta = buffHTMLmeta | |||
setmetatable(clear.nodes, meta) | |||
end | |||
end | |||
elseif meta[type](copy) then clear[1] = copy end | |||
end | |||
setmetatable(clear, copyMeta or meta) | |||
return self | |||
end, | |||
_parent = function(self, s, outs, ...) return self:_(outs and self[next]:_str(s, outs, ...) or self[next](s)) end, | |||
getParent = function(self, ...) return (assert(self, ' (:function(), not .function())')[next] or rawset(rawset(self, next, getmetatable(self)())[next], require, {self})):_(...) end, | |||
_inHTML = function(self, ...) | |||
local HTML, meta = mw.html.create(...), getmetatable(self) | |||
if not buffHTMLmeta then | |||
local mwHTMLmeta = getmetatable(mw.html.create()) | |||
buffHTMLmeta, mwHTMLfunc = rawset(mw.clone(mwHTMLmeta), mw.html, mwHTMLmeta), mwHTMLmeta.__index | |||
for k, v in next, { | |||
[rawget] = function(HTML, Buffer, ...) | |||
buffHTMLmeta[require] = HTML | |||
if ... then return select('#', ...)==1 and Buffer:_(...) or assert(Buffer[...], ('" %s " does not match any Module:Buffer function'):format(tostring(...)))(Buffer, select(2, ...)) end | |||
return Buffer | |||
end, | |||
getParent = function(HTML, ...) return HTML[rawget](HTML, HTML:allDone()[next], ...) end,--return to buffer that created it | |||
getBuffer = function(HTML, ...) return HTML[rawget](HTML, buffHTMLmeta[next], ...) end,--return to last buffer used | |||
_out = function(HTML, ...) return HTML:getParent():_(HTML):_out(...) end, | |||
_inv = function(HTML, s, outs, ...) return HTML.nodes:_(outs and HTML:getParent():_str(s, outs, ...) or HTML:getParent()(s)) end | |||
} do buffHTMLmeta.__index[k] = v end | |||
if new_G then | |||
for k, v in pairs(gfuncs) do buffHTMLmeta.__index[k] = v end | |||
gfuncs = nil | |||
end | |||
local mbpairs, outFuncs, htmlArg, nonSelf, spinach = meta.__pairs, {}, {parent = true, selfClosing = true, tagName = true}, {tag = true, done = true, allDone = true} | |||
spinach = {--spinach makes html.nodes buffer... get it?... | |||
[rawset] = math.huge, | |||
_out = function(nodes, ...) return nodes:getParent('_', nodes:getHTML()):_out(...) end, | |||
_add = function(nodes, t)--children are unenhanced | |||
local HTML, nodeFunc = nodes[next], buffHTMLmeta[require].nodes | |||
for k, v in mbpairs(t) do buffHTMLmeta.__call(HTML, v~=true and v) end | |||
for k, v in mbpairs(t, false) do | |||
if htmlArg[k] then HTML[k] = v | |||
elseif v and v~=true then | |||
if nonSelf[k] then | |||
if k=='tag' then | |||
if tostring(v)==v then mwHTMLfunc.tag(HTML, v) | |||
elseif v[1] and v[1]~=true then | |||
local tag = mwHTMLfunc.tag(HTML, v[1]) | |||
setmetatable(nodeFunc._add(rawset(setmetatable(tag.nodes, meta), next, tag), v), nil)[1], tag.nodes[next] = false | |||
else nodeFunc._add(HTML.nodes, v) end | |||
else buffHTMLmeta.__call(mwHTMLfunc[k](HTML), v) end--k = done/allDone | |||
elseif mwHTMLfunc[k] then | |||
if k=='node' or type(v)~='table' then mwHTMLfunc[k](HTML, v) | |||
else | |||
for x, y in next, v do | |||
if y and y~=true then mwHTMLfunc[k](HTML, x, y) end | |||
end | |||
end | |||
else nodeFunc[k](HTML.nodes, v) end | |||
end | |||
end | |||
return nodes | |||
end | |||
} | |||
function makeNodesBuffer(HTML) | |||
local nodes = setmetatable(HTML.nodes, meta) | |||
nodes[next], nodes.parent = HTML, HTML | |||
for k, v in next, buffHTMLmeta.__index do | |||
nodes[k] = rawset(outFuncs, k, outFuncs[k] or function(nodes, ...) return v(nodes[next], ...) end)[k] | |||
end | |||
for k, v in next, spinach do nodes[k] = v end | |||
nodes._inHTML, nodes._build = nodes.tag | |||
end | |||
for k in next, nonSelf do--any HTML objects returned by these funcs will be granted Module:Buffer enhancements | |||
local func = mwHTMLfunc[k] | |||
buffHTMLmeta.__index[k] = function(t, ...) | |||
local HTML = func(t, ...) | |||
if not HTML[next] then makeNodesBuffer(setmetatable(rawset(HTML, next, t), buffHTMLmeta)) end | |||
return HTML | |||
end | |||
end | |||
for k, v in next, {--add new Buffer object functions | |||
getHTML = function(self, ...) | |||
buffHTMLmeta[next] = self | |||
if ... then | |||
if type(...)=='table' then return buffHTMLmeta[require](...) | |||
else return assert(buffHTMLmeta[require][...], ('" %s " does not match any mw.html function'):format(tostring(...)))(buffHTMLmeta[require], select(2, ...)) end | |||
end | |||
return buffHTMLmeta[require] | |||
end, | |||
_html = function(self, ...) return self:_(self:getHTML(), ...) end | |||
} do meta.__index[k] = v end | |||
buffHTMLmeta.__call = function(h, ...) return ... and ('table'==type(...) and spinach._add or h.nodes._)(h.nodes, ...) or h.nodes end | |||
end | |||
makeNodesBuffer(setmetatable(HTML, buffHTMLmeta)) | |||
rawset(setmetatable(HTML, rawset(buffHTMLmeta, require, HTML)), next, self) | |||
return self:getHTML() | |||
end, | |||
_build = function (self, nodes) return table.insert(nodes, self()) end--for compatibility with regular mw.html objects | |||
}, | |||
__call = function(t, ...) | |||
local t2 = t[rawset] and t[rawset] > #t and getmetatable(t)():_all(t) or t | |||
if select('#', ...)==0 then return rawset(t, 'last_concat', t.last_concat or table.concat(t2)).last_concat end | |||
return table.concat(t2, ...) or '' | |||
end, | |||
__tostring = function(t, ...) | |||
if type(t)~='table' then return t end | |||
local n, r = select('#', ...), getmetatable(t) | |||
if n > 1 then | |||
local k, outs, seps = 2, r[select](n, ...) | |||
r = r(t(seps[1])) | |||
while outs > 1 do | |||
r:_(t[next](seps[k]), 1) | |||
t, k = t[next], k + 1 | |||
outs = t[next] and outs - 1 or 0 | |||
end | |||
return table.concat(r, seps[k]) or '' | |||
end | |||
return t(...) | |||
end, | |||
__concat = function(a, b, Buffer) | |||
if Buffer then return error end | |||
Buffer = getmetatable(a) | |||
local us, them = pcall(Buffer and Buffer.__concat, false, next, 1) | |||
if not us or them~=error then Buffer = getmetatable(b) end | |||
return Buffer():_all{a, b}() | |||
end, | |||
__pairs = function(t, ...)--pairs always iterates in order | |||
if not map then | |||
map = setmetatable({}, {__mode='k'}) | |||
function mBuffIter(t, i) i = map[t].i[nil==i and 1 or map[t].n[i]] return i, t[i] end | |||
function mBuffOther(t, i) i = map[t].o[nil==i and 1 or map[t].o[i]] return i, t[i] end | |||
function mBuffMap(t) | |||
local ti, tn, to, n = {}, {}, {}, #t--reduces table lookups | |||
map[t] = {i = ti, n = tn, o = to} | |||
for k = 1, n do | |||
table.insert(ti, k) | |||
tn[k] = k + 1 | |||
end | |||
if n==0 or next(t, n)~=nil then | |||
local start = next(t)==1 and n or nil | |||
for k, v in next, t, start do | |||
if tn[k] then--no op, since: t={[2]=1,[1]=2}; #t => 2; next(t,#t) => 1,2 | |||
elseif tonumber(k)==k then table.insert(ti, k) | |||
elseif k~=t and v~=t then | |||
table.insert(to, k) | |||
to[k] = #to + 1 | |||
end | |||
end | |||
end | |||
if #ti~=n then | |||
table.sort(ti) | |||
for k, v in next, ti do tn[v] = k + 1 end | |||
end | |||
end | |||
end | |||
local n = select('#', ...) | |||
if ...==true or n==0 then mBuffMap(t) end | |||
return ...==nil and mBuffIter or mBuffOther, t | |||
end, | |||
__ipairs = pairs | |||
},{__tostring = function()return'Module:Buffer'end, | |||
__call = function(self, ...) | |||
if not libFunc then--adds string and mw libraries; also add global functions if passed | |||
libFunc = {__call = function(t, self, ...) return t[1](type(self)~='table' and self or self:_str(), ...) end} | |||
for _, library in ipairs{mw.text, string, mw.ustring} do | |||
for k, func in pairs(library) do self.__index[library==mw.ustring and k .. '_' or k] = setmetatable({func}, libFunc) end | |||
end | |||
new_G = ... and type(...)=='table' and (...)._G==... and ...~=_G and (...).mw and (...).mw.log==mw.log and ... | |||
if new_G then | |||
gfuncs = { | |||
_G = function(self, name, var) | |||
if rawget(new_G, name) then | |||
local metaG = getmetatable(new_G) | |||
if not metaG then | |||
metaG = {__index = {}} | |||
setmetatable(new_G, metaG) | |||
end | |||
metaG.__index[name] = new_G[name] | |||
end | |||
new_G[name] = var or self | |||
return self | |||
end, | |||
_R = function(self, name, var) new_G[name] = var return self end, | |||
_B = function(self, var) return var or var~=false and self end | |||
} | |||
for k, v in pairs(gfuncs) do self.__index[k] = v end | |||
end | |||
end | end | ||
if new_G and ... and (...)==new_G then--rawget circumvents 'attempt to read nil global' error | |||
local new, name = setmetatable({}, self), select(2, ...) | |||
return | if name and type(name)=='string' then new_G[name] = new end | ||
return new | |||
end | |||
return setmetatable({}, self):_(...) | |||
end, | |||
__index = function(t, i) | |||
return function(...) return t.__index[i](t(), select(2,...)) end | |||
end | end | ||
}) | }) |
Revision as of 22:19, 16 February 2015
Documentation for this module may be created at Module:Buffer/doc
return setmetatable({[type] = function(v) if v and v~=true then--reject nil/boolean; faster than 2 type() comparisons local str = tostring(v) if str~=v and str=='table' then return table.concat(v) end return str~='' and str or nil end end, [select] = function(n, ...) local seps, meta = {select(2, ...)} if type(seps[#seps])=='table' then meta = rawset(table.remove(seps), '__index', function(t, i) return meta[1] end) setmetatable(seps, meta) end return ..., seps end, __index = { _ = function(self, v, ...) local at, raw = ... if select('#', ...)==1 and at==not not at then raw, at = at end if raw then self[rawset] = math.huge else v = getmetatable(self)[type](v) end if v or raw then if at then at = math.max(1, (tostring(at)==at or at < 1) and #self + at or at) if at > #self + 1 then self[rawset] = self[rawset] and math.max(at, self[rawset]) or at end end self.last_concat = table.insert(self, select(at and 1 or 2, at, v)) end return self end, _nil = function(self, at, v2) if v2~=true and v2~=false then--faster than type(v2) ~= 'boolean' self[rawset] = math.huge at = math.max(1, at and (tostring(at)==at or at < 1) and #self + at or at or #self) if v2 then self[at] = v2 else table.remove(self, at) end end return self end, _all = function(self, t, valKey) for k, v in getmetatable(self).__pairs(t) do self:_mix(v) end if valKey then for k, v in getmetatable(self).__pairs(t, false) do if tonumber(v)==v then self:_(k, v) end end end return self end, _mix = function(self, v, a) return v and ((type(v)~='table' or getmetatable(v)) and self._ or self._all)(self, v, a) or self end,--internal helper, do not list in doc _str = function(self, ...) return getmetatable(self).__tostring(self, ...) end, _in = function (self, ...) return rawset(getmetatable(self)(...), next, self) end,--Module:Buffer objects use [next] rather than 'parent' to avoid traversal by mw.html.allDone() _out = function(self, ...) if self[next] then local n, parent = select('#', ...), self[next] if n > 1 then local k, outs, seps = 1, getmetatable(self)[select](n, ...) while outs > 0 do parent:_(self(seps[k])) self, parent, k = parent, parent[next], k + 1 outs = parent and outs - 1 or 0 end else return parent:_(self(...)) end end return self[next] or self end, _c = function(self, clear, copy) assert(type(clear)=='table', copy and "Buffer:_c(clear, copy) only accepts tables for arg 'clear'." or "Two possible causes: 1) Called Buffer:_c(clear, copy) without colon, or 2) Type of 'clear' is not 'table'." ) for k in next, clear do clear[k] = nil end local meta, copyMeta, copyType = getmetatable(self) if copy then if type(copy)=='table' then for k, v in next, copy do clear[k] = type(v)=='table' and mw.clone(v) or v end clear[rawset] = clear[rawset] or math.huge copyMeta = getmetatable(copy) if copyMeta then if not buffHTMLmeta then meta():_inHTML() end if copyMeta==buffHTMLmeta[mw.html] then copyMeta = buffHTMLmeta setmetatable(clear.nodes, meta) end end elseif meta[type](copy) then clear[1] = copy end end setmetatable(clear, copyMeta or meta) return self end, _parent = function(self, s, outs, ...) return self:_(outs and self[next]:_str(s, outs, ...) or self[next](s)) end, getParent = function(self, ...) return (assert(self, ' (:function(), not .function())')[next] or rawset(rawset(self, next, getmetatable(self)())[next], require, {self})):_(...) end, _inHTML = function(self, ...) local HTML, meta = mw.html.create(...), getmetatable(self) if not buffHTMLmeta then local mwHTMLmeta = getmetatable(mw.html.create()) buffHTMLmeta, mwHTMLfunc = rawset(mw.clone(mwHTMLmeta), mw.html, mwHTMLmeta), mwHTMLmeta.__index for k, v in next, { [rawget] = function(HTML, Buffer, ...) buffHTMLmeta[require] = HTML if ... then return select('#', ...)==1 and Buffer:_(...) or assert(Buffer[...], ('" %s " does not match any Module:Buffer function'):format(tostring(...)))(Buffer, select(2, ...)) end return Buffer end, getParent = function(HTML, ...) return HTML[rawget](HTML, HTML:allDone()[next], ...) end,--return to buffer that created it getBuffer = function(HTML, ...) return HTML[rawget](HTML, buffHTMLmeta[next], ...) end,--return to last buffer used _out = function(HTML, ...) return HTML:getParent():_(HTML):_out(...) end, _inv = function(HTML, s, outs, ...) return HTML.nodes:_(outs and HTML:getParent():_str(s, outs, ...) or HTML:getParent()(s)) end } do buffHTMLmeta.__index[k] = v end if new_G then for k, v in pairs(gfuncs) do buffHTMLmeta.__index[k] = v end gfuncs = nil end local mbpairs, outFuncs, htmlArg, nonSelf, spinach = meta.__pairs, {}, {parent = true, selfClosing = true, tagName = true}, {tag = true, done = true, allDone = true} spinach = {--spinach makes html.nodes buffer... get it?... [rawset] = math.huge, _out = function(nodes, ...) return nodes:getParent('_', nodes:getHTML()):_out(...) end, _add = function(nodes, t)--children are unenhanced local HTML, nodeFunc = nodes[next], buffHTMLmeta[require].nodes for k, v in mbpairs(t) do buffHTMLmeta.__call(HTML, v~=true and v) end for k, v in mbpairs(t, false) do if htmlArg[k] then HTML[k] = v elseif v and v~=true then if nonSelf[k] then if k=='tag' then if tostring(v)==v then mwHTMLfunc.tag(HTML, v) elseif v[1] and v[1]~=true then local tag = mwHTMLfunc.tag(HTML, v[1]) setmetatable(nodeFunc._add(rawset(setmetatable(tag.nodes, meta), next, tag), v), nil)[1], tag.nodes[next] = false else nodeFunc._add(HTML.nodes, v) end else buffHTMLmeta.__call(mwHTMLfunc[k](HTML), v) end--k = done/allDone elseif mwHTMLfunc[k] then if k=='node' or type(v)~='table' then mwHTMLfunc[k](HTML, v) else for x, y in next, v do if y and y~=true then mwHTMLfunc[k](HTML, x, y) end end end else nodeFunc[k](HTML.nodes, v) end end end return nodes end } function makeNodesBuffer(HTML) local nodes = setmetatable(HTML.nodes, meta) nodes[next], nodes.parent = HTML, HTML for k, v in next, buffHTMLmeta.__index do nodes[k] = rawset(outFuncs, k, outFuncs[k] or function(nodes, ...) return v(nodes[next], ...) end)[k] end for k, v in next, spinach do nodes[k] = v end nodes._inHTML, nodes._build = nodes.tag end for k in next, nonSelf do--any HTML objects returned by these funcs will be granted Module:Buffer enhancements local func = mwHTMLfunc[k] buffHTMLmeta.__index[k] = function(t, ...) local HTML = func(t, ...) if not HTML[next] then makeNodesBuffer(setmetatable(rawset(HTML, next, t), buffHTMLmeta)) end return HTML end end for k, v in next, {--add new Buffer object functions getHTML = function(self, ...) buffHTMLmeta[next] = self if ... then if type(...)=='table' then return buffHTMLmeta[require](...) else return assert(buffHTMLmeta[require][...], ('" %s " does not match any mw.html function'):format(tostring(...)))(buffHTMLmeta[require], select(2, ...)) end end return buffHTMLmeta[require] end, _html = function(self, ...) return self:_(self:getHTML(), ...) end } do meta.__index[k] = v end buffHTMLmeta.__call = function(h, ...) return ... and ('table'==type(...) and spinach._add or h.nodes._)(h.nodes, ...) or h.nodes end end makeNodesBuffer(setmetatable(HTML, buffHTMLmeta)) rawset(setmetatable(HTML, rawset(buffHTMLmeta, require, HTML)), next, self) return self:getHTML() end, _build = function (self, nodes) return table.insert(nodes, self()) end--for compatibility with regular mw.html objects }, __call = function(t, ...) local t2 = t[rawset] and t[rawset] > #t and getmetatable(t)():_all(t) or t if select('#', ...)==0 then return rawset(t, 'last_concat', t.last_concat or table.concat(t2)).last_concat end return table.concat(t2, ...) or '' end, __tostring = function(t, ...) if type(t)~='table' then return t end local n, r = select('#', ...), getmetatable(t) if n > 1 then local k, outs, seps = 2, r[select](n, ...) r = r(t(seps[1])) while outs > 1 do r:_(t[next](seps[k]), 1) t, k = t[next], k + 1 outs = t[next] and outs - 1 or 0 end return table.concat(r, seps[k]) or '' end return t(...) end, __concat = function(a, b, Buffer) if Buffer then return error end Buffer = getmetatable(a) local us, them = pcall(Buffer and Buffer.__concat, false, next, 1) if not us or them~=error then Buffer = getmetatable(b) end return Buffer():_all{a, b}() end, __pairs = function(t, ...)--pairs always iterates in order if not map then map = setmetatable({}, {__mode='k'}) function mBuffIter(t, i) i = map[t].i[nil==i and 1 or map[t].n[i]] return i, t[i] end function mBuffOther(t, i) i = map[t].o[nil==i and 1 or map[t].o[i]] return i, t[i] end function mBuffMap(t) local ti, tn, to, n = {}, {}, {}, #t--reduces table lookups map[t] = {i = ti, n = tn, o = to} for k = 1, n do table.insert(ti, k) tn[k] = k + 1 end if n==0 or next(t, n)~=nil then local start = next(t)==1 and n or nil for k, v in next, t, start do if tn[k] then--no op, since: t={[2]=1,[1]=2}; #t => 2; next(t,#t) => 1,2 elseif tonumber(k)==k then table.insert(ti, k) elseif k~=t and v~=t then table.insert(to, k) to[k] = #to + 1 end end end if #ti~=n then table.sort(ti) for k, v in next, ti do tn[v] = k + 1 end end end end local n = select('#', ...) if ...==true or n==0 then mBuffMap(t) end return ...==nil and mBuffIter or mBuffOther, t end, __ipairs = pairs },{__tostring = function()return'Module:Buffer'end, __call = function(self, ...) if not libFunc then--adds string and mw libraries; also add global functions if passed libFunc = {__call = function(t, self, ...) return t[1](type(self)~='table' and self or self:_str(), ...) end} for _, library in ipairs{mw.text, string, mw.ustring} do for k, func in pairs(library) do self.__index[library==mw.ustring and k .. '_' or k] = setmetatable({func}, libFunc) end end new_G = ... and type(...)=='table' and (...)._G==... and ...~=_G and (...).mw and (...).mw.log==mw.log and ... if new_G then gfuncs = { _G = function(self, name, var) if rawget(new_G, name) then local metaG = getmetatable(new_G) if not metaG then metaG = {__index = {}} setmetatable(new_G, metaG) end metaG.__index[name] = new_G[name] end new_G[name] = var or self return self end, _R = function(self, name, var) new_G[name] = var return self end, _B = function(self, var) return var or var~=false and self end } for k, v in pairs(gfuncs) do self.__index[k] = v end end end if new_G and ... and (...)==new_G then--rawget circumvents 'attempt to read nil global' error local new, name = setmetatable({}, self), select(2, ...) if name and type(name)=='string' then new_G[name] = new end return new end return setmetatable({}, self):_(...) end, __index = function(t, i) return function(...) return t.__index[i](t(), select(2,...)) end end })