置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

模組:Arguments/doc

萌娘百科,萬物皆可萌的百科全書!轉載請標註來源頁面的網頁連結,並聲明引自萌娘百科。內容不可商用。
跳至導覽 跳至搜尋

此頁面為 Module:Arguments 的說明文件

該模塊來自於英語維基百科的同名模塊,英文原文詳見歷史版本[1]

這個模塊提供了從#invoke傳遞的參數的簡單處理。它是一個元模塊,用於其他模塊,不應該直接從#Invoke調用。它的特點包括:

  • 簡單地修剪參數和刪除空白參數。
  • 參數可以同時由當前框架和父框架傳遞。
  • 參數可以直接從另一個Lua模塊或調試控制台傳入。
  • 參數是根據需要獲取的,這有助於避免<ref>...</ref>標籤帶來的(一些)問題。
  • 大多數功能都可以定製。

基礎使用

首先,你需要加載(load)本模塊(module),它包含一個叫 getArgs 的函數。

local getArgs = require('Module:Arguments').getArgs

最基本的情況下,您可以在主函數使用getArgs函數。變量args的類型是一個表(table),其中包含從#invoke傳過來的參數(argument)。

local getArgs = require('Module:Arguments').getArgs
local p = {}

function p.main(frame)
	local args = getArgs(frame)
	
    -- 主函数的代码会在这里运行。

end

return p

然而,我們更推薦使用一個函數單獨用來處理來自於#invoke的參數。這意味著,如果別人用另一個Lua模塊調用你的模塊,你不必再次通過frame(框架)對象獲取args變量。這會提高性能。

local getArgs = require('Module:Arguments').getArgs
local p = {}

function p.main(frame)
	local args = getArgs(frame)
	return p._main(args)
end

function p._main(args)
	-- 主函数的代码。
end

return p

如果你想要從#invoke中訪問多個函數,同時這些函數也可以使用#invoke的參數,你可以使用包裝函數(wrapper function),就像下面的例子一樣。

local getArgs = require('Module:Arguments').getArgs

local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame)
		return p[funcName](args)
	end
end

local p = {}

p.func1 = makeInvokeFunc('_func1')

function p._func1(args)
	-- 第一个函数的代码。
end

p.func2 = makeInvokeFunc('_func2')

function p._func2(args)
    -- 第二个函数的代码。
end

return p

參數選項

以下參數選項(option)是可用的,下文會對其進行解釋。

local args = getArgs(frame, {
	trim = false,
	removeBlanks = false,
	valueFunc = function (key, value)
		-- Code for processing one argument
	end,
	frameOnly = true,
	parentOnly = true,
	parentFirst = true,
	wrappers = {
		'Template:A wrapper template',
		'Template:Another wrapper template'
	},
	readOnly = true,
	noOverwrite = true
})

空白參數和空格的處理

空白參數(blank argument)經常會讓MediaWiki的編輯者產生困惑。因為在模板的語法,空白字符串和僅包括空格的字符串會被當做false處理。但是在Lua,空白字符串和僅包括空格的字符串會被處理為true。如果你在寫Lua模塊的時候沒有對參數產生足夠重視,你可能會把本應是false的變量當做true。為了避免這種情況,空白變量會被默認去除。

在處理位置參數的時候,空格可能會導致棘手的問題。對於已命名的參數,空格會被修剪(trim)掉。對於位置參數,雖然空格通常會保留,但是大多數時候空格是不需要的,所以模塊也會默認修剪掉這些空格。

然而,你有時候可能需要空白參數作為輸入內容,有時候也想要保留多出來的空格,比如想將模板的內容按照所寫的那樣精確轉化時。這時,你可以把trim變量和removeBlanks(清除空白參數)變量設置為false

local args = getArgs(frame, {
	trim = false,
	removeBlanks = false
})

自定義參數格式

有時你可能需要去除特定的某些空白參數,或者你想要把所有的位置參數都變成小寫字母。你可以使用valueFunc參數選項。這個參數選項必須是一個函數,且需要兩個形參(parameters),分別是keyvalue,並且只返回一個值。這個返回值,就是args表(table)在指定鍵key下獲取到的元素。

示例1:這個函數保留第一個參數的空格,但會修剪其它參數的空格,以及清除所有空白的參數。

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if key == 1 then
			return value
		elseif value then
			value = mw.text.trim(value)
			if value ~= '' then
				return value
			end
		end
		return nil
	end
})

示例2:這個函數會清除所有的空白參數,並且把所有的參數都變成小寫字母,但是不會修剪位置參數的空格。

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if not value then
			return nil
		end
		value = mw.ustring.lower(value)
		if mw.ustring.find(value, '%S') then
			return value
		end
		return nil
	end
})

注意:如果傳過來的輸入既不是string類型,也不是nil,這個函數會失效。如果你的模塊在main函數調用了getArgs函數,並且這個函數被其他Lua類調用的時候,很可能會出現這種情況。這時候,你應該檢查輸入的類型。但是,如果你有一個函數用來特別處理來自於#invoke的參數,不會出現這種問題(例如你使用了p.mainp._main函數,或者之類的)。


增加類型檢查示例1/示例2

示例1:

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if key == 1 then
			return value
		elseif type(value) == 'string' then
			value = mw.text.trim(value)
			if value ~= '' then
				return value
			else
				return nil
			end
		else
			return value
		end
	end
})

示例2:

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if type(value) == 'string' then
			value = mw.ustring.lower(value)
			if mw.ustring.find(value, '%S') then
				return value
			else
				return nil
			end
		else
			return value
		end
	end
})

需要注意的是,每次從args表獲取參數的時候,valueFunc都會大約被調用一次。為了確保性能,你需要保證你的代碼的高效性。

框架和父框架

args中的參數既可以從當前框架傳遞,也可以從其父框架傳遞。我們來通過示例來理解上面這段話。我們有一個叫做Module:ExampleArgs的模塊,它可以輸出傳入的前兩個位置參數中。

Module:ExampleArgs
local getArgs = require('Module:Arguments').getArgs
local p = {}

function p.main(frame)
	local args = getArgs(frame)
	return p._main(args)
end

function p._main(args)
	local first = args[1] or ''
	local second = args[2] or ''
	return first .. ' ' .. second
end

return p

然後,模塊Module:ExampleArgs被模板Template:ExampleArgs調用。這個模板包括以下代碼{{#invoke:ExampleArgs|main|firstInvokeArg}}

接下來,如果我們通過以下方式調用模板Template:ExampleArgs,會出現以下情況。

代碼 結果
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg secondTemplateArg

以下三種參數選項可以改變參數傳遞情況:frameOnlyparentOnly,和parentFirst。如果你設置frameOnly參數選項,那麼只有從當前框架傳遞來的參數會被接受。如果你設置parentOnly參數選項,那麼只有從父框架傳遞來的參數會被接受。如果你設置parentFirst參數選項,當前框架和父框架傳遞來的參數都會被接受,但是父框架的參數會被優先接受。下面是部分示例。


frameOnly
代碼 結果
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg
parentOnly
代碼 結果
{{ExampleArgs}}
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg
parentFirst
代碼 結果
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg

注意:

  1. 如果你同時設置了frameOnlyparentOnly參數選項,那麼模塊不會從#invoke接收到任何參數。
  2. 在一些情況下,父框架傳遞過來的參數可能無法獲得,比如getArgs被傳遞給了基框架而不是父框架。這時候,只有框架參數會被使用,(除非設置了parentOnly,在這種情況下不會使用參數)並且parentFirstframeOnly參數不會起作用。 [1]

包裝器

包裝器參數選項可以規定少數模板作為包裝模板(wrapper template)。也就是說,這些模板唯一的作用就是去調用一個模塊。如果這個模塊發現是自己被包裝模板調用的,它會只檢查父框架的參數,否則,它會只檢查傳遞給getArgs的參數。這允許模塊既可以被#invoke調用,也可以被包裝模板調用。在模塊被包裝模板調用的時候,並不會因為既需要檢查當前框架,也需要檢查父框架,而帶來性能損失。


我們以Template:Side box模板舉例,這個模板的有效內容[2]僅有{{#invoke:Side box|main}}這一小段。如果僅對於這個模板,我們可以使用parentOnly參數選項來優化(因為這樣可以避免參數檢查),但是這樣會造成很大的問題,可能會影響其它的頁面。比如,其他頁面出現的{{#invoke:Side box|main|text=Some text}}中的|text=Some text會被完全忽略。而使用wrappers參數選項,把模板'Template:Side box'包裝為包裝模板,就可以避免這個問題。

wrappers參數選項既可以被指定為一個字符串,也可以被指定為字符串數組。


local args = getArgs(frame, {
	wrappers = 'Template:Wrapper template'
})


local args = getArgs(frame, {
	wrappers = {
		'Template:Wrapper 1',
		'Template:Wrapper 2',
		-- Any number of wrapper templates can be added here.
	}
})

注意:

  1. 模塊會自動地檢測自己是被包裝模板調用還是被沙盒子頁面調用。所以無需顯式指定沙盒頁面。
  2. wrappers參數選項會在特定時候有效地改變frameOnlyparentOnly。例如,如果將parentOnly顯式設置為false,並設置了wrappers,通過包裝模板的調用,當前框架和父框架都會被加載,而沒有通過包裝模板的調用僅僅會調用當前框架。
  3. 如果wrappers被設定,但並沒有可用的父框架,模塊一直從當前框架獲取參數傳遞給getArgs

對args表的寫入

有時你可能需要在args表中寫入新的值。模塊的默認設定允許你這樣做。(通常,創建一個新表,從args表複製需要的參數,是更好的編程習慣)

args.foo = 'some value'

你可以通過readOnlynoOverwrite參數選項來監測對args的寫入。如果設定了readOnly,那麼args表無法被寫入。如果設定了noOverwrite,那麼args表可以被寫入,但是從#invoke傳入的參數無法被修改。

ref標籤

這個模塊使用元表來從#invoke中獲取參數。這樣可以無需pairs()函數,同時獲取當前框架和父框架的參數。這樣你的模塊可以接受<ref>...</ref>標籤(tag)作為輸入。

只要Lua可以訪問到<ref>...</ref>標籤(reference),它們就會被MediaWiki軟體處理,然後會有引用內容在頁面的底部(注釋與外部連結)出現。如果模塊的輸出省略了<ref>...</ref>標籤,會觸發一個bug:在引用列表會出現這個引用內容,但是沒有數字連接到這個引用。這對於使用pairs()來檢測是使用當前框架還是父框架的參數的模塊來說是一個問題,因為這些模塊會自動處理每個可用的參數。

然而本模塊解決了這個問題,通過同時訪問當前框架和父框架,僅在必要的時候獲取參數。但是如果你的模塊使用pairs(args)了,這個問題還是會出現。

本模塊已知的缺陷

元表(metatable)的使用帶來的副作用。Lua中大多數的table tools並不會正常運行在args表上。包括#運算符,next()函數,還有table library中的函數。如果你需要在你的模塊用到這些,你應該用自己的函數來處理參數而不是這個模塊。

  1. 這一段可能需要看完後面的部分才能夠理解,翻譯者注。
  2. 指的是除了<noinclude>...</noinclude>的內容