使用者:渚 花/Lua參考手冊(翻譯)
頁面User:サンムル/Lua參考手冊/syntaxhighlight.css沒有內容。
本頁面之全部或部分原來自MediaWiki的[14],依 CC BY-SA 3.0 授權引入;原貢獻者可以在這裡看到。 |
- 本頁面是為在萌娘百科上使用擴展:Scribunto進行Lua編程的編輯者的便利而創建並維護。
- 本頁面將儘可能地與官方技術文檔及實際情況保持同步更新。如果你發現本頁面中的內容與官方技術文檔及實際情況有所出入,可以討論頁或評論區提出更改。 本頁面,或在
- 本頁面中涉及的部分技術資料可能超前於現有版本,部分功能可能尚未部署,這些內容將會特別註明。
- 由於本頁面是由MediaWiki的文檔搬運而來的,所以本文中很多藍鏈可能會錯誤地指向不存在的位置。如果後來的讀者看到這些連結,可以嘗試幫忙修改。
本頁面介紹的是在萌娘百科上使用的Lua參考手冊。其中部分內容取自MediaWiki及Lua5.1參考手冊。
介紹
入門
首先在模块
名字空間下創建一個頁面,例如:模塊:HelloWorld。
將以下代碼複製到這個頁面中:
-- 模块:HelloWorld local p = {} -- p表示一个包(package) function p.say( frame ) return "Hello, world!" end return p
保存更改後,在另一個(不在模块
名字空間下的)頁面中編寫:
{{#invoke:HelloWorld|say}}
這樣就成功調用了HelloWorld
模塊公開的say
函數。調用的輸出結果為:Hello, world!
。
如果想要調用另一個模塊,只需要將HelloWorld
替換成那個模塊所在頁面的名稱(不帶模块:
名字空間前綴)即可。
從模板調用Lua代碼有諸多優勢,一個問題的解決方法並不局限於解決它所使用的語言到底是wiki還是Lua。從總體上而言,wiki代碼與Lua代碼協同工作,各自獨立的同時保持整體統一。從模板的角度而言,它允許了將複雜的代碼邏輯放在Lua模塊中實現,從而增強了wiki代碼的可讀性。
模塊結構
簡單而言,模塊本身必須返回一個表(table),這個表包含了所有能被{{#invoke:}}
調用的函數。一般來說,如上所示,先聲明一個局部變量表,再將函數寫在這個表中,最後把這個表返回。
{{#invoke:}}
只能調用類型為function
的變量,試圖調用其他類型(括table
、string
、number
等)都會拋出一個錯誤。
沒有加到這個表中的函數,無論是局部的還是全局的,對於隔著{{#invoke:}}
的「外部」調用頁面來說都是無法訪問的。但需要注意的一點是,當你在一個模塊中申明了一個全局變量,當你在其他模塊中require()此模塊時,這個全局變量也能夠被訪問到。因此對於模塊來說,最好將所有的函數和變量聲明為局部變量,以防覆蓋到其他模塊中的同名變量的作用域,引發難以發現的錯誤。
從Wiki文本關聯參數
從外部通過{{#invoke:}}
調用模塊中的函數時會傳入一個框架對象,它是被函數接受的唯一參數。通過在函數內部訪問框架對象的args
屬性,可以獲取到外部調用時傳入的其他參數。另外,若模塊被模板包裝,還可以使用frame:getParent()獲取表示外部模板的框架對象,然後通過args
屬性獲取調用模板時傳入的參數。
框架對象還用於操作一些Wiki文本解釋器的功能,例如調用解析器函數、展開模板、以及展開任意Wiki文本。
返回內容
模塊函數應該返回一個字符串,但無論返回什麼值都會被函數tostring()轉換並不帶分隔符地級聯。這個字符串會併入維基文本作為{{#invoke:}}
展開的結果。
在頁面解析到這步時,模板已經展開,解析函數和擴展標籤已進行,預保存轉換(例如簽名波浪線符號~~~和豎線符號)也均已發生。所以模塊的輸出文本中不能使用這些特性。例如,如果一個模塊返回"Hello, [[world]]! {{welcome}}
,頁面會識別為 "hello, world! {{welcome}}。
此外,User:渚 花/需要修正連結指向是在保存編輯的時候被處理的。
模塊文檔
Scribunto允許模塊附帶文檔,通過自動將模塊與維基文檔頁面相關聯。默認情況下,模塊的"/doc"子頁面會被關聯為模塊的文檔,插入在模塊的原始碼上面。例如,"Module:Bananas"的文檔是"Module:Bananas/doc"。
你可以使用以下 MediaWiki-namespace messages消息(message)來配置被關聯為模塊的文檔:
- scribunto-doc-page-name: 這個消息用來設置用來做模塊的文檔頁面的名稱。文檔的名稱(除去前綴「模塊:」)作為
$1
傳遞。如果是在模塊名字空間的話,在這裡確定的頁面會被解讀為維基文本(wikitext),而不是Lua源文件,也不會在{{#invoke}}
被調用時使用。默認設定是"Module:$1/doc",也就是/doc子頁面。需要注意的是,解析器函數(parser function)和花括號擴展(brace expansion)可能無法在這個消息中使用。 - scribunto-doc-page-does-not-exist: 如果文檔不存在,會顯示(display)這個消息。頁面的名稱會作為
$1
傳遞。默認為空。 - scribunto-doc-page-show: 只有文檔存在,才會顯示這個消息。頁面的名字作為
$1
傳遞。默認是嵌入文檔頁。 - scribunto-doc-page-header: 作為文檔頁面本身時顯示的標題。文檔所屬的模塊的名稱(除去前綴「模塊:」)作為
$1
傳遞。默認是僅僅以斜體顯示簡短的解釋。
注意:模塊不能被直接分類,也不能直接加入維基內鏈(interwiki link)。你可以把這些內容加入到文檔頁面的標籤(tag)<includeonly>...</includeonly>
中,這樣這些內容會被插入到模塊頁面。
Lua language
變量名稱
在Lua中,變量名(也叫做「標識符」)可以是字母、數字和下劃線的任意組合,但不能以數字開頭。變量名是大小寫敏感的,即foo
、Foo
和FOO
都是各不相同的變量名。
以下是Lua保留的關鍵字,我們定義的變量名不應該與它們相同:
and
break
do
else
elseif
end
false
for
function
if
in
local
nil
not
or
repeat
return
then
true
until
while
還有一些形似下劃線+大寫字母的變量名作為Lua的內部全局變量而被保留。
其他的符號有:
#
%
(
)
*
+
,
-
.
..
...
/
:
;
<
<=
=
==
>
>=
[
]
^
{
}
~=
注釋
- 單行注釋:以兩個中橫線
--
為起始,一直持續到這一行的末尾。 - 多行注釋:如果在兩個中橫線
--
後緊跟一個形似「左方括號[
+0或多個等號=
+左方括號」的片段,則表明這段注釋可以包含多行內容,直到遇到一個形似「右方括號]
+對應數量的等號+右方括號」的片段為止。
注釋不能寫在字符串中,那樣會使它成為字符串的一部分。
-- 单行注释:以两个中横线为起始,一直持续到这一行的末尾。 --[[ 多行注释 被限制在两层方括号的范围内。 ]] --[=[ 你可以在两层方括号间添加任意数量的等号,使得多行注释能够互相嵌套且不会重叠混淆。 ]=] --[==[ 更多等号的多行注释 --[===[ 内部的更更多等号的多行注释 --[=[也能包裹更少等号的内部注释]=] --以及单行注释 ]===] 甚至还能包裹等号数量不对应的多行注释 --[[ 只要内部的右侧等号数量不与外层的左侧等号数量相同即可 ]===] ]==]
數據類型
Lua是動態類型語言,這意味著所有變量或函數參數都沒有類型,只有值才擁有類型。所有值都有類型。
Lua有8種基本數據類型,然而只有六種在編寫模塊時會用到。type()
函數會以字符串形式返回一個值的類型。
tostring()
函數會將一個值轉化為字符串。tonumber()
函數會在可能時將值變為數字,如果不能則返回nil。沒有其他專門的函數轉化一個值為其他類型
Lua會自動進行類型轉換。當需要字符串,如級聯時,數字會自動轉為字符串。當對字符串進行數學運算時,Lua會嘗試將其轉為數字。當需要布爾值時,所有nil和false之外的值都會被認定為真。
nil (空值)
nil是空值類型,是「為了不存在的值而存在的數據類型」。nil沒有指針。
nil不能用作表(table)的鍵(key),並且表中不存在的域就是nil。
轉化為字符串時,nil轉化為"nil"。轉化為布爾值時,nil被認定為假。
boolean (布爾類型)
布爾類型是true
和false
。
當被轉化為字符串時,轉化結果是"true"或"false"。
和其餘程式語言不同,布爾類型不能直接轉化為數字類型;進行布爾類型轉換時,只有false和nil會被轉化為是false,數字0和空白字符串都會轉化為true。
string (字符串)
Lua的字符串類型是一串8位字節;應用程式可以用任何特定的編碼來解釋它們。
字符串常量(literal)可以單引號或雙引號包括('
or "
),這兩者沒有區別。下面是轉義字符。
\a
(bell, byte 7)\b
(backspace, byte 8)\t
(horizontal tab, byte 9)\n
(newline, byte 10)\v
(vertical tab, byte 11)\f
(form feed, byte 12)\r
(carriage return, byte 13)\"
(double quote, byte 34)\'
(single quote, byte 39)\\
(backslash, byte 92)
文字換行符也可以通過在字符串前面加反斜槓的方式包含在字符串中。可以使用轉義序列\ddd來指定字節,其中ddd是0-255範圍內的十進位值。如果想用轉義序列包括Unicode字符,必須指定UTF-8[1]的各個字節。一般來說,直接輸入Unicode字符更簡單。
字符串常量也可以通過長括號(long bracket)——實際上就是兩個方括號——來定義。
一個左長括號包括一個中括號,然後是0個或多個等於號,接著是另一個中括號。
左長括號必須與對應的右長括號對應,例如]]
, ]=]
, or ]=====]
。
如果左長括號接下來就是一個空行,那麼第一個空行不會在字符串里保留,但是右長括號中的換行會保留。
使用長括號的字符串不能解釋轉義字符。
-- 这个字符串 foo = [[ bar\tbaz ]] -- 相当于下面的字符串 foo = 'bar\\tbaz\n'
注意:所有的字符串轉化為布爾類型都會轉化為true,而不是像其他語言一樣的false。
number (數字)
Lua只有一種數字類型,通常被表示為雙精度浮點型。在這種格式下,-9007199254740992和9007199254740992中的數字可以精確表示。更大的數字和帶有小數部分的數字可能會有捨入錯誤(round-off error)。
數字常量使用英文句號(period)(.
)作為十進位分隔符,不需要分組分隔符,例如123456.78
。數字可以使用E記號表示,無需空格,比如1.23e-10
,123.45e20
, or 1.23E5
。整數也可以使用十六進位前綴0x
表示,例如0x3A
。
NaN和正無窮和負無窮是被正確地的方式儲存和處理的,Lua沒有提供名字叫NaN的常量。常量math.huge
是正無窮,等同於除法1/0
。除法0/0
可以快速生成一個NaN。
需要注意的是,進行布爾類型轉化的時候,所有的數字都會轉化為true。這和大多數把0轉化為false的語言不同。當轉化為字符串的時候,NaN會轉化為nan
或者-nan
,無窮會被轉化為inf
或者-inf
;有窮數字會轉化為十進位數字,可能會使用E記號。
table (表)
Lua的表(tabe)是關聯數組,和PHP的array和JavaScript中的object很相似。
通常使用花括號創建表。空表是{}
。為了創建時填充欄位,可以在大括號中包括以括號和/或分號分隔的欄位說明列表。有以下幾種形式。
[expression1] = expression2
將expression1的(當前)元素作為鍵(key),expression2的(當前)值作為在當前鍵下的值(value)。[2]name = expression
相當於["name"] = expression
expression
大致相當於[i] = expression
, 其中i是從1開始的數字,每次使用這段代碼填充欄位i都會遞增。如果這段代碼作為最後一個欄位出現,且expression有多個值,那麼所有的值都會使用,否則只保留第一個值。
表中的值可以通過中括號來訪問,例如table[key]
。字符串鍵也可以通過符號點來訪問,例如table.key
和table['key']
等同。調用是表中的值的函數使用冒號,例如table:func( ... )
,table['func']( table, ... )
和table.func( table, ... )
等同。
一個數組(或序列,sequence)是這樣的表,對於所有的從1到N的正整數,其值均為非零,對於大於N的所有正整數,其值均為無值(nil)。許多Lua的函數只在數組上運行,並且忽略所有非正整數的鍵。
與PHP和JavaScript不同,除了nil和NaN的的所有值都可以都可以被用作鍵,這些鍵都是合乎語法且不同的。下面的示例展示了一些可以作為鍵的類型。
-- 创建表 t = {} t["foo"] = "foo" t.bar = "bar" t[1] = "one" t[2] = "two" t[3] = "three" t[12] = "the number twelve" -- 数字12 t["12"] = "the string twelve" -- 字符串12 t[true] = "true" --布尔类型 t[tonumber] = "yes, even functions may be table keys" -- 即使函数类型也可以作为表的键 t[t] = "yes, a table may be a table key too. Even in itself." -- 表类型也可以作为表的键,甚至这个表本身。 -- 下面的代码创建了一个和上面的表大体等同的表。 t2 = { foo = "foo", bar = "bar", "one", "two", [12] = "the number twelve", ["12"] = "the string twelve", "three", [true] = "true", [tonumber] = "yes, even functions may be table keys", } t2[t2] = "yes, a table may be a table key too. Even in itself."
除了nil以外的值,在表中都可以作為值存儲。存儲nil相當於刪除這個鍵,訪問沒有被設定的鍵都會返回nil。
要注意,表被傳入為一個函數作為參數的時候,並不是複製一個新表作為參數。在調用這個函數的函數裡,原始的參數也改變了。以下偽碼可以幫助你理解。[3]
function f(tbl) print("第二次打印",tbl[1]) tbl[1] = 2 print("第三次打印",tbl[1]) end t = {} t[1] = 1 print("第一次打印",t[1]) f(tbl) print("第四次打印",t[1])
輸出結果應該是
當一個表被轉化為字符串時,結果通常是"table"。除非__tostring
元方法[4]被重寫。所有的表,即使是空表也會被當做布爾類型的true。
function (函數)
Lua的函數是上等公民。它們可以被匿名創建,作為參數傳遞,分配給變量等。
函數通常使用function
關鍵字創建,通過圓括號調用(call)。對於實名函數(named function),本地函數(local function)和作為表的成員的函數,Lua提供了語法糖,詳見 函數聲明 和 函數調用 等部分。
Lua的函數是閉包。函數包括聲明這個函數的命名空間的一個引用,並且可以訪問和操縱這個命名空間的變量。
像表一樣,如果一個函數賦值給一個變量,或者作為函數的參數傳遞,它仍然是可以被調用的"函數對象"。
當被轉化為字符串時,轉化結果是"function"。
不支持的類型
自定義(userdata)類型被用來保存不透明值,其他語言可以用它來擴展Lua。例如,自定義類型可以被用來存儲C語言的指針或者結構體。為了允許Scribunto搭建Lua環境,自定義編譯代碼不被允許,也沒有這樣的擴展使用。
線程(thread)類型表示協同程序(coroutine)的句柄,在Scribunto沙盒中不允許使用。
Metatables (元表)
每個表都可以與一個叫元表(metatable)的表相關聯。元表可以被一些運算符和函數使用,為表指定不同的行為。一個表的元表可以使用getmetatable() 函數獲得,使用setmetatable() 函數設置。
元表中的數據可以直接被元函數(meta function)獲取,就像被使用rawget()函數獲取一樣。
可以影響元表本身的欄位如下:
- __index
- 如果用鍵
[key]
訪問表,本應該返回nil的時候,會調用本元欄位。如果本元方法是一個表,那麼就會像這樣__index[key]
訪問這個表。(這可能會套娃調用這個表的元表的__index)。如果這個元欄位是一個函數[5],那麼就會像這樣__index( t, key )
調用這個函數。rawget()函數會繞過本元欄位。 - __newindex
- 如果你用
t[key] = value
代碼給表中的一個鍵複製,但是rawget( t, key )
會返回nil的時候[6],本元欄位會被調用。如果這個元欄位是一個表,那麼就會像這樣__newindex[key] = value
調用這個表也可能出現和上面一樣的套娃情況。如果本元欄位是一個函數,那麼就會像這樣__newindex( t, key, value )
調用這個函數。rawset()函數會繞過本元欄位。 - __call
- 當表當做一個函數調用的時候,像這樣,
t( ··· )
,會調用本元欄位。本元方法的值一定是一個函數,可以像是__call( t, ··· )
被調用。[7] - __mode
- 這個元欄位可以讓表持有弱引用(weak reference)。這個欄位必須是一個字符串。默認情況下,如果一個值作為表的鍵或者值,那麼這個值不會被垃圾回收,但是如果這個元欄位包括小寫字母'k',那麼當沒有非弱引用時,鍵可能會被回收,'v'代表值會進行同樣的操作。在這兩種任何一種情況,對應的鍵和值都會被去除。需要注意,在一個表被用作元表之後,修改此欄位,是未定義行為(undefined behavior,UB)。[8][9]
以下是其餘的元欄位。
注意:在Lua,所有的字符串共用一個元表,這個元表的__index對應著string
表。這個元表在Scribunto不可訪問,不可被引用。模塊只能訪問它的複製。
Variables (變量)
變量用來儲存值。Lua有三種變量:全局變量,局部變量(本地變量),表的欄位。
一個變量名代表一個全局變量或者局部變量(或者函數參數,它也是一種局部變量)。變量默認是全局變量,除非使用local
指定為局部變量。所有沒有被指定值的變量都會默認值為nil。
全局變量儲存在一個叫做全局表的Lua標準表中。這個表可以通過全局變量_G
訪問。可以為這個表設定元表。訪問全局變量相當於,訪問全局表下,以變量名為欄位下的值,所以訪問全局變量時,__index和__newindex元方法會像普通的表被訪問時一樣被調用。
函數的變量環境(environment)可以用getfenv()函數訪問,用setfenv()函數修改。在Scribunto中,這些函數被嚴格限制。
局部變量是有詞法範圍的,詳見局部變量聲明。
表達式
表達式是有值的:字面量(數字,字符串,true,false,nil),匿名函數聲明,表構造表達式,變量的引用,函數調用,參數表達式,用括號括起來的表達式,結合一元運算符的表達式,被二元運算符連接的表達式等。
大多數表達式只有一個值。函數調用和參數表達式可以有多個值。需要注意,被圓括號括起來的函數調用和參數表達式會丟失除了第一個值以外的值。
exp-list
表達式列表是用逗號分隔的一系列表達式。表達式列表會包括最後一個表達式的所有值,強制除最後一個值的其餘值為單值(捨去多出來的值,或用nil代表空值)。
算術運算符
Lua支持基本的算術運算:加法、減法、乘法、除法、求模(取模)、乘方和取相反數。
當所有的運算對象都是數字,和tonumber()函數處理後返回非nil值的字符串時,運算會正常進行。
如果運算對象是有正確重載的元方法的表時,會調用元方法。
運算符 | 操作 | 示例 | 元方法 | 注釋 |
---|---|---|---|---|
+ | 加法 | a + b | __add | |
- | 減法 | a - b | __sub | |
* | 乘法 | a * b | __mul | |
/ | 除法 | a / b | __div | 除0不會報錯,而是會返回NaN或無窮大。 |
% | 求模 | a % b | __mod | 被定義為 a % b == a - math.floor( a / b ) * b
|
^ | 乘方 | a ^ b | __pow | 允許非負整數作為冪指數 |
- | 取相反數 | -a | __unm |
關係運算符
Lua的關係運算符包括==
, ~=
, <
, >
, <=
, and >=
。關係運算符返回布爾值。
等於(==
)會首先判斷操作數的類型,如果是不同類型,返回false。對值進行比較。nil,布爾類型,數字,字符串會正常比較。只有當兩個函數是同一個函數對象時,返回true。function() end == function() end
會返回false,因為它們是兩個不同的匿名函數。表會默認按照同樣方式比較,元方法__eq被重載時除外。
不等於 (~=
) 的結果是對等於的結果取反。
對於順序運算符,如果兩端是數字和字符串,會直接進行比較。[10]否則會檢查是否有可用的元方法。
a < b
: 使用__lt
a <= b
: 如果可用的話默認使用__le
,否則使用__lt
,等價於not ( b < a )
a > b
: 相當於b < a
a >= b
: 相當於b <= a
如果沒有可用的元方法,會拋出(raise)異常(error)。
邏輯運算符
邏輯運算符是and
,or
和not
,它們的返回值都是布爾類型。只有nil和false會被當做false,其他的都會被當做true。
and
:如果左運算對象是false,直接返回false,否則返回右運算對象。
or
:如果左運算對象是true,直接返回true,否則返回右運算對象。
not
:返回結果總是true或false。
注意and
和or
有短路特性。例如,foo() or bar()
如果foo()
返回true,bar()
不會被執行;只有foo()
返回false時,會執行bar()
連接運算符
連接(級聯)運算符是兩個點,像這樣a .. b
。如果兩個運算對象都是數和字符串,它們會都轉化為字符串,然後連接。否則,如果可用的話使用__concat元方法元方法,否則會拋出異常。
在Lua中,字符串時不可變對象,Lua不提任何種類的"string builder"。所以重複執行代碼a = a .. b
,會在每次循環新建一個字符串,並垃圾回收舊字符串。如果需要連接很多字符串,使用string.format()函數,或者把所有字符串放到一個數組里,使用table.concat(),會更快。
長度運算符
長度運算符是#
,使用方法是#a
。如果a
是一個字符串,它會返回字節長度。如果a
是一個數組,那麼會返回數組長度。
如果a
是一個表,但不是一個數組,那麼#a
會返回滿足一下條件的N值,使得a[N]不是nil,a[N+1]是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)
。
函數調用
函數調用和大多數語言一樣,函數名後面是小括號括起來的表達式列表。
func( expression-list )
像Lua通常那樣,表達式列表最後一個表達式可能提供多個值。
如果調用函數時,提供的參數個數比需要的參數個數(函數定義時指定的參數個數)少,沒有提供的參數將會是nil值。如果提供參數比需要的參數多,那麼多出來的參數會被截斷。函數也可以有可變個參數,詳見函數聲明。
Lua也允許一個函數作為函數的返回值,像這樣func()()
。[11]為了確認被調用的函數,有時需要比變量訪問還要複雜的表達式,可以使用括號表達式來代替變量訪問。
Lua在以下兩種情況有語法糖。一種是當表作為一個對象(object)訪問時。這時函數可以作為表的一個方法。下面的語法
table:name( expression-list )
相當於
table.name( table, expression-list )
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 ( ''var-list'' ) ''block'' end
所有參數列表中的變量對於函數來說都是局部變量,這些變量可以在函數調用是確定。函數體(block)中可以聲明局部變量。
函數調用,在參數列表確定值之後,函數體的會執行。如果執行到了return語句時,會直接退出函數體,return語句的返回值即為函數的返回值。如果函數執行到了函數體的底端,但是沒有遇到return語句,函數會返回空值。
Lua的函數是詞法閉包的。一個是,函數在被聲明的作用域中,會將「靜態私有」變量看作為局部變量。例如,
-- 这个函数返回一个用来在增加一个数到它的参数上的函数。 function makeAdder( n ) return function( x ) -- 在这个函数外部的变量n,在这个函数里是可获得的。 return x + n end end local add5 = makeAdder( 5 ) mw.log( add5( 6 ) ) -- 会打印 11
函數可以接受可變個參數,通過將變量表達式...
[12]作為參數列表的最後一個。
function ( ''var-list'', ... ) ''[[#block|block]]'' end
在函數體裡,可以使用變量表達式,變量表達式的值是所有多出來的變量。例如,
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變量之前實現的,所以在函數聲明結束之前,factorial並沒有被賦值,函數體內的"factorial"指的並不是被賦值的那個變量。這時函數內部的factorial可能指的是外部命名空間中的可能存在的名字叫factorial的變量。為了避免這種情況,可以先聲明本地變量,然後把函數賦值給這個變量,或者使用函數聲明語句語法。
語句
語句(statement)是代碼運行時的基本單元:賦值、結構控制、函數調用、變量聲明等。
一個chunk是一串代碼。它們通常可以選擇被分號隔開。chunk可以被用作匿名函數的函數體,所以在chunk里,可以聲明局部變量,接受參數和返回值。
一個block像chunk一樣,也是一串代碼。通過下面的語句可以創建一個block,do block end
。這樣可以限制變量的作用域,或者在其餘block中加入return
或者break
語句。[13]
賦值
variable-list = expression-list
變量列表(variable-list)是用逗號隔開的一系列變量,表達式列表是一個或多個表達式。所有的表達式會在被賦值之前計算,所以a, b = b, a
會交換a和b的值。
局部變量聲明
local variable-list
local variable-list = expression-list
局部變量可以在一個block或者chunk中聲明。上面的第一種聲明形式,僅僅聲明了變量,但並沒有賦值,所以它們的值都是nil。第二種聲明形式對變量進行了賦值。
需要注意的是,局部變量在聲明之後才可見(visible)。所以像這樣的聲明 local x = x
,聲明了一個局部變量叫x,給這個變量賦的值是外部命名空間的x的值。在包含這個局部變量的代碼塊結束之前,這個局部變量保持可見。
流程控制
while exp do block end
只要exp表達式是true值,就會一直重複block內的內容。
repeat block until exp
直到exp運算出來的值是true之前,不斷重複block的內容。
for name = exp1, exp2, exp3 do block end
for name = exp1, exp2 do block end
第一種for循環會聲明一個名字叫name的局部變量,這個變量的初始值是exp1,每次循環都會加exp3到這個變量,直到它大於exp2。(如果exp3是負數正好相反)。exp3可以被省略,相當於是1。如果exp1,exp2,exp3其中之一是非數字值,例如nil
和false
,會拋出異常。所有的值都會被在循環開始之前提前計算。
除了變量var,limit,step不能被訪問以外,這種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
需要注意,變量name對於這個代碼塊是局部變量。如果需要在循環後使用這個變量的值,需要賦值給循環外的變量。
for var-list in expression-list do block end
第二種for循環和迭代器(iterator)函數共同使用。像第一種形式一樣,表達式只有循環開始之前會被計算一次。
除了變量func,static,var不能被訪問以外,這種for循環和下面的大體上等同。
do local func, static, var = expression-list while true do local var-list = func( static, var ) var = var1 -- ''var1'' is the first variable in ''var-list'' if var == nil then break end block end end
注意,var-list中的變量對於代碼塊來說是局部變量。如果想在循環之外使用這些變量的值,需要賦值給循環外的變量。
通常,expression-list是一個返回三個值的函數調用,如果這個迭代器函數僅僅依靠傳入的參數來寫入的話,會更高效。如果不能的話,Programming in Lua建議使用一個閉包,來返回一個表作為靜態變量,每次循環時刷新這個表的成員的值。
if exp1 then block1 elseif exp2 then block2 else block3 end
如果exp1為true,運行block1,否則,如果exp2為true時,運行block2,否則運行block3。else block3
部分可以被省略,elseif exp2 then block2
可以被省略或重複多次。
return expression-list
return語句用來從函數或者chunk(其實也是一個函數)返回值。expression-list是用逗號隔開的零個或更多個表達式。
Lua的尾調用[14]:如果expression-list包括恰好一個函數調用,這個函數調用時,當前的棧幀會被重用。這在處理調用棧的函數上有應用。例如getfenv()
和 debug.traceback()
函數。
return語句必須是block中最後一條語句。如果需要在代碼中間需要return語句,可以使用代碼塊do return end
。
break
break語句用來跳出一個while、repeat、for循環,跳過循環內後面的語句。
break語句必須是代碼塊最後一個語句。如果需要在代碼中間需要break語句,可以使用代碼塊do break end
。
函數調用作為語句
函數調用可以作為語句。這時函數僅僅因為函數調用的副作用被調用(例如mw.log()中的),返回值會被忽略。
函數聲明語句
Lua提供了語法糖,可以使函數聲明和函數實現更加自然。下面的語句等價。
-- 基本声明 function func( ''var-list'' ) ''[[#block|block]]'' end func = function ( ''var-list'' ) ''[[#block|block]]'' end
-- 本地函数声明 local function func( ''var-list'' ) ''[[#block|block]]'' end local func; func = function ( ''var-list'' ) ''[[#block|block]]'' end
-- 函数作为表的一个字段 function table.func( ''var-list'' ) ''[[#block|block]]'' end table.func = function ( ''var-list'' ) ''[[#block|block]]'' end
-- 函数作为表的一个方法 function table:func( ''var-list'' ) ''[[#block|block]]'' end table.func = function ( self, ''var-list'' ) ''[[#block|block]]'' end
注意,這裡的冒號和函數調用時的冒號,都將叫做"self"的參數加入到函數的第一個參數裡。
錯誤處理
可以通過error()和assert()來拋出(throw/raise)異常。為了捕獲(catch)異常,使用pcall() 或 xpcall()。需要注意,有些Scribunto內部異常不能在Lua代碼中捕獲。
垃圾收集
Lua自動管理內存。這意味著你無需手動管理和釋放內存。Lua通過時不時運行垃圾收集器(garbage collector),收集不再使用的對象,和只能通過弱引用來獲取的對象。所有的內存對象都會自動內存管理:表,函數,字符串等。
垃圾自動進行收集,無法被Scribunto配置。
標準庫
Lua標準庫(standard library)提供了基本服務和對性能關鍵的函數。下面只記錄了Scribunto可用的標準庫部分。
基本函數
_G
這個變量持有一個當前全局變量的引用。全局變量foo
可以通過_G.foo
訪問。注意:_G,它可以像其餘變量一樣重新分配值,像其餘的變量一樣。這時,G不再指向全局變量表。
foo = 1 mw.log( foo ) -- logs "1" _G.foo = 2 mw.log( foo ) -- logs "2" _G = {} -- G不再指向全局变量表 _G.foo = 3 mw.log( foo ) -- still logs "2"
全局變量表可以像其他的表一樣使用。
-- 调用一个函数,它的名字存储在var中 _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
被用作error的錯誤文本(text):如果是nil(或未指定),錯誤文本是"assertion failed!",如果是一個字符串或者數字,錯誤文本即為該值;否則assert本身會拋出異常。
如果v
是其他值,assert會返回,包括v
和message
在內的所有參數。
在Lua常用做法是,通過函數的返回值來判斷函數是否正常運行。如果返回值是"true"值,說明函數正常運行,未正常運行返回nil或者false作為第一個返回值,錯誤信息作為第二個返回值。錯誤檢查可以通過函數調用來實現。
-- 下面的代码,不会检查函数是否运行错误 local result1, result2, etc = func( ... ) -- 下面的代码和上面的相同,但是会检查运行错误 local result1, result2, etc = assert( func( ... ) )
error
error( message, level )
提交一個異常,它的文本是message
。
error
通常會加入錯誤拋出地點的一些信息。如果level
是1或者被省略,那樣這個信息是error
自己的位置。2是,信息是一個函數的位置,這個函數拋出了異常。以此類推。[15]level
為0,省略位置信息。
getfenv
getfenv( f )
這個函數可能會失效,取決於allowEnvFuncs
工程配置。
返回一個全局表(global variable table)。f
用來指定:
- 如果是1,nil,或者被省略,返回
getfenv
函數的變量環境(environment)。通常這個結果和_G相同。 - 2-10返回在調用棧高處的函數的變量環境。例如,2返回的是調用這個函數的函數的變量環境,3返回的是調用調用這個函數的函數的函數的變量環境,以此類推。如果這個值比調用棧的函數個數多,或者目標棧高度通過尾調用返回值,會拋出異常。
- 如果傳入值是個函數,那麼會返回該函數的變量環境。
標準庫函數和Scribunto庫函數中的函數的運行環境首刀保護。使用getfenv
函數獲取它們的環境會返回nil。
getmetatable
getmetatable( table )
如果元表已有__metatable
欄位,將會返回這個值,而不是這個表的元表。
ipairs
ipairs( t )
返回這樣的值:迭代器函數,表t,和0。可以在for
循環中按照以下方式使用。
for i, v in ipairs( t ) do block end
這會迭代地返回序對(1 , t[1] ) , ( 2 , t[2] )...直到t[i]為nil。
如果一個表提供了__pairs
元方法,這個標準函數的行為會被重載。如果這個元方法存在的話,調用這個函數的三個返回值將會是__ipairs( t )
。
next
next( table, key )
這個函數允許遍歷(traversal)表的鍵。如果key
的值為0或者未指定,返回這個表的「第一個」鍵和它的值,否則,返回「下一個」鍵和它的值。如果所有的鍵都被迭代過,返回nil。通過表達式next( t ) == nil
可以判斷一個表是否為空表。
注意,一個表的鍵按照什麼順序返回並沒有指定。即使這個表的鍵都是數字。如果想按照數字順序遍歷表,使用numerical for 或 ipairs。
如果在使用next遍歷時,給原本不存在的鍵賦值時,會產生未定義行為。但是,給一個已存在的鍵賦值,即使給賦nil值,也是允許的。
pairs
pairs( t )
返回3個值。一個迭代函數(next或類似功能的函數),表t
,和nil。這個函數可以在for循環使用。
for k, v in pairs( t ) do -- process each key-value pair end
這個函數會迭代表t
所有的鍵值對,像next一樣。對於在迭代時對表的修改的限制,見next的文檔。
元方法__pairs可以改變這個函數的行為。如果這個元方法存在,調用pairs函數的三個返回值是__pairs( t )
。
pcall
pcall( f, ... )
在保護模式(protected mode)調用函數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
是字符串'#',返回...
中參數的個數。[16]
或者說,不考慮...
中的存在nil值的話,select
大體上相當於下面的代碼。(下面的代碼中,如果...
存在nil值可能導致的問題,見#和unpack)。
function select( index, ... ) local t = { ... } if index == '#' then return #t else return unpack( t, index ) end end
setmetatable
setmetatable( table, metatable )
給一個表設置元表,metatable
可以為空,但是必須明確改名。
如果當前元表有__metatable欄位,setmetatable
會拋出異常。
tonumber
tonumber( value, base )
嘗試將value
轉為為數字。如果是數字或者可以轉化為數字的字符串,那麼tonumber
返回這個數字,否則返回nil。
可選參數base
(默認為10)指定進制。base
可以是2到36之間的數字,如果base大於10,字母'A'(大小寫均可)表示10,'B'表示11,'Z'表示35,以此類推。
十進位下,value
可以小數部分,或用E記號表示,十六進位下,可以有前綴"0x"。在其他進制下,只能接受無符號整數。
tostring
tostring( value )
將value
轉化為字符串。對於如何進行轉化,詳見Data types。
元方法__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]
。如果參數是nil或未指定,i
默認為1,j
默認為#table
。
注意,如果table
不是序列,或者j
為nil或未指定,返回結果可能不確定,詳見長度運算符。
xpcall
xpcall( f, errhandler )
這個函數和pcall
很相似,只是會在異常信息返回之前,傳遞給errhandler
函數。
這個函數大致相當於下面的 偽碼。
function xpcall( f, errhandler ) try return true, f() catch ( message ) message = errhandler( message ) return false, message end end
Debug library
debug.traceback
debug.traceback( message, level )
這個函數返回一個字符串,對函數的調用棧幀進行回溯。可選的message字符串會被加到輸出結果最前面。可選的level
數字指定,開始回溯的棧高度。
Math library
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 )
返回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>e^x</math>的值。
math.floor
math.floor( x )
返回小於等於x
的最大整數(向下取整)。
math.fmod
math.fmod( x, y )
取余:返回x
除以y
後,向0方向取餘數的結果。例如,math.fmod( 10, 3 )
結果是1
。[17]
math.frexp
math.frexp( x )
返回滿足以下條件的m
和e
值。
- 如果
x
非0有窮,<math>x = m \times 2*e</math>,其中,e
是整數,m
的絕對值在<math>[0.5, 1)</math>範圍內。 - 如果
x
為0,m
和e
均為0。 - 如果
x
是NaN或無窮大,m
isx
ande
未指定。
math.huge
這個值表示正無窮大,它大於等於其餘數值。
math.ldexp
math.ldexp( m, e )
返回 <math>m \times 2^e</math> (e
應為整數).
math.log
math.log( x )
返回 x
的自然對數值。
math.log10
math.log10( x )
返回以10為底的 x
的對數值。
math.max
math.max( x, ... )
返回傳入參數的最大值。
傳入NaN的行為不確定。當前[18],如果第一個參數x
是NaN,會返回NaN,其餘的NaN會忽略。
math.min
math.min( x, ... )
返回傳入參數的最小值。
傳入NaN的行為不確定。當前(同上),如果第一個參數x
是NaN,會返回NaN,其餘的NaN會忽略。
math.modf
math.modf( x )
返回兩個值,分別是x
的整數部分和小數部分。例如,math.modf( 1.25 )
結果是1, 0.25
。
math.pi
<math>\pi</math>的值。
math.pow
math.pow( x, y )
相當於x^y
.
math.rad
math.rad( x )
將角度值x
轉化為弧度制。
math.random
math.random( m, n )
返回一個偽隨機數。
m
和n
可以省略,但是它們必須是整數值。
- 如果沒有參數,返回<math>[0,1)</math>範圍內的實數。
- 只有一個參數,返回<math>[1,m]</math>範圍內的整數。
- 如果兩個參數,返回<math>[m,n]</math>範圍內的整數。
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
的雙曲正切值。
Operating system library
os.clock
os.clock()
返回這個程序使用CPU的大致時間,以秒為單位。[19]
os.date
os.date( format, time )
- Language library's formatDate 可以用在更加全面的日期格式。
返回一個包括時間和日期的字符串或表,通過format
確定格式。如果format
被省略或為nil,默認為"%c"。
這個函數會對給定的time
,進行格式轉化。如果沒有給定,會轉化當前時間。
如果format
以'!'開頭,時間會轉化為UTC而不是用戶所在時區的時間。如果format
是字符串"*t",會返回右以下欄位的表。
- year (完整年份)
- month (1–12)
- day (1–31)
- hour (0–23)
- min (0–59)
- sec (0–60,閏秒時為60)
- wday (星期,星期日為1)
- yday (這一年的第幾天)
- isdst (一個布爾變量,是否為夏令時。如果信息不可用本欄位可能不存在)
如果format
不是"*t",這個函數會和C語言函數strftime遵循同樣規則返回。[20]
os.difftime
os.difftime( t2, t1 )
返回從t1
到t2
兩個時間之間的秒數。[21]
os.time
os.time( table )
返回一個數字表示當前時間的值。
如果該函數不帶參數調用,返回當前時間。如果傳入的是一個表,會返回這個表表示的時間。這個表必須有欄位"year","month"和"day",也可以包括欄位"hour"(默認為12),"min"(默認為0),"sec"(默認為0)和"isdst"。
Package library
require
require( modulename )
加載(load)指定的包(package)。
首先,這個函數會在package.loaded[modulename]
中尋找這個包,來判斷這個包是否已被加載。如果已被加載,返回package.loaded[modulename]
。
否則,會調用package.loaders
序列中的每一個加載器(loader),試圖找到可以加載這個包的加載器,如果找到了加載器,會調用這個加載器,。加載器的返回值會保存在package.loaded[modulename]
中,並被返回。
關於加載器的信息,詳見package.loaders
。
例如,你有一個包"Module:Giving"包括以下內容。
local p = {} p.someDataValue = 'Hello!' return p
你可以通過下面的代碼加載這個包:
local giving = require( "Module:Giving" ) local value = giving.someDataValue -- value会被赋值 'Hello!'
package.loaded
這個表保存已被加載的包。鍵為包的名字,值為包被加載時的返回值。
package.loaders
這個表保存用來加載包的搜索器函數(searcher function)的序列。每個搜索器被調用時僅傳入一個參數,是被加載的包的名字。如果包被找到,搜索器必須返回一個可用來加載這個包的函數,並把會被require會返回的值返回。否則,返回nil。
Scribunto提供兩個搜索器:
- 在
package.preload[modulename]
搜索加載器函數。 - 在Scribunto提供的模塊中搜索,然後會在Module: 命名空間中查找。必須帶有"Module:"前綴。
注意,Lua標準中的加載器未被 提供。
package.preload
這個表提供加載器函數,它們被Scribuntopackage.loaders第一個搜索器使用。
package.seeall
package.seeall( table )
將表table
的__index元方法設定為_G。
String library
在所有的字符串函數中,第一個字符在位置 1,而不是像C,PHP,JavaScript一樣在位置0.下標可以為負數,表示從字符串最後一個字符倒數。位置 -1表示倒數第一個字符,-2是倒數第二個。
Warning: string library假定字符串編碼為1個字節,不應用來處理Unicode字符。如果處理Unicode字符,使用Scribunto Ustring library中的方法。
部分函數可能需要#Patterns為前置知識。
string.byte
string.byte( s, i, j )
將字符串看作字節的數組,返回字節值s[i]
, s[i+1]
, ···, s[j]
。i
的默認值為 1;j的默認值為j
is i
。和mw.ustring.byte()相似。
string.char
string.char( ... )
接受0個或更多個整數。返回一個長度是參數個數的字符串,對應的字符的字節值為對應的參數。
local value = string.char( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21 ) -- value的值为'Hello!'
使用Unicode碼點(codepoint)而不是字節值的類似的函數詳見mw.ustring.char()。
string.find
string.find( s, pattern, init, plain )
尋找字符串s
中第一個與匹配模式匹配的匹配。如果找到了匹配,函數find
返回 s
中匹配起點和終點的下標。否則,返回nil。如果匹配中有捕獲(capture),成功匹配後也會返回捕獲值。[22]
可選參數init
指定從哪裡開始查找,這個值可以為負數,默認值為 1。可選參數plain
如果為true,會關閉模式匹配機制,這時這個函數僅僅是"尋找子串",pattern
中不會有字符會被當做"魔法字符"。[23]
注意,如果plain
被給定,那麼init
也需要被給定。
對於Ustring patterns 中類似的函數,參見mw.ustring.find()。在那裡,init
將是字符串下標,而不是字節下標。
string.format
string.format( formatstring, ... )
返回一個字符串。這個函數將其可變個的參數,按照第一個參數(必須是字符串)的指示,進行格式化處理。
這個函數格式化字符串使用printf
格式化說明符[24],但是有以下限制。
- 可用 '-', '+', ' ', '#'和 '0'.
- Integer field widths up to 99 are supported. '*' is not supported.
- Integer precisions up to 99 are supported. '*' is not supported.
- 長度修飾符不支持。
- 支持的轉化說明符是'c', 'd', 'i', 'o', 'u', 'x', 'X', 'e', 'E', 'f', 'g', 'G', 's', '%', 以及不再標準的 'q'.
- 位置說明符(例如"%2$s")不支持。
長度修飾符 'q' 類似於 's',可以轉化字符串為,Lua解釋器可以安全讀取的形式:字符串會在雙引號間寫入,所有的雙引號,換行符,嵌入的0和反斜槓會被轉義。
字符串和數字,按照數據類型轉化。其餘類型不會自動轉化為字符串。包含NUL('\0')的字符串(字節碼0)不會被正確處理。[25]
string.gmatch
string.gmatch( s, pattern )
返回一個迭代器函數,每次調用時,返回s
中,pattern
中的下一個捕獲。如果pattern
中沒有捕獲,那麼每次調用會返回整個匹配。
對於這個函數,在匹配模式中的最開始的'^
'不會解釋為魔法字符,而會被看作為普通字符,因為這樣會避免迭代。
對於匹配模式是真正按照描述的那樣工作的,參見Ustring patterns章節中的mw.ustring.gmatch()。
string.gsub
string.gsub( s, pattern, repl, n )
返回s
的複製品,其中所有的(前n個,如果給定n的話)與pattern
匹配的匹配會被替換為repl
,它可以是一個字符串,表,或者函數。gsub
也會把匹配總數作為第二個參數返回。
如果repl
是一個字符串,則會把這個字符串用來替換。repl
中, %
作為轉義字符。符合格式%n
的repl
子串,其中n是從1到9的數字,表示第n個被捕獲的子串。%0
表示整個匹配,%%
表示單個 %
。
如果repl
是一個表,會在每次匹配時訪問這個表,將第一個捕獲作為鍵。如果匹配模式中沒有捕獲,則會把整個匹配用作鍵。
如果repl
是一個函數,這個函數會每次匹配時調用,所有的捕獲會按照順序作為參數傳入。如果匹配模式沒有捕獲,會將整個匹配作為唯一的參數傳入。
如果repl
的返回值是一個字符串或者數,會被用來字符串替換,否則,如果是false或nil,並不會發生替換,也就是說,原本的匹配會留在字符串。
對於Ustring patterns中類似函數,參見mw.ustring.gsub()。
string.len
string.len( s )
按照字節返回字符串的長度。這個函數不會被ASCII NUL字符干擾。相當於code style="white-space:nowrap">#s。
對於類似功能,使用Unicode碼點而不是字節的函數,參見 mw.ustring.len() 。
string.lower
string.lower( s )
返回字符串的複製,其中,其中所有的ASCII大寫字母會被轉化為小寫字母。其餘字符不會被轉化。
對於類似功能的函數,詳見mw.ustring.lower() ,其中Unicode定義的所有的大寫字母都會轉化為小寫字母。
string.match
string.match( s, pattern, init )
尋找字符串中第一個匹配pattern
的陪陪。如果找到了一個,返回這個匹配的捕獲。否則返回nil。如果匹配中無捕獲,則返回整個匹配。
可選參數init
指定從哪裡開始查找。這個值默認為1,可以為負數。
對於Ustring patterns中相似函數,詳見mw.ustring.match()。其中init
下標是按照字符而不是字節計算。
string.rep
string.rep( s, n )
返回一個字符串,是n
個s
連接在一起。與mw.ustring.rep()相同。
string.reverse
string.reverse( s )
返回一個字符串,是s
按字節倒轉。
string.sub
string.sub( s, i, j )
返回一個s
的子串,從位置i
開始j
結束。i
和j
都可以是負數。如果j
是nil或被省略,會以字符串末尾結束。
可以用string.sub(s,1,j)
,返回s
長度為j
的前綴。string.sub(s, -i)
返回長度為i
的s
的後綴。
對於相似函數,詳見mw.ustring.sub()。其中下標馬昭字符而不是字節計算。
string.upper
string.upper( s )
返回字符串的複製,其中,其中所有的ASCII小寫字母會被轉化為大寫字母。其餘字符不會被轉化。
對於類似功能的函數,詳見 mw.ustring.upper(),其中Unicode定義的所有的小寫字母都會轉化為大寫字母。
Patterns (匹配模式)
Lua的匹配和正則表達式很像,但是並不等同。尤其是注意Lua的匹配在以下方面和正則表達式和PCRE[26] 的不同。
- 轉義字符是百分號(
%
), 而不是右斜槓(\
)。 - 圓點(
.
) 匹配所有的字符,包括換行符。 - 區分大小寫。
- 不支持豎線(
|
運算符). - 量詞字符(quantifier) (
*
,+
,?
, 和-
) 只能用於匹配單個字符或字符類(character class),不能用來捕獲組。 - 唯一非貪婪的量詞字符是
-
, 相當於PCRE的*?
, - 沒有廣義有限量詞,例如 PCRE中的
{n,m}
。 - 僅有的零寬度斷言是
^
,$
, 和%f[set]
。例如PCRE的\b
或者(?=···)
不存在。 - 匹配模式不識別類似於'\ddd'的轉義字符。 然而,因為匹配模式是一個字符串,創建匹配模式字符串是,這種轉義可能被按照字面意思處理。
也要注意,匹配模式中不能包括嵌入的零字節(ASCII NUL,\0
),應使用%z
。
對於相似的使用Unicode碼的匹配模式匹配函數,詳見Ustring patterns。
Character class
字符類(character class)用來表示一系列字符。允許用以下組合來描述一個字符類。
- 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
: All characters not in%u
.%W
: 所有不在%w
中的字符。%X
: 所有不在%x
中的字符。%Z
: 所有不在%z
中的字符。%x
: (x是非字母數字字符)表示字符 x。這是用來轉義魔法字符的方式。任何標點字符,甚至是非魔法字符,都可以和'%
'結合,在匹配模式中表示自己本身。[set]
: 表示一個字符類,其中包括set中所有字符的組合。可以通過'-
'分隔字符末尾來指定一系列字符。上面提到的%x
類也可以作為set的一部分。其餘的字符指代它們本身。例如,[%w_]
(或[_%w]
)表示所有的數字字母加上下劃線,[0-7]
表示所有八進位數字(0-7),[0-7%l%-]
表示八進位數字,下劃線和'-
' 字符。範圍和類的交互未定義,也就是說,[%a-z]
或[a-%%]
這樣的匹配模式無意義。[^set]
:表示set的補集。
Pattern items
一個匹配模式項(pattern item)可以是:
- 一個字符類,匹配類中的單個字符。
- 字符類後接'
*
',匹配出現0次或更多次的字符。總是匹配更長的序列。 - 字符類後接'
+
',匹配出現1次或更多次的字符。總是匹配更長的序列。 - 字符串後接'
-
',匹配出現0次或更多次的字符。總是匹配更短的序列,和'*
'不同。 - 字符串後接'
?
',匹配出現0次或一次的字符。 %n
,其中n是0到9的數字。匹配和第n個捕獲匹配的子串(見下文)。%bxy
, 其中x和y是兩個不同的字符。匹配以x開始以y結束,且平衡(balanced)的字符串。平衡的意思是,如果用一個計數器,從左到右遍歷字符串,每次碰到x+1,每次碰到y-1,那麼字符串會在計數器為0的那個y截止。例如,%b()
匹配平衡括號的表達式。%f[set]
,邊界匹配。它會匹配一個在任意位置的空字符串,它的下一個字符屬於set,前一個字符串不屬於set。集合set如前所述。目標字符串的最開始和最末尾的位置也可能會被匹配,此時將它們看作字符 '\0'。
在Lua 5.1,已經出現了frontier pattern,但是沒有被Lua文檔記載,在5.2才被官方記載。 Lua 5.2.1 和5.1.0中的實現相同。
Pattern
匹配模式(pattern)是匹配模式項的序列。
匹配模式最前面的'^
'匹配目標字符串的最開始,匹配模式最後面的'$
'匹配目標字符串的最尾端。出現在其餘位置的'^
'和'$
無特殊含義,僅表示它們本身。
Captures
一個匹配模式可以包括被包含在括號之內的子匹配模式,或者叫做捕獲(capture)。匹配成功時,目標字符串中與捕獲匹配的字串,會被儲存(捕獲),供將來使用。捕獲按照它們的左括號來編號,例如,在匹配(a*(.)%w(%s*))
中,匹配a*(.)%w(%s*)
的字符串部分會作為第一個捕獲存儲(具有編號 1),匹配.
的作為第二個捕獲,具有編號 2,匹配%s*
作為第三個匹配。
捕獲的引用可以出現在匹配模式本身裡面,指代在先前被匹配的文檔。例如,([a-z])%1
會匹配一對相同的小寫字母,([a-z])([a-z])([a-z])[a-z]%3%2%1
匹配長度為7的回文字符串。
特殊情況,空白捕獲()
捕獲的是當前字符串位置(一個數字)。例如,如果用匹配模式()aa()
匹配字符串flaaap
,會有兩個捕獲:3 和 5。
Table library
table library中的大多數函數假定傳入的表是一個序列。
不推薦使用函數table.foreach()
,table.foreachi()
,table.getn()
,儘管它們可能可用。推薦使用for循環與 pairs()或ipairs()結合的方式,或者長度運算符。
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 )
將value
插入到table
中的pos
位置,這個位置後面的元素向後順延。pos
的默認值是表的長度+1,因此調用table.insert(t, x)
會在表t
的最後插入x
。
下標大於#table
的元素會被移動。如果表不是數組的可能後果詳見長度運算符。
table.maxn
table.maxn( table )
返回表中最大的數字下標。如果表中沒有正數字下標,返回0.
這個函數會遍歷整個表。大致相當於以下代碼。
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 )
返回表中最後一個元素
下標大於#table
的元素會被移動。如果表不是數組的可能後果詳見長度運算符。
table.sort
table.sort( table, comp )
將表中從table[1]
到table[#table]
按照給定排序方法排序。如果指定了comp
,那麼它一定是接受兩個表作為參數的函數,如果第一個值比第二個值小,返回true。(這樣排序過後,not comp(a[i+1],a[i])
會為true)。如果comp
未指定,會使用Lua運算符<
。
這個排序算法並不穩定。也就是說,同樣大小的兩個元素,在排序後相對位置可能會被破壞。
Scribunto libraries
所有的Scribunto libraries都位於表mw
中。
Base functions
mw.addWarning
mw.addWarning( text )
當預覽編輯時,會在預覽頁面上方增加報錯。text
被解析為維基代碼。
mw.allToString
mw.allToString( ... )
對於所有參數調用tostring(),然後把它們使用tab相連。
mw.clone
mw.clone( value )
創建一個值的深度複製(deep copy)。所有的表(和它們的元表)被重建,但是函數仍然會共享。
mw.getCurrentFrame
mw.getCurrentFrame()
返回當前框架對象,通常是來自於最近的#invoke
的框架對象。
mw.incrementExpensiveFunctionCount
mw.incrementExpensiveFunctionCount()
在"高性能解析函數"計數上加1,如果超出限制拋出異常。詳見$wgExpensiveParserFunctionLimit|$wgExpensiveParserFunctionLimit
。
mw.isSubsting
mw.isSubsting()
如果#invoke
被替換引用了,返回true,否則返回false。對於替換引用與未替換引用的討論,詳見Returning text。引用錯誤:無效的 <ref>
標籤,沒有名稱的參考必須要有內容
mw.loadData
mw.loadData( module )
有時一個模塊需要很大的數據表,例如,一個用來轉換度量單位的通用模塊,可能需要一個大表,包括單位及其轉換係數。有時這些模塊可能在同一個頁面使用多次。每次{{#invoke:}}
解析這個大表可能會大量時間。為了避免這個問題,提供了函數mw.loadData()
。
mw.loadData
和require()
很相似,但是有以下的不同:
- 被加載模塊並不是每調用一次
{{#invoke:}}
被解析,而是僅在每次加載頁面時。
- 被加載模塊不會被記錄在
package.loaded
。
- 從被加載模塊返回的值必須是表,不支持其餘類型。
- 被返回的表(和表中表)只能包括布爾類型,數字,字符串,或者其餘表。不允許其餘數據類型,包括函數。
- 返回的表(和表中表)不可以有 元表。
- 表中所有鍵必須是布爾類型,數字和字符串。
- 事實上,
mw.loadData()
返回的表具有一個元方法,這個遠方吧提供對模塊返回的表的只讀訪問。因為表中不提直接包含數據,所以pairs()
和ipairs()
可以正常使用,但是其餘方法,例如#value
,next()
和 Table library中的函數,不會正常使用。
假設上文提到的單位轉換模塊的代碼在模塊"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(),然後把得到的字符串附加到日誌緩衝區(log buffer)。
在debug控制台下,函數print()
可看做是這個函數的別名。
mw.logObject
mw.logObject( object )
mw.logObject( object, prefix )
調用函數mw.dumpObject(),然後將結果附加到日誌緩衝區。如果給定了prefix
,它會被附加到序列化字符串的前面(日誌文檔將會是"prefix = object-string")。
Frame object
框架對象(frame object,或幀對象),是一個對{{#invoke:}}
傳遞的參數,和解析器的接口。
需要注意,沒有frame library。也沒有名字為frame
的全局變量。框架對象通常包含從{{#invoke:}}
傳入的參數,可以被mw.getCurrentFrame()
函數獲取。
frame.args
一個表,可以獲取被傳入框架的參數。例如,下面是一個從維基文本調用的模塊。
{{#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 argument)會將名字和參數前後兩端的空白部分去除,然後傳入Lua,匿名參數(unnamed argument)會保留空白部分。
由於性能原因,frame.args
並不是直接包含所有傳入參數的表,而是使用的元表。需要時,從MediaWiki請求獲取參數值。這意味著大多數用於表的方法不能正常使用,包括#frame.args
, next( frame.args )
, 和Table library中的函數。
如果#invoke中包含了預處理語句,例如模板調用、三層括號參數,它們在傳遞給Lua時不會被展開,除非Lua請求獲得它們的值。如果#invoke的參數包括一些特定的XML標記,例如<pre>
, <nowiki>
, <gallery>
和 <ref>
,這些標籤(tag)會被轉化為條狀標記(strip marker)[27] ,在被#invoke返回後轉化為HTML。
frame:callParserFunction
frame:callParserFunction( name, args )
frame:callParserFunction( name, ... )
frame:callParserFunction{ name = string, args = table }
- 注意 命名參數的使用.
調用解析函數,返回一個字符串。本地Lua函數或Scribunto library函數應儘可能使用這個接口。
下面的調用大致相當於被注釋的維基文本。
-- {{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' } }
注意,和 frame:expandTemplate()相同,函數名字和參數在傳遞給處理器函數時不會被預處理。
frame:expandTemplate
frame:expandTemplate{ title = title, args = table }
- 注意 命名參數的使用。
這是嵌入包含。調用
frame:expandTemplate{ title = 'template', args = { 'arg1', 'arg2', name = 'arg3' } }
大致相當於維基文本{{template|arg1|arg2|name=arg3}}
。作為嵌入包含,如果傳入標題參數(title)不包含命名空間前綴(namespace prefix),會默認命名空間為Template:。
注意,標題和參數在傳入末班之前不會被預處理。
-- This is roughly equivalent to wikitext like {{template|{{!}}}} frame:expandTemplate{ title = 'template', args = { '|' } } -- This is roughly equivalent to wikitext like {{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() 函數,後者的name參數為
'#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:}}
創建的框架對象調用該函數時,返回一個框架對象,這個框架對象在頁面上調用了{{#invoke:}}
。如果被前文提到的被返回對象調用該函數,返回nil。
例如,如果模板{{Example}}
包括代碼{{#invoke:ModuleName}}
,一個頁面嵌入了此模板,並傳入此模板參數({{Example|arg1|arg2}}
),在Module:ModuleName中調用 mw.getCurrentFrame():getParent().args[1], mw.getCurrentFrame():getParent().args[2]
會返回"arg1", "arg2"
。
frame:getTitle
frame:getTitle()
將與此框架關聯的標題作為字符串返回。對於被{{#invoke:}}
創建的框架,返回值是被調用的模塊的標題。
frame:newChild
frame:newChild{ title = title, args = table }
- 注意 命名參數的使用.
生成一個新框架對象 。這是當前框架的子框架(child)有可選的參數和標題。
這主要在debug控制台下,用來測試被{{#invoke:}}
調用的測試函數。一次性創建的框架數被限制。
frame:preprocess
frame:preprocess( string )
frame:preprocess{ text = string }
這個函數用來在框架中增加維基文本,例如模板、解析器函數,和類似於{{{1}}}
這類的參數。一些特殊的,用XML格式寫的標籤(tag),例如<pre>
, <nowiki>
, <gallery>
and <ref>
等,會被換為[Special:MyLanguage/strip marker|條狀標記]]" — ,在被#invoke返回後轉化為HTML。
如果你想增加單個模板,使用frame:expandTemplate
,而不是嘗試用構造一個維基文本字符串,傳入到此方法之中。在參數包含pipe character或者其餘維基標記時,前者更快,且出現錯誤傾向更少。
如果你想增加一個解析函數,因為和上面同樣的原因,請使用frame:callParserFunction
。
frame:getArgument
frame:getArgument( arg )
frame:getArgument{ name = arg }
對於指定的參數,獲取一個對象(object)。如果未給定參數,返回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 )
相同。這個函數考慮到向後兼容性被包括在庫中。
Hash library
mw.hash.hashValue
mw.hash.hashValue( algo, value )
使用指定的算法哈希(hash,或散列)一個字符串值。合法的算法可以通過mw.hash.listAlgorithms()獲取。引用錯誤:無效的 <ref>
標籤,沒有名稱的參考必須要有內容
mw.hash.listAlgorithms
mw.hash.listAlgorithms()
返回一個支持的哈希算法序列,用作mw.hash.hashValue()中。
HTML library
mw.html
是一個從Lua創建複雜HTML代碼的便利接口。一個mw.html對象可以用mw.html.create
創建。
下面文檔中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 )
創建一個HTML對象,包括tagName
類型的HTML元素。為了創建空mw.html對象,也可以傳遞空字符串或者nil作為tagName
。
args
可以是具有以下鍵的表。
args.selfClosing
: 強制當前標籤是自閉合[28] 的,即使mw.html不認為它是自閉合的。
args.parent
: 當前html實例的父對象(用於內部使用)。
mw.html:node
html:node( builder )
在當前mw.html實例中加入一個子對象節點(builder
)。如果傳入nil參數,則無操作(no-op/no operation)。builder
子節點是一個表示html元素的字符串。
mw.html:wikitext
html:wikitext( ... )
追加一組沒有確定數量的維基文本字符串到對象中。
注意追加會在遇到第一個nil參數時停止。
mw.html:newline
html:newline()
在mw.html對象中加入新行。
mw.html:tag
html:tag( tagName, args )
在給定的tagName
中加入新子節點,返回一個mw.html實例代表新節點。args
參數和mw.html.create
中的參數一樣。
mw.html:attr
html:attr( name, value )
html:attr( table )
以name
和value
作為名稱和值為對象設置HTML屬性。此外擁有 名稱->值 對的屬性表也可以傳入。 在第一種形式中,value為nil會導致已經設置的name屬性被撤掉。
mw.html:getAttr
html:getAttr( name )
獲取先前使用html:attr()
和給定的名字設定過的對象的屬性值。
mw.html:addClass
html:addClass( class )
給節點的類屬性增加一個類名。如果傳入的是nil,則無操作。
mw.html:css
html:css( name, value )
html:css( table )
以name
和value
作為名稱和值為對象設置HTML屬性。此外擁有 名稱->值 對的屬性表也可以傳入。在第一種形式中,value為nil會導致已經設置的name屬性被撤掉。
mw.html:cssText
html:cssText( css )
增加純css
文本給節點的style屬性。如果傳入nil參數,則無操作。
mw.html:done
html:done()
返回創建當前節點的父節點。像jQuery.end一樣,這是一個很方便的函數,允許將多個子節點的創建連結到一條語句中。
mw.html:allDone
html:allDone()
類似於 html:done()
, 但是會回溯到樹節點的根部,將其返回。
Language library
語言代碼詳見 language code。[29] 許多MediaWiki的語言代碼和 IETF language tags類似,但是並不是所有的維基語言代碼都是IETF標籤,反之亦然。
下面文檔中mw.language.name
在全局庫(表)mw.language
中可用; mw.language:name
和 lang:name
是語言對象(language object)的方法。(詳見mw.language.new
或 mw.language.getContentLanguage
)。
翻譯者梳理。一個語言代碼是:
- 合法的(valid):語言代碼合乎語法即可,無論這個語言是否存在。在mw.language.isValidCode返回true。
- 合法內置代碼(be valid built-in code):1.是合法的。2.僅包含ASCII字母、數字和連字符,且至少兩個字符長度。在mw.language.isValidCode返回true。
- 被支持的(supported):1.是合法的。2.不包括大寫字母。3.在當前運行MediaWiki版本中有信息文件(message file)。在mw.language.isSupportedLanguage返回true。
- 已知的(known):1.合法內置代碼。2.在mw.language.fetchLanguageNames返回非空字符串。在mw.language.isKnownLanguageTag中返回true。
mw.language.fetchLanguageName
mw.language.fetchLanguageName( code, inLanguage )
返回給定語言代碼的全名:默認為語言自稱[30] ,如果給定了inLanguage
,則轉化為給定語言。
mw.language.fetchLanguageNames
mw.language.fetchLanguageNames()
mw.language.fetchLanguageNames( inLanguage )
mw.language.fetchLanguageNames( inLanguage, include )
獲取Mediawiki已知(known)的語言的序列,返回值是一個表,將語言代碼映射到語言名稱上。
默認情況,語言名稱是語言自稱。傳入inLanguage
參數使得返回的是所有在指定語言的名字。
默認情況下,只有Mediawiki已知的語言名字會被返回,return
中傳入'all'
會返回所有可用的語言 (例如來自於 Extension:CLDR的語言)。如果傳入'mwfile'
,返回結果會僅包括這樣的語言,它們被MediaWiki內核或已安裝擴展包括的自定義信息。如果想顯示選擇默認值,可以傳遞'mw'
。
mw.language.getContentLanguage
mw.language.getContentLanguage()
mw.getContentLanguage()
返回一個維基的默認文本語言的新建對象。
mw.language.getFallbacksFor
mw.language.getFallbacksFor( code )
返回包括MediaWiki對於指定代碼的依賴語言(fallback language)的列表。[31]
mw.language.isKnownLanguageTag
mw.language.isKnownLanguageTag( code )
如果語言被MediaWiki"已知",返回true。
一個語言"已知"(be known),如果這個語言是"有效的內置代碼"(在mw.language.isValidBuiltInCode
中返回true),且在 mw.language.fetchLanguageName
中返回一個非空字符串。
mw.language.isSupportedLanguage
mw.language.isSupportedLanguage( code )
檢查該語言代碼code
是否有任何本地化可用。
一個語言"受支持"(supported),如果它是一個"合法的"(valid)[32] 語言。不包括大寫字母,並且在Mediaviki的當前運行版本存在消息文件。
有可能出現這種情況,一個語言的代碼是"受支持"(supported)但是不是"已知的"(known),(例如,mw.language.isKnownLanguageTag
返回true的語言)。也需要注意,有些代碼儘管在 mw.language.isValidBuiltInCode
返回false,但是還是"受支持"(supported)。
mw.language.isValidBuiltInCode
mw.language.isValidBuiltInCode( code )
如果語言代碼是用於MediaWiki內部自定義的有效格式,返回true。
代碼可能事實上不對應任何已知的語言。
一個語言是"合法的內置語言",如果它是一個合法的語言(在mw.language.isValidCode
中返回true),且僅包含ASCII字母數字和連字符,且至少兩個字符長度。
注意,有些語言代碼是"被支持的"(supported),儘管這個函數返回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對於指定代碼的依賴語言(fallback language)的列表。相當於mw.language.getFallbacksFor( lang:getCode() )
mw.language:isRTL
lang:isRTL()
如果該語言從右到左書寫返回true,從左到右書寫返回false。
mw.language:lc
lang:lc( s )
尊重給定的語言的特別轉化規則,將字符串轉化為小寫字母。
如果Ustring library被加載了,調用 mw.ustring.lower() 會按照mw.language.getContentLanguage():lc( s )
實現。
mw.language:lcfirst
lang:lcfirst( s )
將字符串第一個字符,按照和lang:lc()相同的方式,轉化為小寫字母。
mw.language:uc
lang:uc( s )
尊重給定的語言的特別轉化規則,將字符串轉化為大寫字母。
如果Ustring library被加載了,調用 mw.ustring.upper() 會按照mw.language.getContentLanguage():uc( s )
.實現。
mw.language:ucfirst
lang:ucfirst( s )
將字符串第一個字符,按照和 lang:uc()相同的方式,轉化為大寫字母。
mw.language:caseFold
lang:caseFold( s )
將字符串轉化為不區分大小寫的比較形式,注意這樣可能使展示的字符串無意義。
mw.language:formatNum
lang:formatNum( n )
lang:formatNum( n, options )
將給定的數字格式化,增加分組和小數點。給定123456.78,按照給定的語言和wiki設置,可能會轉化為123,456.78", "123.456,78", 甚至"١٢٣٬٤٥٦٫٧٨" 。
option
是包含可選參數的表,其中可選參數可以是:
noCommafy
: 如果設置為true,會省略分隔符,使用隔點(.
)作為小數點。數字轉化仍然存在,可能包括轉化數字分隔符。
mw.language:formatDate
lang:formatDate( format, timestamp, local )
按照給定的格式化字符串(format參數)格式化一個時間。如果省略了timestamp
,默認是當前時間。local
的值必須是一個布爾類型或者nil。如果為true,時間會按照wiki's local time格式化,而不是按照UTC。
格式化字符串和timestamp
的可用值和 來自於 Extension:ParserFunctions的#time parser function 相同。注意,在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, allowedIntervals )
將一個秒數轉化為更易讀的方式。例如,12345會轉化為 3 hours, 25 minutes and 45 seconds,作為字符串返回。
allowedIntervals
是一個可以給定的表,它的值命名了使用的時間單位,包括'millennia', 'centuries', 'decades', 'years', 'weeks', 'days', 'hours', 'minutes', 'seconds'等[33]
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 )
按照給定的數字n
,從forms
(必須是一個表)或者...
中選擇恰當的單詞變形形式。例如,在英文,你可以使用代碼n .. ' ' .. lang:plural( n, 'sock', 'socks' )
或 n .. ' ' .. lang:plural( n, { 'sock', 'socks' } )
來生成語法正確的文本,1 sock或200 socks。
序列中需要的值依照不同的語言不同,細節詳見localization of magic words 和 translatewiki's FAQ on PLURAL。
mw.language:convertGrammar
lang:convertGrammar( word, case )
lang:grammar( case, word )
- 注意兩個函數中,不同的參數順序。
convertGrammar
matches the order of the method of the same name on MediaWiki's Language object, while grammar
matches the order of the parser function of the same name, documented at Special:MyLanguage/Help:Magic words#Localisation.
按照給定的屈折代碼case
,返回word
的正確屈折變化[34]形式。
可用的word
或case
值依照不同的語言不同,細節詳見Special:MyLanguage/Help:Magic words#Localisation 和 translatewiki:Grammar
mw.language:gender
lang:gender( what, masculine, feminine, neutral )
lang:gender( what, { masculine, feminine, neutral } )
按照what
選擇對應的性[35],可以是"male","female"或一個註冊用戶名。
mw.language:getArrow
lang:getArrow( direction )
按照direction
返回一個Unicode箭頭字符。
- forwards: "→"或 "←",按照該語言的方向性(directionality)。
- backwards:"←" 或 "→", 按照該語言的方向性。
- left: "←"
- right: "→"
- up: "↑"
- down: "↓"
mw.language:getDir
lang:getDir()
按照該語言的方向性,返回"ltr"或"rtl"。
mw.language:getDirMark
lang:getDirMark( opposite )
按照該語言的方向性和opposite
的true或false,返回一個包括 U+200E (從左到右標記)或 U+200F (從右到左標誌)的字符串。
mw.language:getDirMarkEntity
lang:getDirMarkEntity( opposite )
按照該語言的方向性和opposite
的true或false,返回 "‎" 或 "‏"。
mw.language:getDurationIntervals
lang:getDurationIntervals( seconds )
lang:getDurationIntervals( seconds, allowedIntervals )
將一個秒數轉化為更易讀的方式。例如,12345會轉化為 3 hours, 25 minutes and 45 seconds。返回一個表,從時間單位名字到數字的映射。
allowedIntervals
是一個可以給定的表,它的值命名了使用的時間單位,包括'millennia', 'centuries', 'decades', 'years', 'weeks', 'days', 'hours', 'minutes', 'seconds'等。
Message library
這個庫是本地化消息(message)和MediaWiki命名空間的接口。
下面文檔中mw.message.name
在全局庫(表)mw.message
中可用,函數mw.message:name
和 msg:name
是消息對象的方法(詳見 mw.message.new
)。
mw.message.new
mw.message.new( key, ... )
對於給定的消息key
,創建一個新的消息對象(message object)。
該消息對象沒有屬性,但是有下文所述方法。
mw.message.newFallbackSequence
mw.message.newFallbackSequence( ... )
按照給定的消息創建新的消息對象。(會使用參數中第一個存在的消息對象)。
該消息對象沒有屬性,但是有下文所述方法。
mw.message.newRawMessage
mw.message.newRawMessage( msg, ... )
使用給定的文本(text)直接生成一個消息對象,而不是從全局的(internationalized)消息中查找。其餘參數會傳遞給新對象的params()
方法。
該消息對象沒有屬性,但是有下文所述方法。
mw.message.rawParam
mw.message.rawParam( value )
包裝傳入的值,這樣它不會被msg:parse()
視為維基文本。
mw.message.numParam
mw.message.numParam( value )
包裝傳入的值,這樣它會準備自動按照lang:formatNum()
格式化。注意,這個函數並不會依賴Language library庫的可用與否。
mw.message.getDefaultLanguage
mw.message.getDefaultLanguage()
對於默認語言,返回一個語言對象。
mw.message:params
msg:params( ... )
msg:params( params )
在消息中加入參數,它們可以是單個參數或者一個序列表。參數必須輸數字,字符串或者被mw.message.numParam()返回的值。如果使用的是序列表,則參數在表中直接可用,使用__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()
返回一個布爾值,表明是否存在消息鍵(message key)。
mw.message:isBlank
msg:isBlank()
返回一個布爾值,表明消息鍵是否為空。如果這個消息鍵不存在或者是空字符串,返回true。
mw.message:isDisabled
msg:isDisabled()
返回一個布爾值,表明是否消息鍵是不可用的。如果消息鍵不可用或者是空字符串或是字符串"-",返回true。
Site library
mw.site.currentVersion
一個保存當前MediaWiki版本的字符串。
mw.site.scriptPath
$wgScriptPath|$wgScriptPath
的值。
mw.site.server
$wgServer|$wgServer
的值。
mw.site.siteName
$wgSitename|$wgSitename
的值。
mw.site.stylePath
$wgStylePath|$wgStylePath
的值。
mw.site.namespaces
是一個來自於全部命名空間的表,按照數字索引。
可用數據為:[36]
- id: 名字空間編號.
- name: 本地名字空間名字.
- canonicalName: 規範名字空間。[37]
- displayName: 用於顯示在0名字空間的名字(因為這個名字通常是空白字符串)。
- hasSubpages: 在此名字空間是否有可用的子頁面。
- hasGenderDistinction: 該名字空間是否在不同的性(gender)下有多個別名。
- isCapitalized: 該名字空間下的頁面,首字母是否大寫。
- isContent: 是否這是一個內容名字空間。
- isIncludable: 該名字空間下的頁面是否可以被嵌入。
- isMovable: 該名字空間下的頁面是否可以被移動。
- isSubject: 該名字空間是否為主題(非討論)名字空間。
- 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中的文章(article)數。
- files: wiki中的文件數。
- edits: wiki中的編輯數。
- users: wiki中的用戶數。
- activeUsers: wiki中的活躍用戶數。
- admins: 屬於群組'sysop'的人數。
mw.site.stats.pagesInCategory
mw.site.stats.pagesInCategory( category, which )
- 這個函數是 性能消耗大的
獲取分類中的數據。如果which
是未指定,nil,或者"*",返回一個具有以下屬性的表。
- all: 總頁面、文件和子類別。
- subcats: 子分類的個數。
- files: 文件個數。
- pages: 頁面個數。
如果which
是上述的鍵之一,只有對應的值會被返回。
每次新類別查詢增加高性能解析函數數。
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連結(interwiki,或wiki內部連結)[38] 前綴的數據。如果filter
是字符串"local",僅返回"本地的"跨wiki前綴。如果filter
是字符串"!local",僅返回"非本地"跨wiki前綴。如果未指定filter
,所有的前綴數據都會返回。此處"本地的"前綴指的是在同一個項目的前綴。例如,在English Wikipedia,其餘語言的Wikipedia是"本地的", 而Wiktionary之類的不是。
這個函數返回的表中的鍵都是跨wiki前綴,值是一個包含以下屬性的表。
- prefix - 跨wiki前綴
- url - 該wiki指向的URL。頁面名稱作為參數$1.
- isProtocolRelative - 一個布爾值,表示這個URL是否是 協議相關。[39]
- isLocal - 該URL是否是當前項目下的。
- isCurrentWiki - 該URL是否是當前wiki下的
- isTranscludable - 使用這個跨wiki前綴的頁面是否是被嵌入[40] 的。這需要跨wiki引用,在Wikimedia 維基上不可用。
- isExtraLanguageLink - 跨維基是否列舉在
$wgExtraInterlanguageLinkPrefixes|$wgExtraInterlanguageLinkPrefixes
中
- displayText - 對於列舉在$wgExtraInterlanguageLinkPrefixes中的連結,這個是展示在跨語言連結的文檔。如果未指定則為nil。
- tooltip - 對於列舉在$wgExtraInterlanguageLinkPrefixes中的連結,這個是當用戶停留在在跨語言連結時的工具提示文本。如果未指定則為nil。
Text library
文檔庫(text library)提供String library和Ustring library中沒有的,一些常見函數。這些函數對於UTF-8字符串安全。
mw.text.decode
mw.text.decode( s )
mw.text.decode( s, decodeNamedEntities )
如果布爾值decodeNamedEntities
被省略或為false,則僅僅命名的HTML實體'<', '>', '&', '"', and ' '被識別。否則,要識別的HTML5命名實體列表將從PHP的 get_html_translation_table
函數中加載。
mw.text.encode
mw.text.encode( s )
mw.text.encode( s, charset )
將字符串中的字符替換為HTML實體。字符 '<', '>', '&', '"'和不換行空格(non-breaking space)會被轉化為恰當的命名實體。其餘的字符轉化為數字實體。
如果charset
被提供,它應該是一個,可以被放入Ustring pattern中的括號的字符串,即[set]
中的"set"。默認的charset是 '<>&"\' '
。(在最後出現的空格是不換行空格,U+00A0)
mw.text.jsonDecode
mw.text.jsonDecode( s )
mw.text.jsonDecode( s, flags )
解碼一個JSON字符串。flags
是0,或者是由mw.text.JSON_PRESERVE_KEYS
和 mw.text.JSON_TRY_FIXING
(使用+
)組合而成。
通常,JSON的以0開始計數的數組會轉化為Lua以1開始的序列。為避免此,可以傳遞mw.text.JSON_PRESERVE_KEYS
。
。並不推薦。
傳遞mw.text.JSON_TRY_FIXING
,可以放寬JSON的一些要求,例如數組或對象中沒有結尾逗號[42] (terminal comma/trailing comma)
局限:
- 如果JSON數組中包含null值,可能不會解析為Lua序列。
- JSON對象(object)會丟棄有null值的鍵。
- 不能直接分辨出,輸入的是一個JSON序列還是具有序列化鍵的對象。
- 一個從1開始的具有序列化鍵的對象,和有著相同的值的JSON數組會被解析為同一個表,儘管它們並不完全等同。除非設置了
mw.text.JSON_PRESERVE_KEYS
。
mw.text.jsonEncode
mw.text.jsonEncode( value )
mw.text.jsonEncode( value, flags )
編碼一個JSON字符串,如果傳入的值不能被編碼為JSON,會拋出異常。flags
是0,或者是由mw.text.JSON_PRESERVE_KEYS
和 mw.text.JSON_PRETTY
(使用+
)組合而成。
通常Lua以1開始的序列表會編碼為一個JSON以0開始的數組。如果flags
中設置了mw.text.JSON_PRESERVE_KEYS
,以0開始的序列表會編碼為JSON數組。
局限:
- 空表會被編碼為數組(
[]
),而不是空對象({}
)。 - 序列表不能被編碼為JSON對象,除非增加一個"虛擬"元素。
- 為了產生帶有nil值的數組,推薦使用
__pairs
的一些技巧。[43] - 從0開始的,有序列化鍵的Lua表會編碼為JSON數組,和從1開始的表一樣。除非設置了
mw.text.JSON_PRESERVE_KEYS
。 - 當數字和表示這個數字的字符串都作為同一個表的鍵,行為未定義。
mw.text.killMarkers
mw.text.killMarkers( s )
mw.text.listToText
mw.text.listToText( list )
mw.text.listToText( list, separator, conjunction )
按照散文風格(下文有示例)連結一個列表。有些像table.concat()
,但是最後一個元素的分隔符不同。
默認的分隔符來自於MediaWiki:comma-separator,默認的連詞(conjunction)是和MediaWiki:word-separator級聯(concatenate)的MediaWiki:and。
示例,使用消息(message)中的默認值:
-- 返回空字符串 mw.text.listToText( {} ) -- 返回字符串 "1" mw.text.listToText( { 1 } ) -- 返回字符串 "1 and 2" mw.text.listToText( { 1, 2 } ) -- 返回字符串 "1, 2, 3, 4 and 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實體,來避免它們被解讀為維基文本,這包括:
- 這些字符: '"', '&', "'", '<', '=', '>', '[', ']', '{', '|', '}'
- 在字符串或新行後面的這些字符: '#', '*', ':', ';', space, tab ('\t')
- 空行將使相關聯的換行符(newline)或者回車符(carriage return character)被轉義。
- 在字符串最開始的,或者在新行後面的"----",會轉義第一個'-'。
- "__" 會轉義一個下劃線。
- "://" 會使冒號被轉義。
- 跟在"ISBN", "RFC" 或 "PMID"後面的空格字符會被轉義。
mw.text.split
mw.text.split( s, pattern, plain )
以匹配Ustring pattern 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樣式的標籤(tag)。
如果給定了attrs
,則它必須是一個帶有字符串鍵的表。字符串值和數字值用作參數的值。如果值是布爾類型true,則作為無值的參數輸出;布爾類型false跳過這個鍵。其餘類型會報錯。
如果未給定content
,只會返回開放標籤(opening tag)。如果content
是布爾類型false。會返回一個自返回標籤。否則必須是一個字符串或數字。這時content內容會被包含在來訪和閉合標籤之中。注意,content不是自動滴HTML編碼的,如果需要的話應使用mw.text.encode()。
如果想正確返回拓展標籤(extension tag)例如<ref>
,應使用 frame:extensionTag()。
mw.text.trim
mw.text.trim( s )
mw.text.trim( s, charset )
去除字符串開始和結尾的空白字符或其餘字符。
如果charset
被提供,它應該是一個,可以被放入Ustring pattern中的括號的字符串,即[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
(省略號)。如果length是正數,會截斷字符串後面;如果是負數,會階段字符串的開頭。如果adjustLength
給定且為true,包括省略號的字符串不會比指定的length長。
ellipsis
的默認值來自於維基文檔語言中的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>條狀標記轉化為對應的文本。其餘種類的條狀標記不變。
mw.text.unstrip
mw.text.unstrip( s )
相當於 mw.text.killMarkers( mw.text.unstripNoWiki( s ) )
.
它不會顯示特殊頁面嵌入後的HTML,<ref>標記等,就像Scribunto早期版本一樣。
Title library
mw.title.equals
mw.title.equals( a, b )
Test for whether two titles are equal. Note that fragments are ignored in the comparison.
mw.title.compare
mw.title.compare( a, b )
Returns -1, 0, or 1 to indicate whether the title a
is less than, equal to, or greater than title b
.
This compares titles by interwiki prefix (if any) as strings, then by namespace number, then by the unprefixed title text as a string. These string comparisons use Lua's standard <
operator.
mw.title.getCurrentTitle
mw.title.getCurrentTitle()
Returns the title object for the current page.
mw.title.new
mw.title.new( text, namespace )
mw.title.new( id )
- This function is expensive when called with an ID
Creates a new title object.
If a number id
is given, an object is created for the title with that page_id. The title referenced will be counted as linked from the current page. If the page_id does not exist, returns nil. The expensive function count will be incremented if the title object created is not for a title that has already been loaded.
If a string text
is given instead, an object is created for that title (even if the page does not exist). If the text string does not specify a namespace, namespace
(which may be any key found in mw.site.namespaces
) will be used. If the text is not a valid title, nil is returned.
mw.title.makeTitle
mw.title.makeTitle( namespace, title, fragment, interwiki )
Creates a title object with title title
in namespace namespace
, optionally with the specified fragment
and interwiki
prefix. namespace
may be any key found in mw.site.namespaces
. If the resulting title is not valid, returns nil.
Note that, unlike mw.title.new()
, this method will always apply the specified namespace. For example, mw.title.makeTitle( 'Template', 'Module:Foo' )
will create an object for the page Template:Module:Foo, while mw.title.new( 'Module:Foo', 'Template' )
will create an object for the page Module:Foo.
Title objects
A title object has a number of properties and methods. Most of the properties are read-only.
Note that fields ending with text
return titles as string values whereas the fields ending with title
return title objects.
- id: The page_id. 0 if the page does not exist. This may be expensive.
- interwiki: The interwiki prefix, or the empty string if none.
- namespace: The namespace number.
- fragment: The fragment, or the empty string. May be assigned.
- nsText: The text of the namespace for the page.
- subjectNsText: The text of the subject namespace for the page.
- text: The title of the page, without the namespace or interwiki prefixes.
- prefixedText: The title of the page, with the namespace and interwiki prefixes.
- fullText: The title of the page, with the namespace and interwiki prefixes and the fragment. Interwiki is not returned if equal to the current.
- rootText: If this is a subpage, the title of the root page without prefixes. Otherwise, the same as
title.text
. - baseText: If this is a subpage, the title of the page it is a subpage of without prefixes. Otherwise, the same as
title.text
. - subpageText: If this is a subpage, just the subpage name. Otherwise, the same as
title.text
. - canTalk: Whether the page for this title could have a talk page.
- exists: Whether the page exists. Alias for file.exists for Media-namespace titles. For File-namespace titles this checks the existence of the file description page, not the file itself. This may be expensive.
- file, fileExists: See #File metadata below.
- isContentPage: Whether this title is in a content namespace.
- isExternal: Whether this title has an interwiki prefix.
- isLocal: Whether this title is in this project. For example, on the English Wikipedia, any other Wikipedia is considered "local" while Wiktionary and such are not.
- isRedirect: Whether this is the title for a page that is a redirect. This may be expensive.
- isSpecialPage: Whether this is the title for a possible special page (i.e. a page in the Special: namespace).
- isSubpage: Whether this title is a subpage of some other title.
- isTalkPage: Whether this is a title for a talk page.
- isSubpageOf( title2 ): Whether this title is a subpage of the given title.
- inNamespace( ns ): Whether this title is in the given namespace. Namespaces may be specified by anything that is a key found in
mw.site.namespaces
. - inNamespaces( ... ): Whether this title is in any of the given namespaces. Namespaces may be specified by anything that is a key found in
mw.site.namespaces
. - hasSubjectNamespace( ns ): Whether this title's subject namespace is in the given namespace. Namespaces may be specified by anything that is a key found in
mw.site.namespaces
. - contentModel: The content model for this title, as a string. This may be expensive.
- basePageTitle: The same as
mw.title.makeTitle( title.namespace, title.baseText )
. - rootPageTitle: The same as
mw.title.makeTitle( title.namespace, title.rootText )
. - talkPageTitle: The same as
mw.title.makeTitle( mw.site.namespaces[title.namespace].talk.id, title.text )
, or nil if this title cannot have a talk page. - subjectPageTitle: The same as
mw.title.makeTitle( mw.site.namespaces[title.namespace].subject.id, title.text )
. - redirectTarget: Returns a title object of the target of the redirect page if the page is a redirect and the page exists, returns false otherwise.
- protectionLevels: The page's protection levels. This is a table with keys corresponding to each action (e.g., "edit" and "move"). The table values are arrays, the first item of which is a string containing the protection level. If the page is unprotected, either the table values or the array items will be nil. This is expensive.
- subPageTitle( text ): The same as
mw.title.makeTitle( title.namespace, title.text .. '/' .. text )
. - partialUrl(): Returns
title.text
encoded as it would be in a URL. - fullUrl( query, proto ): Returns the full URL (with optional query table/string) for this title.
proto
may be specified to control the scheme of the resulting url: "http", "https", "relative" (the default), or "canonical". - localUrl( query ): Returns the local URL (with optional query table/string) for this title.
- canonicalUrl( query ): Returns the canonical URL (with optional query table/string) for this title.
- getContent(): Returns the (unparsed) content of the page, or nil if there is no page. The page will be recorded as a transclusion.
Title objects may be compared using relational operators. tostring( title )
will return title.prefixedText
.
Since people find the fact surprising, note that accessing any expensive field on a title object records a "link" to the page (as shown on Special:WhatLinksHere, for example). Using the title object's getContent()
method or accessing the redirectTarget
field records it as a "Template:Int", and accessing the title object's file
or fileExists
fields records it as a "Template:Int".
File metadata
Title objects representing a page in the File or Media namespace will have a property called file
. This is expensive. This is a table, structured as follows:
- exists: Whether the file exists. It will be recorded as an image usage. The
fileExists
property on a Title object exists for backwards compatibility reasons and is an alias for this property. If this is false, all other file properties will be nil. - width: The width of the file. If the file contains multiple pages, this is the width of the first page.
- height: The height of the file. If the file contains multiple pages, this is the height of the first page.
- pages: If the file format supports multiple pages, this is a table containing tables for each page of the file; otherwise, it is nil. The # operator can be used to get the number of pages in the file. Each individual page table contains a width and height property.
- size: The size of the file in bytes.
- mimeType: The MIME type of the file.
Expensive properties
The properties id, isRedirect, exists, and contentModel require fetching data about the title from the database. For this reason, the expensive function count is incremented the first time one of them is accessed for a page other than the current page. Subsequent accesses of any of these properties for that page will not increment the expensive function count again.
Other properties marked as expensive will always increment the expensive function count the first time they are accessed for a page other than the current page.
URI library
mw.uri.encode
mw.uri.encode( s, enctype )
Percent-encodes the string. The default type, QUERY
, encodes spaces using '+' for use in query strings; PATH
encodes spaces as %20; and WIKI
encodes spaces as '_'.
Note that the "WIKI" format is not entirely reversible, as both spaces and underscores are encoded as '_'.
mw.uri.decode
mw.uri.decode( s, enctype )
Percent-decodes the string. The default type, QUERY
, decodes '+' to space; PATH
does not perform any extra decoding; and WIKI
decodes '_' to space.
mw.uri.anchorEncode
mw.uri.anchorEncode( s )
Encodes a string for use in a MediaWiki URI fragment.
mw.uri.buildQueryString
mw.uri.buildQueryString( table )
Encodes a table as a URI query string. Keys should be strings; values may be strings or numbers, sequence tables, or boolean false.
mw.uri.parseQueryString
mw.uri.parseQueryString( s, i, j )
Decodes the query string s
to a table. Keys in the string without values will have a value of false; keys repeated multiple times will have sequence tables as values; and others will have strings as values.
The optional numerical arguments i
and j
can be used to specify a substring of s
to be parsed, rather than the entire string. i
is the position of the first character of the substring, and defaults to 1. j
is the position of the last character of the substring, and defaults to the length of the string. Both i
and j
can be negative, as in string.sub.
mw.uri.canonicalUrl
mw.uri.canonicalUrl( page, query )
Returns a URI object for the canonical URL for a page, with optional query string/table.
mw.uri.fullUrl
mw.uri.fullUrl( page, query )
Returns a URI object for the full URL for a page, with optional query string/table.
mw.uri.localUrl
mw.uri.localUrl( page, query )
Returns a URI object for the local URL for a page, with optional query string/table.
mw.uri.new
mw.uri.new( s )
Constructs a new URI object for the passed string or table. See the description of URI objects for the possible fields for the table.
mw.uri.validate
mw.uri.validate( table )
Validates the passed table (or URI object). Returns a boolean indicating whether the table was valid, and on failure a string explaining what problems were found.
URI object
The URI object has the following fields, some or all of which may be nil:
- protocol: String protocol/scheme
- user: String user
- password: String password
- host: String host name
- port: Integer port
- path: String path
- query: A table, as from mw.uri.parseQueryString
- fragment: String fragment.
The following properties are also available:
- userInfo: String user and password
- hostPort: String host and port
- authority: String user, password, host, and port
- queryString: String version of the query table
- relativePath: String path, query string, and fragment
tostring()
will give the URI string.
Methods of the URI object are:
mw.uri:parse
uri:parse( s )
Parses a string into the current URI object. Any fields specified in the string will be replaced in the current object; fields not specified will keep their old values.
mw.uri:clone
uri:clone()
Makes a copy of the URI object.
mw.uri:extend
uri:extend( parameters )
Merges the parameters table into the object's query table.
Ustring library
The ustring library is intended to be a direct reimplementation of the standard String library, except that the methods operate on characters in UTF-8 encoded strings rather than bytes.
Most functions will raise an error if the string is not valid UTF-8; exceptions are noted.
mw.ustring.maxPatternLength
The maximum allowed length of a pattern, in bytes.
mw.ustring.maxStringLength
The maximum allowed length of a string, in bytes.
mw.ustring.byte
mw.ustring.byte( s, i, j )
Returns individual bytes; identical to string.byte().
mw.ustring.byteoffset
mw.ustring.byteoffset( s, l, i )
Returns the byte offset of a character in the string. The default for both l
and i
is 1. i
may be negative, in which case it counts from the end of the string.
The character at l
== 1 is the first character starting at or after byte i
; the character at l
== 0 is the first character starting at or before byte i
. Note this may be the same character. Greater or lesser values of l
are calculated relative to these.
mw.ustring.char
mw.ustring.char( ... )
Much like string.char(), except that the integers are Unicode codepoints rather than byte values.
local value = mw.ustring.char( 0x41f, 0x440, 0x438, 0x432, 0x435, 0x442, 0x21 ) -- value is now 'Привет!'
mw.ustring.codepoint
mw.ustring.codepoint( s, i, j )
Much like string.byte(), except that the return values are codepoints and the offsets are characters rather than bytes.
mw.ustring.find
mw.ustring.find( s, pattern, init, plain )
Much like string.find(), except that the pattern is extended as described in Ustring patterns and the init
offset is in characters rather than bytes.
mw.ustring.format
mw.ustring.format( format, ... )
Identical to string.format(). Widths and precisions for strings are expressed in bytes, not codepoints.
mw.ustring.gcodepoint
mw.ustring.gcodepoint( s, i, j )
Returns three values for iterating over the codepoints in the string. i
defaults to 1, and j
to -1. This is intended for use in the iterator form of for
:
for codepoint in mw.ustring.gcodepoint( s ) do -- block end
mw.ustring.gmatch
mw.ustring.gmatch( s, pattern )
Much like string.gmatch(), except that the pattern is extended as described in Ustring patterns.
mw.ustring.gsub
mw.ustring.gsub( s, pattern, repl, n )
Much like string.gsub(), except that the pattern is extended as described in Ustring patterns.
mw.ustring.isutf8
mw.ustring.isutf8( s )
Returns true if the string is valid UTF-8, false if not.
mw.ustring.len
mw.ustring.len( s )
Returns the length of the string in codepoints, or nil if the string is not valid UTF-8.
See string.len() for a similar function that uses byte length rather than codepoints.
mw.ustring.lower
mw.ustring.lower( s )
Much like string.lower(), except that all characters with lowercase to uppercase definitions in Unicode are converted.
If the Language library is also loaded, this will instead call lc() on the default language object.
mw.ustring.match
mw.ustring.match( s, pattern, init )
Much like string.match(), except that the pattern is extended as described in Ustring patterns and the init
offset is in characters rather than bytes.
mw.ustring.rep
mw.ustring.rep( s, n )
Identical to string.rep().
mw.ustring.sub
mw.ustring.sub( s, i, j )
Much like string.sub(), except that the offsets are characters rather than bytes.
mw.ustring.toNFC
mw.ustring.toNFC( s )
Converts the string to Normalization Form C. Returns nil if the string is not valid UTF-8.
mw.ustring.toNFD
mw.ustring.toNFD( s )
Converts the string to Normalization Form D. Returns nil if the string is not valid UTF-8.
mw.ustring.upper
mw.ustring.upper( s )
Much like string.upper(), except that all characters with uppercase to lowercase definitions in Unicode are converted.
If the Language library is also loaded, this will instead call uc() on the default language object.
Ustring patterns
Patterns in the ustring functions use the same syntax as the String library patterns. The major difference is that the character classes are redefined in terms of Unicode character properties:
%a
: represents all characters with General Category "Letter".%c
: represents all characters with General Category "Control".%d
: represents all characters with General Category "Number, decimal digit".%l
: represents all characters with General Category "Lowercase Letter".%p
: represents all characters with General Category "Punctuation".%s
: represents all characters with General Category "Separator", plus tab, linefeed, carriage return, vertical tab, and form feed.%u
: represents all characters with General Category "Uppercase Letter".%w
: represents all characters with General Category "Letter" or "Decimal Number".%x
: adds fullwidth character versions of the hex digits.
Like in String library patterns, %A
, %C
, %D
, %L
, %P
, %S
, %U
Template:IntTemplate:Int%W
here represent the complementary set ("all characters without given General Category").
In all cases, characters are interpreted as Unicode characters instead of bytes, so ranges such as [0-9]
, patterns such as %b«»
, and quantifiers applied to multibyte characters will work correctly. Empty captures will capture the position in code points rather than bytes.
Loadable libraries
These libraries are not included by default, but if needed may be loaded using require()
.
bit32
This emulation of the Lua 5.2 bit32
library may be loaded using
bit32 = require( 'bit32' )
The bit32 library provides bitwise operations on unsigned 32-bit integers. Input numbers are truncated to integers (in an unspecified manner) and reduced modulo 232 so the value is in the range 0 to 232−1; return values are also in this range.
When bits are numbered (as in bit32.extract()), 0 is the least-significant bit (the one with value 20) and 31 is the most-significant (the one with value 231).
bit32.band
bit32.band( ... )
Returns the bitwise AND of its arguments: the result has a bit set only if that bit is set in all of the arguments.
If given zero arguments, the result has all bits set.
bit32.bnot
bit32.bnot( x )
Returns the bitwise complement of x
.
bit32.bor
bit32.bor( ... )
Returns the bitwise OR of its arguments: the result has a bit set if that bit is set in any of the arguments.
If given zero arguments, the result has all bits clear.
bit32.btest
bit32.btest( ... )
Equivalent to bit32.band( ... ) ~= 0
bit32.bxor
bit32.bxor( ... )
Returns the bitwise XOR of its arguments: the result has a bit set if that bit is set in an odd number of the arguments.
If given zero arguments, the result has all bits clear.
bit32.extract
bit32.extract( n, field, width )
Extracts width
bits from n
, starting with bit field
. Accessing bits outside of the range 0 to 31 is an error.
If not specified, the default for width
is 1.
bit32.replace
bit32.replace( n, v, field, width )
Replaces width
bits in n
, starting with bit field
, with the low width
bits from v
. Accessing bits outside of the range 0 to 31 is an error.
If not specified, the default for width
is 1.
bit32.lshift
bit32.lshift( n, disp )
Returns the number n
shifted disp
bits to the left. This is a logical shift: inserted bits are 0. This is generally equivalent to multiplying by 2disp
.
Note that a displacement over 31 will result in 0.
bit32.rshift
bit32.rshift( n, disp )
Returns the number n
shifted disp
bits to the right. This is a logical shift: inserted bits are 0. This is generally equivalent to dividing by 2disp
.
Note that a displacement over 31 will result in 0.
bit32.arshift
bit32.arshift( n, disp )
Returns the number n
shifted disp
bits to the right. This is an arithmetic shift: if disp
is positive, the inserted bits will be the same as bit 31 in the original number.
Note that a displacement over 31 will result in 0 or 4294967295.
bit32.lrotate
bit32.lrotate( n, disp )
Returns the number n
rotated disp
bits to the left.
Note that rotations are equivalent modulo 32: a rotation of 32 is the same as a rotation of 0, 33 is the same as 1, and so on.
bit32.rrotate
bit32.rrotate( n, disp )
Returns the number n
rotated disp
bits to the right.
Note that rotations are equivalent modulo 32: a rotation of 32 is the same as a rotation of 0, 33 is the same as 1, and so on.
libraryUtil
This library contains methods useful when implementing Scribunto libraries. It may be loaded using
libraryUtil = require( 'libraryUtil' )
libraryUtil.checkType
libraryUtil.checkType( name, argIdx, arg, expectType, nilOk )
Raises an error if type( arg )
does not match expectType
. In addition, no error will be raised if arg
is nil and nilOk
is true.
name
is the name of the calling function, and argIdx
is the position of the argument in the argument list. These are used in formatting the error message.
libraryUtil.checkTypeMulti
libraryUtil.checkTypeMulti( name, argIdx, arg, expectTypes )
Raises an error if type( arg )
does not match any of the strings in the array expectTypes
.
This is for arguments that have more than one valid type.
libraryUtil.checkTypeForIndex
libraryUtil.checkTypeForIndex( index, value, expectType )
Raises an error if type( value )
does not match expectType
.
This is intended for use in implementing a __newindex
metamethod.
libraryUtil.checkTypeForNamedArg
libraryUtil.checkTypeForNamedArg( name, argName, arg, expectType, nilOk )
Raises an error if type( arg )
does not match expectType
. In addition, no error will be raised if arg
is nil and nilOk
is true.
This is intended to be used as an equivalent to libraryUtil.checkType()
in methods called using Lua's "named argument" syntax, func{ name = value }
.
libraryUtil.makeCheckSelfFunction
libraryUtil.makeCheckSelfFunction( libraryName, varName, selfObj, selfObjDesc )
This is intended for use in implementing "methods" on object tables that are intended to be called with the obj:method()
syntax. It returns a function that should be called at the top of these methods with the self
argument and the method name, which will raise an error if that self
object is not selfObj
.
This function will generally be used in a library's constructor function, something like this:
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
The luabit library modules "bit" and "hex" may be loaded using
bit = require( 'luabit.bit' ) hex = require( 'luabit.hex' )
Note that the bit32 library contains the same operations as "luabit.bit", and the operations in "luabit.hex" may be performed using string.format()
and tonumber()
.
The luabit module "noki" is not available, as it is entirely useless in Scribunto. The luabit module "utf8" is also not available, as it was considered redundant to the Ustring library.
ustring
The pure-Lua backend to the Ustring library may be loaded using
ustring = require( 'ustring' )
In all cases the Ustring library (mw.ustring
) should be used instead, as that replaces many of the slower and more memory-intensive operations with callbacks into PHP code.
Extension libraries
Some MediaWiki extensions provide additional Scribunto libraries. These are also located in the table mw
, usually in the table mw.ext
, however, they are only present when certain extensions are installed (in addition to the Scribunto extension itself).
Such extensions use Scribunto provided hooks:
Writing Scribunto libraries provides information on how such libraries can be developed to provide Lua interfaces for Mediawiki extensions.
The following libraries are planned, or are in Gerrit pending review.
- (none at this time)
mw.wikibase
Wikibase Client provides access to localizable structured data. See Extension:Wikibase Client/Lua. This is supported by Wikidata.
mw.wikibase.lexeme
WikibaseLexeme provides access to Wikibase Lexeme entities. This is supported by Wikidata:Lexicographical data.
mw.wikibase.mediainfo
WikibaseMediaInfo provides access to Wikibase MediaInfo entities. See Extension:WikibaseMediaInfo/Lua. This is supported by Structured Data on Commons. See Commons:Structured data/Lua.
mw.bcmath
BCmath provides arbitrary-precision arithmetic to Lua modules. See BCmath documentation via "LDoc" link at Extension:BCmath#Usage.
mw.smw
Semantic Scribunto provides native support for the Scribunto extension to Semantic MediaWiki extension.
mw.ext.data
JsonConfig provides access to localizable tabular and map data. See Extension:JsonConfig/Tabular. Tabular Data and GeoJSON Map Data is supported in Commons "Data:" namespace.
mw.ext.cargo
Cargo provides a means to query its data store from Lua. See Extension:Cargo/Other features#Lua support.
mw.ext.cattools
CategoryToolbox provides a means to check from Lua if a certain page belongs to a category
mw.ext.FlaggedRevs
FlaggedRevs provides a means to access the stability settings of a page from Lua.
mw.ext.TitleBlacklist
TitleBlacklist provides a means to test and obtain information about blacklisted page naming entries from Lua.
mw.ext.ParserFunctions
ParserFunctions provides a means to evaluate a parser function expressions from Lua.
mw.ext.articlePlaceholder
ArticlePlaceholder provides a means to override default Wikibase renderings from Lua. See Extension:ArticlePlaceholder/Module:AboutTopic.
與標準Lua庫的不同之處
修改的函數
以下的函數經過了調整:
- setfenv()
- getfenv()
- 可能無法使用,具體根據配置決定。即使可以使用,但如果試圖操作上層環境將會失敗。
- getmetatable()
- 修改以防止不正規地操作上層環境。(在較新的Lua版本中,getmetatable('字符串').__index==string為true,但在MediaWiki中,這個元表是得不到的。)
- tostring()
- 將表和函數轉換為字符串類型時,不再顯示指針地址。使得內存損壞漏洞更難以被利用。
- pairs()
- ipairs()
- 添加對元方法__pairs和__ipairs(在Lua 5.2版本中添加)的支持。
- pcall()
- xpcall()
- 某些內部錯誤無法被捕獲。
- require()
- 能加載某些Scribunto的內建模塊,以及萌娘百科上的現有模塊(Module名字空間下的頁面)。如果要加載現有模塊,必須使用包含名字空間的完整頁面名稱。另外無法訪問本地的文件系統。
移除的函數和包
以下包幾乎全部被移除。僅列出的函數是可以使用的。
- package.*
- 移除了所有操作文件系統和C庫的函數。剩餘可以使用的函數和子包有:
- 操作本地文件系統和C庫的版本已被移除,作為代替添加了能訪問Module名字空間下的頁面的版本。
- os.*
- 這個包里部分不安全的函數已被移除。剩餘可以使用的函數有:
- debug.*
- 這個包里大部分不安全的函數已被移除。剩餘可以使用的函數有:
以下的函數和包不能使用:
- collectgarbage()
- module()
- coroutine.*
- No application is known for us, so it has not been reviewed for security.
- dofile()
- loadfile()
- io.*, file.*
- 允許操作本地文件系統,不安全。
- load()
- loadstring()
- 這些函數允許動態加載並運行Lua代碼,處於可用性原因不需要這些功能。
- print()
- 有更完善的函數mw.log(),用來輸出控制台消息。
- string.dump()
- 可能暴露上層環境中的隱私數據。
其他警示
- Referential data structures
- Circular data structures and data structures where the same node may be reached by more than one path cannot be correctly sent to PHP. Attempting to do so will cause undefined behavior. This includes (but is not limited to) returning such data structures from the module called by
{{#invoke:}}
and passing such data structures as parameters to Scribunto library functions that are implemented as callbacks into PHP.Such data structures may be used freely within Lua, including as the return values of modules loaded with
mw.loadData()
.
Writing Scribunto libraries
This information is useful to developers writing additional Scribunto libraries, whether for inclusion in Scribunto itself or for providing an interface for their own extensions.
A Scribunto library will generally consist of five parts:
- The PHP portion of the library.
- The Lua portion of the library.
- The PHP portion of the test cases.
- The Lua portion of the test cases.
- The documentation.
Existing libraries serve as a good example.
Library
The PHP portion of the library is a class that must extend Scribunto_LuaLibraryBase
. See the documentation for that class for implementation details. In the Scribunto extension, this file should be placed in engines/LuaCommon/NameLibrary.php
, and a mapping added to Scribunto_LuaEngine::$libraryClasses
. Other extensions should use the ScribuntoExternalLibraries hook. In either case, the key should match the Lua module name ("mw.name" for libraries in Scribunto, or "mw.ext.name" for extension libraries).
The Lua portion of the library sets up the table containing the functions that can be called from Lua modules. In the Scribunto extension, the file should be placed in engines/LuaCommon/lualib/mw.name.lua
. This file should generally include boilerplate something like this:
local object = {} local php function object.setupInterface( options ) -- Remove setup function object.setupInterface = nil -- Copy the PHP callbacks to a local variable, and remove the global php = mw_interface mw_interface = nil -- Do any other setup here -- Install into the mw global mw = mw or {} mw.ext = mw.ext or {} mw.ext.NAME = object -- Indicate that we're loaded package.loaded['mw.ext.NAME'] = object end return object
The module in engines/LuaCommon/lualib/libraryUtil.lua
(load this with local util = require 'libraryUtil'
) contains some functions that may be helpful.
Be sure to run the Scribunto test cases with your library loaded, even if your library doesn't itself provide any test cases. The standard test cases include tests for things like libraries adding unexpected global variables. Also, if the library is loaded with PHP, any upvalues that its Lua functions have will not be reset between #invoke's. Care must be taken to ensure that modules can't abuse this to transfer information between #invoke's.
Test cases
The Scribunto extension includes a base class for test cases, Scribunto_LuaEngineTestBase
, which will run the tests against both the LuaSandbox and LuaStandalone engines. The library's test case should extend this class, and should not override static function suite()
. In the Scribunto extension, the test case should be in tests/engines/LuaCommon/NameLibraryTest.php
and added to the array in ScribuntoHooks::unitTestsList()
(in common/Hooks.php
); extensions should add the test case in their own UnitTestsList
hook function, probably conditional on whether $wgAutoloadClasses['Scribunto_LuaEngineTestBase']
is set.
Most of the time, all that is needed to make the test case is this:
class ClassNameTest extends Scribunto_LuaEngineTestBase { protected static $moduleName = 'ClassNameTest'; function getTestModules() { return parent::getTestModules() + array( 'ClassNameTest' => __DIR__ . '/ClassNameTests.lua'; ); } }
This will load the file ClassNameTests.lua
as if it were the page "Module:ClassNameTests", expecting it to return an object with the following properties:
- count: Integer, number of tests
- provide( n ): Function that returns three values:
n
, the name of testn
, and a string that is the expected output for testn
. - run( n ): Function that runs test
n
and returns one string.
If getTestModules()
is declared as shown, "Module:TestFramework" is available which provides many useful helper methods. If this is used, ClassNameTests.lua
would look something like this:
local testframework = require 'Module:TestFramework' return testframework.getTestProvider( { -- Tests go here } )
Each test is itself a table, with the following properties:
- name: The name of the test.
- func: The function to execute.
- args: Optional table of arguments to pass to the function.
- expect: Results to expect.
- type: Optional "type" of the test, default is "Normal".
The type controls the format of expect
and how func
is called. Included types are:
- Normal:
expect
is a table of return values, or a string if the test should raise an error.func
is simply called. - Iterator:
expect
is a table of tables of return values.func
is called as with an iterated for loop, and each iteration's return values are accumulated. - ToString: Like "Normal", except each return value is passed through
tostring()
.
Test cases in another extension
There are (at least) two ways to run PHPUnit tests:
- Run phpunit against core, allowing the tests/phpunit/suites/ExtensionsTestSuite.php to find the extension's tests using the UnitTestsList hook. If your extension's test class names all contain a unique component (e.g. the extension's name), the
--filter
option may be used to run only your extension's tests. - Run phpunit against the extension directory, where it will pick up any file ending in "Test.php".
Either of these will work fine if Scribunto is loaded in LocalSettings.php. And it is easy for method #1 to work if Scribunto is not loaded, as the UnitTestsList hook can easily be written to avoid returning the Scribunto test when $wgAutoloadClasses['Scribunto_LuaEngineTestBase']
is not set.
But Jenkins uses method #2. For Jenkins to properly run the tests, you will need to add Scribunto as a dependency for your extension. See Template:Gerrit for an example of how this is done.
If for some reason you need the tests to be able to run using method #2 without Scribunto loaded, one workaround is to add this check to the top of your unit test file:
if ( !isset( $GLOBALS['wgAutoloadClasses']['Scribunto_LuaEngineTestBase'] ) ) { return; }
Documentation
Modules included in Scribunto should include documentation in the Scribunto libraries section above. Extension libraries should include documentation in a subpage of their own extension page, and link to that documentation from the Extension libraries subsection above.
許可證
本參考手冊部分內容來源於Lua 5.1 reference manual,其使用的是MIT許可證。
Copyright © 1994–2012 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
本參考手冊的任何內容在修改、引用或傳播時,在遵守萌娘百科知識共享協議3.0版本 署名-非商業性使用-相同方式共享 (by-nc-sa)的同時,需要包含上述MIT許可證。
注釋及外部連結
- ↑ 可能錯誤的連結
- ↑ 下文的「值」,有的時候指的是與「鍵」對應的「值」,有的時候指的僅僅是單純意義上的值,可能需要加以區分。
- ↑ 偽碼也許不可執行,它是為了呈現代碼邏輯或程序實現過程的,類似代碼的東西。
- ↑ 「方法」(method)實際上也是一種函數。
- ↑ 此時也可以叫做「元方法」
- ↑ 也就是對於這個鍵,表中沒有值的時候
- ↑ 類似於C++的operator()運算符重載。
- ↑ 未定義行為是危險的,不要嘗試未定義行為,沒人知道未定義行為會產生什麼後果。
- ↑ 這篇文章可以幫助理解這段內容,翻譯者注。[1]
- ↑ 原文檔並沒有註明字符串會如何進行比較,翻譯者注。可能是按照大多數程式語言一樣,按照字典序比較。
- ↑ 這裡,func()函數返回的函數被調用
- ↑ 這裡是三個點,前面的連接運算符是兩個點。
- ↑ 在下文,chunk和block可能不做區分,統稱為「代碼塊」。
- ↑ 指的是return語句中調用函數。
- ↑ 3是,信息是一個函數1的位置,這個函數調用了函數2,函數2拋出了異常。
- ↑ 可以參考此文章[2]。
- ↑ 關於求模和取余的差別,可參考[3]。
- ↑ 可能在後續的Lua版本下,這個行為會被修改。
- ↑ 這個函數可能會有bug,詳情可以見這篇文章[4]。另外,這篇文章中提到的一些函數可能在Scribunto中不可用。
- ↑ 可以參考此文章[5]
- ↑ 原文檔並沒有註明t1和t2的類型和格式,翻譯者注。實際上這兩個變量均應為os.time函數的返回值。
- ↑ 可以參考此文章[6]
- ↑ 指的是匹配模式中具有特殊匹配意義的字符,即
^$()%.[]*+-?
。將會在#Patterns詳細介紹。 - ↑ 可參考此頁面[7]或[8]
- ↑ 在C語言等程式語言中,NUL會被視為字符串結束的標誌。
- ↑ 是一個Perl庫,也可以正則表達式匹配。
- ↑ 是一種特殊的字符串,以刪除字符(ASCII 127)開始。例如,
{{#tag:}}
會被轉化為\127'"`UNIQ--tagname-8 hex digits-QINU`"'\127
。 ——來自於[9]。 - ↑ 指的是不需要左右閉合的標籤,例如<br>等。<br><br />可能會被認為是錯誤的。
- ↑ 語言代碼在是MediaWiki合法的語言簡寫,MediaWiki使用這些代碼來區分語言。
- ↑ 例如「中文」,「English」,「日本語 」
- ↑ 有些語言具有依賴語言。如果MediaWiki不能支持當前語言,會使用依賴語言。詳見[10]。
- ↑ 在
mw.language.isValidCode
下返回true。 - ↑ 分別為「千年」「百年」「十年」「年」「星期」「天」「小時」「分鐘」「秒」。
- ↑ 語言學術語,是詞形變化的一種。
- ↑ 語言學術語。
- ↑ 部分名詞解釋詳見幫助:名字空間
- ↑ 所有命名空間都有一個通用於所有wiki的「規範(canonical)」前綴。——來自[11]
- ↑ 詳見Help:高級編輯#連結,超連結。
- ↑ 協議相關是這樣的。對於一個頁面<code>//example.com/wiki/Foo</code>,被HTTP協議的頁面訪問此頁面,解析器會將其視為http://example.com/wiki/Foo,在HTTPS協議的頁面訪問請求下,解析器視為https://example.com/wiki/Foo,那麼,這個頁面是協議相關的。 ——翻譯自頁面[12]
- ↑ 嵌入,指的是把一個文檔的內容引用到另一個文檔中。
- ↑ 在SGML、 HTML與XML文檔,如果某些Unicode字符在文檔的當前編碼方式(如ISO-8859-1)中不能直接表示,那麼可以通過字符值引用或者字符實體引用兩種轉義序列來表示這些不能直接編碼的字符。 下文列出在HTML與XML文檔中有效的字符實體引用。 ——維基百科頁面[13]
- ↑ 指的是列表等數據結構中最後一個元素後面的逗號,例如[1,2,3,]中3後面出現的逗號。
- ↑ 原文並未說明是什麼樣的技巧,翻譯者注。
- ↑ 同2222行的註解。