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)
check = 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 type(v) == 'table' then
if str~=v and str=='table' then return table.concat(v) end
return getmetatable(v) and getmetatable(v).__tostring and
return str~='' and str or nil
tostring(v)
end
or table.concat(v)
end,
end
[select] = function(n, ...)
return v--i.e. numbers or strings
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 valid = getmetatable(self).check(v)
local at, raw = ...
if valid then
if select('#', ...)==1 and at==not not at then raw, at = at end
table.insert(self, valid)
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,
_in = function(self, v)
_all = function(self, t, valKey)
return setmetatable({
for k, v in getmetatable(self).__pairs(t) do self:_mix(v) end
parent = self,
if valKey then
getmetatable(self).check(v)
for k, v in getmetatable(self).__pairs(t, false) do
}, getmetatable(self))
if tonumber(v)==v then self:_(k, v) end
end
end
return self
end,
end,
_out = function(child, v2, outs)
_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 = child.parent:_(child(v2))
_str = function(self, ...) return getmetatable(self).__tostring(self, ...) end,
if outs and outs > 0 then repeat
_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()
child = parent
_out = function(self, ...)
parent = parent.parent
if self[next] then
outs = parent and parent:_(child()) and (outs - 1) or 0
local n, parent = select('#', ...), self[next]
until outs == 0 end
if n > 1 then
return parent or child
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
__call = function(t, i)
local new, name = setmetatable({}, self), select(2, ...)
return table.concat(t, i)
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
},
{__call = function(self, v)
return setmetatable({self.check(v)}, self)
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
})