<languages/>
此手冊記載Template:Ll的文檔,用於MediaWiki的Template:Ll擴展。 部分內容(英文原文)取自Lua 5.1參考手冊(翻譯時參考了Lua參考手冊的中文翻譯),其許可協議為MIT許可證。
介紹
入門
在已啟用Scribunto的MediaWiki wiki上,以「Module:」前綴為標題建立一個頁面,例如「Module:Bananas」。 進入該新頁面,複製下列文本:
local p = {} --p代表包(package)
function p.hello( frame )
return "Hello, world!"
end
return p
保存之後,另一個非模組的頁面將會寫入:
{{#invoke:Bananas|hello}}
你應該將「Bananas」替換成你需要調用的模組。這將會使模組調用「hello」函數。{{#invoke:Bananas|hello}}
將會被函數輸出的結果替換,在這個例子中他會被替換成,「Hello, world!」
從模板的環境中調用Lua代碼確實是一個好辦法。 這意味著從調用頁面的角度來說,語法不依賴與模板邏輯是否被Lua或者維基文本執行。 這也避免了把複雜語法加到wiki內容命名空間中。
模組結構
模組本身必須返回一個包含能被{{#invoke:}}
調用的函數的表(table)。
一般來說,如上所示,先聲明一個局部變量表,函數被寫在這個表中,並模組代碼的結尾返回(return)這個表。
任何沒有加到這個表中的函數,無論是局部還是全局,都不能被{{#invoke:}}
訪問,但是局部變量可能會被其他的用require()
加載的模組訪問。
對於模組來說,最好將所有的函數和變量聲明為局部變量。
訪問維基文本中的參數
{{#invoke:}}
調用函數時,會將框架對象(frame object)作為單一的參數。要訪問傳遞到{{#invoke:}}
的參數,代碼通常會使用框架對象的args
表,也可以訪問傳遞到了包含{{#invoke:}}
的模板的參數,方法是使用frame:getParent()
,並訪問該框架的args
。
框架對象也用來訪問對應環境的維基文本解析器,例如調用解析器函式、擴展模板以及展開任意的維基文本字串。
返回文本
模組函數通常返回單個的字串;無論返回什麼值都會透過tostring()轉換,然後連接在一起。這個字串就是轉化成維基文本代碼{{#invoke:}}
的結果。
在解析頁面的這一點上,模板都是已經被展開的,解析器函式和擴展標籤都已經被處理,而且預存的轉換(例如簽名的擴展以及pipe trick)都已經完成。因此,模組不能在輸出文本中使用這些特性。例如,如果一個模組返回"Hello, [[world]]! {{welcome}}"
,頁面就會顯示「Hello, world! {{welcome}}」。
另一方面,替換引用是在加工的早期階段處理的,所以只有當其他嘗試的替換引用會被處理時才使用{{subst:#invoke:}}
。失敗的替換引用因為會保持為維基文本,所以都會在下一次編輯時被處理。這通常需要避免。
模組文檔
Scruibunto允許模組可以被自動關聯的模組維基文本頁面關聯文檔;預設情況下,模組的「/doc」子頁面是用來作為文檔,並且會在模組頁面的代碼頂部顯示其內容。例如,「模組:Bananas」的文檔頁面就是「模組:Bananas/doc」。
這也可以使用以下MediaWiki命名空間下的消息配置:
scribunto-doc-page-name
—設置用來作文檔頁面的名稱。 模組(除了模組:prefix)的名稱會透過$1
。 如果在模組命名空間,這裡的頁面通常會視為維基文本而不是Lua代碼,也不會被{{#invoke:}}
使用。 模組的頁面通常是「Module:$1/doc」這樣的模組/doc子頁面。注意解析器函式等其他可擴展代碼在這個消息中不被使用。 請注意,此消息中解析器函式和其他大括號擴展可能無法使用。scribunto-doc-page-does-not-exist
— 文檔頁面不存在時顯示的消息。 頁面名稱傳遞為$1
。 預設為空。scribunto-doc-page-show
— 文檔頁面存在時顯示的消息。 頁面名稱傳遞為$1
。 預設是嵌入包含文檔頁面。scribunto-doc-page-header
— 檢視文檔頁面本身時顯示的標題。 模組的名稱(有Module:前綴)傳遞為$1
。 預設以斜體顯示簡要說明。
注意模組不可以被直接分類,也不可以直接添加跨維基連結。
這些應該放在文檔頁面裡面的<includeonly>...</includeonly>
標籤中,當文檔頁面被引用到模組頁面時,這些分類和跨維基連結就會應用於模組頁面。
Lua語言
變量名稱
Lua中的名稱(names)(也叫標識符(identifiers))通常可以是任何字母、數字和下劃線的字串,但不可以以數字開頭。名稱區分大小寫;「foo」「Foo」和「FOO」都是不同的名稱。
下列關鍵字是保留的,不能用作名稱:
and
break
do
else
elseif
end
false
for
function
if
in
local
nil
not
or
repeat
return
then
true
until
while
以下劃線開頭後面接大寫字母的名稱是留給內部的Lua全局變量的。
下面這些文本也屬於保留字:
#
%
(
)
*
+
,
-
.
..
...
/
:
;
<
<=
=
==
>
>=
[
]
^
{
}
~=
注釋
注釋在任何地方(除了字串內)由--
開始。如果--
緊接著開放的中括號,注釋就會一直延伸到下一個中括號;否則注釋會延伸到這一行的結尾。
-- Lua的注释是由两个连字符(<code>-</code>)开始,延续到一行末尾。
--[[ 多行的字符串和注释
可以被两层中括号括起来。]]
--[=[ 像这样的注释可以紧随其他--[[注释]]。]=]
--[==[ 像这样的注释可以有其他的
--[===[ 修长的 --[=[注释]=] --跟随着
]===] 多次,即使它们所有
--[[ 都没有用匹配的长括号分隔! ]===]
]==]
數據類型
Lua是動態類型語言,意味著變量和函數值都不會有種類,只有值會有。所有的值都有類型。
Lua有8個基本類型,然而只有6個是與Scribunto擴展相關。type()
函數會返回值的類型。
tostring()
能夠將值轉化為字串(string)。tonumber()
能夠將值轉化為數字(number)(如果可能的話),而其他情況則會返回空值(nil)。沒有用於將一個值轉化為其他的數據類型的明確的函數。
凡是將與字串(string)連接在一起的地方,數字(number)會自動轉化為字串。使用計算符號時,字串會由tonumber()
自動轉化為數字辨識。當運算中需要將一個值作為布爾值(boolean)時,除了nil和false之外,所有的值都會視為true。
空值(nil)
「空值」是nil
的數據類型,用來表示這個值不存在。
空值不能用作表(table)中的鍵(key),且表中某個欄位「未指定」與「值為nil」沒有區別。
當空值轉化為字串時,其結果會是「nil」;轉化為布爾值(boolean)時,空值會被視為false。
布爾值(boolean)
布爾值就是true
(真)和false
(假)。
當布爾值轉化為字串時,結果就是「true」或者「false」。
不像很多其他語言,布爾值不會直接轉化為數字。而且只有false和nil作為布爾值時也會視為false;數字0和空字串都是視為true。
字串(string)
Lua字串會視為一系列的8比特字節;這取決於應用程式以哪種特定的編碼來解析。
字串會記錄在任何一組單雙引號('
或"
)中;就像JavaScript而不像PHP,這兩者(指的單引號和雙引號)無區別。以下轉義序列能被識別:
\a
(響鈴,字節7)\b
(退格,字節8)\t
(水平制表符,字節9)\n
(換行,字節10)\v
(縱向制表符,字節11)\f
(換頁,字節12)\r
(回車,字節13)\"
(雙引號,字節34)\'
(單引號,字節39)\\
(反斜線,字節92)
在字串代碼中直接換行,應該在前面加一個反斜線(\)。字節也可以透過轉義序列'\ddd',這樣ddd是0~255中的字節值。使用轉義序列來代替Unicode字元,則為UTF-8的單個編碼字節必須要指定;總的來說,直接輸入Unicode字元會更加簡單。
字串也可以用長括號定義。
長括號之間可以夾雜著0個或更多個等號(兩邊的等號要等量),例如[[
、[=[
或[=====[
。
開放的長括號必須被相應的閉合的長括號(或者說是結束標記)連結,例如]]
、]=]
或者]=====]
.。
特殊情況下,開放的長括號緊跟著連續換行但未被包括的字串,新一行只會持續到閉合長括號前。
由長括號定義的字串不會處理轉義序列。
-- 长字符串
foo = [[
bar\tbaz
]]
-- 等效于此引号分隔的字符串
foo = 'bar\\tbaz\n'
注意,在轉化為布爾值時,所有的字串都會視為true(真)。這不像其他的語言將空字串視為false(假)。
數字(number)
Lua只有一種數字類型,就是典型的雙精度浮點數。這種格式下,-9007199254740992到9007199254740992之間的整數都會準確表達,更大的數和帶有小數部分的數將會受到捨入的誤差。
數字可以用點(.
)來表示小數,例如123456.78
。數字也可以用不帶空格的科學計數法,例如1.23e-10
、123.45e20
或者1.23E5
。也可以用16進位表示整數,方法就是以0x
開頭,例如0x3A
。
雖然NaN和正負無窮大都可以正確地儲存、處理,但是Lua不提供相應的直接文字表示方法。math.huge
是正無窮大,相當於1/0
,此外,像0/0
這樣的除法就可以生成NaN。
重申一遍,在轉化為布爾值時,任何數字都會被視為true。這不像其他語言,數字0通常視為false。數字在轉化為字串時,數字都會被視為有限小數和科學計數;NaN是"nan"
或者"-nan"
;無窮大就是"inf"
或"-inf"
。
表(table)
Lua的表是關聯數組(associative arrays),很像PHP的數組和JavaScript的對象(object)。
表要用一對花括號建立。空表是{}
。建立有多個欄位的表時,逗號和分號可以分隔表中的各個欄位。表的內容可以用以下形式表示:
[表達式1] = 表達式2
,意思是鍵為表達式1,它與值表達式2匹配。即表達式1的值是表達式2。名稱 = 表達式
,它等價於["名稱"] = 表達式
。表达式
大致相當於[i] = 表達式
,在這裡i是在這個表中從1開始排序的正整數。如果最後一個欄位和表達式有多個值,所有的值都會使用;否則只有第一個會保留。
表中的欄位用中括號訪問,例如table[key]
。字串鍵(key)同樣也可以用作點來表示的名字,例如table.key
就與table['key']
等價。調用表中的一個函數也可以用冒號,例如table:func( ... )
,相當於table['func']( table, ... )
或者table.func( table, ... )
。
序列(sequence)是從1到N的所有正整數且沒有比N更大的正整數、且非空值的表。很多Lua函數僅會操作序列,忽略所有的非正整數的鍵。
不像很多其他的語言(例如PHP或JavaScript),在Lua任何值(除了nil和NaN)都可以作為鍵,而且不會執行類型轉換。參看下面的範例:
-- 创建表
t = {}
t["foo"] = "foo"
t.bar = "bar"
t[1] = "一"
t[2] = "二"
t[3] = "三"
t[12] = "数字十二"
t["12"] = "字符串十二"
t[true] = "true"
t[tonumber] = "是的,即使函数也可以用作表格键"
t[t] = "是的,表格也可以用作表格的键,即使是它本身。"
-- 这将创建一个大致相当于上面的表
t2 = {
foo = "foo",
bar = "bar",
"一",
"二",
[12] = "数字十二",
["12"] = "字符串十二",
"三",
[true] = "true",
[tonumber] = "是的,即使函数也可以用作表格键",
}
t2[t2] = "是的,表格也可以用作表格的键,即使是它本身。"
類似地,任何非nil的值都可以在表中儲存為值。將表中存儲nil相當於刪除表中的對應的鍵,並且調用表中任何一個不存在的鍵都會返回nil。
注意,在Lua中,表從來不會複製出一個獨立的新表;如果表作為一個參數傳遞到函數,那麼函數能修改表中的鍵或值,這些變化在調用者(caller)的作用域中都會可見。
當轉化為字串時,結果通常是"table",但使用__tostring
元方法可以重寫這個轉化方法。作為布爾值時,即使是空的表也會視為真(true)。
函數(function)
Lua中的函數是一等的(first-class)的值:可以匿名建立,或作為參數傳遞,或給變量賦值,等等。
函數透過function
(「函數」的英文)關鍵字,並使用圓括號調用。有一些語法糖可以用來命名函數,局部函數,並且可以作為表中的一個域值。參看函數聲明和函數調用。
Lua函數是閉包,這意味著它們維護對它們聲明的作用域的引用,並可以訪問和操作該作用域中的變量。
類似於表,如果函數一個函數被分配給另一個變量,或者作為參數傳遞給另一個函數,它仍然是相同的被調用的底層「函數對象」。
函數轉化為字串時,結果是"function"。
不支持的類型
使用者數據(userdata)用來儲存其他語言中的值;例如,一個使用者數據可以用來儲存C的指針或結構。使用Scribunto運行環境不允許使用使用者數據。
執行緒數據類型代表協同處理,在Scribunto的沙盒中不可用。
元表
每個表都可以關聯另一個表,成為元表(metatable)。元表的欄位將由特定的操作符或函數使用,從而為表指定不同的或者回落的行為。表的元表透過getmetatable()函數獲取,透過setmetatable()函數設置。
訪問元函數時,會像rawget()這樣訪問元表欄位。
以下元表欄位可以影響表本身:
- __index
- 如果表訪問
t[key]
返回nil就使用這個。 如果這個欄位的值是表,訪問就會在這個表中重複進行,例如__index[键]
(會調用這個表的元表的__index)。 如果這個欄位的值是函數,函數就會像__index( t, 鍵 )
這樣調用。 rawget()函數會繞過這個元方法。 - __newindex
- 這個元方法用於將鍵賦值到表中,即
t[鍵]=值
,但是rawget( t, key )
會返回空值(nil)。 如果這個欄位的值是表,賦值就會在這個表中重複進行,例如__newindex[鍵] = 值
(會調用這個表的元表的__newindex)。 如果這個欄位的值是函數,那麼函數就會像這樣調用:__newindex( t, 鍵, 值)
。 rawset()函數會繞過這個元方法。 - __call
- 對表應用函數調用語法
t( ... )
時,就會使用這個元方法。 這個值必須是函數,會像__call( t, ··· )
這樣調用。 - __mode
- 這用於使表保持弱引用(weak references)。 這個值一定是一個字串。 預設情況下,任何一個值被作為表格中的鍵或值時是不會被垃圾回收的。 但如果元表欄位包含字母k,且沒有非弱引用,鍵可能會被作為垃圾收集。而且如果包含v則值有可能也會作為垃圾收集;其他的情況,對應的鍵和值都會從表中移除。 注意,如果在表用作元表之後欄位被改變,則行為未定義。
其他元表欄位包括:
注意:在Lua中,所有的字串都會共用一個單一的元表,其__index
就是指的string
表。在Scribunto中,這個元表不允許訪問,也不能被string
表引用;對模組可用的string表是一個副本。
變量
變量是儲存值的地方。Lua有三種變量:全局(global)變量、局部(local)變量和表(table)中的欄位(field,又稱「域」)。
名稱分為全局和局部變量(或者是函數變量,是局部變量的一種)。定義一個局部變量,可以使用關鍵詞local
,否則預設視為全局變量。任何沒有賦值的變量都會視為有nil值。
全局變量儲存在叫做環境的Lua表中;這個表通常是作為全局變量_G
的值。這個全局變量表也可以設置元表;__index和__newindex元方法都可以用於全局變量表,就像其他的表一樣。
函數的環境可以使用getfenv()函數獲取,使用setfenv()函數修改;在Scribunto中,這些函數如果全部可用,就會受到嚴重限制。
局部變量是有詞法作用域的;參見局部變量定義了解詳細資訊。
表達式
表達式是有值的:字面量(數字、字串、真、假、空值)、匿名函數聲明、表構造函數、變量引用、函數調用、變量參數表達式、用括號括起來的表達式、一進位和二進位運算的表達式。
大多數表達式都有一個值;函數調用和變量參數表達式可以有任何數量個值。注意用括號括一個函數調用或變量參數表達式只能保留第一個值,其他的值會失去。
表達式列表是逗號分隔的表達式列表。除了最後一個表達式以外,所有的值都只能是一個值(如果表達式沒有值,則丟棄附加值,或者使用nil);最後一個表達式的所有值都包含在表達式列表的值中。
算數運算符
Lua支持以下常見的算數運算符:加減乘除、模運算、冪和取反。
當所有操作值為數字或字串時,即使用tonumber()返回非nil時,這些操作符有他們通常的意義。
如果一個操作數是一個有合適的元方法的表,元方法就會被調用。
操作 | 功能 | 範例 | 元方法 | 注釋 |
---|---|---|---|---|
+ | 加法 | a + b | __add | |
- | 減法 | a - b | __sub | |
* | 乘法 | a * b | __mul | |
/ | 除法 | a / b | __div | 除以零不會出錯,會返回NaN或者無窮大 |
% | 模運算 | a % b | __mod | 定義為a % b == a - math.floor( a / b ) * b
|
^ | 冪運算 | a ^ b | __pow | 允許非整數指數 |
- | 取相反數 | -a | __unm |
關係運算符
Lua的關係運算符是==
、~=
、<
、>
、<=
和>=
。關係運算的結果一定是布爾值(boolean)。
等於號(==
)首先比較兩個值的種類;如果兩個值是不同的種類,結果為假(false)。然後比較值:空值、布爾值、數字和字串照常比較。對於函數,則是看兩個函數是否引用同一個準確的函數對象;像這樣檢測兩個不同的(但作用相同的)匿名函數function() end == function() end
一定會返回假(false)。表也會預設像函數這樣比較,但是可能會由於使用__eq元方法而改變結果。
不等號(~=
)與等於號作用相反。
對於排序運算符,如果兩者都是數字,或者兩者都是字串,則直接進行比較。其次檢查元方法:
a < b
使用__lt
a <= b
使用__le
如果可用,或者__lt
可用,那麼它等價於not ( b < a )
a > b
等價於b < a
a >= b
等價於b <= a
如果必需的元方法不可用,會產生錯誤。
邏輯運算符
邏輯運算是and
(與)、or
(或)和not
(非)。在邏輯運算中,只有空值(nil)和false被視為false,其他的都被視為true。
對於and
,如果左邊的操作數被視為假,那麼被返回這個操作數,將右邊的操作數忽略;否則返回右邊的操作數。
對於or
,如果左邊的操作數視為真,那麼返回左邊的操作數,忽略右邊的操作數;否則返回右邊的操作數。
對於not
,其結果一定是布爾值(true或false)。
注意由and
和or
組成的簡短語句。例如,foo() or bar()
只會調用bar()
,除非foo()
不是在它的返回false或nil。
連接運算符
連接運算符就是兩個點(dot),比如a .. b
。如果兩個操作數都是數字或字串,它們會被轉化為字串然後返回。但是如果__concat元方法可用,就會使用這樣的元方法。如果它存在但無效,則會產生錯誤。
注意Lua的字串是不可變的(immutable),而且Lua不提供任何類型的「字串構造器(string builder)」,所以反覆進行a = a .. b
會必須為每次迭代建立一個新字串,並最終將舊字串作為垃圾收集。如果許多字串都需要連接,則應使用string.format(),或將所有的字串添加到一個序列然後最後使用table.concat()連接。
長度運算符
長度運算符是#
,像#a
這樣使用。如果a
是字串,會返回字串的字節長度。如果a
是序列表,會返回序列的長度。
如果a
是一個不是序列的表,#a
會返回0或者能夠使「a[n]不是nil而a[N+1]是nil」成立的值N,即使有的更高的索引不是nil值。例如,
-- 这不是序列,因为a[3]是nil而a[4]不是
a = { 1, 2, nil, 4 }
-- 会输出2或4。
-- 即使这个表没有被修改,这个值也有可能改变。
mw.log( #a )
運算優先級
Lua的操作符優先級,從高到低為:
- ^
- not # - (負號)
- * / %
- + - (減號)
- ..
- < > <= >= ~= ==
- and
- or
在同一級中,二元運算符會從左到右運算,例如a / b / c
相當於(a / b) / c
。冪運算和級聯會從右往左,例如a ^ b ^ c
相當於a ^ (b ^ c)
>
函數調用
Lua的函數調用與其他的語言很類似:函數名稱後面跟著被括號括起來的參數列表。
func( 表达式列表 )
和往常一樣在Lua表達的列表,列表中的最後一個表達式可以提供多個參數值。
如果傳遞給函數的參數比函數定義中的參數少,則額外的參數將被賦值nil。如果表達式列表的值比參數多,多餘的值會被捨棄。可以讓函數接受可變個數的參數,參見函數聲明的細節。
Lua允許直接調用由函數返回的值,例如func()()
。如果需要比變量訪問更複雜的表達式來確定要調用的函數,則可以使用括號表達式來代替變量訪問。
Lua的語法有兩個常見的語法糖例子。第一個是當一個表被當做對象使用,並且這個對象有一個函數被調用,那麼語法
table:name( 表达式列表 )
完全等同於
table.name( 表, 表达式列表 )
第二種常見的情況就是Lua透過含有名稱至值的映射的表作為函數唯一參數實施命名參數的工具。這種情況下,包圍著參數的括號可以省去。如果將一個(由引號或中括號分割的)字串作為調用函數時的唯一參數,那麼包圍著這個參數的括號也可以省去。比如調用
func{ arg1 = exp, arg2 = exp } func"string"
等同於
func( { arg1 = exp, arg2 = exp } ) func( "string" )
它們也可以被組合使用。以下使用是等價的:
table:name{ arg1 = exp, arg2 = exp } table.name( table, { arg1 = exp, arg2 = exp } )
函數聲明
方法的定義語法如下:
function nameoptional ( var-listoptional )
语句块
end
var-list中的所有變量對函數都是局部的,這些變量被函數調用的表達式列表賦值。在這個語句塊中,多餘的局部變量會被忽略。
函數被調用時,block中的語句會在由var-list建立與變量表對應的局部變量和指定值之後執行。如果執行到返回語句,語句塊就會退出,函數調用表達式的值就會是返回語句給予的值。如果執行到代碼段末尾,還沒有返回語句,則函數調用返回的結果是0個值。
Lua函數是詞法閉包。一個常見的習慣用法是在函數聲明的作用域內聲明「私有靜態(private static)」變量作為局部變量。比如,
-- 这会返回将它的参数增加一个数字的函数
function makeAdder( n )
return function( x )
-- 外面的这个n在这里是可以加到x中的
return x + n
end
end
local add5 = makeAdder( 5 )
mw.log( add5( 6 ) )
-- 输出11
函數可以聲明接受可變數量的(即任何數量個)參數,透過將...
作為變量列表的最後一項:
在這個語句塊內,可以使用變量表達式...
,結果會是函數調用中的所有額外的值。比如,
local join = function ( separator, ... )
-- 把额外的变量收集到一个新表中
local args = { ... }
-- 获得当前额外变量的准确个数
local n = select( '#', ... )
return table.concat( args, separator, 1, n )
end
join( ', ', 'foo', 'bar', 'baz' )
-- 返回字符串"foo, bar, baz"
select()函數就是用來作用於這些參數表達式的;特別地,如要獲取參數表達式的值的數量,應當使用select( '#', ... )
而非#{ ... }
來數參數表達式有多少個,因為{ ... }
不一定是序列。
Lua為將函數聲明和賦值提供到變量中提供語法糖;參見函數聲明語句的細節。
注意這個不會起效:
local factorial = function ( n )
if n <= 2 then
return n
else
return n * factorial( n - 1 )
end
end
因為這個函數聲明是在局部變量賦值聲明完成之前就處理好的,函數主體中的「factorial」會指向函數外(通常是未定義的)變量。這個問題可以透過先聲明一個局部變量然後再將它分配到後來的聲明中,或者使用函數聲明語句語法。
語句
語句是執行的基本單元:一個賦值、控制結構、函數調用、變量聲明,等等。
代碼塊(chunk)是語句(statements)的序列,可以由分號分開。一個代碼塊基本上被考慮為匿名函數的主體,所以它可以聲明局部變量,接受參數,並返回值。
語句塊(block)也是語句序列,就像一個代碼塊(chunk)。語句塊可以被分隔以建立單個語句(statement):do 語句塊 end
。這些通常用來限制局部變量的作用範圍,或者在另一個塊的中間加入return
或break
。
賦值
變量列表 = 表達式列表
var-list是由逗號分隔的變量;表達式列表是由逗號分隔的一組一個或多個表達式。所有的表達式都會在賦值之前被求值,所以a, b = b, a
會交換a與b的值。
局部變量定義
local 變量列表
local 變量列表 = 表達式列表
局部變量可以在一個語句塊或代碼塊內任意地方聲明。第一種形式,不需要表達式列表,聲明變量但不賦值,所以這些變量都會將nil作為值二中形式,為局部變量賦值,參見上面的賦值。
注意:局部變量顯式聲明於local關鍵字後面,形式為local 變量名。比如語句 local x = x
聲明一個名為「x」的局部變量,並將全局變量「x」的值賦予這個變量。局部變量只在其聲明的語句塊結尾前的地方生效。
控制結構
while 表達式 do 語句塊 end
只要表達式還是(視為)true時,就會反覆執行while語句。
repeat 語句塊 until 表達式
反覆執行語句塊,直到表達式(視為)是true。語句塊內聲明的局部變量可以用於表達式中。
for 名稱 = 表達式1, 表達式2, 表達式3 do 語句塊 end
for 名稱 = 表達式1, 表達式2 do 語句塊 end
for循環的第一種形式會聲明一個局部變量,然後從exp1以exp3的步長到exp2重複語句塊。注意exp3可以省略,相當於1,但是非數字值比如nil
和false
是錯誤的。循環開始前,所有的表達式都會先被計算。
這種形式的for循環大致相當於
do
local var, limit, step = tonumber( exp1 ), tonumber( exp2 ), tonumber( exp3 )
if not ( var and limit and step ) then
error()
end
while ( step > 0 and var <= limit ) or ( step <= 0 and var >= limit ) do
local name = var
block
var = var + step
end
end
不過變量var、limit和step在其他地方都不可訪問。注意變量「name」是對語句塊是局部變量;如果要在循環以外用它的值,它必須被複製到在循環外面定義的變量。
第二種形式的for循環會與迭代函數一起作用。就像在第一種形式里,表達式列表會在開始循環之前就賦值了。
這種形式的for循環大致相當於
do
local func, static, var = expression-list
while true do
local var-list = func( static, var )
var = var1 -- ''var1''是''var-list''中的第一个变量
if var == nil then
break
end
block
end
end
除了變量func、static和var在其他地方不能被獲得。注意var-list中的變量在語句塊中相當於局部變量;如要在循環外使用它們,需要複製到在循環之外聲明的變量。
通常expression-list是返回3個值的一個函數調用。如果迭代器函數可以被寫入,那麼只取決於傳入的參數,這會更加有效。否則,在Lua中編程建議返回閉包比返回表更好,因為靜止的變量在每次迭代更新其成員。
if 表達式1 then 語句塊1 elseif 表達式2 then 語句塊2 else 語句塊3 end
當表達式1返回true時執行語句塊1,否則,當表達式2返回true時執行語句塊2,否則執行語句塊3。else 語句塊3
部分可以省去,elseif 表達式2 then 語句塊2
部分可以重複,也可以省去。
return 表達式列表
返回語句用來返回從函數或者代碼塊(只是一個函數)。表達式列表是由逗號分隔開的零個或更多個表達式。
Lua實現尾調用(tail calls)。如果表達式列表包含一個函數調用,對那個函數的調用會重新使用當前的堆疊項(stack frame)。這可用於處理調用堆疊的函數,比如getfenv()
和debug.traceback()
。
返回語句必須是語句塊的最後一個語句。如果某些原因語句塊的中間需要返回,那麼可能需要明顯的語句塊do return end
。
break
break語句用來中止一個while、repeat或for循環的執行,並跳到循環後面的語句。
break聲明必須是語句塊(block)的最後一個聲明。如果某些原因語句塊的中間需要中斷,那麼可能需要明顯的語句塊do return end
。
函數調用作為語句
函數可以作為語句被調用,此時函數只會起到任何的「副作用(side effects)」(例如mw.log()向日誌輸出資訊),返回的值會被忽略。
函數聲明語句
Lua提供了語法糖來使得函數的定義更加自然。以下幾種定義相互等價。
-- 基本声明 function func( var-list ) 语句块 end func = function ( var-list ) 语句块 end
-- 局部函数 local function func( var-list ) 语句块 end local func; func = function ( var-list ) 语句块 end
-- 作为表中的字段的函数 function table.func( var-list ) 语句块 end table.func = function ( var-list ) 语句块 end
-- 作为表的方法的函数 function table:func( var-list ) 语句块 end table.func = function ( self, var-list ) 语句块 end
注意,這裡的冒號符號與函數調用的冒號符號相類似,在參數列表的開頭添加了一個隱式參數,名為self
。
錯誤處理
錯誤可以透過error()和assert()「拋出」,使用pcall() 或者xpcall()可以「捕獲」錯誤。注意,某些Scribunto的內部錯誤是不能被Lua層面的代碼捕獲處理。
垃圾回收
Lua能自動管理內存。這意味著你不需要關心新建對象時內存空間的申請,或者對象不需使用時內存空間的釋放。Lua的內存管理會自動執行「垃圾回收」,將不會再被訪問的死對象或者被弱引用保持的對象的內存空間收回。幾乎所有Lua類型元素都能被回收,包括表、方法、字串等。
垃圾回收是自動運行的,不能被Scribunto配置。
標準庫
Lua標準庫為Lua提供基本的性能和關鍵功能。本文檔只給出Lua標準庫中在Scribunto啟用的一部分內容。
基本函數
_G
這個變量持有對當前全局變量表的引用;全局變量foo
也會作為_G.foo
被訪問。注意,然而,對_G本身並沒有什麼特別的,可能被以同樣的方式作為任何其他變量:
foo = 1
mw.log( foo ) -- 输出1
_G.foo = 2
mw.log( foo ) -- 输出2
_G = {} -- _G不再指向全局变量表
_G.foo = 3
mw.log( foo ) -- 还是输出2
全局變量表可以當作普通的表來使用。例如,
-- 调用一个名称存储在变量中的函数
_G[var]()
-- 输出所有局部变量的名称和转化为字符串后的值
for k, v in pairs( _G ) do
mw.log( k, v )
end
-- 输出新的局部变量的创建
setmetatable( _G, {
__newindex = function ( t, k, v )
mw.log( "Creation of new global variable '" .. k .. "'" )
rawset( t, k, v )
end
} )
_VERSION
包含正在運行的Lua語言版本的字串,例如「Lua 5.1」。
assert
assert( v, message, ... )
如果v
是nil或false,拋出錯誤,message
就會用作錯誤的文本:如果錯誤文本為nil(或者未指定),則文本是"assertion failed!"(「斷言失敗!」);如果是字串或者數字,文字就是那個值;否則assert本身就會拋出錯誤。
如果v
是任何其他的值,assert就會返回包括v
和message
在內的全部變量。
在Lua的一個比較常見的慣用用法是,一個函數在正常操作時返回true值,並在失敗時返回nil或false作為為第一個值、錯誤資訊作為第二值。容易的錯誤檢查可以透過調用函數assert
來實現:
-- 这个不会检查错误
local result1, result2, etc = func( ... )
-- 这个作用相同,但是会查错
local result1, result2, etc = assert( func( ... ) )
error
error( message, level )
用文本message
來發出一個錯誤。
error
一般會提供出錯的位置的資訊。如果level
是1或者省略,那麼資訊就是調用error
本身的位置,2使用被調用錯誤的函數調用的位置,等等。0會省略位置資訊。
getfenv
getfenv( f )
注意,這個函數可能會無效,取決於配置中的allowEnvFuncs
。
返回運行環境(全局變量表),就像f
指定的:
- 如果1、nil或者未指定,返回調用
getfenv
函數的環境。通常這與_G相同。 - 整數2~10返回更高一級的環境。例如,2返回被這一個函數調用的函數的環境,3返回調用這一個函數的函數的環境,以此類推。如果這個堆疊值越高,錯誤也會隨之上升,否則這個堆疊級別會返回尾調用(tail call)。
- 傳遞函數返回在調用該函數時將使用的環境。
透過所有的基本函數和Scribunto基本庫函數使用的環境都被保護。嘗試訪問這些環境中使用getfenv
將返回nil。
getmetatable
getmetatable( table )
如果元表擁有__metatable
欄位,這個值就會直接返回,而不是返回事實上的元表。
ipairs
ipairs( t )
返回3個值:迭代函數、表t
和0。它是供for
的迭代形式使用的:
for i, v in ipairs( t ) do
-- process each index-value pair
end
它會迭代數對(1, t[1])、(2,t[2])等,直到t[i]是nil時。
如果__ipairs
元方法存在,那麼標準行為會被覆蓋,調用會返回與__ipairs( t )
的返回值一致的值。
next
next( table, key )
允許遍歷表中的鍵。如果key
是nil或者未指定,返回表中的第一個鍵和值,否則,返回下一個鍵和值。如果沒有更多的鍵可以用,返回nil。可以透過使用next( t ) == nil
來檢查表是否是空的。
注意鍵被返回的順序是沒有指定的,即使表有數字的索引(indexes)。如要以數字順序遍歷表,使用數字的for或ipairs。
如果遍歷時使用next,任何不存在的鍵被賦給一個值,則行為未定義。可以給一個存在的欄位賦一個新的值(包括nil)。
pairs
pairs( t )
返回三個值:迭代器函數(next或者類似的)、表t
和nil。這是用於for
的迭代器形式。
for k, v in pairs( t ) do
-- 处理每个键值对
end
這會遍歷t
中的鍵值對,就像next做的那樣。參考next的文檔以了解遍歷期間修改表的限制。
如果__pairs元方法存在,那麼標準行為會被覆蓋,調用會返回與__pairs( t )
的返回值一致的值。
pcall
pcall( f, ... )
用指定的參數在「保護模式」下調用函數f
。這意味著如果在調用f
時出錯,pcall會返回false與錯誤消息。如果沒有錯誤發生,pcall會返回true與調用返回的所有值。
用偽代碼表示,pcall
的定義類似如下:
function pcall( f, ... )
try
return true, f( ... )
catch ( message )
return false, message
end
end
rawequal
rawequal( a, b )
與a == b
相同,只是忽略了所有__eq元方法。
rawget
rawget( table, k )
與table[k]
相同,只是忽略了所有__index元方法。
rawset
rawset( table, k, v )
與table[k] = v
相同,只是忽略了所有__newindex元方法。
select
select( index, ... )
如果index
是數字,返回index之後的...
中對應位置的數。如果index
是字串"#",返回...
中參數的個數。
也就是說,select
有點像以下代碼,只是即使當...
包含nil值時也可以正常工作(參考#和unpack以了解關於nil的問題)。
function select( index, ... )
local t = { ... }
if index == '#' then
return #t
else
return unpack( t, index )
end
end
setmetatable
setmetatable( table, metatable )
設置表的元表,metatable
可能是nil,但是必須是清楚地提供的。
如果當前的元表有一個__metatable欄位,setmetatable
會報錯。
tonumber
tonumber( value, base )
嘗試將value
轉化為數字。如果已經是數字或者可以轉化為數字的字串,tonumber
就會返回這個數字,否則會返回nil。
base
是可選的,預設為10,指定解析數字的進位基數。這個基數可以是2到36之間的任何整數。對於大於10,字母A(大小寫均可)代表10,B代表11,以此類推,Z代表35。
十進位下,值可以有小數部分,或者以科學計數法表示,而且甚至可以以「0x」開頭以表示16進位。其他情況,只會接受不帶符號的整數。
tostring
tostring( value )
將value
轉化為字串。參考上方的數據類型以了解各種類型被轉換時的細節。
對於表,標準的轉換行為可以被__tostring元方法覆蓋。如果這個元方法存在,那麼調用tostring會返回由__tostring( value )
返回的單個值。
type
type( value )
以字串形式返回value
的類型"nil"
、"number"
、"string"
、"boolean"
、"table"
或"function"
。
unpack
unpack( table, i, j )
從給定的表返回值,像table[i], table[i+1], ···, table[j]
這樣的如果被寫出會直接返回。i
和j
如果沒有給出或者是nil,取其預設值1和#table
。
注意如果table
不是一個序列且j
是nil或未指定,則結果是不確定的,參考長度操作符以了解詳細。
xpcall
xpcall( f, errhandler )
這個很像pcall
,只是錯誤消息在返回之前傳遞到函數errhandler
中。
用偽代碼表示,xpcall
的定義類似如下:
function xpcall( f, errhandler )
try
return true, f()
catch ( message )
message = errhandler( message )
return false, message
end
end
調試庫
debug.traceback
debug.traceback( message, level )
以字串的形式返回調用棧。可選的message參數會被連接到調用棧資訊的前面。可選的level參數表示返回多少層調用棧。
數學(math)庫
math.abs
math.abs( x )
返回x
的絕對值。
math.acos
math.acos( x )
返回x
的反餘弦值(以弧度表示)。
math.asin
math.asin( x )
返回x
的反正弦值(以弧度表示)。
math.atan
math.atan( x )
返回x
的反正切值(以弧度表示)。
math.atan2
math.atan2( y, x )
使用兩個參數的符號(signs)以找到結果的象限,返回y/x
的反正切值(弧度制)。
math.ceil
math.ceil( x )
返回不小於x
的最小整數。
math.cos
math.cos( x )
返回x
(以弧度表示)的餘弦值。
math.cosh
math.cosh( x )
返回x
的雙曲餘弦值。
math.deg
math.deg( x )
將弧度角x
轉化為角度。
math.exp
math.exp( x )
返回。
math.floor
math.floor( x )
返回小於或等於x
的最大整數。
math.fmod
math.fmod( x, y )
返回x
除以y
的餘數,並將商捨入到零。比如,math.fmod( 10, 3 )
產生1
。
math.frexp
math.frexp( x )
返回像這樣的兩個值m
和e
:
- 如果
x
是無窮大且非零,那麼、e
是整數,m
的絕對值在區間內 - 如果
x
是零,那麼m
和e
都是0 - 如果
x
是NaN(非數字)或無窮大,那麼m
是x
而e
不指定
math.huge
代表正無窮大的值;比任何其他數值都要大或與之相等。
math.ldexp
math.ldexp( m, e )
返回(e
是整數)。
math.log
math.log( x )
返回x
的自然對數。
math.log10
math.log10( x )
返回x
的以10為底的對數。
math.max
math.max( x, ... )
返回其參數的最大值。
對於NaN的行為未指定。當前,如果x
是NaN,那麼會返回NaN,但是其他的NaN就會被忽略。
math.min
math.min( x, ... )
返回其參數的最小值。
對於NaN的行為未指定。當前,如果x
是NaN,那麼會返回NaN,但是其他的NaN就會被忽略。
math.modf
math.modf( x )
返回兩個數字,x
的整數部分和x
的小數部分。比如,math.modf( 1.25 )
產生1, 0.25
。
math.pi
的值。
math.pow
math.pow( x, y )
與x^y
相同。
math.rad
math.rad( x )
將角度x
轉化為弧度角。
math.random
math.random( m, n )
返回偽隨機數。
參數m
、n
可省略,但是如果指定了,則必須能夠轉化為整數。
- 沒有參數時返回區間內的實數。
- 有一個參數時返回區間內的整數。
- 有兩個參數時返回區間內的整數。
注意,如果m
或者n
小於−2147483648或者大於2147483647,或者n - m
大於2147483646,那麼輸出可能會不正確。
math.randomseed
math.randomseed( x )
以x
作為偽隨機數生成器的種子。
注意使用同一個種子會導致math.random
輸出相同的數列。
math.sin
math.sin( x )
返回 x
(以弧度表示)的正弦值。
math.sinh
math.sinh( x )
返回x
的雙曲正弦值。
math.sqrt
math.sqrt( x )
返回x
的平方根。與x^0.5
相同。
math.tan
math.tan( x )
返回x
(以弧度表示)的正切值。
math.tanh
math.tanh( x )
返回x
的雙曲正切值。
作業系統庫
os.clock
os.clock()
返回程序大約使用的CPU時間,以秒為單位。
os.date
os.date( format, time )
- 語言庫的formatDate可以被用於更加全面的日期格式。
返回包含日期和時間的字串或表,以format
為格式。如果格式被省略或者是nil,則使用「%c」。
如果給定了time
,則就是被格式化的時間(參考os.time()
。否則使用當前的時間。
如果format
以!開頭,則日期按照UTC格式而不是伺服器的本地時間。在這個可選字元之後,如果格式是字串"*t",那麼日期返回帶有以下欄位的表。
- year(完整的)
- month(1~12)
- day(1~31)
- hour(0~23)
- min(0~59)
- sec(0~60,允許閏秒的情況)
- wday(weekday,Sunday是1)
- yday(一年的某一天)
- isdst(夏令時,布爾值,資訊不可用時可能不存在)
如果格式不是"*t",那麼日期以字串形式返回日期,按照和C函數strftime相同的規則格式化。
os.difftime
os.difftime( t2, t1 )
返回從t1
到t2
兩個時間的秒數。
os.time
os.time( table )
返回代表當前時間的數字。
調用且沒有變量時,返回當前時間。若傳入了表,則表中編碼的時間就會被解析。表必須有years、month、days這幾個欄位,並且可能也包括hour(預設為12)、min(預設為0)、sec(預設為0)和isdst。
包庫
require
require( modulename )
加載指定的模組。
首先會檢查package.loaded[模块名]
以檢查模組是否已被加載,如果是,返回package.loaded[模块名]
。
否則,返回package.loaders
序列中的每一個加載器以嘗試尋找模組的加載器。若找到加載器,則調用這個加載器。加載器返回的值存儲在package.loaded[modulename]
中並將其返回。
參見package.loaders
以了解可用的加載器的資訊。
例如,如果你有一個模組「模組:Giving」其中有如下代碼:
local p = {}
p.someDataValue = '您好!'
return p
你可以用以下代碼在其它模組載入此模組:
local giving = require( "Module:Giving" )
local value = giving.someDataValue -- 值现在等于 '您好!'
package.loaded
這個表存儲已加載的模組。鍵為模組名稱,值為模組被加載時返回的值。
package.loaders
表存儲了在加載模組時要用的搜索器函數(searcher function)的序列。每一個搜索器函數會被帶有單個參數調用:要加載的模組名稱。如果找到模組,搜索器必須返回會事實上加載這個模組的函數,並返回要被require返回的值。否則,返回nil。
Scribunto提供了兩種搜索器:
- 在
package.preoload[modulename]
中尋找加載器函數 - 在Scribunto提供的模組中尋找模組名稱,如果沒找到,在「模組:」命名空間下尋找。「模組:」前綴必須提供。
注意沒有包括標準的Lua加載器。
package.preload
這個表存儲加載器函數,被Scribunto在package.loaders中包括的第一個搜索器。
package.seeall
package.seeall( table )
字串庫
在所有字串函數中,第一個字元是第1位,而不是像C、PHP、JavaScript中的那樣第0位。索引(indexes)可以是負的,表示從字串最末開始倒數,比如-1表示最後一個字元,-2表示倒數第二個,等等。
警告:字串庫假定單字節字串編碼。不能處理Unicode字元。要對Unicode字元進行操作,使用Scribunto Ustring庫中對應的方法。
string.byte
string.byte( s, i, j )
如果字串被考慮為字節的數組,返回s[i]
、s[i+1]
、···、s[j]
的字節值。i
的預設值為1;j
的預設值為i
。等價於mw.ustring.byte()。
string.char
string.char( ... )
接受零個或更多個整數。返回和長度與參數個數相同的字串,每個字元的字節值等於其對應的參數。
local value = string.char( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21 ) --值现在是'Hello!'
參看mw.ustring.char()以了解使用Unicode codepoint而非字節值的類似函數。
string.find
string.find( s, pattern, init, plain )
尋找字串s
中pattern
的第一個匹配(match)。如果找到一個匹配,返回s
中起止點的序列,否則返回nil。如果匹配模式有捕獲物(capture),則在成功的匹配中被捕獲的值也會被返回在兩個索引之後。
第三個參數init
是可選的,指定從哪裡開始搜索,預設值是1,可以是負數。第四個參數plain
也是可選的,如果是true,則會關閉模式匹配機制,則函數做的只是簡單地「找子串」操作,pattern
中的字元就不會被看作魔法字元。
注意給了plain
就必須給init
。
參考mw.ustring.find()以了解用於Ustring pattern的類似函數,而且init
是按照字元而非字節。
string.format
string.format( formatstring, ... )
返回變量數字的參數將第一個參數(必須是字串)格式化後的版本。
格式字串使用printf
格式指定器但有所限制。
- 「-」「+」「 」「#」和「0」是被認可的。
- 支持最多99個整數欄位。「*」不支持。
- 支持最多99個整數精確度。「*」不支持。
- 長度修改器不支持。
- 認可c、d、i、o、u、x、X、e、E、f、g、G、s、%這些轉換器,以及非標準的q。
- 不支持像「%2$s」這樣的位置指定器。
轉換指定器q類似於s,但是會以特定的專用於表述字串的格式來形成字串;字串會被寫在雙引號中,所有的雙引號、新行、嵌入的零、反斜槓都會被轉義。
數字和字串之間的轉換會像數據類型中說的那嚴格:其他類型不會自動轉化為字串。包含NUL字元的字串(字節值0)不能被正常處理。
string.gmatch
string.gmatch( s, pattern )
返回一個迭代器函數,每次被調用,都會從字串s
中的pattern
返回下一個捕獲。如果pattern
不會指定捕獲,則整個匹配都會在每次調用時產生。
對於這個函數,開始的^
不是魔法字元,因為這個會避免迭代。它被看做是普通字元。
參看mw.ustring.gmath()以了解其類似函數,其匹配模式是被擴展的,參考Ustring匹配模式。
string.gsub
string.gsub( s, pattern, repl, n )
將字串s
的所有(或者前n
個,如果給定了)出現的pattern
替換為由repl
指定的替換物(replacement),這個替換物可以是字串、表或者函數。gsub
也會作為第二個值返回發生了的匹配的總次數。
如果repl
是一個字串,則其值直接用於替換。字元%
用作轉義符(escape character):repl
中的任何%d
形式的序列,d是1到9之間,代表第d個被捕獲的子串。序列%0
代表整個匹配(match),序列%%
代表單個%
。
如果repl
是表,則每次匹配查詢這個表,其鍵(key)為第一個捕獲物(capture);如果匹配模式(pattern)不指定捕獲,則整個匹配(match)用作鍵。
如果repl
是函數,則每次匹配發生時調用這個函數,所有被捕獲的子串都會依次被傳入作為參數。如果匹配模式不指定捕獲,則整個匹配會作為單個參數傳入函數。
如果表格查詢或者函數調用返回的值是字串或者數字,則用作替換字串,否則,如果是false或nil,則不會進行替換,也就是說原始匹配仍保留在字串中。
參看mw.ustring.gsub()以了解其類似函數,其匹配模式是被擴展的,參考Ustring匹配模式。
string.len
string.len( s )
返回字串的字節長度。不會被ASCII NUL字元混淆。等同於#s。
參看mw.ustring.len()以了解使用Unicode codepoint而非字節值的類似函數。
string.lower
string.lower( s )
將字串的所有ASCII大寫字元轉為小寫後返回。所有其他字元不改變。
參考mw.ustring.lower()以了解類似的函數,該函數可以將Unicode定義的所有的大寫字母轉化為小寫字母。
string.match
string.match( s, pattern, init )
尋找字串中pattern
的第一個匹配,如果找到一個,則match
返回從樣式匹配中的捕獲,否則返回nil。如果pattern
不指定捕獲,則返回整個字串。
第三個參數init
是可選的,用來表示從哪裡開始搜索,其預設值為1,可以是負數。
參看mw.ustring.math()以了解其類似函數,其匹配模式是被擴展的,參考Ustring匹配模式。
string.rep
string.rep( s, n )
返回字串s
重複n
次並連接後的字串。等價於mw.ustring.rep()。
string.reverse
string.reverse( s )
返回字串s
被逆轉後的字串(按字節逆轉)。
string.sub
string.sub( s, i, j )
返回s
的從i
開始持續到j
的子串(substring);i
和j
可以是負的。如果j
是nil或未指定,則會一直到字串末尾。
特別地,調用string.sub(s,1,j)
會返回字串s
的長度j
的前綴,而string.sub(s, -i)
會返回字串s
的長度為i
的後綴。
參看mw.ustring.sub()以了解使用字元而非字節值的類似函數。
string.upper
string.upper( s )
將字串的所有ASCII小寫字元轉為大寫後返回。所有其他字元不改變。
參考mw.ustring.upper()以了解類似的函數,該函數可以將Unicode定義的所有的小寫字母轉化為大寫字母。
匹配模式(patterns)
注意Lua的匹配模式類似於正則表達式(regular expression),但是並不一樣。特別地,注意正則表達式和PCRE之間的以下區別:
- 用於引用的字串是百分號(
%
)而非反斜槓(\
)。 - 點(
.
)總是匹配所有字元,包括新行。 - 沒有大小寫不敏感模式。
- 沒有選擇功能(
|
操作符)。 - 量詞(quantifier,
*
、+
、?
和-
)只能用於單獨的字元或者字元類,不能捕獲組。 - 唯一非貪婪的量詞是
-
,相當於PCRE的*?
量詞。 - 沒有廣義的有限量詞,比如PCRE中的
{"n","m"}
。 - 零寬的assertion是
^
、$
和%f[set]
frontier樣式,像PCRE的\b
和(?=…)
不可用。 - 樣式匹配本身不認識像'\"ddd"'這樣的轉義。然而,由於樣式匹配是字串,這一類轉義或許可以用於在建立樣式匹配字串的文字。
注意匹配模式不能包含嵌入的零字節(ASCII NUL,"\0"
)。應該使用%z
。
參考Ustring匹配模式以了解使用Unicode字元的類似的樣式匹配機制。
字元類
字元類是一組字元的集合。以下集合可以用於定義字元類。
x
|
(x 不是魔法字元^$()%.[]*+-? 之一)代表字元x 自身。
|
---|---|
.
|
(一個點)代表所有字元。 |
%a
|
代表所有ASCII字母。 |
%c
|
代表所有ASCII控制字元。 |
%d
|
代表所有數字。 |
%l
|
代表所有ASCII小寫字母。 |
%p
|
代表所有標點字元。 |
%s
|
代表所有ASCII空白字元。 |
%u
|
代表所有ASCII大寫字母。 |
%w
|
代表所有ASCII字母數字字元。 |
%x
|
代表所有十六進位數字。 |
%z
|
代表所有ASCII NUL,即零字節。 |
%A
|
所有不在%a 中的字元。
|
%C
|
所有不在%c 中的字元。
|
%D
|
所有不在%d 中的字元、
|
%L
|
所有不在%l 中的字元。
|
%P
|
所有不在%p 中的字元。
|
%S
|
所有不在%s 中的字元。
|
%U
|
所有不在%u 中的字元。
|
%W
|
所有不在%w 中的字元。
|
%X
|
所有不在%x 中的字元。
|
%Z
|
所有不在%z 中的字元。
|
%x
|
(x 不是字母數字字元)代表字元x 。這是轉義魔法字元的標準方式。任何標點字元(甚至是非魔法字元)都可以跟'% '用以代表樣式匹配中的自身。
|
[set]
|
代表集合set中所有字元的組合。一系列字元可以透過用' 範圍和類之間的交互是沒被定義的,因此像 |
[^set]
|
代表set的補集。 |
模式條目(pattern item)
一個模式條目可以是
- 單個字元類,匹配類中的單個字元。
- '
*
'前的單個字元類,匹配這個類中重複0次或者更多次的字元。這個重複項總是匹配可能的最長序列。 - '
+
'前的單個字元類,匹配這個類中重複一次或者更多次的字元。這個重複項總是匹配可能的最長序列。 - '
-
'前的單個字元類,匹配這個類中重複0次或者更多次的字元。不像*
,這個重複項總是匹配可能的最短序列。 - '
?
'前的單個字元類,匹配這個類中0次或1次出現的字元。 %n
,n可以是1到9之間,匹配相當於第n個被捕獲的子字串(見下)。%bxy
,x和y是兩個不同的字元,匹配從x開始、以y結尾的字元,且x和y的數目是平衡的。也就是說,如果從左到右讀,讀到x時加一,讀到y時減一,那麼結束的y則是第一個計數到達0時的y。例如,%b()
是一個平衡的表達。%f[set]
,一個frontier pattern,這樣的項匹配任何位置的空字串,而下一個字元屬於集合set,而前一個字元不屬於set。集合set在前面已經有描述。子計畫的開始和結束時按照字元'\0'處理的。'\0'
注意frontier pattern存在於Lua 5.1,但是該版本的文檔沒有提及,Lua 5.2中才正式加入,不過Lua 5.2.1中的實現和5.1.0中的是一樣的。
模式(pattern)
模式(pattern)是模式條目(pattern item)的序列。
模式開頭的^
會從字串的開始處匹配,而模式末尾的$
會匹配字串的最末尾。其他地方的^
和$
都代表自身,無特殊含義。
捕獲
模式可以包括用小括號括起來的子模式(sub-patterns),描述了「捕獲」。匹配成功時,字串的匹配捕獲的子字串會被存儲(被「捕獲」)以備使用。捕獲是根據左邊的括號被標號的。比如,在模式(a*(.)%w(%s*))
中,匹配a*(.)%w(%s*)
的字串部分被存儲在第一個捕獲(所以是第一項),匹配.
的字元被捕獲,記為第2項,匹配%s*
的則是第3項。
捕獲參考可以出現在字串自身,而返回參考早前被捕獲的文本。比如,([a-z])%1
會匹配任何一對相同的小寫字母,而([a-z])([a-z])([a-z])[a-z]%3%2%1
會匹配任何7個字母的回文。
特殊情況,空的捕獲()
會捕獲當前的字串位置(一個數字)。比如我們對字串"flaaap"
執行模式"()aa()"
,那麼會有兩個捕獲:3和5。
表(table)庫
這個庫的大多數函數假設作為參數的表是序列。
函數table.foreach()
、table.foreachi()
和table.getn()
或許可用但是不推薦。應該使用pairs()的for循環、ipairs()的for循環和長度操作符。
table.concat
table.concat( table, sep, i, j )
給一個所有元素都是字串或數字的數組,返回table[i] .. sep .. table[i+1] ··· sep .. table[j]
。
sep
的預設值為空字串,i
的預設值為1,j
的預設值為表的長度。如果i
大於j
,返回空字串。
table.insert
table.insert( table, value )
table.insert( table, pos, value )
在表table
的位置pos
處插入元素value
,會將其他元素的位置增加1以給這個元素提供插入空間。pos
的預設值為表的長度加1,所以調用table.insert(t, x)
會在表t
的末尾插入x
。
大於#table
的元素都會被提高,參考長度操作符以了解當表不是序列時的注意事項。
table.maxn
table.maxn( table )
返回給定的表的最大正數索引,或者表沒有正數索引時返回零。
會遍歷整個表,大致相當於
function table.maxn( table )
local maxn, k = 0, nil
repeat
k = next( table, k )
if type( k ) == 'number' and k > maxn then
maxn = k
end
until not k
return maxn
end
table.remove
table.remove( table, pos )
從表格table
中移走位於pos
處的元素,將後面的元素前移。pos
的預設值為表的長度,所以調用table.remove( t )
會移除表t
的最後一個元素。
大於#table
的元素都會被移動,參考長度操作符以了解當表不是序列時的注意事項。
table.sort
table.sort( table, comp )
從table[1]
到table[#table]
,按照給定的次序給表的元素排序。如果給了comp
,則它必須是接收兩個表元素的函數,並且當第一個小於第二個時返回true(所以not comp(a[i+1],a[i])
會在排序後為true)。如果沒有給定comp
,則使用標準的Lua操作符%lt;
。
排序算法並不穩定;也就是說,當兩個元素按照給定的順序被看作相等時,它們在排序後的相對位置可能會改變。
Scribunto庫
所有Scribunto庫位於表mw
中。
基本函數
mw.addWarning
mw.addWarning( text )
在預覽編輯時加一個警告資訊。text
解析為維基文本。
mw.allToString
mw.allToString( ... )
對所有的參數調用tostring(),然後用制表符作為分隔符連接起來。
mw.clone
mw.clone( value )
深拷貝一個值。所有的表和它們的元表被重構,但是新表和舊錶共用函數。
mw.getCurrentFrame
mw.getCurrentFrame()
返回目前的框架對象,通常是最近的#invoke
中的框架對象。
mw.incrementExpensiveFunctionCount
mw.incrementExpensiveFunctionCount()
使得「高開銷解析器函式」計數器加一,並在其超過限制時拋出異常(參見$wgExpensiveParserFunctionLimit
)。
mw.isSubsting
mw.isSubsting()
如果當前的#invoke
被替換引用時返回true,否則false。參見上方討論的返回文本。
mw.loadData
mw.loadData( module )
有時一個模組需要大量表格的數據,例如,用於轉換計量單位的通用模組可能需要一張大表的已識別的單位及其轉換係數。而且有時這些模組會在一個頁面中使用多次。每次{{#invoke:}}
都解析大表格的數據會用大量時間。mw.loadData()
正是為了避免這個問題。
mw.loadData
類似於require()
,但是有以下區別:
- 加載的模組每頁只會解析一次,而不是每次調用
{{#invoke:}}
就解析一次。 - 加載的模組不會記錄在
package.loaded
中。
從加載的模組返回的值必須是表。其他數據類型不支持。
- 返回的表(以及其所有子表)只能包含布爾值、數字、字串和其他表。其他的數據類型,比如函數,不允許。
- 返回的表(和所有子表)不能有metatable元表。
- 所有的表鍵必須是布爾值、數字、字串。
- 由
mw.loadData()
返回的表會元方法,可以提供只讀獲取由模組返回的表。因為不能直接包含數據,pairs()
和ipairs()
會起作用,但是其他方法如#值
、next()
和表庫的函數不會起作用。
上述假定的單位轉換模組可能將其代碼存儲在「Module:Convert」然後將其數據存儲在「Module:Convert/data」,且「Module:Convert」會使用local data = mw.loadData( 'Module:Convert/data' )
來有效地加載數據。
mw.dumpObject
mw.dumpObject( object )
將object
序列化為人類可讀的字串並返回。
mw.log
mw.log( ... )
將參數傳遞到mw.allToString(),然後將結果字串加載控制台後。
在調試控制台,print()
等價於這個函數。
mw.logObject
mw.logObject( object )
mw.logObject( object, prefix )
調用mw.dumpObject()然後將結果加到控制台輸出的後面。如果給了prefix
,則會被加到控制台輸出並緊隨一個等於號在序列化字串之前,比如輸出的字串可以是"prefix = object-string"。
框架對象(Frame object)
框架(frame對象)是接口。透過框架來訪問傳遞至{{#invoke:}}
和解析器函式的參數。
注意沒有框架庫,也沒有叫做frame
的全局變量。框架對象通常為被{{#invoke:}}
調用的函數的參數,當然也可以從mw.getCurrentFrame()
獲得。
frame.args
用來訪問傳遞到frame的參數的表。例如,一個模組從如下的維基文本調用
{{#invoke:module|function|arg1|arg2|name=arg3}}
那麼frame.args[1]
會返回"arg1"
,frame.args[2]
會返回"arg2"
,frame.args['name']
或frame.args.name
會返回"arg3"
。在參數列表迭代可以使用pairs( frame.args )
或ipairs( frame.args )
。
然而由於Lua實現表迭代器,迭代的順序不確定,參數出現在維基文本中的順序也無從得知。
注意這個表中的值總是為字串,tonumber()
可以用於在需要時轉化為數字。但是,鍵是數字,即使在調用時清楚提供:{{#invoke:module|function|1|2=2}}
給予被數字鍵1
和2
索引的字串值"1"
和"2"
。
在MediaWiki模板調用中,命名參數(named arguments)會在傳遞到Lua前移除名稱和值的多餘空格,而匿名參數(unnamed arguments)不會移除空格。
考慮到性能,frame.args
使用元表,而非直接包含參數。參數值會從根據需求從MediaWiki請求得到。這意味著大多數其他表格方法不會正常生效,包括#frame.args
、next( frame.args )
和表庫中的函數。
如果在#invoke的參數中包含了像模板調用和三層括號變量這樣的預處理器(preprocessor)語法,那麼這些在傳遞到Lua之後不會被展開,直到值被Lua請求時才會展開。如果在#invoke的參數中包含了用XML標記形式寫的特殊標籤,例如<pre>
、<nowiki>
、<gallery>
和<ref>
,這些標籤會被轉化為strip marker——一種特殊字串,由刪除符(ASCII 127)開始,在從#invoke返回後轉化為HTML。
frame:callParserFunction
frame:callParserFunction( name, args )
frame:callParserFunction( name, ... )
frame:callParserFunction{ name = string, args = table }
- 注意使用了命名參數。
調用解析器函式,返回適當的字串。這相比於frame:preprocess
更優,但如果有可能,最好優先使用原生的Lua函數或Scribunto庫函數。
以下調用與以下維基文本基本相同:
-- {{ns:0}}
frame:callParserFunction{ name = 'ns', args = 0 }
-- {{#tag:nowiki|some text}}
frame:callParserFunction{ name = '#tag', args = { 'nowiki', 'some text' } }
frame:callParserFunction( '#tag', { 'nowiki', 'some text' } )
frame:callParserFunction( '#tag', 'nowiki', 'some text' )
frame:callParserFunction( '#tag:nowiki', 'some text' )
-- {{#tag:ref|some text|name=foo|group=bar}}
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', name = 'foo', group = 'bar'
} }
注意,函數名稱和參數不會在傳遞到解析器函式之前被預處理(preprocess),frame:expandTemplate()也是如此。
frame:expandTemplate
frame:expandTemplate{ title = title, args = table }
- 注意使用了命名參數。
這是嵌入包含。函數調用
frame:expandTemplate{ title = 'template', args = { 'arg1', 'arg2', name = 'arg3' } }
在Lua腳本中的行為大致和{{template|arg1|arg2|name=arg3}}
在維基文本中的行為一樣。如果頁面名沒有命名空間前綴,那麼函數會認為頁面在模板命名空間內。
注意標題與參數在傳遞到模版之前並未預處理:
-- 这与维基文本{{template|{{!}}}}基本相同
frame:expandTemplate{ title = 'template', args = { '|' } }
-- 这与维基文本{{template|{{((}}!{{))}}}}基本相同
frame:expandTemplate{ title = 'template', args = { '{{!}}' } }
frame:extensionTag
frame:extensionTag( name, content, args )
frame:extensionTag{ name = string, content = string, args = table_or_string }
這大致相當於調用frame:callParserFunction(),其函數名稱為'#tag:' .. name
而content
加到參數args
中。
-- 这些都相同
frame:extensionTag{ name = 'ref', content = 'some text', args = { name = 'foo', group = 'bar' } }
frame:extensionTag( 'ref', 'some text', { name = 'foo', group = 'bar' } )
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', name = 'foo', group = 'bar'
} }
-- 这些都相同
frame:extensionTag{ name = 'ref', content = 'some text', args = 'some other text' }
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', 'some other text'
} }
frame:getParent
frame:getParent()
若在由{{#invoke:}}
建立的框架調用,返回調用了$2的頁面的框架。若在該框架調用,會返回nil。
比如,如果模板{{Example}}
包含代碼{{#invoke:ModuleName|FunctionName|A|B}}
,而另一頁透過代碼{{Example|C|D}}
來嵌入包含該模板,那麼在Module:ModuleName中,調用frame.args[1]
和frame.args[2]
會返回"A"
和"B"
,調用frame:getParent().args[1]
和frame:getParent().args[2]
則會返回"C"
和"D"
,其中frame
是函數調用的第一個參數。
frame:getTitle
frame:getTitle()
以字串形式返回與框架關聯的標題。對於由{{#invoke:}}
建立的框架,返回被調用的模組的標題。
frame:newChild
frame:newChild{ title = title, args = table }
- 注意使用了命名參數。
建立新的框架對象,該對象是當前框架對象的子對象,可以有可選的參數和標題。
這個主要用於測試函數要被{{#invoke:}}
調用時的調試。任何一次建立的框架的數量是受限制的。
frame:preprocess
frame:preprocess( string )
frame:preprocess{ text = string }
在當前框架環境下展開維基文本,比如,模板、解析器函式以及像{{{1}}}
這樣的參數都會展開。某些特殊的寫成XML格式的標記,比如<pre>
、<nowiki>
、<gallery>
和<ref>
都會被替換為「strip marker」——一類特殊的字串,由刪除符(ASCII 127)開頭,在從#invoke
返回後被替換成HTML。
如果你使用單個模板,使用frame:expandTemplate
而非嘗試建造維基文本以使用這個方法。這樣更快且更不容易出錯,尤其是參數包含管道符或其他維基標記時。
同理,展開單個解析器函式時應使用frame:callParserFunction
。
frame:getArgument
frame:getArgument( arg )
frame:getArgument{ name = arg }
獲得特定參數的對象,或者沒有提供參數時返回nil。
返回的對象有一個方法,object:expand()
,可以返回對應參數的展開後的維基文本。
frame:newParserValue
frame:newParserValue( text )
frame:newParserValue{ text = text }
返回有一個方法object:expand()
的對象,該方法可以返回frame:preprocess( text )
的結果。
frame:newTemplateParserValue
frame:newTemplateParserValue{ title = title, args = table }
- 注意使用了命名參數。
返回有一個方法object:expand()
的對象,該方法可以返回使用給定的參數調用frame:expandTemplate
的結果。
frame:argumentPairs
frame:argumentPairs()
等同於pairs( frame.args )
。考慮到向後兼容。
哈希庫
mw.hash.hashValue
mw.hash.hashValue( algo, value )
按照指定的算法算出字串的哈希值。可以透過mw.hash.listAlgorithms()獲得有效的算法。
mw.hash.listAlgorithms
mw.hash.listAlgorithms()
返回支持的哈希算法的列表,以用於mw.hash.hashValue()。
HTML庫
mw.html
是用於在Lua中構建複雜HTML樹的友好接口。使用mw.html.create
方法來建立mw.html對象。
被記為mw.html.name
在全局mw.html
表是可用的,被記為mw.html:name
和html:name
是一個HTML對象的方法(參見mw.html.create
)。
一個基礎的例子如下所示:
local div = mw.html.create( 'div' )
div
:attr( 'id', 'testdiv' )
:css( 'width', '100%' )
:wikitext( 'Some text' )
:tag( 'hr' )
return tostring( div )
-- Output: <div id="testdiv" style="width:100%;">Some text<hr /></div>
mw.html.create
mw.html.create( tagName, args )
建立一個新的mw.html對象,其包含一個標籤名稱為tagName
的HTML元素。你也可以傳遞一個空的字串或nil作為tagName
,以建立一個新的空的mw.html對象。
args
可以是有以下鍵的表:
args.selfClosing
:強制當前標籤自我閉合,即使mw.html不認為其為自我閉合的args.parent
:當前mw.html實例的上級對象(用於內部使用)
mw.html:node
html:node( builder )
向當前的mw.html實例附加mw.html(builder
)子節點。如果傳遞nil,那麼函數不做任何事。(builder
)節點是要建立的HTML元素的種類的字串代表。
mw.html:wikitext
html:wikitext( ... )
給mw.html對象加上不定數量的維基文本字串。
注意遇到第一個nil項就會停。
mw.html:newline
html:newline()
給mw.html對象加新行。
mw.html:tag
html:tag( tagName, args )
給mw.html對象添加一個新的節點,其標籤名稱為tagName
,返回代表這個新的節點的mw.html實例。args
參數和mw.html.create
的參數是一樣的。
mw.html:attr
html:attr( name, value )
html:attr( table )
將節點的HTML屬性的name
屬性的值設為value
。也可以選擇使用表,其鍵值對即為屬性名稱-值對。第一種形式中,如果值為nil,會導致這個給定名稱的已被設置屬性設為未被設置。
mw.html:getAttr
html:getAttr( name )
獲得已經透過html:attr()
設置的屬性name
的值。
mw.html:addClass
html:addClass( class )
給節點的類(class)屬性添加一個類名稱(class name)。如果參數為nil,則無效。
mw.html:css
html:css( name, value )
html:css( table )
使用給定的name
和value
給節點設置CSS屬性。也可以選擇使用表,其鍵值對即為CSS名稱-值對。第一種形式中,如果值為nil,會導致這個給定名稱的已被設置的CSS設為未被設置。
mw.html:cssText
html:cssText( css )
給節點的屬性添加一些純css
文本。如果參數為nil,則無效。
mw.html:done
html:done()
返回當前節點被建立時所在的上級節點。類似於jQuery.end,這是個方便地函數可以允許建立多個子節點,而由一個語句串在一起。
mw.html:allDone
html:allDone()
類似於html:done()
,但是會遍歷直到樹節點的根部再返回。
語言庫
語言代碼在語言代碼中由描述。很多MediaWiki的語言代碼類似於IETF語言標籤,但不是所有MediaWiki語言代碼都是有效的IETF標籤,反之亦然。
被記為mw.language.name
在全局mw.language
表是可用的,被記為mw.language:name
和lang:name
是一個語言對象的方法(參見mw.language.new
或mw.language.getContentLanguage
)。
mw.language.fetchLanguageName
mw.language.fetchLanguageName( code, inLanguage )
給定的語言代碼的完整語言名稱:預設為本地名稱,如有inLanguage
的值,則是被翻譯為目標語言的語言名稱。
mw.language.fetchLanguageNames
mw.language.fetchLanguageNames()
mw.language.fetchLanguageNames( inLanguage )
mw.language.fetchLanguageNames( inLanguage, include )
獲取MediaWiki已知的語言列表,返回將語言代碼映射到語言名稱的表。
預設返回的名稱是語言自稱;傳遞inLanguage
值會返回那個語言下的所有名稱。
預設只會返回MediaWiki已知的語言名稱,給include
傳遞'all'
會返回所有可用的語言(例如,從Template:Ll中),傳遞'mwfile'
會僅包括擁有在MediaWiki核心或啟用的擴展包括的自訂消息的語言。如要清楚地選擇預設,返回'mw'
。
mw.language.getContentLanguage
mw.language.getContentLanguage()
mw.getContentLanguage()
返回wiki當前的預設語言的語言對象。
mw.language.getFallbacksFor
mw.language.getFallbacksFor( code )
返回MediaWiki針對指定語言代碼的備選語言代碼列表。
mw.language.isKnownLanguageTag
mw.language.isKnownLanguageTag( code )
若語言代碼為MediaWiki已知的語言,返回true。
語言代碼「已知」意味著是個「有效的內置代碼」(例如,對於mw.language.isValidBuiltInCode
返回true),對於mw.language.fetchLanguageName
返回一個非空字串。
mw.language.isSupportedLanguage
mw.language.isSupportedLanguage( code )
檢查MediaWiki的語言代碼內是否有任何本地化可用。
語言「受支持」意味著是個「有效的」代碼(對於mw.language.isValidCode
返回true),不包含任何大寫字母,並在MediaWiki的當前運行版本中有個消息檔案。
一個語言代碼可能既「受支持」又「未知」(例如,對mw.language.isKnownLanguageTag
返回true)。還要注意,儘管mw.language.isValidBuiltInCode
返回false,特定的代碼仍是「受支持」的。
mw.language.isValidBuiltInCode
mw.language.isValidBuiltInCode( code )
如果語言代碼是用於MediaWiki內部自訂的有效形式,返回true。
這個代碼可能不對應任何已知語言。
語言代碼是「有效的內置代碼」意味著這是個「有效」代碼(比如,對於mw.language.isValidCode
返回true),只包括ASCII字母、數字和連字元,並至少兩個字元長度。
注意有些代碼「受支持」(即mw.language.isSupportedLanguage
會返回true),即使這個函數返回false。
mw.language.isValidCode
mw.language.isValidCode( code )
若語言代碼字串是有效形式的,返回true,無論其是否存在。這包括了所有單獨用於透過MediaWiki命名空間自訂使用的語言代碼。
這個代碼可能不對應任何已知語言。
一個語言代碼有效意味著不包含任何不安全字元(逗號、單雙引號、斜槓、反斜槓、尖括號、連字號或ASCII NUL)且允許出現在頁面標題中。
mw.language.new
mw.language.new( code )
mw.getLanguage( code )
建立新的語言對象。語言對象沒有任何可公開獲取的屬性,不過可以含有幾個方法,下面列出。
不同語言代碼在頁面中的使用有次數限制。超過限制會報錯。
mw.language:getCode
lang:getCode()
返回這個語言對象的語言代碼。
mw.language:getFallbackLanguages
lang:getFallbackLanguages()
返回MediaWiki針對此語言對象的備選語言代碼列表。等同mw.language.getFallbacksFor( lang:getCode() )
。
mw.language:isRTL
lang:isRTL()
若語言是從右至左寫的,返回true,否則返回false。
mw.language:lc
lang:lc( s )
將字串轉化為小寫,但遵從給定的語言的任何特殊規則。
當加載了ustring庫,mw.ustring.lower()函數就會透過調用mw.language.getContentLanguage():lc( s )
來實現。
mw.language:lcfirst
lang:lcfirst( s )
將字串的第一個字元轉化為小寫,就像lang:lc()那樣。
mw.language:uc
lang:uc( s )
將字串轉化為大寫,但遵從給定的語言的任何特殊規則。
當加載了ustring庫,mw.ustring.upper()函數就會透過調用mw.language.getContentLanguage():lc( s )
來實現。
mw.language:ucfirst
lang:ucfirst( s )
將字串的第一個字元轉化為大寫,就像lang:lc()那樣。
mw.language:caseFold
lang:caseFold( s )
將字串轉換為不區分大小寫的比較表示形式。注意,顯示其結果可能無任何意義。
mw.language:formatNum
lang:formatNum( n )
lang:formatNum( n, options )
格式化數字,使用給定語言的合適的分組符合小數點。給予123456.78,可能會產生123,456.78、123.456,78或甚至١٢٣٬٤٥٦٫٧٨,取決於語言和wiki配置。
options
是包含選項設置的表,可以是:
noCommafy
:若為true,則忽略分組符並使用點(.
)作為小數點。 數字轉化仍會發生,可能包括轉化數字分隔符。
mw.language:formatDate
lang:formatDate( format, timestamp, local )
根據給定的格式字串格式化一個日期。如果省略了timestamp
,預設為當前時間。local
的值必須是boolean或nil,如果是true,時間會格式化為wiki的當地時間而非UTC。
timestamp
的格式字串和支持的值與Template:Ll的#time解析器函式完全相同。
注意雖然反斜槓可能需要在Lua字串字面量中寫兩次,由於Lua也使用反斜槓轉義,而維基文本不需要:
-- 这个字符串字面量包含新行,不是两个字符"\n",所以不等同于{{#time:\n}}。
lang:formatDate( '\n' )
-- 等同于{{#time:\n}},不是{{#time:\\n}}。
lang:formatDate( '\\n' )
-- 等同于{{#time:\\n}},不是{{#time:\\\\n}}。
lang:formatDate( '\\\\n' )
mw.language:formatDuration
lang:formatDuration( seconds )
lang:formatDuration( seconds, chosenIntervals )
將秒數的時間間隔轉化為更加已讀的單位,例如12345轉化為3 hours, 25 minutes and 45 seconds(3時25分45秒),作為字串返回結果。
chosenIntervals
,如提供,是一個指定了要在響應中使用的間隔單位名稱的表(table)。包括'millennia
', 'centuries
', 'decades
', 'years
', 'weeks
', 'days
', 'hours
', 'minutes
'和'seconds
'。
mw.language:parseFormattedNumber
lang:parseFormattedNumber( s )
這需要一個以lang:formatNum()格式化的數字,並返回實際數字。換句話說,這基本上是tonumber()
根據語言轉換的版本。
mw.language:convertPlural
lang:convertPlural( n, ... )
lang:convertPlural( n, forms )
lang:plural( n, ... )
lang:plural( n, forms )
從forms
(必須是序列表)或...
基於數字n
選擇合適的語法形式。例如,在英語你必須使用n .. ' ' .. lang:plural( n, 'sock', 'socks' )
或n .. ' ' .. lang:plural( n, { 'sock', 'socks' } )
來生成語法正確的文本:只有1 sock或200 socks。
序列的必填值取決於語言,詳見魔術字的本地化和translatewiki針對PLURAL的常見問題。
mw.language:convertGrammar
lang:convertGrammar( word, case )
lang:grammar( case, word )
- 注意兩個別稱之間的不同參數順序。
convertGrammar
匹配MediaWiki的Language對象的相同名稱的方法的順序,而grammar
匹配相同名稱的解析器函式的順序,可參考使用說明:魔術字#本地化。
這會選擇給定的變形碼case
的合適的word
變形形式。
word
和case
的可能的值是依賴於語言的,參見Special:MyLanguage/Help:Magic words#Localisation和translatewiki:語法以了解詳情。
mw.language:gender
lang:gender( what, masculine, feminine, neutral )
lang:gender( what, { masculine, feminine, neutral } )
選擇對應what
的性別的字串,可以是male、female或註冊的使用者名稱。
mw.language:getArrow
lang:getArrow( direction )
返回對應方向direction
的Unicode箭頭字元:
- forwards:「→」或「←」,取決於語言的書寫方向。
- backwards:「←」或「→」,取決於語言的書寫方向。
- left:「←」
- right:「→」
- up:「↑」
- down:「↓」
mw.language:getDir
lang:getDir()
根據語言的書寫方向,返回"ltr"(從左至右)或"rtl"(從右至左)。
mw.language:getDirMark
lang:getDirMark( opposite )
返回包含U+200E(從左至右標記)或U+20F(從右至左標記)的字串,取決於語言的書寫方向以及opposite
的值。
mw.language:getDirMarkEntity
lang:getDirMarkEntity( opposite )
返回「‎」或「‏」,取決於語言的書寫方向和opposite
的值。
mw.language:getDurationIntervals
lang:getDurationIntervals( seconds )
lang:getDurationIntervals( seconds, chosenIntervals )
將秒數的時間間隔轉化為更加已讀的單位,例如12345轉化為3 hours, 25 minutes and 45 seconds(3時25分45秒),返回從單位名稱映射到數字的表。
chosenIntervals
,如提供,是一個指定了要在響應中使用的間隔單位名稱的表(table)。包括millennia
、centuries
、decades
、years
、weeks
、days
、hours
、minutes
和seconds
。
這些單元關鍵字也是響應表中使用的鍵。響應中僅設置具有非零值的單位,除非響應為空,在這種情況下,返回值為0的最小單位。
系統消息庫
這個庫是對本地化消息和MediaWiki:命名空間的介面。
被記為mw.message.name
在全局mw.message
表是可用的,被記為mw.message:name
和msg:name
是一個消息對象的方法(參見mw.message.new
)。
mw.message.new
mw.message.new( key, ... )
建立一個給定消息key
的新消息對象。
剩下的參數傳遞到新的對象的params()
的方法。
消息對象沒有屬性,但是有下面列出的幾個方法。
mw.message.newFallbackSequence
mw.message.newFallbackSequence( ... )
建立給定的消息的新的消息對象(存在的第一個會被使用)。
消息對象沒有屬性,但有下面列出的幾種方法。
mw.message.newRawMessage
mw.message.newRawMessage( msg, ... )
建立新的消息對象,使用給定的文本,而不是查找國際化的(internationalized)消息。剩下的參數會傳遞到新對象的params()
方法中。
消息對象沒有屬性,但是有下面列出的幾個方法。
mw.message.rawParam
mw.message.rawParam( value )
包裝(wrap)該值使之不會被msg:parse()
解析為維基文本。
mw.message.numParam
mw.message.numParam( value )
包裝(wrap)該值使之自動被格式化為lang:formatNum()
。注意這不依賴事實上有效的語言庫。
mw.message.getDefaultLanguage
mw.message.getDefaultLanguage()
返回預設語言的語言對象。
mw.message:params
msg:params( ... )
msg:params( params )
給消息添加參數,參數可以一被傳遞為獨立的參數或者作為一個序列表。參數必須是數字、字串或由mw.message.numParam()或mw.message.rawParam()返回的特殊的值。如果使用序列表,參數必須是直接出現在表中,使用__index元方法的參考不起作用。
返回msg
對象,以允許鏈式調用。
mw.message:rawParams
msg:rawParams( ... )
msg:rawParams( params )
像:params(),但是會先透過mw.message.rawParam()傳遞所有的參數。
返回msg
對象,以允許鏈式調用。
mw.message:numParams
msg:numParams( ... )
msg:numParams( params )
像:params(),但是會先透過mw.message.numParam()傳遞所有的參數。
返回msg
對象,以允許鏈式調用。
mw.message:inLanguage
msg:inLanguage( lang )
指定一個語言,以在加工消息時使用。lang
可以是字串,或者帶有getCode()
元表的表(比如語言對象)。
預設的語言是由mw.message.getDefaultLanguage()
返回的。
返回msg
對象,以允許鏈式調用。
mw.message:useDatabase
msg:useDatabase( bool )
指定是否在MediaWiki:命名空間查找消息(比如在資料庫中查找),或者只是使用MediaWiki分配的預設消息。
預設為true。
返回msg
對象,以允許鏈式調用。
mw.message:plain
msg:plain()
替換參數按原樣返回消息維基文本。模板調用和解析器函式都是完整的。
mw.message:exists
msg:exists()
返回表示消息鍵是否存在的布爾值。
mw.message:isBlank
msg:isBlank()
返回表示消息鍵是否有內容的布爾值。當消息鍵不存在或者消息是空字串時返回true。
mw.message:isDisabled
msg:isDisabled()
返回表示消息鍵是否被禁用的布爾值。如果消息鍵不存在,或者消息是空字串,或者是字串"-"則返回true。
站點資訊庫
mw.site.currentVersion
包含當前MediaWiki版本資訊的字串值。
mw.site.scriptPath
mw.site.server
$wgServer
的值。
mw.site.siteName
$wgSitename
的值。
mw.site.stylePath
$wgStylePath
的值。
mw.site.namespaces
包含所有命名空間數據的表,由數字索引。
可用的數據為:
- id:命名空間數字。
- name:本地命名空間名稱。
- canonicalName:規範(canonical)命名空間名稱。
- displayName:為命名空間0設置,用於顯示的名稱(因為這個名稱通常是空白字串)。
- hasSubpages:這個命名空間是否啟用了子頁面。
- hasGenderDistinction:這個命名空間在不同的性別是否有不同的別稱。
- isCapitalized:這個命名空間的頁面的第一個字母是否會轉化為大寫。
- isContent:這個命名空間是否為內容命名空間。
- isIncludable:這個命名空間的頁面是否可以被嵌入包含。
- isMovable:這個命名空間的頁面是否可以移動。
- isSubject:這個命名空間是否為一個主題命名空間(subject namespace)。
- isTalk:這個命名空間是否為討論頁。
- defaultContentModel:這個命名空間的預設內容模型(字串)。
- aliases:這個命名空間的別稱的列表。
- subject:對應主題命名空間的數據。
- talk:對應討論頁命名空間的數據。
- associated:與之有關聯的命名空間的數據。
設置了元表以便於按照名稱(本地化的或者規範的)查找命名空間。比如,mw.site.namespaces[4]
和mw.site.namespaces.Project
都會返回關於Project命名空間的資訊。
mw.site.contentNamespaces
只包含內容命名空間的表,按數字索引。參考mw.site.namespaces以了解詳細內容。
mw.site.subjectNamespaces
只包含主題命名空間的表,按數字索引。參考mw.site.namespaces以了解詳細內容。
mw.site.talkNamespaces
只包含討論命名空間的表,按數字索引。參考mw.site.namespaces以了解詳細內容。
mw.site.stats
包含站點統計的表。可用的統計有:
- pages:wiki的頁面數量。
- articles:wiki的文章數量。
- files:wiki的檔案數量。
- edits:wiki的編輯次數。
- users:wiki的使用者數量。
- activeUsers:wiki的活躍使用者數量。
- admins:wiki中sysop使用者群組的使用者數量。
mw.site.stats.pagesInCategory
mw.site.stats.pagesInCategory( category, which )
- 這個函數是高開銷函數
獲得關於分類的統計數據。如果which
擁有指定值"*
",則結果為有如下內容的表:
- all:總共的頁面、檔案和子分類。
- subcats:子分類的數量。
- files:檔案的數量。
- pages:頁面的數量。
如果which
是以上鍵(all、subcats、files、pages)中的一個,則結果為對應值的數字。
每次新的分類查詢都會增大高開銷函數次數。
mw.site.stats.pagesInNamespace
mw.site.stats.pagesInNamespace( ns )
返回給定的命名空間(由數字指定)的頁面數量。
mw.site.stats.usersInGroup
mw.site.stats.usersInGroup( group )
返回給定的使用者群組的使用者數量。
mw.site.interwikiMap
mw.site.interwikiMap( filter )
返回包含可用的跨wiki前綴的數據的表。如果filter
是字串"local",則只會返回關於本地跨wiki前綴的數據。如果filter
是字串"!local",則只會返回非本地跨wiki前綴的數據。如果沒有指定filter,則所有的前綴的數據都會返回。這個"local"前綴是同一個計畫的。比如在英文維基百科,其他語言的維基百科都會考慮為本地的(local),而維基詞典不會。
這個函數返回的表的鍵是跨wiki前綴,值是帶有以下屬性的子表:
- prefix——跨wiki前綴。
- url——跨wiki指向的URL。頁面名稱由參數$1體現。
- isProtocalRelative——布爾值,顯示URL是否為URL。
- isLocal——這個URL是否是當前wiki的站點的。
- isCurrentWiki——這個URL是否是為當前wiki的。
- isTranscludable——使用這個跨wiki前綴的頁面能否嵌入包含。這個要求scary transclusion,而這在維基媒體的wiki是禁用的。
- isExtraLanguageLink——跨wiki是否列舉在了
$wgExtraInterlanguageLinkPrefixes
。 - displayText——對於列舉在$wgExtraInterlanguageLinkPrefixes中的連結,跨語言連結顯示的文本。未指定時為nil。
- tooltip——對於列舉在$wgExtraInterlanguageLinkPrefixes的連結,當使用者懸浮在跨語言連結上時顯示的浮窗提示文本。未指定時為nil。
文本庫
文本庫提供了一些常見的文本處理函數,這些函數來自字串庫和Ustring庫,並且可用於UTF-8字串。
mw.text.decode
mw.text.decode( s )
mw.text.decode( s, decodeNamedEntities )
將字串中的HTML元素替換為對應的字元。
如果布爾值decodeNameEntities
被省略或者為false,則只有被命名的實體「<」「>」「&」「"」和「 」會被認可。否則,認可的HTML5命名實體的列表會從PHP的get_html_translation_table
函數中加載。
mw.text.encode
mw.text.encode( s )
mw.text.encode( s, charset )
使用HTML實體替換字串中的字元。字元「<」「>」「&」「"」和非換行空格會被適當的命名實體替換,所有其他的都會被替換為數字實體。
如果提供了charset
,則它應該是合適的字串,且被Ustring模式的括號括住,比如[set]
中的「set」。預設的charset是'<>&"\' '
(末尾的空格為非換行空格,U+00A0)。
mw.text.jsonDecode
mw.text.jsonDecode( s )
mw.text.jsonDecode( s, flags )
解析JSON字串。flags
是0或flagsmw.text.JSON_PRESERVE_KEYS
和mw.text.JSON_TRY_FIXING
的組合(使用+
)。
通常JSON的數組會被重組到Lua的有鍵的序列表,如果要避免這個,可以傳入mw.text.JSON_PRESERVE_KEYS
。
如果要降低JSON的特定需求,比如數組或對象不應有結尾的逗號,可傳入mw.text.JSON_TRY_FIXING
。不推薦這樣做。
限制:
- 如果數組含有null值,解析的JSON數組可能不是Lua序列。
- JSON對象會丟棄含有null值的鍵。
- 不能直接分辨帶有序列整數鍵的是JSON數組還是JSON對象。
- 帶有序列整數鍵從1開始的的JSON對象會被解析到作為有相同值的JSON數組的相同的表結構,儘管這些不一定總是相等,除非使用了
mw.text.JSON_PRESERVE_KEYS
。
mw.text.jsonEncode
mw.text.jsonEncode( value )
mw.text.jsonEncode( value, flags )
編碼JSON字串。如果傳入的值不能被JSON編碼則會報錯。flags
是0或flagsmw.text.JSON_PRESERVE_KEYS
和mw.text.JSON_PRETTY
的組合(使用+
)。
通常Lua的帶有鍵的序列表會被編碼稱JSON的不帶鍵的序列;如果flags
中設置了mw.text.JSON_PRESERVE_KEYS
,不帶鍵的序列表會被編碼為JSON數組。
限制:
- 空的表總是會被編碼為空的數組(
[]
),而不是空的對象({}
)。 - 如果沒有加入無效(dummy)元素,序列表不能被編碼為JSON對象。
- 如果要產生帶有nil值的對象,需要設置
__pairs
元方法。 - 帶有從0開始的序列整數鍵的Lua表會被編碼為JSON數組,帶有從1開始的整數鍵的Lua表也是如此,除非使用了
mw.text.JSON_PRESERVE_KEYS
。 - 如果同一個表中,既使用了數字,又使用了代表那個數字的字串作為鍵,則行為未指定。
mw.text.killMarkers
mw.text.killMarkers( s )
除去字串中所有的strip marker。
mw.text.listToText
mw.text.listToText( list )
mw.text.listToText( list, separator, conjunction )
使用自然語言組合一個列表,類似於table.concat()
,但是最後一項前面的分隔符不同。
預設的分隔符取自wiki內容語言的MediaWiki:comma-separator,預設的連詞取自由MediaWiki:word-separator連接的MediaWiki:and。
比如,對消息使用預設值:
-- 返回空字符串
mw.text.listToText( {} )
-- 返回"1"
mw.text.listToText( { 1 } )
-- 返回"1和2"(如果wiki的语言设置为“中文”,下同)
mw.text.listToText( { 1, 2 } )
-- 返回"1、2、3、4和5"
mw.text.listToText( { 1, 2, 3, 4, 5 } )
-- 返回"1; 2; 3; 4 or 5"
mw.text.listToText( { 1, 2, 3, 4, 5 }, '; ', ' or ' )
mw.text.nowiki
mw.text.nowiki( s )
使用HTML實體替換字串中的多種字元,以避免被解析為維基文本。包括:
- 以下字元:
"
、&
、'
、<
、=
、>
、[
、]
、{
、|
、}
- 字串開頭或新行後面的的以下字元:
#
、*
、:
、;
、空格、制表符('\t') - 空行會有關聯的新行或返迴轉義的字元(Blank lines will have one of the associated newline or carriage return characters escaped)
- 字串開始處或新行後的的
----
會使得第一個-
被轉義 __
會使一個下劃線被轉義://
會使冒號被轉義ISBN
、RFC
或PMID
後的空白字元會被轉義
mw.text.split
mw.text.split( s, pattern, plain )
在匹配了Ustring模式的pattern
的地方分割字串。如果指定了plain
且為true,則pattern
會被解釋為純字串而不是Lua模式(就像mw.ustring.find()
的這個參數一樣)。返回包含子字串的表。
比如,mw.text.split( 'a b\tc\nd', '%s' )
會返回表{ 'a', 'b', 'c', 'd' }
。
如果pattern
匹配空字串,s
會被分割成單個字元。
mw.text.gsplit
mw.text.gsplit( s, pattern, plain )
返回會迭代子字串的迭代器函數,返回的相當於調用mw.text.split()
。
mw.text.tag
mw.text.tag( name, attrs, content )
mw.text.tag{ name = string, attrs = table, content = string|false }
- 注意使用了命名參數。
生成name
的HTML樣式的標籤。
如果指定了attrs
,則必須是帶有字串鍵的表。字串和數字值都會被使用為屬性的值,布爾值的true會被輸出為HTML5的無值參數,布爾值的false會跳過這個鍵,其他的都會錯誤。
如果沒有給出content
(或者是nil),只會返回開始標籤。如果content
是布爾值false,則會返回自我閉合標籤。否則它必須是字串或數字,這樣內容就會被開始標籤和結束標籤包圍。注意內容不會自動被編碼為HTML,如有需要,使用mw.text.encode()。
對於返回擴展標籤的屬性,比如<ref>
,應該使用frame:extensionTag()。
mw.text.trim
mw.text.trim( s )
mw.text.trim( s, charset )
從字串的開始和結尾移除空白字元或其他字元。
如果提供了charset
,則它應該是合適的字串,且被Ustring模式的括號括住,比如[set]
中的「set」。預設的charset是ASCII空白字元,"\t\r\n\f "
。
mw.text.truncate
mw.text.truncate( text, length )
mw.text.truncate( text, length, ellipsis )
mw.text.truncate( text, length, ellipsis, adjustLength )
將文本text
裁剪到指定的長度,如果執行了裁剪,加入ellipsis
(省略號)。如果長度為正,則字串末尾被裁剪,如果為負,則字串的開頭會被裁剪。如果給定了adjustLength
且為true,則包含省略號的字串不會長於指定的長度。
ellipsis
的預設值取自wiki的內容語言的MediaWiki:ellipsis。
例如,使用預設的「...」省略號:
-- 返回"foobarbaz"
mw.text.truncate( "foobarbaz", 9 )
-- 返回"fooba..."
mw.text.truncate( "foobarbaz", 5 )
-- 返回"...arbaz"
mw.text.truncate( "foobarbaz", -5 )
-- 返回"foo..."
mw.text.truncate( "foobarbaz", 6, nil, true )
-- 返回"foobarbaz",因为比"foobarba..."更短
mw.text.truncate( "foobarbaz", 8 )
mw.text.unstripNoWiki
mw.text.unstripNoWiki( s )
將MediaWiki的<nowiki> strip marker替換為對應的文本。其他類型的strip marker不會改變。
mw.text.unstrip
mw.text.unstrip( s )
等同於mw.text.killMarkers( mw.text.unstripNoWiki( s ) )
。
這個不在顯示特殊頁面嵌入包含、<ref>後的HTML,就像Scribunto早期版本的那樣。
標題庫
mw.title.equals
mw.title.equals( a, b )
檢測兩個標題是否相等。注意比較時忽略碎片(fragments)。
mw.title.compare
mw.title.compare( a, b )
返回-1、0、1,表示標題a
是否小於、等於或大於標題b
。
這會按照作為字串的跨wiki前綴(如果有)比較,然後按命名空間數字,然後按照作為字串的未加前綴的標題文本比較。字串比較使用Lua標準的<
操作符。
mw.title.getCurrentTitle
mw.title.getCurrentTitle()
返回當前頁面的標題對象。
mw.title.new
mw.title.new( text, namespace )
mw.title.new( id )
- 用ID調用時該函數是高開銷函數
建立新的標題對象。
如果給了id
,則那個帶有那個page_id的頁面的對象會被建立。引用的標題會被認為連結到了當前頁面。如果page_id不存在,返回nil。如果建立的標題對象不是對於已經加載的標題,則高開銷函數數量會被增加。
然而,如果給了字串text
,那麼就會建立那個標題的對象(即使那個頁面不存在)。如果文本字串不指定命名空間,則使用namespace
(可以在mw.site.namespaces
的任何鍵中找到)。如果文本不是有效的標題,則會返回nil。
mw.title.makeTitle
mw.title.makeTitle( namespace, title, fragment, interwiki )
建立命名空間namespace
內標題title
的標題對象,可以有指定的fragment
和interwiki
前綴。namespace
可以是在mw.site.namespaces
中找到的任何鍵。如果結果的標題無效,返回nil。
注意,不像mw.title.new()
,這個方法總會應用指定的命名空間。比如,mw.title.makeTitle( 'Template', 'Module:Foo' )
會為頁面Template:Module:Foo建立對象,而mw.title.new( 'Module:Foo', 'Template' )
會為頁面Module:Foo建立對象。
標題對象
標題對象有許多屬性和方法。大多數屬性是只讀的。
注意以text
結尾的欄位返回作為字串值的標題,而以title
結尾的欄位返回標題對象。
- id:頁面ID。不存在時返回
0
。 注意可能有高開銷. - interwiki:跨wiki前綴,如果無,則為空白字串。
- namespace:命名空間數字。
- fragment:碎片(也叫段落/錨點連接),或者空字串。可能被賦值。
- nsText:頁面的命名空間的文本。
- subjectNsText:頁面的主題命名空間的文本。
- text:頁面標題,不含命名空間和跨wiki前綴。
- prefixedText:頁面標題,帶有命名空間和跨wiki前綴。
- fullText:頁面標題,包括命名空間、跨wiki前綴和碎片。如果跨wiki等於當前wiki則不返回跨wiki。
- rootText:如果這是子頁面,根頁面的標題,不帶前綴。否則,等同於
title.text
。 - baseText:如果這是子頁面,則這個子頁面的上級頁面的標題,不帶前綴。否則,等同於
title.text
。 - subpageText:如果這是個子頁面,子頁面名稱。否則,和
title.text
相同。 - canTalk:這個標題的頁面能否擁有討論頁。
- exists:該頁面是否存在。Media命名空間頁面的
file.exists
別名。對於File命名空間的頁面,這將檢查檔案描述頁面的存在,而不是檔案本身。此函數可能為高開銷。 - file,fileExists:參見下面的#檔案元數據。
- isContentPage:這個頁面是否在內容命名空間內。
- isExternal:此頁面是否具有跨wiki的前綴。
- isLocal:此頁面是否在此計畫中。例如,在英語維基百科上,任何其他語言維基百科都被視為「本地」(Local),而維基字典等則被視為非「本地」。
- isRedirect:是否是重新導向頁面的標題。此函數可能為高開銷。
- isSpecialPage:該頁面是否可能是特殊頁面(即「Special」命名空間中的頁面)。
- isSubpage:該頁面是否為其他頁面的子頁面。
- isSubpage:該頁面是否為討論頁。
- isSubpageOf( title2 ):該頁面是否為給定頁面的子頁面。
- inNamespace( ns ):該頁面是否在給定的命名空間中。命名空間可以由在
mw.site.namespaces
中定義的任何鍵指定。 - inNamespaces( ... ):標題是否在給定的命名空間中的任何一個中間。命名空間可以由在
mw.site.namespaces
中定義的任何鍵指定。 - hasSubjectNamespace( ns ):標題的主題命名空間是否在指定的命名空間內。命名空間必可以由在
mw.site.namespaces
中定義的任何鍵指定。 - contentModel:此標題的內容模型,字串,可能會造成高開銷。
- basePageTitle:等同於
mw.title.makeTitle( title.namespace, title.baseText )
。 - rootPageTitle:等同於
mw.title.makeTitle( title.namespace, title.rootText )
。 - talkPageTitle:等同於
mw.title.makeTitle( mw.site.namespaces[title.namespace].talk.id, title.text )
,如果該標題沒有討論頁則為nil
。 - subjectPageTitle:等同於
mw.title.makeTitle( mw.site.namespaces[title.namespace].subject.id, title.text )
。 - redirectTarget:返回重新導向頁面的目標頁面的標題對象,但如果不是重新導向頁面,則返回
false
。 - protectionLevels:頁面的保護等級。其值為一個表,鍵對應每個操作(如
"edit"
、"move"
),值為數組,第一項是包含對應保護等級的字串,如果頁面未被保護,則表的值或者數組的項就會為nil
。此函數高開銷。 - cascadingProtection:該頁面應用的級聯保護,為一個表,鍵為
"restrictions"
(自身為一個表,鍵類似於protectionLevels
擁有的那些)和"sources"
(列舉保護級聯來源的標題的數組)。如果沒有保護級聯到此頁面,則"restrictions"
和"sources"
可能是空的。此函數開銷較高。 - subPageTitle( text ):等同於
mw.title.makeTitle( title.namespace, title.text .. '/' .. text )
。 - partialUrl():返回編碼的
title.text
,就像在URL中會有的那樣。 - fullUrl( query, proto )::返回此標題的完整URL(帶有可選的query表/字串)。可以指定proto以控制返回URL的協議:
"http"
、"https"
、"relative"
(預設值)或"canonical"
。 - localUrl( query ):返回此標題的本地的URL(帶有可選的query表/字串)。
- canonicalUrl( query ):返回此標題的規範URL(帶有可選的query表/字串)。
- getContent():返回頁面的(未解析的)內容,如果頁面不存在則返回
nil
。頁面會被記錄為嵌入包含。
標題對象可以使用關係運算符比較。tostring( title )
會返回title.prefixedText
。
由於這可能難以置信,所以請注意獲取標題對象的任何高開銷的欄位會記錄一次對頁面的「連入」(就像Special:連入頁面中展示的那樣)。使用標題對象的getContent()
方法或訪問redirectTarget
欄位會記錄為「嵌入」,訪問標題對象的file
或fileExists
欄位會記錄為「檔案連結」。
檔案元數據
代表File或Media命名空間下的頁面的標題對象會擁有稱為file
屬性。這是高開銷的。這是一個表,其結構如下:
- exists:檔案是否存在。會記錄一次圖像使用。標題對象的
fileExists
屬性的存在是為了考慮向後兼容,可以看做該屬性的別稱。如果這是false
,所有其他屬性都會是nil
。 - width:檔案寬度。若檔案有多個頁面,第一頁的寬度。
- height:檔案的高度。若檔案有多個頁面,第一頁的高度。
- pages:如果檔案格式支持多頁,這是包含檔案每個頁面的表,否則為
nil
。「#」操作符可以用於獲取檔案頁數。每個單獨的頁面表都包含一個width和height屬性。 - size:檔案的字節長度。
- mimeType:檔案的MIME類型。
- length:媒體檔案的長度,單位為秒。不支持長度的媒體則為0。
高開銷屬性
屬性id
、isRedirect
、exists
和contentModel
需要從資料庫獲取標題數據。因此,第一次獲取除了當前頁面之外的任何頁面的這些屬性中的一個時,高開銷函數數量會增加。之後獲取那個頁面的這些屬性中的任何一個都不會再次增加高開銷函數數量。
其他標記為高開銷的屬性總是會在第一次獲取除當前頁面之外的頁面時增加高開銷函數數量。
URI庫
mw.uri.encode
mw.uri.encode( s, enctype )
百分號編碼字串。預設類型,"QUERY"
,使用「+」編碼空格以用於查詢字元;"PATH"
將空格編碼為%20,"WIKI"
將空格編碼為「_」。
注意"WIKI"格式不是完全可以逆轉的,因為空格和下劃線都會編碼為「_」。
mw.uri.decode
mw.uri.decode( s, enctype )
百分號解碼字串。預設類型,"QUERY"
,將「+」解碼為空格;"PATH"
不執行額外的解碼,"WIKI"
將「_」解碼為空格。
mw.uri.anchorEncode
mw.uri.anchorEncode( s )
編碼字串以用於MediaWiki URI fragment。
mw.uri.buildQueryString
mw.uri.buildQueryString( table )
將表編碼為URI查詢字串。鍵必須是字串,值可以是字串、數字、序列表或布爾值false。
mw.uri.parseQueryString
mw.uri.parseQueryString( s, i, j )
將查詢字串s
解碼為表。字串中沒有值的鍵會擁有false值,重複多次的鍵會有序列表作為其值,其他的都會有字串作為值。
可選的數字參數i
和j
可以用於指定要解析的s
的子串,而非整個字串。i
是子串的第一個字元位置,預設為1。j
是子串的最後一個字元位置,預設為字串長度。i
和j
都可以是負數,就像string.sub那樣。
mw.uri.canonicalUrl
mw.uri.canonicalUrl( page, query )
mw.uri.fullUrl
mw.uri.fullUrl( page, query )
mw.uri.localUrl
mw.uri.localUrl( page, query )
mw.uri.new
mw.uri.new( s )
利用傳入的字串或表構造一個新的URI對象。參見URI對象的描述以了解表可能的欄位。
mw.uri.validate
mw.uri.validate( table )
驗證傳入的表(或URI對象)是否有效。返回布爾值,以表示表是否有效,以及如果無效,一個描述問題發生原因的字串。
URI對象
URI對象有以下欄位,其中的部分或全部可能是nil:
- protocol:字串 協議
- user:字串 使用者
- password:字串 密碼
- host:字串 主機名
- port:整數 埠
- path:字串 路徑
- query:表,就像從mw.uri.parseQueryString中的那樣
- fragment:字串 分段
以下屬性也是可用的:
- userInfo:字串 使用者和密碼
- hostPort:字串 主機和埠
- authority:字串 使用者、密碼、主機、埠
- queryString::字串 查詢表的版本
- relativePath:字串 路徑、查詢字串、分段
tostring()
會產生URI字串。
URI對象的方法為:
mw.uri:parse
uri:parse( s )
將字串解析為當前的URI對象。字串中指定的任何欄位都會被當前的對象替換;未指定的欄位都會保留舊值。
mw.uri:clone
uri:clone()
製作URI對象的拷貝。
mw.uri:extend
uri:extend( parameters )
將參數表合併到對象的查詢表。
ustring庫
ustring庫相當於標準字串庫的重新實現,不過方法會操作於UTF-8編碼的字串的字元,而非字節。
大多數函數會在字串不是有效的UTF-8時報錯,但有例外。
mw.ustring.maxPatternLength
匹配模式(pattern)允許的最大長度,以字節為單位。
mw.ustring.maxStringLength
字串允許的最大長度,以字節為單位。
mw.ustring.byte
mw.ustring.byte( s, i, j )
返回單獨的字節,等同於string.byte()。
mw.ustring.byteoffset
mw.ustring.byteoffset( s, l, i )
返回字元在字串內的字節偏移值。l
和i
的預設值都是1.i
可以是負數,即倒過來計數。
位於l
== 1的字元是以i
字節開頭或在該字節之後的第一個字元,位於l
== 0的字元是在i
字節開頭或之前的第一個字元。注意這可能是同一個字元。更大或者更小的l
值都是相對這些進行計算的。
mw.ustring.char
mw.ustring.char( ... )
非常像string.char(),但是整數為Unicode代碼點而非字節值。
local value = mw.ustring.char( 0x41f, 0x440, 0x438, 0x432, 0x435, 0x442, 0x21 ) -- 值现在为“Привет!“
mw.ustring.codepoint
mw.ustring.codepoint( s, i, j )
很像string.byte(),但是返回的值是代碼點,且偏移值為字元而非字節。
mw.ustring.find
mw.ustring.find( s, pattern, init, plain )
非常像string.find(),但是匹配模式是擴展了的,在Ustring patterns中有描述,且init
是按照字元而非字節。
mw.ustring.format
mw.ustring.format( format, ... )
等同於string.format()。字串的寬度和精度是以字節表達,而非編號。
mw.ustring.gcodepoint
mw.ustring.gcodepoint( s, i, j )
返回用於在字串內迭代代碼點的三個值。i
預設為1,j
預設為-1。這是為了用於for
形式的迭代:
for codepoint in mw.ustring.gcodepoint( s ) do
-- 语句块
end
mw.ustring.gmatch
mw.ustring.gmatch( s, pattern )
非常像string.gmatch(),但是匹配模式是擴展了的,在ustring匹配模式中有描述。
mw.ustring.gsub
mw.ustring.gsub( s, pattern, repl, n )
非常像string.gsub(),但是匹配模式是擴展了的,在ustring匹配模式中有描述。
mw.ustring.isutf8
mw.ustring.isutf8( s )
若字串是有效的UTF-8,返回true,否則返回false。
mw.ustring.len
mw.ustring.len( s )
返回字串的長度,或者不是有效的UTF-8時返回nil。
參見string.len()以了解使用字節長度而非代碼點的類似函數。
mw.ustring.lower
mw.ustring.lower( s )
非常像string.lower(),但是所有在Unicode中定義了小寫到大寫轉換的字元都會被轉換。
mw.ustring.match
mw.ustring.match( s, pattern, init )
非常像string.match(),但是匹配模式是擴展了的,在ustring匹配模式中有描述,且init
偏移是按照字元而非字節。
mw.ustring.rep
mw.ustring.rep( s, n )
等同於string.format()。
mw.ustring.sub
mw.ustring.sub( s, i, j )
非常像string.sub(),但是偏移值為字元而非字節。
mw.ustring.toNFC
mw.ustring.toNFC( s )
將字串轉化為正規形式C。如果字串不是有效的UTF-8則返回nil。
mw.ustring.toNFD
mw.ustring.toNFD( s )
將字串轉化為正規形式D。如果字串不是有效的UTF-8則返回nil。
mw.ustring.upper
mw.ustring.upper( s )
非常像string.upper(),但是所有在Unicode中定義了大寫到小寫轉換的字元都會被轉換。
ustring匹配模式
ustring函數中的匹配模式使用和字串庫匹配模式相同的語法。主要區別是,字串類會根據Unicode字元屬性重新定義。
%a
:代表一般類別「控制」中的所有字元。%c
:代表一般類別「控制」中的所有字元。%d
:代表一般類別「數字、十進位數字」中的所有字元。%l
:代表一般類別「小寫字母」中的所有字元。%p
:代表一般類別「標點」中的所有字元。%s
:代表一般類別「分隔符」以及制表符、換行、回車、垂直制表符和換頁符中的所有字元。%u
:代表一般類別「大寫字母」中的所有字元。%w
:代表一般類別「字母或十進位數字」中的所有字元。%x
:加上十六進位數字的全寬字元。
就像在字串庫匹配模式中的那樣,%A
, %C
, %D
, %L
, %P
, %S
, %U
和⧼word-separator⧽%W
代表所有補集(不在給定的一般類別內的所有字元)。
在所有情況下,字串解析為Unicode字元而非字節,所以像[0-9]
這樣的範圍、%b«»
這樣的模式匹配和應用於多個字元的量詞都可以正確起作用。空的捕獲會捕獲代碼點而非字節。
可加載的庫
這些庫預設不包括,但是如有需要可透過require()
加載。
bit32
可以透過以下方式模擬加載Lua 5.2 bit32
庫
bit32 = require( 'bit32' )
bit32庫提供了無符號的32位整數的位運算。輸入的整數會被截成整數(方法未指定)並用232模除,這樣值就是在0到232-1之間的,返回的值也會是這個範圍。
如果字節被編號(就像bit32.extract()中那樣),那麼0是最低位的字節(帶有值20的),31是最高位的(帶有值231的)。
bit32.band
bit32.band( ... )
返回參數的「按位與」運算:對於結果中的每一位,只有當所有參數中都設置了該位時,結果中才會有這一位。
如果沒有給參數,則結果會設置所有位。
bit32.bnot
bit32.bnot( x )
返回x
的「取反」。
bit32.bor
bit32.bor( ... )
返回參數的「按位或」運算:對於結果中的每一位,只要所有參數中有任何一個設置了該位,結果中就會有這一位。
如果沒有給參數,則結果會清除所有位。
bit32.btest
bit32.btest( ... )
等同於bit32.band( ... ) ~= 0
bit32.bxor
bit32.bxor( ... )
返回參數的「按位異或」運算:對於結果中的每一位,只有所有參數中設置了該位的參數個數為奇數,結果中才會有這一位。
如果沒有給參數,則結果會清除所有位。
bit32.extract
bit32.extract( n, field, width )
從n
導出width
位,以field
為開始。訪問0到31範圍之外的位都是錯誤的。
如未指定,width
預設為1。
bit32.replace
bit32.replace( n, v, field, width )
替換n
中的width
位,以field
位開始,v
開始的低width
位。訪問0到31範圍之外的位都是錯誤的。
如未指定,width
預設為1。
bit32.lshift
bit32.lshift( n, disp )
返回數n
向左移動disp
位。這是一個邏輯移位:插入的位為0。這通常相當於乘以2的disp
次方。
請注意,超過31的位移將導致0。
bit32.rshift
bit32.rshift( n, disp )
返回數n
向右移動disp
位。這是一個邏輯移位:插入的位為0。這通常相當於除以2的disp
次方。
請注意,超過31的位移將導致0。
bit32.arshift
bit32.arshift( n, disp )
返回數n
向右移動disp
位。這是一個算數移位:如果disp
是正的,那麼插入的位將會與原始數字的31位相同。
注意超過31的移位將會導致0或4294967295。
bit32.lrotate
bit32.lrotate( n, disp )
返回數n
向左旋轉disp
位。
注意旋轉位數相當於模32:旋轉32位相當於旋轉0位,旋轉33位相當於旋轉1位,以此類推。
bit32.rrotate
bit32.rrotate( n, disp )
返回數n
向右旋轉disp
位。
注意旋轉位數相當於模32:旋轉32位相當於旋轉0位,旋轉33位相當於旋轉1位,以此類推。
libraryUtil
本庫包含在實現Scribunto庫時的一些有用方法。可以透過以下方式加載:
libraryUtil = require( 'libraryUtil' )
libraryUtil.checkType
libraryUtil.checkType( name, argIdx, arg, expectType, nilOk )
type( arg )
不符合預期類型expectType
時報錯。此外,如果arg
是nil且nilOk
為true,則不會報錯。
name
是調用函數的名稱,argIdx
是參數列表中參數的位置。這些用于格式化錯誤消息。
libraryUtil.checkTypeMulti
libraryUtil.checkTypeMulti( name, argIdx, arg, expectTypes )
type( arg )
不符合預期類型數組expectTypes
中的任何字串時報錯。
用於可以有多個有效類型的參數。
libraryUtil.checkTypeForIndex
libraryUtil.checkTypeForIndex( index, value, expectType )
type( value )
不符合預期類型expectType
時報錯。
用於實現__newindex
元方法。
libraryUtil.checkTypeForNamedArg
libraryUtil.checkTypeForNamedArg( name, argName, arg, expectType, nilOk )
type( arg )
不符合預期類型expectType
時報錯。此外,如果arg
是nil且nilOk
為true,則不會報錯。
在使用Lua的命名參數語法(func{ name = value }
)中,此函數用作libraryUtil.checkType()
的等效。
libraryUtil.makeCheckSelfFunction
libraryUtil.makeCheckSelfFunction( libraryName, varName, selfObj, selfObjDesc )
此函數用於在用於被obj:method()
語法調用的對象表中實現「方法」,會返回一個應該在這些方法頂部調用的函數,並使用self
參數和方法名稱,如果self
對象不是selfObject
則會拋出錯誤。
此函數通常用於庫的構造函數中,類似於這樣:
function myLibrary.new()
local obj = {}
local checkSelf = libraryUtil.makeCheckSelfFunction( 'myLibrary', 'obj', obj, 'myLibrary object' )
function obj:method()
checkSelf( self, 'method' )
end
function obj:method2()
checkSelf( self, 'method2' )
end
return obj
end
luabit
可使用如下代碼來加載luabit庫模組的「bit」和「hex」:
bit = require( 'luabit.bit' ) hex = require( 'luabit.hex' )
注意bit32庫包含了luabit.bit中的相同操作,luabit.hex也可以使用string.format()
和tonumber()
來運行。
luabit模組noki不可用,因為在Scribunto中完全無用。luabit模組utf8也不可用,因為對Ustring庫來說是多餘的。
ustring
純Lua中對Ustring庫的後備支持可以使用如下代碼加載
ustring = require( 'ustring' )
任何情況下,都應該使用Ustring庫(mw.ustring
),因為這將取代很多帶有PHP代碼回調、更慢且消耗內存的操作。
擴展庫
一些MediaWiki擴展提供額外的Scribunto庫。這些都位於表mw
中,通常是在表mw.text
中,然而,這些只有在安裝了特定擴展時才存在(加上Scribunto擴展本身)。
這些擴展使用Scribunto提供的鉤子:
Writing Scribunto libraries提供了如何開發這些庫以為MediaWiki擴展提供Lua接口的資訊。
以下庫是計劃中的,在Gerrit中等待覆核。
- (目前還沒有)
mw.wikibase
Template:Ll提供了對可本地化的結構數據的訪問,尤其是維基數據。 參見md_docs_topics_lua.html和Template:Ll。
mw.wikibase.lexeme
WikibaseLexeme提供了對Wikibase Lexeme實體的訪問,由Wikidata:Lexicographical data支持。
mw.wikibase.mediainfo
WikibaseMediaInfo提供了對Wikibase MediaInfo實體的訪問。 參見Template:Ll。 這是由Structured Data on Commons支持的,參見Commons:Structured data/Lua。
mw.bcmath
BCmath提供了Lua模組中的任意精度運算,可透過Extension:BCmath#Usage中的LDoc連結參見BCmath文檔。
mw.smw
Semantic Scribunto提供了Scribunto擴展對 Semantic MediaWiki擴展的原生支持。
mw.ext.data
JsonConfig提供了對可本地化的表格和地圖數據的訪問。參見Extension:JsonConfig/Tabular。Tabular Data和GeoJSON Map Data是在Commons的「Data:」命名空間中支持的。
mw.ext.cargo
Cargo提供了從Lua中查詢數據的方法,參見Extension:Cargo/Other features#Lua support。
mw.ext.cattools
CategoryToolbox提供了在Lua中查詢某個頁面是否屬於特定分類的方法。 該擴展是實驗性的,在公開的WikiMedia wiki中沒有啟用。
mw.ext.FlaggedRevs
FlaggedRevs提供了從Lua中訪問頁面的穩定性數據的方法。
mw.ext.TitleBlacklist
TitleBlacklist提供了從Lua中檢測黑名單中的頁面名稱項以及獲取有關資訊的方法。
mw.ext.ParserFunctions
ParserFunctions提供了從Lua中評估解析器函式表達式的方法。
mw.ext.articlePlaceholder
ArticlePlaceholder提供了從Lua中覆蓋預設的Wikibase渲染的方法,參見Extension:ArticlePlaceholder/Module:AboutTopic。
mw.ext.externalData
ExternalData提供了從Lua中從網際網路中獲取結構化數據的方法,參見Extension:External Data/Lua。
mw.ext.seo
WikiSEO提供了為當前頁面獲取SEO數據的方法,參見Extension:WikiSEO#Usage in lua modules。
與標準Lua的不同之處
改變的函數
以下函數被修改了:
- setfenv()
- getfenv()
- 可能不可用,取決於配置。如果可用,嘗試獲取上級環境會失敗。
- getmetatable()
- 僅應用於表以避免未授權而獲取上級環境。
- tostring()
- 不提供表和函數的指針地址。這是為了使得內存侵蝕更難被利用。
- pairs()
- ipairs()
- 支持__pairs和__ipairs元方法(在Lua 5.2中增加的)。
- pcall()
- xpcall()
- 不能攔截某些內部錯誤。
- require()
- 可以獲取Scribunto分發的內置模組,以及在wiki的Module命名空間下存在的模組。如需獲取wiki模組,使用包括命名空間的完整頁面名稱。不能獲取本地檔案系統。
移除的函數和包
以下包被幾乎移除。只有列出來的函數可用。
- package.*
- 檔案系統和對C庫的取得被移除了。 可用的函數和表為:
- package.loaded
- package.preload
- package.loaders
- 可獲取本地檔案系統或加載C庫的加載器不存在。 添加了Module命名空間頁面的加載器。
- package.seeall()
- os.*
- 有些不安全的函數,例如os.execute(),因而不被允許。 可用的函數為:
- debug.*
- 大多數函數都是不安全的。 可用的函數為:
以下函數和包不可用。
- collectgarbage()
- module()
- coroutine.*
- 沒有已知的應用,故沒有檢查安全性。
- dofile()
- loadfile()
- io.*, file.*
- 允許獲取本地檔案系統,不安全。
- load()
- loadstring()
- 這些被省略了以允許Lua原始碼的靜態解析。 此外,允許這些會使得Lua代碼被直接添加在文章和模板頁面,而這不會因為可用性原因被需要。
- print()
- 這在wikitech-l中有討論,決定省略以支持返回值,以提高代碼質量。 如有需要,mw.log()可以用於在調試控制台輸出資訊。
- string.dump()
- 可能會從上級環境中暴露私有資訊。
額外注意事項
- 參考資料結構
- 循環資料結構和同一節點可能透過多條路逕到達的資料結構無法正確發送到PHP。 嘗試這樣做會導致不確定的行為。 這包括(但不限於)從
{{#invoke:}}
調用的模組返回此類資料結構,並將此類資料結構作為參數傳遞給在PHP中作為回調實現的庫函數。
這樣的資料結構可以在Lua中自由使用,包括用作透過mw.loadData()加载的模块的返回值
。
編寫Scribunto庫
此資訊對於編寫其他Scribunto庫的開發者很有用,無論是包含在Scribunto本身還是為他們自己的擴展提供接口。
Scribunto庫通常由五個部分組成:
- 庫的PHP部分。
- 庫的Lua部分。
- 測試用例的PHP部分。
- 測試用例的Lua部分。
- 文檔。
現有的庫就是一個很好的例子。
庫
庫的PHP部分必須是繼承了Scribunto_LuaLibraryBase
的類。有關實現細節,請參閱該類的文檔。在Scribunto擴展中,這個檔案應該放在engines/LuaCommon/NameLibrary.php
中,並在Scribunto_LuaEngine::$libraryClasses
中添加一個映射。其他擴展應該使用ScribuntoExternalLibraries鉤子。在上述兩種中的任何一種情況下,鍵都應該與Lua模組名稱匹配(「mw.name」用於Scribunto中的庫,「mw.ext.name」用於擴展庫)。
庫的Lua部分設置了包含可以從Lua模組調用的函數的表。在Scribunto擴展中,該檔案應該放在engines/LuaCommon/lualib/mw.名称.lua
中,通常應包含如下樣板檔案:
local object = {}
local php
function object.setupInterface( options )
-- 移除setup函数
object.setupInterface = nil
-- 将PHP回调复制到局部变量,并删除全局变量
php = mw_interface
mw_interface = nil
-- 在此处进行任何其他设置
-- 安装到mw全局变量
mw = mw or {}
mw.ext = mw.ext or {}
mw.ext.NAME = object
-- 表示我们已经加载了
package.loaded['mw.ext.NAME'] = object
end
return object
engines/LuaCommon/lualib/libraryUtil.lua
中的模組(使用local util = require 'libraryUtil'
加載此模組)包含一些可能有用的函數。
確保在加載庫的情況下運行Scribunto測試用例,即使您的庫本身不提供任何測試用例。標準測試用例包括像添加意外全局變量的庫之類的測試。此外,如果庫是用PHP加載的,其Lua函數所具有的任何上值都不會在#invoke之間重置,必須注意確保模組不能濫用在#invoke之間傳輸資訊。
測試樣例
Scribunto擴展包括一個用於測試用例的基類Scribunto_LuaEngineTestBase
,該類將針對LuaSandbox和LuaStandalone引擎運行測試。
庫的測試用例應該擴展這個類,並且不應該覆蓋static function suite()
。
在Scribunto擴展中,測試用例應該在tests/engines/LuaCommon/NameLibraryTest.php
並添加到ScribuntoHooks::unitTestsList()
中的數組中(在common/Hooks.php
中),擴展應該在自己的Template:Ll
鉤子函數中添加測試用例,可能取決於是否設置了$wgAutoloadClasses['Scribunto_LuaEngineTestBase']
。
大多數時候,製作測試用例需要做的包括:
class ClassNameTest extends Scribunto_LuaEngineTestBase { protected static $moduleName = 'ClassNameTest'; function getTestModules() { return parent::getTestModules() + array( 'ClassNameTest' => __DIR__ . '/ClassNameTests.lua'; ); } }
這將加載檔案ClassNameTests.lua
,就好像它是頁面「Module:ClassNameTests」一樣,並期望返回具有以下屬性的對象:
- count: 整數,測試次數
- provide(n):函數,返回三個值:
n
,測試n
的名稱,以及作為測試預期輸出的字串n
。 - run(n):函數,運行測試
n
並返回一個字串。
如果getTestModules()
像上面一樣被聲明,那麼「Module:TestFramework」是可以用來提供許多有用的輔助方法,如果使用了,那麼ClassNameTests.lua
看起來像這樣:
local testframework = require 'Module:TestFramework' return testframework.getTestProvider( { -- 此处放测试 } )
每個測試本身就是一個表,具有以下屬性:
- name:測試的名稱。
- func:要執行的函數。
- args:傳遞給函數的可選參數表。
- expect:預期結果。
- type:測試的可選類型,預設為「Normal」。
type控制expect
的格式以及func
的調用方式。包括以下類型:
- Normal:
expect
是返回值的表,但如果測試應該引發錯誤,則為字串。func
被簡單地調用。 - Iterator:
expect
是返回值的表。func
與迭代for循環一樣被調用,並且每次迭代的返回值都會累加。 - ToString:和「Normal」一樣,但每個返回值都透過
tostring()
傳遞。
在其他擴展中的測試樣例
有(至少)兩種方式來運行PHPUnit測試:
- 針對核心運行phpunit,允許tests/phpunit/suites/ExtensionsTestSuite.php使用Template:Ll鉤子找到擴展的測試。 如果您的擴展的測試類名稱都包含一個唯一的組件(例如擴展的名稱),則可以使用
--filter
選項以僅運行您的擴展的測試。 - 對擴展目錄運行phpunit,這將獲取以「Test.php」結尾的任何檔案。
如果在LocalSettings.php中加載了Scribunto,則其中任何一個都可以正常運作。如果未加載Scribunto,那麼方法#1很容易生效,因為可以輕鬆編寫UnitTestsList鉤子以避免在未設置$wgAutoloadClasses[ 'Scribunto_LuaEngineTestBase' ]
時返回Scribunto測試。
但是Jenkins使用方法#2。為了讓Jenkins正確運行測試,您需要將Scribunto添加到擴展的依賴項。有關如何完成此操作的範例,請參見Template:Gerrit。
如果由於某種原因,您需要能夠在不加載Scribunto的情況下使用方法#2運行測試,一種解決方法是將此檢查添加到單元測試檔案的頂部:
if ( !isset( $GLOBALS['wgAutoloadClasses']['Scribunto_LuaEngineTestBase'] ) ) {
return;
}
文檔
Scribunto中包含的模組應該在上面的Scribunto庫部分中包含文檔。擴展庫應該在其自己的擴展頁面的子頁面中包含文檔,並從上方的擴展庫章節中連結到該文檔。
參見
許可協議
以下內容為譯文,請以英文原文為準。
本手冊(的英文原文)取自Lua 5.1 參考手冊,在MIT許可證下可用。
軟體著作權持有人據此條款,授權許可任何獲得該軟體的副本和與其有關的文檔檔案(「該軟體的副本和與其有關的文檔檔案」以下稱為「該軟體」)的人,無償地、不受任何限制(包括使用、複製、修改、合併、出版、分發、再許可和/或銷售軟體副本的權利)地處理該軟體,且可以將該軟體提供給他人並對其以同樣方式授權許可,但需符合下列條件:
上述著作權聲明和本許可聲明應包含在所有該軟體的副本或帶有該軟體大部分內容的實體之內。
本軟體按「原樣」提供,無任何明示或暗示的保證,包括但不限於適銷性、特定用途適用性和非侵權性的保證。在任何情況下,作者或著作權持有人均不對因本軟體或本軟體的使用或其他交易而引起的、與之相關的任何索賠、損害賠償或其他責任負責,無論是合同訴訟、侵權訴訟還是其他訴訟。本衍生手冊也可以根據同一許可證的條款進行複製。
[[Category:Lua{{#translation:}}]]