Module:TScope

From Wikibooks, open books for an open world
Jump to: navigation, search
Documentation[edit] [history] [purge]

This module provides several functions to facilitate programming with wiki templates. The common theme is that they deal with template scope, the rules of what information is available where in templates.

All of these functions must be invoked directly by the template they are providing their service to: they cannot serve their purpose from inside a wrapper template. This is because they exploit a feature of Scribunto allowing a module to access the template parameters to (and name of) the immediate template in which the module is invoked.

Call functions

Each of these functions calls another template with a set of parameters formed by merging the set of parameters to the surrounding template with the set of parameters to the module invocation. This is useful if the surrounding template is meant to be a shell providing a modified form of the services of another, underlying template. The shell template doesn't have to explicitly pass along every parameter to the underlying template; in fact, the shell doesn't even have to know what all the parameters to the underlying template are, just the particular parameters that matter to the way it modifies the services. If the underlying template is later changed by, say, adding parameters, the implementation of the shell doesn't have to be touched unless the new parameters actually matter to the way the shell modifies the services (although the documentation of the shell might need to be changed if it duplicates explanations of parameters from the underlying template). See for example {{dialog/view}}.

The first unnamed parameter to the invocation names the template to call.

Named parameters to the invocation are passed into the call. Each named parameter to the surrounding template is passed into the call unless overridden by a same-named invocation parameter.

The functions differ from each other in how they handle unnamed parameters.

override

This function handles additional unnamed parameters to the invocation, after the first naming the template to call, in the same way as named parameters: each unnamed invocation parameter is passed into the call in its corresponding position (the first additional parameter becomes unnamed-parameter-1 to the call, etc.), while each unnamed parameter to the surrounding template is passed into the call unless overridden by an invocation parameter in corresponding position.

For example, if page Template:Foo contains invocation

{{#invoke:TScope|override|bar|inner|quux=inner}}

and foo is called elsewhere by {{foo|outer|baz=outer|quux=outer}}, then the invocation would call Template:Bar with parameters 1=inner, quux=inner, and baz=outer.

The first additional unnamed invocation parameter, after the name of the template to call, is passed into the call with index 1, the second additional unnamed invocation parameter is passed into the call with index 2, and so on. This means, however, that if the unnamed invocation parameters were passed explicitly by their integer names, the integer names specified to the invocation would be one more than the parameter numbers received by the called template. That is,

{{#invoke:TScope|override|bar|baz|5=quux}}

which is equivalent to

{{#invoke:TScope|override|1=bar|2=baz|5=quux}}

would call Template:Bar with parameters 1=baz and 4=quux.

prepend

This function handles unnamed parameters by passing them all into the call, first all additional unnamed parameters to the invocation and then all unnamed parameters to the surrounding template. The indices of unnamed surrounding-template parameters are increased by the largest call-index of any of the additional unnamed invocation parameters. For example, if page Template:Foo contains invocation

{{#invoke:TScope|prepend|bar|quux|baz}}

and foo is called elsewhere by {{foo|fnord}}, then the invocation would call Template:Bar with parameters 1=quux, 2=baz, and 3=fnord.

Each set of unnamed parameters (invocation parameters, and surrounding-template parameters) is treated as a solid block of indices starting with 1, even if some slots within the block (even at the start of the block) are unoccupied. Recalling the note under function override regarding the off-by-one discrepancy between invocation-indices and call-indices, if page Template:Foo contains invocation

{{#invoke:TScope|prepend|bar|5=quux|3=baz}}

and foo is called elsewhere by {{foo|3=fnord}}, then the invocation would call Template:Bar with parameters 2=baz, 4=quux, and 7=fnord.

append

As function prepend, except that rather than unnamed parameters to the surrounding template having their indices increased, instead unnamed parameters to the module invocation have their indices increased, by the largest index of any unnamed parameter to the surrounding template. For example, if Template:Foo contains invocation

{{#invoke:TScope|append|bar|quux|baz}}

and foo is called elsewhere by {{foo|fnord}}, then the invocation would call Template:Bar with parameters 1=fnord, 2=quux, and 3=baz.

drop

As function override, except that only named parameters of the surrounding template are passed on to the called template; unnamed parameters are passed only if specified directly to the module invocation.

shiftLeft

Similar to function override, but the first unnamed parameter to the invocation after the name of the template to call is not a parameter to pass into the call, but instead is an integer by which to decrement the indices of unnamed parameters to the surrounding template, dropping any that decrease below 1. For example, if Template:Foo contains invocation

{{#invoke:TScope|shiftLeft|bar|1}}

and foo is called elsewhere by {{foo|baz|quux|fnord}}, then the invocation would call Template:Bar with parameters 1=quux and 2=fnord; while invocation

{{#invoke:TScope|shiftLeft|bar|-2|inner}}

would call Template:Bar with parameters 1=inner, 3=baz, 4=quux, and 5=fnord.

map

This function calls a named template multiple times, using an interface somewhat similar to function override. As usual, the first unnamed parameter to the invocation names the template to call. If that is the only parameter to the invocation, the target template is called once for each unnamed parameter to the surrounding template, passing in that unnamed parameter as the first unnamed parameter to the call, and passing in all named parameters from the surrounding template; the results are concatenated in increasing order of the indices of the unnamed parameters. For example, if Template:Foo contains invocation

{{#invoke:TScope|map|bar}}

and foo is called elsewhere by {{foo|baz|quux|fnord}}, then the invocation would call Template:Bar three times, with respectively parameter 1=baz, 1=quux, and 1=fnord.

Named parameters to the invocation override same-named parameters to the surrounding template. The optional second unnamed parameter to the invocation must be a non-negative integer indicating so many leading unnamed parameters to the surrounding template should be passed as later unnamed parameters to each call instead of being featured as first-unnamed to a call. For example, if Template:Foo contains invocation

{{#invoke:TScope|map|bar|2|quux=inner}}

and foo is called elsewhere by {{foo|one|two|three|four|five|baz=outer|quux=outer|fnord=outer}}, then the invocation would call Template:Bar three times, with respectively 1=three, 1=four, 1=five, and each call would get 2=one, 3=two, baz=outer, quux=inner, fnord=outer. Additional unnamed parameters to the invocation are also passed to each call, overriding any passed through from the surrounding template; thus, in the immediately preceding example, if the invocation were instead

{{#invoke:TScope|map|bar|2|inner|quux=inner}}

the calls would be the same except with 2=inner instead of 2=one.

static

This function returns the name of the template containing the invocation of the module; in contrast to magic word {{PAGENAME}}, which returns the name of the page being displayed. For example, if page Quux is viewed, and contains a call to Template:Bar, which contains a call to Template:Foo, which invokes this function and also calls magic word {{PAGENAME}}, the call to the magic word returns Quux while the invocation returns Template:Foo.

echo

This function returns, in general, two wikitables giving first the names and values of all parameters passed to the invocation of the module, then the names and values of all parameters passed to the template containing the invocation of the module. If the invocation is given no parameters beyond the name of the function, that wikitable is omitted.

local export = {}

export.override = function( frame )
	local title = frame.args[1]
	local args = {}
	for v, k in pairs( frame:getParent().args ) do
		args[v] = k
	end
	for v, k in pairs( frame.args ) do
		if type( v ) == "number" then
			if v ~= 1 then
				args[ v - 1 ] = k
			end
		else
			args[v] = k
		end
	end
	return frame:expandTemplate{ title = title, args = args }
end

export.prepend = function( frame )
	local title = frame.args[1]
	local args = {}
	local displace = 0;
	for v, k in pairs( frame.args ) do
		if (type( v ) == "number") and (v ~= 1) then
			args[ v - 1 ] = k
			displace = math.max( displace, (v - 1) )
		end
	end
	for v, k in pairs( frame:getParent().args ) do
		if type( v ) == "number" then
			args[ displace + v ] = k
		else
			args[v] = k
		end
	end
	for v, k in pairs( frame.args ) do
		if type( v ) ~= "number" then
			args[v] = k
		end
	end
	return frame:expandTemplate{ title = title, args = args }
end

export.append = function( frame )
	local title = frame.args[1]
	local args = {}
	local displace = 0;
	for v, k in pairs( frame:getParent().args ) do
		if type( v ) == "number" then
			displace = math.max( displace, v )
		end
		args[v] = k
	end
	for v, k in pairs( frame.args ) do
		if type( v ) == "number" then
			if v ~= 1 then
				args[ displace + v - 1 ] = k
			end
		else
			args[v] = k
		end
	end
	return frame:expandTemplate{ title = title, args = args }
end

export.drop = function( frame )
	local title = frame.args[1]
	local args = {}
	for v, k in pairs( frame:getParent().args ) do
		if type( v ) ~= "number" then
			args[v] = k
		end
	end
	for v, k in pairs( frame.args ) do
		if type( v ) == "number" then
			if v ~= 1 then
				args[ v - 1 ] = k
			end
		else
			args[v] = k
		end
	end
	return frame:expandTemplate{ title = title, args = args }
end

export.shiftLeft = function( frame )
	local title = frame.args[1]
	local args = {}
	local displace = tonumber( frame.args[2] )
	if displace == nil then displace = 0 end
	for v, k in pairs( frame:getParent().args ) do
		if type( v ) == "number" then
			if v >= displace then
				args[ v - displace ] = k
			end
		else
			args[v] = k
		end
	end
	for v, k in pairs( frame.args ) do
		if type( v ) == "number" then
			if v > 2 then
				args[ v - 2 ] = k
			end
		else
			args[v] = k
		end
	end
	return frame:expandTemplate{ title = title, args = args }
end

export.map = function( frame )
	local title = frame.args[1]
	local displace = frame.args[2]
	if displace == nil then
		displace = 0
	else
		displace = tonumber( displace )
	end
	local args = {}
	local data = {}
	local maxv = 0
	for v, k in pairs( frame:getParent().args ) do
		if (type( v ) ~= "number") then
			args[v] = k
		elseif v <= displace then
			args[v + 1] = k
		else
			data[v] = k
			maxv = math.max( v, maxv )
		end
	end
	for v, k in pairs( frame.args ) do
		if type( v ) ~= "number" then
			args[v] = k
		elseif v > 2 then
			args[v - 1] = k
		end
	end
	local result = ""
	for v = 1, maxv do
		if data[v] ~= nil then
			args[1] = data[v]
			result = result .. frame:expandTemplate{ title = title, args = args }
		end
	end
	return result
end

export.static = function( frame )
	return frame:getParent():getTitle()
end

local function tabulate( args )
	local s = ''
	for k, v in pairs( args ) do
		s = s .. '|-\n| ' .. k .. '\n| <code>' .. v .. '</code>\n'
	end
	if s ~= '' then
		s = '{| class="wikitable"\n|-\n! key\n! value\n' .. s .. '|}'
	end
	return s
end

export.echo = function( frame )
	local mp = tabulate( frame.args )
	local cp = tabulate( frame:getParent().args )
	if mp ~= '' then
		mp = 'module parameters:\n' .. mp .. '\n'
	end
	if cp ~= '' then
		cp = 'context parameters:\n' .. cp .. '\n'
	else
		cp = 'no context parameters.\n'
	end
	return mp .. cp
end

return export