2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

User:渚 花/Lua参考手册(翻译)

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
本页面阅读须知
Icon-info.png
  • 本页面是为在萌娘百科上使用扩展: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的变量,试图调用其他类型(括tablestringnumber等)都会抛出一个错误。

没有加到这个表中的函数,无论是局部的还是全局的,对于隔着{{#invoke:}}的“外部”调用页面来说都是无法访问的。但需要注意的一点是,当你在一个模块中申明了一个全局变量,当你在其他模块中require()此模块时,这个全局变量也能够被访问到。因此对于模块来说,最好将所有的函数和变量声明为局部变量,以防覆盖到其他模块中的同名变量的作用域,引发难以发现的错误。

从Wiki文本关联参数

从外部通过{{#invoke:}}调用模块中的函数时会传入一个框架对象,它是被函数接受的唯一参数。通过在函数内部访问框架对象的args属性,可以获取到外部调用时传入的其他参数。另外,若模块被模板包装,还可以使用frame:getParent()获取表示外部模板的框架对象,然后通过args属性获取调用模板时传入的参数。

框架对象还用于操作一些Wiki文本解释器的功能,例如调用解析器函数展开模板、以及展开任意Wiki文本

返回内容

模块函数应该返回一个字符串,但无论返回什么值都会被函数tostring()转换并不带分隔符地级联。这个字符串会并入维基文本作为{{#invoke:}}展开的结果。

在页面解析到这步时,模板已经展开,解析函数和扩展标签已进行,预保存转换(例如签名波浪线符号~~~和竖线符号)也均已发生。所以模块的输出文本中不能使用这些特性。例如,如果一个模块返回"Hello, [[world]]! {{welcome}},页面会识别为 "hello, world! {{welcome}}。

此外,[[替换引用|{{{2}}}]]需要修正链接指向是在保存编辑的时候被处理的。

模块文档

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中,变量名(也叫做“标识符”)可以是字母数字下划线的任意组合,但不能以数字开头。变量名是大小写敏感的,即fooFooFOO都是各不相同的变量名。

以下是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 (布尔类型)

布尔类型是truefalse


当被转化为字符串时,转化结果是"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-10123.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] = expression2expression1的(当前)元素作为(key),expression2的(当前)值作为在当前键下的(value)。[2]
  • name = expression 相当于 ["name"] = expression
  • expression 大致相当于 [i] = expression, 其中i是从1开始的数字,每次使用这段代码填充字段i都会递增。如果这段代码作为最后一个字段出现,且expression有多个值,那么所有的值都会使用,否则只保留第一个值。


表中的值可以通过中括号来访问,例如table[key]。字符串键也可以通过符号点来访问,例如table.keytable['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会首先从第一个运算对象的元表寻找这个元方法,如果没有找到才会从第二个运算对象寻找。
对于关系运算符,只有两个运算对象的元方法是同一个函数对象时,才会使用元方法。不同的匿名函数,即使有着相同的函数体和闭包,不会被当做相同的函数。
* __metatable 影响 getmetatable()setmetatable()函数。


注意:在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)。

逻辑运算符

逻辑运算符是andornot,它们的返回值都是布尔类型。只有nil和false会被当做false,其他的都会被当做true。

and:如果左运算对象是false,直接返回false,否则返回右运算对象。

or:如果左运算对象是true,直接返回true,否则返回右运算对象。

not:返回结果总是true或false。

注意andor有短路特性。例如,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的运算符优先级,从高到低:


  1. ^
  2. not # - (负号)
  3. * / %
  4. + - (减法)
  5. ..
  6. < > <= >= ~= ==
  7. and
  8. 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里,可以声明局部变量,接受参数和返回值。


一个blockchunk一样,也是一串代码。通过下面的语句可以创建一个blockdo 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其中之一是非数字值,例如nilfalse,会抛出异常。所有的值都会被在循环开始之前提前计算。

除了变量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,否则运行block3else 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会返回,包括vmessage在内的所有参数。


在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 )


获取一个对应的元表。非表类型会返回nil。


如果元表已有__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 foripairs


如果在使用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 )


返回满足以下条件的me值。

  • 如果x非0有穷,<math>x = m \times 2*e</math>,其中,e是整数,m的绝对值在<math>[0.5, 1)</math>范围内。
  • 如果 x 为0,me 均为0。
  • 如果 x是NaN或无穷大, m is x and e 未指定。

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 )


返回一个伪随机数。


mn可以省略,但是它们必须是整数值。

  • 如果没有参数,返回<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 )


返回从t1t2两个时间之间的秒数。[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提供两个搜索器:


  1. package.preload[modulename] 搜索加载器函数。
  2. 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]


mw.ustring.format()相同。


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中, %作为转义字符。符合格式%nrepl子串,其中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 )


返回一个字符串,是ns连接在一起。与mw.ustring.rep()相同。


string.reverse

string.reverse( s )


返回一个字符串,是s按字节倒转。

string.sub

string.sub( s, i, j )


返回一个s的子串,从位置i开始j结束。ij都可以是负数。如果j是nil或被省略,会以字符串末尾结束。


可以用string.sub(s,1,j),返回s长度为j的前缀。string.sub(s, -i)返回长度为is的后缀。

对于相似函数,详见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, 其中xy是两个不同的字符。匹配以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的默认值是表的长度。如果ij大,返回空字符串。


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>标签无效;没有name(名称)的ref(参考)必须有内容


mw.loadData

mw.loadData( module )


有时一个模块需要很大的数据表,例如,一个用来转换度量单位的通用模块,可能需要一个大表,包括单位及其转换系数。有时这些模块可能在同一个页面使用多次。每次{{#invoke:}}解析这个大表可能会大量时间。为了避免这个问题,提供了函数mw.loadData()


mw.loadDatarequire()很相似,但是有以下的不同:


  • 被加载模块并不是每调用一次{{#invoke:}}被解析,而是仅在每次加载页面时。


  • 从被加载模块返回的值必须是表,不支持其余类型。


  • 被返回的表(和表中表)只能包括布尔类型,数字,字符串,或者其余表。不允许其余数据类型,包括函数。


  • 返回的表(和表中表)不可以有 元表


  • 表中所有键必须是布尔类型,数字和字符串。


  • 事实上,mw.loadData()返回的表具有一个元方法,这个远方吧提供对模块返回的表的只读访问。因为表中不提直接包含数据,所以pairs()ipairs()可以正常使用,但是其余方法,例如#valuenext()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]会返回arg1frame.args[2] 会返回arg2frame.args['name'] (或 frame.args.name)会返回arg3。也可以使用pairs( frame.args )ipairs( frame.args )迭代所有的参数。 然而,因为Lua执行表迭代的方式,像这样迭代参数会使得参数按照未指定的顺序返回,这样就无法得知它们在维基文本中原来的顺序。

注意,这个表的值都是字符串格式,可能需要tonumber()来转化为数字。然后,键可以是数字,即使是调用时显式提供。例如,{{#invoke:module|function|1|2=2}},对应两个字符串值12,和两个数字键12


在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:' .. namecontent加入到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>标签无效;没有name(名称)的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:namehtml: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 )

namevalue作为名称和值为对象设置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 )


namevalue作为名称和值为对象设置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:namelang:name是语言对象(language object)的方法。(详见mw.language.newmw.language.getContentLanguage)。


翻译者梳理。一个语言代码是:


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 wordstranslatewiki'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]形式。


可用的wordcase值依照不同的语言不同,细节详见Special:MyLanguage/Help:Magic words#Localisationtranslatewiki: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,返回 "&lrm;" 或 "&rlm;"。


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:namemsg: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 libraryUstring library中没有的,一些常见函数。这些函数对于UTF-8字符串安全。


mw.text.decode

mw.text.decode( s )
mw.text.decode( s, decodeNamedEntities )


将字符串中的HTML实体[41] 替换为对应的字符。


如果布尔值decodeNamedEntities被省略或为false,则仅仅命名的HTML实体'&lt;', '&gt;', '&amp;', '&quot;', and '&nbsp;'被识别。否则,要识别的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_KEYSmw.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_KEYSmw.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 )


从一个字符串去除所有的维基条状标记[44]


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, %UTemplate: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库的函数。剩余可以使用的函数和子包有:
package.loaded
package.preload
package.loaders
操作本地文件系统和C库的版本已被移除,作为代替添加了能访问Module名字空间下的页面的版本。
package.seeall()
os.*
这个包里部分不安全的函数已被移除。剩余可以使用的函数有:
os.clock()
os.date()
os.difftime()
os.time()
debug.*
这个包里大部分不安全的函数已被移除。剩余可以使用的函数有:
debug.traceback()

以下的函数和包不能使用:

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 test n, and a string that is the expected output for test n.
  • 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:


  1. 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.
  2. 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许可证。

注释及外部链接

  1. 可能错误的链接
  2. 下文的“值”,有的时候指的是与“键”对应的“值”,有的时候指的仅仅是单纯意义上的值,可能需要加以区分。
  3. 伪码也许不可执行,它是为了呈现代码逻辑或程序实现过程的,类似代码的东西。
  4. “方法”(method)实际上也是一种函数。
  5. 此时也可以叫做“元方法”
  6. 也就是对于这个键,表中没有值的时候
  7. 类似于C++的operator()运算符重载。
  8. 未定义行为是危险的,不要尝试未定义行为,没人知道未定义行为会产生什么后果。
  9. 这篇文章可以帮助理解这段内容,翻译者注。[1]
  10. 原文档并没有注明字符串会如何进行比较,翻译者注。可能是按照大多数编程语言一样,按照字典序比较。
  11. 这里,func()函数返回的函数被调用
  12. 这里是三个点,前面的连接运算符是两个点。
  13. 在下文,chunk和block可能不做区分,统称为“代码块”。
  14. 指的是return语句中调用函数。
  15. 3是,信息是一个函数1的位置,这个函数调用了函数2,函数2抛出了异常。
  16. 可以参考此文章[2]
  17. 关于求模取余的差别,可参考[3]
  18. 可能在后续的Lua版本下,这个行为会被修改。
  19. 这个函数可能会有bug,详情可以见这篇文章[4]。另外,这篇文章中提到的一些函数可能在Scribunto中不可用。
  20. 可以参考此文章[5]
  21. 原文档并没有注明t1和t2的类型和格式,翻译者注。实际上这两个变量均应为os.time函数的返回值。
  22. 可以参考此文章[6]
  23. 指的是匹配模式中具有特殊匹配意义的字符,即 ^$()%.[]*+-?。将会在#Patterns详细介绍。
  24. 可参考此页面[7][8]
  25. 在C语言等编程语言中,NUL会被视为字符串结束的标志。
  26. 是一个Perl库,也可以正则表达式匹配。
  27. 是一种特殊的字符串,以删除字符(ASCII 127)开始。例如,{{#tag:}}会被转化为\127'"`UNIQ--tagname-8 hex digits-QINU`"'\127 。 ——来自于[9]
  28. 指的是不需要左右闭合的标签,例如<br>等。<br><br />可能会被认为是错误的。
  29. 语言代码在是MediaWiki合法的语言简写,MediaWiki使用这些代码来区分语言。
  30. 例如“中文”,“English”,“日本語
  31. 有些语言具有依赖语言。如果MediaWiki不能支持当前语言,会使用依赖语言。详见[10]
  32. mw.language.isValidCode下返回true。
  33. 分别为“千年”“百年”“十年”“年”“星期”“天”“小时”“分钟”“秒”。
  34. 语言学术语,是词形变化的一种。
  35. 语言学术语。
  36. 部分名词解释详见帮助:名字空间
  37. 所有命名空间都有一个通用于所有wiki的“规范(canonical)”前缀。——来自[11]
  38. 详见Help:高级编辑#链接,超链接
  39. 协议相关是这样的。对于一个页面<code>//example.com/wiki/Foo</code>,被HTTP协议的页面访问此页面,解析器会将其视为http://example.com/wiki/Foo,在HTTPS协议的页面访问请求下,解析器视为https://example.com/wiki/Foo,那么,这个页面是协议相关的。 ——翻译自页面[12]
  40. 嵌入,指的是把一个文档的内容引用到另一个文档中。
  41. 在SGML、 HTML与XML文档,如果某些Unicode字符在文档的当前编码方式(如ISO-8859-1)中不能直接表示,那么可以通过字符值引用或者字符实体引用两种转义序列来表示这些不能直接编码的字符。 下文列出在HTML与XML文档中有效的字符实体引用。 ——维基百科页面[13]
  42. 指的是列表等数据结构中最后一个元素后面的逗号,例如[1,2,3,]中3后面出现的逗号。
  43. 原文并未说明是什么样的技巧,翻译者注。
  44. 同2222行的注解。