模組: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),分別是key
和value
,並且只返回一個值。這個返回值,就是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.main
和p._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 |
以下三種參數選項可以改變參數傳遞情況:frameOnly
,parentOnly
,和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 |
注意:
- 如果你同時設置了
frameOnly
和parentOnly
參數選項,那麼模塊不會從#invoke接收到任何參數。 - 在一些情況下,父框架傳遞過來的參數可能無法獲得,比如getArgs被傳遞給了基框架而不是父框架。這時候,只有框架參數會被使用,(除非設置了parentOnly,在這種情況下不會使用參數)並且
parentFirst
和frameOnly
參數不會起作用。 [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.
}
})
注意:
- 模塊會自動地檢測自己是被包裝模板調用還是被沙盒子頁面調用。所以無需顯式指定沙盒頁面。
- wrappers參數選項會在特定時候有效地改變frameOnly和parentOnly。例如,如果將parentOnly顯式設置為false,並設置了wrappers,通過包裝模板的調用,當前框架和父框架都會被加載,而沒有通過包裝模板的調用僅僅會調用當前框架。
- 如果wrappers被設定,但並沒有可用的父框架,模塊一直從當前框架獲取參數傳遞給
getArgs
。
對args表的寫入
有時你可能需要在args表中寫入新的值。模塊的默認設定允許你這樣做。(通常,創建一個新表,從args表複製需要的參數,是更好的編程習慣)
args.foo = 'some value'
你可以通過readOnly
和noOverwrite
參數選項來監測對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中的函數。如果你需要在你的模塊用到這些,你應該用自己的函數來處理參數而不是這個模塊。