模組:Arguments/doc
此頁面為 Module:Arguments 的說明文件
此頁面是Module:Arguments的模組檔案。 此頁面可能包含了模板的使用說明、分類和其他內容。 |
此模組檔案被引用於約4,050,000個頁面,佔全部頁面的52%。 為了避免造成大規模的影響,所有對此模組檔案的編輯應先於沙盒或測試樣例上測試。 測試後無誤的版本可以一次性地加入此模組檔案中,但是修改前請務必於討論頁發起討論。 模板引用數量會自動更新。 |
本模組已與en:Module:Arguments保持全域手動同步。 請注意,若您修改本地的模組,將可能影響同步。 |
此模組是呼叫其他模組的模組。
此模組提供了對透過{{#invoke:}}
(以下簡稱#invoke)傳遞參數的簡單處理。這是元模組(meta-module),只能被其他模組使用,而不應被#invoke直接呼叫。其特性如下:
- 對參數的簡易修整,移除空白參數。
- 參數可以在當前框架或父框架中同時傳遞。(具體見下)
- 參數可以直接透過其他Lua模組或除錯控制台傳遞。
- 可自訂更多特性。
基本用法
[編輯]首先,您需要透過require函數載入這個模組。這個模組包含了一個名為getArgs
的函數。
local getArgs = require('Module:Arguments').getArgs
最簡單的方法是在使用getArgs函數。變數args
是包含#invoke參數的表(table)。(詳見下文。)
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
-- 主要的模块放此处。
end
return p
最佳實踐
[編輯]最佳的做法是,先用專門的函數來處理來自#invoke的參數。這樣,其他Lua模組直接呼叫該模組時,就無需再需要弄一個frame對象,從而提升效能,減小開銷。
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame) -- 从#invoke中获得的参数
return p._main(args)
end
function p._main(args)
-- 主要模块放此处。
end
return p
多個函數
[編輯]如果你需要多個函數使用這些參數,而且你希望這些函數可用於#invoke,你可以使用包裝函數(wrapper function)。
local getArgs = require('Module:Arguments').getArgs
local p = {}
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
p.func1 = makeInvokeFunc('_func1')
function p._func1(args)
-- 第一个函数的代码。
end
p.func2 = makeInvokeFunc('_func2')
function p._func2(args)
-- 第二个函数的代码。
end
return p
選項
[編輯]你可以使用如下面這段代碼所示的選項。這些選項會在下文中介紹。
local args = getArgs(frame, {
trim = false,
removeBlanks = false,
valueFunc = function (key, value)
-- 用于处理一个参数的函数的代码。
end,
frameOnly = true,
parentOnly = true,
parentFirst = true,
wrappers = {
'Template:一个包装模板',
'Template:另一个模板'
},
readOnly = true,
noOverwrite = true
})
修整參數和移除空白的參數
[編輯]將模板轉換為Lua的新手易在空白參數上犯錯。在模板語法中,空白字串和僅包含空白字元(whitespace,空格、換行等)的字串被視為假(false)。然而,在Lua,空白字串和只包含空白字元的字串則會被視為真(true)。這就是說,如果你在寫Lua模組時,不注意這些參數,你可能會把本想視為假的東西視為真。為了避免這種情況,這個模組預設會移除所有的空白參數。
類似地,空白字元在處理位置參數(positional arguments)時會發生問題。雖然來自#invoke的具名參數(named arguments)中的多餘空白字元會被修整(trim),但是對一些位置參數仍然保留。大多數時候,多餘的空白字元是不需要的,所以這個模組預設剔除這些空白字元。
然而,有時輸入時又需要使用這些空白字元,或者需要保留空白參數。把某些模板準確地轉化為模組時,可能有必要這麼做。如果你需要這樣,你可以將trim
和removeBlanks
參數設為false
。
local args = getArgs(frame, {
trim = false,
removeBlanks = false
})
對參數進行自訂格式化
[編輯]有時,你需要移除某些空白參數,但是還有些空白參數又不想移除,或者,你需要將所有位置參數轉化為小寫字母。你可以使用valueFunc
選項。這個參數的值必須是一個接收兩個參數key
和value
並且只返回一個值的函數,這個值是你在args
表中索引名為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
})
註:如果傳入了既不是字串又不是空值(nil)的值,上面這個函數會失敗。當你在你的模組的主函數使用getArgs
函數,而且那個函數被另一個Lua模組呼叫時,就可能出現此情況。這種情況下,你需要檢查你輸入的內容的類型(type)。如果你使用一個專門用於來自#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
表中的參數可以從當前框架或父框架同時傳遞。這句話有點難懂,可以看下面的例子。假設我們有個稱為模块:ExampleArgs
的模組,這個模組輸出(print)前兩個傳入的位置參數。
模組: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
|
然後,模块:ExampleArgs
被模板:ExampleArgs
呼叫,模板:ExampleArgs
內容如下:{{#invoke:ExampleArgs|main|firstInvokeArg}}
。它會輸出內容firstInvokeArg。
現在,如果我們呼叫模板:ExampleArgs
,其結果如下表所示:
代碼 | 結果 |
---|---|
{{ExampleArgs}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}}
|
firstInvokeArg secondTemplateArg |
有三個選項可以用來改變行為:frameOnly
、parentOnly
和parentFirst
。如果設置frameOnly
,那麼只有從當前框架傳入的參數可以被接受;如果設置 parentOnly
,那麼只有從父框架傳入的參數會被接受;如果你設置parentFirst
,那麼當前框架和父框架的參數都會接受,但是父框架優先於當前框架。以下是對於模板:ExampleArgs
的結果:
- 設為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
選項都會沒有效果。
包裝
[編輯]包裝(wrapper)選項用於指定一部分模板作為包裝模板(wrapper templates),也就是說,要呼叫模組的模板。如果模組檢測到是被包裝模板呼叫的,則只會檢查父框架中的參數;否則,只檢查傳遞到getArgs的框架的參數。這允許模組要麼被#invoke呼叫,要麼透過包裝模板呼叫,而不會由於為每次參數尋找(argument lookup)同時檢查框架和父框架而損失效能。
比如,Template:Side box的內容(除了<noinclude>...</noinclude>
標籤內的)為{{#invoke:Side box|main}}
。檢查直接傳遞到模板的#invoke陳述式的參數是沒有道理的,因為這裏沒有指定參數。我們可以透過parentOnly選項避免檢查傳遞到#invoke的參數,但如果這樣做,#invoke也不會從其他頁面起作用。如果是這樣,代碼{{#invoke:Side box|main|text=Some text}}
中的|text=Some text
會直接忽略,無論是從哪個頁面使用的。使用wrappers
選項以指定「Template:Side box」為包裝,我們可以使得{{#invoke:Side box|main|text=一些文本}}
能夠從大多數頁面使用,而不需要檢查Template:Side box頁面自身的參數。
容器可以指定為字串,或字串的陣列。
local args = getArgs(frame, {
wrappers = 'Template:Wrapper template'
})
local args = getArgs(frame, {
wrappers = {
'Template:Wrapper 1',
'Template:Wrapper 2',
-- 可以在此处添加多个包装模板。
}
})
注意:
- 模組會自動檢測是否是從包裝模板的/sandbox子頁面呼叫的,所以不需要清楚地指定沙盒頁面。
- wrappers選項有效改變frameOnly和parentOnly的預設的選項。如果,比如,設置了wrappers時清楚地將parentOnly設為false,透過包裝模板呼叫會導致同時載入框架和父框架的參數,儘管非經由包裝模板的呼叫會導致只載入框架參數。
- 如果設置了wrappers但是沒有可用的父框架,模組總是會從傳遞給
getArgs
的框架中得到參數。
寫入參數列
[編輯]有時給參數列寫入新值會很有用。這可以透過此模組的預設設置實現。(然而,記住最好的代碼風格是,將需要的參數列中的參數複製到一個新的表中。)
args.foo = '一些值'
可以帶有readOnly
和noOverwrite
選項修改此行為。如果設置了readOnly
,則完全不可能將任何值寫到參數列中。如果設置了noOverwrite
,則可以將新值添加到此表,但是如果需要重寫從#invoke傳遞的任何參數則不可能添加值。
ref標籤
[編輯]模組使用元表以從#invoke中取得參數。這允許不使用pairs()
函數就取得框架參數和父框架參數。如果你需要將<ref>...</ref>
標籤作為輸入時,這會很有用。
<ref>...</ref>
標籤是從Lua中取得的,因此會被MediaWiki軟件處理,引用會在文章底部的參考文獻列表中顯示。如果模組繼續從輸出中省略索引標籤,則會產生一個假引用 —— 在參考文獻列表中顯示,但是沒有與之連結的數字。模組如果使用pairs()
來檢測是否從框架或父框架中使用參數,就會出現此問題,因為這些模組會自動處理每一個可用變數。
此模組允許既取得框架又取得父框架而僅在需要時取得這些參數,從而解決此問題。然而,模組其他位置使用pairs(args)
時,仍會出現此問題。
已知限制
[編輯]元表(metatable)的使用也有其缺點。大多數正常Lua表工具都不會對args表正常工作,包括#
運算子號、next()
函數和表庫(table library)中的函數。如果這對你的模組重要,你需要使用你自己的用來處理參數的函數,而不是這個模組。