本页面之全部或部分原来自MediaWiki的[14],依 CC BY-SA 3.0 授权引入;原贡献者可以在这里看到。 |
本页面介绍的是在萌娘百科上使用的Lua参考手册。其中部分内容取自MediaWiki及Lua5.1参考手册。
首先在模块
名字空间下创建一个页面,例如:模块:HelloWorld。
将以下代码复制到这个页面中:
-- 模块:HelloWorld local p = {} -- p表示一个包(package) function p.say( frame ) return "Hello, world!" end return p
保存更改后,在另一个(不在模块
名字空间下的)页面中编写:
{{#invoke:HelloWorld|say}}
这样就成功调用了HelloWorld
模块公开的say
函数。调用的输出结果为:Hello, world!
。
如果想要调用另一个模块,只需要将HelloWorld
替换成那个模块所在页面的名称(不带模块:
名字空间前缀)即可。
从模板调用Lua代码有诸多优势,一个问题的解决方法并不局限于解决它所使用的语言到底是wiki还是Lua。从总体上而言,wiki代码与Lua代码协同工作,各自独立的同时保持整体统一。从模板的角度而言,它允许了将复杂的代码逻辑放在Lua模块中实现,从而增强了wiki代码的可读性。
简单而言,模块本身必须返回一个表(table),这个表包含了所有能被{{#invoke:}}
调用的函数。一般来说,如上所示,先声明一个局部变量表,再将函数写在这个表中,最后把这个表返回。
{{#invoke:}}
只能调用类型为function
的变量,试图调用其他类型(括table
、string
、number
等)都会抛出一个错误。
没有加到这个表中的函数,无论是局部的还是全局的,对于隔着{{#invoke:}}
的“外部”调用页面来说都是无法访问的。但需要注意的一点是,当你在一个模块中申明了一个全局变量,当你在其他模块中require()此模块时,这个全局变量也能够被访问到。因此对于模块来说,最好将所有的函数和变量声明为局部变量,以防覆盖到其他模块中的同名变量的作用域,引发难以发现的错误。
从外部通过{{#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)来配置被关联为模块的文档:
$1
传递。如果是在模块名字空间的话,在这里确定的页面会被解读为维基文本(wikitext),而不是Lua源文件,也不会在{{#invoke}}
被调用时使用。默认设定是"Module:$1/doc",也就是/doc子页面。需要注意的是,解析器函数(parser function)和花括号扩展(brace expansion)可能无法在这个消息中使用。$1
传递。默认为空。$1
传递。默认是嵌入文档页。$1
传递。默认是仅仅以斜体显示简短的解释。
注意:模块不能被直接分类,也不能直接加入维基内链(interwiki link)。你可以把这些内容加入到文档页面的标签(tag)<includeonly>...</includeonly>
中,这样这些内容会被插入到模块页面。
在Lua中,变量名(也叫做“标识符”)可以是字母、数字和下划线的任意组合,但不能以数字开头。变量名是大小写敏感的,即foo
、Foo
和FOO
都是各不相同的变量名。
以下是Lua保留的关键字,我们定义的变量名不应该与它们相同:
and
break
do
else
elseif
end
false
for
function
if
in
local
nil
not
or
repeat
return
then
true
until
while
还有一些形似下划线+大写字母的变量名作为Lua的内部全局变量而被保留。
其他的符号有:
#
%
(
)
*
+
,
-
.
..
...
/
:
;
<
<=
=
==
>
>=
[
]
^
{
}
~=
--
为起始,一直持续到这一行的末尾。--
后紧跟一个形似“左方括号[
+0或多个等号=
+左方括号”的片段,则表明这段注释可以包含多行内容,直到遇到一个形似“右方括号]
+对应数量的等号+右方括号”的片段为止。注释不能写在字符串中,那样会使它成为字符串的一部分。
-- 单行注释:以两个中横线为起始,一直持续到这一行的末尾。 --[[ 多行注释 被限制在两层方括号的范围内。 ]] --[=[ 你可以在两层方括号间添加任意数量的等号,使得多行注释能够互相嵌套且不会重叠混淆。 ]=] --[==[ 更多等号的多行注释 --[===[ 内部的更更多等号的多行注释 --[=[也能包裹更少等号的内部注释]=] --以及单行注释 ]===] 甚至还能包裹等号数量不对应的多行注释 --[[ 只要内部的右侧等号数量不与外层的左侧等号数量相同即可 ]===] ]==]
Lua是动态类型语言,这意味着所有变量或函数参数都没有类型,只有值才拥有类型。所有值都有类型。
Lua有8种基本数据类型,然而只有六种在编写模块时会用到。type()
函数会以字符串形式返回一个值的类型。
tostring()
函数会将一个值转化为字符串。tonumber()
函数会在可能时将值变为数字,如果不能则返回nil。没有其他专门的函数转化一个值为其他类型
Lua会自动进行类型转换。当需要字符串,如级联时,数字会自动转为字符串。当对字符串进行数学运算时,Lua会尝试将其转为数字。当需要布尔值时,所有nil和false之外的值都会被认定为真。
nil是空值类型,是“为了不存在的值而存在的数据类型”。nil没有指针。
nil不能用作表(table)的键(key),并且表中不存在的域就是nil。
转化为字符串时,nil转化为"nil"。转化为布尔值时,nil被认定为假。
布尔类型是true
和false
。
当被转化为字符串时,转化结果是"true"或"false"。
和其余编程语言不同,布尔类型不能直接转化为数字类型;进行布尔类型转换时,只有false和nil会被转化为是false,数字0和空白字符串都会转化为true。
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。
Lua只有一种数字类型,通常被表示为双精度浮点型。在这种格式下,-9007199254740992和9007199254740992中的数字可以精确表示。更大的数字和带有小数部分的数字可能会有舍入错误(round-off error)。
数字常量使用英文句号(period)(.
)作为十进制分隔符,不需要分组分隔符,例如123456.78
。数字可以使用E记号表示,无需空格,比如1.23e-10
,123.45e20
, or 1.23E5
。整数也可以使用十六进制前缀0x
表示,例如0x3A
。
NaN和正无穷和负无穷是被正确地的方式储存和处理的,Lua没有提供名字叫NaN的常量。常量math.huge
是正无穷,等同于除法1/0
。除法0/0
可以快速生成一个NaN。
需要注意的是,进行布尔类型转化的时候,所有的数字都会转化为true。这和大多数把0转化为false的语言不同。当转化为字符串的时候,NaN会转化为nan
或者-nan
,无穷会被转化为inf
或者-inf
;有穷数字会转化为十进制数字,可能会使用E记号。
Lua的表(tabe)是关联数组,和PHP的array和JavaScript中的object很相似。
通常使用花括号创建表。空表是{}
。为了创建时填充字段,可以在大括号中包括以括号和/或分号分隔的字段说明列表。有以下几种形式。
[expression1] = expression2
将expression1的(当前)元素作为键(key),expression2的(当前)值作为在当前键下的值(value)。[2]name = expression
相当于 ["name"] = expression
expression
大致相当于 [i] = expression
, 其中i是从1开始的数字,每次使用这段代码填充字段i都会递增。如果这段代码作为最后一个字段出现,且expression有多个值,那么所有的值都会使用,否则只保留第一个值。
表中的值可以通过中括号来访问,例如table[key]
。字符串键也可以通过符号点来访问,例如table.key
和table['key']
等同。调用是表中的值的函数使用冒号,例如table:func( ... )
,table['func']( table, ... )
和table.func( table, ... )
等同。
一个数组(或序列,sequence)是这样的表,对于所有的从1到N的正整数,其值均为非零,对于大于N的所有正整数,其值均为无值(nil)。许多Lua的函数只在数组上运行,并且忽略所有非正整数的键。
与PHP和JavaScript不同,除了nil和NaN的的所有值都可以都可以被用作键,这些键都是合乎语法且不同的。下面的示例展示了一些可以作为键的类型。
-- 创建表 t = {} t["foo"] = "foo" t.bar = "bar" t[1] = "one" t[2] = "two" t[3] = "three" t[12] = "the number twelve" -- 数字12 t["12"] = "the string twelve" -- 字符串12 t[true] = "true" --布尔类型 t[tonumber] = "yes, even functions may be table keys" -- 即使函数类型也可以作为表的键 t[t] = "yes, a table may be a table key too. Even in itself." -- 表类型也可以作为表的键,甚至这个表本身。 -- 下面的代码创建了一个和上面的表大体等同的表。 t2 = { foo = "foo", bar = "bar", "one", "two", [12] = "the number twelve", ["12"] = "the string twelve", "three", [true] = "true", [tonumber] = "yes, even functions may be table keys", } t2[t2] = "yes, a table may be a table key too. Even in itself."
除了nil以外的值,在表中都可以作为值存储。存储nil相当于删除这个键,访问没有被设定的键都会返回nil。
要注意,表被传入为一个函数作为参数的时候,并不是复制一个新表作为参数。在调用这个函数的函数里,原始的参数也改变了。以下伪码可以帮助你理解。[3]
function f(tbl) print("第二次打印",tbl[1]) tbl[1] = 2 print("第三次打印",tbl[1]) end t = {} t[1] = 1 print("第一次打印",t[1]) f(tbl) print("第四次打印",t[1])
输出结果应该是
当一个表被转化为字符串时,结果通常是"table"。除非__tostring
元方法[4]被重写。所有的表,即使是空表也会被当做布尔类型的true。
Lua的函数是上等公民。它们可以被匿名创建,作为参数传递,分配给变量等。
函数通常使用function
关键字创建,通过圆括号调用(call)。对于实名函数(named function),本地函数(local function)和作为表的成员的函数,Lua提供了语法糖,详见 函数声明 和 函数调用 等部分。
Lua的函数是闭包。函数包括声明这个函数的名字空间的一个引用,并且可以访问和操纵这个名字空间的变量。
像表一样,如果一个函数赋值给一个变量,或者作为函数的参数传递,它仍然是可以被调用的"函数对象"。
当被转化为字符串时,转化结果是"function"。
自定义(userdata)类型被用来保存不透明值,其他语言可以用它来扩展Lua。例如,自定义类型可以被用来存储C语言的指针或者结构体。为了允许Scribunto搭建Lua环境,自定义编译代码不被允许,也没有这样的扩展使用。
线程(thread)类型表示协同程序(coroutine)的句柄,在Scribunto沙盒中不允许使用。
每个表都可以与一个叫元表(metatable)的表相关联。元表可以被一些运算符和函数使用,为表指定不同的行为。一个表的元表可以使用getmetatable() 函数获得,使用setmetatable() 函数设置。
元表中的数据可以直接被元函数(meta function)获取,就像被使用rawget()函数获取一样。
可以影响元表本身的字段如下:
[key]
访问表,本应该返回nil的时候,会调用本元字段。如果本元方法是一个表,那么就会像这样__index[key]
访问这个表。(这可能会套娃调用这个表的元表的__index)。如果这个元字段是一个函数[5],那么就会像这样__index( t, key )
调用这个函数。rawget()函数会绕过本元字段。t[key] = value
代码给表中的一个键复制,但是rawget( t, key )
会返回nil的时候[6],本元字段会被调用。如果这个元字段是一个表,那么就会像这样__newindex[key] = value
调用这个表也可能出现和上面一样的套娃情况。如果本元字段是一个函数,那么就会像这样__newindex( t, key, value )
调用这个函数。rawset()函数会绕过本元字段。t( ··· )
,会调用本元字段。本元方法的值一定是一个函数,可以像是__call( t, ··· )
被调用。[7]
以下是其余的元字段。
注意:在Lua,所有的字符串共用一个元表,这个元表的__index对应着string
表。这个元表在Scribunto不可访问,不可被引用。模块只能访问它的复制。
变量用来储存值。Lua有三种变量:全局变量,局部变量(本地变量),表的字段。
一个变量名代表一个全局变量或者局部变量(或者函数参数,它也是一种局部变量)。变量默认是全局变量,除非使用local
指定为局部变量。所有没有被指定值的变量都会默认值为nil。
全局变量储存在一个叫做全局表的Lua标准表中。这个表可以通过全局变量_G
访问。可以为这个表设定元表。访问全局变量相当于,访问全局表下,以变量名为字段下的值,所以访问全局变量时,__index和__newindex元方法会像普通的表被访问时一样被调用。
函数的变量环境(environment)可以用getfenv()函数访问,用setfenv()函数修改。在Scribunto中,这些函数被严格限制。
局部变量是有词法范围的,详见局部变量声明。
表达式是有值的:字面量(数字,字符串,true,false,nil),匿名函数声明,表构造表达式,变量的引用,函数调用,参数表达式,用括号括起来的表达式,结合一元运算符的表达式,被二元运算符连接的表达式等。
大多数表达式只有一个值。函数调用和参数表达式可以有多个值。需要注意,被圆括号括起来的函数调用和参数表达式会丢失除了第一个值以外的值。
exp-list
表达式列表是用逗号分隔的一系列表达式。表达式列表会包括最后一个表达式的所有值,强制除最后一个值的其余值为单值(舍去多出来的值,或用nil代表空值)。
Lua支持基本的算术运算:加法、减法、乘法、除法、求模(取模)、乘方和取相反数。
当所有的运算对象都是数字,和tonumber()函数处理后返回非nil值的字符串时,运算会正常进行。
如果运算对象是有正确重载的元方法的表时,会调用元方法。
运算符 | 操作 | 示例 | 元方法 | 注释 |
---|---|---|---|---|
+ | 加法 | a + b | __add | |
- | 减法 | a - b | __sub | |
* | 乘法 | a * b | __mul | |
/ | 除法 | a / b | __div | 除0不会报错,而是会返回NaN或无穷大。 |
% | 求模 | a % b | __mod | 被定义为 a % b == a - math.floor( a / b ) * b
|
^ | 乘方 | a ^ b | __pow | 允许非负整数作为幂指数 |
- | 取相反数 | -a | __unm |
Lua的关系运算符包括==
, ~=
, <
, >
, <=
, and >=
。关系运算符返回布尔值。
等于(==
)会首先判断操作数的类型,如果是不同类型,返回false。对值进行比较。nil,布尔类型,数字,字符串会正常比较。只有当两个函数是同一个函数对象时,返回true。function() end == function() end
会返回false,因为它们是两个不同的匿名函数。表会默认按照同样方式比较,元方法__eq被重载时除外。
不等于 (~=
) 的结果是对等于的结果取反。
对于顺序运算符,如果两端是数字和字符串,会直接进行比较。[10]否则会检查是否有可用的元方法。
a < b
: 使用 __lt
a <= b
: 如果可用的话默认使用 __le
,否则使用__lt
,等价于not ( b < a )
a > b
: 相当于 b < a
a >= b
: 相当于 b <= a
如果没有可用的元方法,会抛出(raise)异常(error)。
逻辑运算符是and
,or
和not
,它们的返回值都是布尔类型。只有nil和false会被当做false,其他的都会被当做true。
and
:如果左运算对象是false,直接返回false,否则返回右运算对象。
or
:如果左运算对象是true,直接返回true,否则返回右运算对象。
not
:返回结果总是true或false。
注意and
和or
有短路特性。例如,foo() or bar()
如果foo()
返回true,bar()
不会被执行;只有foo()
返回false时,会执行bar()
连接(级联)运算符是两个点,像这样a .. b
。如果两个运算对象都是数和字符串,它们会都转化为字符串,然后连接。否则,如果可用的话使用__concat元方法元方法,否则会抛出异常。
在Lua中,字符串时不可变对象,Lua不提任何种类的"string builder"。所以重复执行代码a = a .. b
,会在每次循环新建一个字符串,并垃圾回收旧字符串。如果需要连接很多字符串,使用string.format()函数,或者把所有字符串放到一个数组里,使用table.concat(),会更快。
长度运算符是#
,使用方法是#a
。如果a
是一个字符串,它会返回字节长度。如果a
是一个数组,那么会返回数组长度。
如果a
是一个表,但不是一个数组,那么#a
会返回满足一下条件的N值,使得a[N]不是nil,a[N+1]是nil。
-- 这不是数组,因为a[3]是nil,但是a[4]不是 a = { 1, 2, nil, 4 } -- 可能输出2或4 -- 即使这个表没有被改变,输出结果也可能会不同。 mw.log( #a )
Lua的运算符优先级,从高到低:
在同一优先级,二进制运算符是左结合的,也就是说a / b / c
被解释为(a / b) / c
。乘方和级联是右结合的,也就是说a ^ b ^ c
被解释为a ^ (b ^ c)
。
函数调用和大多数语言一样,函数名后面是小括号括起来的表达式列表。
func( expression-list )
像Lua通常那样,表达式列表最后一个表达式可能提供多个值。
如果调用函数时,提供的参数个数比需要的参数个数(函数定义时指定的参数个数)少,没有提供的参数将会是nil值。如果提供参数比需要的参数多,那么多出来的参数会被截断。函数也可以有可变个参数,详见函数声明。
Lua也允许一个函数作为函数的返回值,像这样func()()
。[11]为了确认被调用的函数,有时需要比变量访问还要复杂的表达式,可以使用括号表达式来代替变量访问。
Lua在以下两种情况有语法糖。一种是当表作为一个对象(object)访问时。这时函数可以作为表的一个方法。下面的语法
table:name( expression-list )
相当于
table.name( table, expression-list )
Lua的第二个语法糖是关于传递命名参数的。如果传入的参数是一个包括参数名-参数值映射的表,作为唯一一个位置参数,那么可以省略小括号。如果传入的是单个字符串也可以这样。例如
func{ arg1 = ''exp'', arg2 = ''exp'' } func"string"
相当于
func( { arg1 = ''exp'', arg2 = ''exp'' } ) func( "string" )
这两个语法糖可以合并,像这样。
table:name{ arg1 = ''exp'', arg2 = ''exp'' } table.name( table, { arg1 = ''exp'', arg2 = ''exp'' } )
下面是函数声明的语法。
function ( ''var-list'' ) ''block'' end
所有参数列表中的变量对于函数来说都是局部变量,这些变量可以在函数调用是确定。函数体(block)中可以声明局部变量。
函数调用,在参数列表确定值之后,函数体的会执行。如果执行到了return语句时,会直接退出函数体,return语句的返回值即为函数的返回值。如果函数执行到了函数体的底端,但是没有遇到return语句,函数会返回空值。
Lua的函数是词法闭包的。一个是,函数在被声明的作用域中,会将“静态私有”变量看作为局部变量。例如,
-- 这个函数返回一个用来在增加一个数到它的参数上的函数。 function makeAdder( n ) return function( x ) -- 在这个函数外部的变量n,在这个函数里是可获得的。 return x + n end end local add5 = makeAdder( 5 ) mw.log( add5( 6 ) ) -- 会打印 11
函数可以接受可变个参数,通过将变量表达式...
[12]作为参数列表的最后一个。
function ( ''var-list'', ... ) ''[[#block|block]]'' end
在函数体里,可以使用变量表达式,变量表达式的值是所有多出来的变量。例如,
local join = function ( separator, ... ) -- 将多出来的参数转化为表。 local args = { ... } -- 获取多出来的参数的个数 local n = select( '#', ... ) return table.concat( args, separator, 1, n ) end join( ', ', 'foo', 'bar', 'baz' ) -- 返回字符串"foo, bar, baz"
select()函数用来处理参数表达式。通常,应该使用select( '#', ... )
而不是#{ ... }
,因为{ ... }
可能并不是一个序列。
Lua提供了将声明函数和函数赋值给变量两者结合到一起的语法糖,详见 函数声明语句。
下面的代码不会运行。
local factorial = function ( n ) if n <= 2 then return n else return n * factorial( n - 1 ) end end
因为函数声明是在函数赋值给factorial变量之前实现的,所以在函数声明结束之前,factorial并没有被赋值,函数体内的"factorial"指的并不是被赋值的那个变量。这时函数内部的factorial可能指的是外部名字空间中的可能存在的名字叫factorial的变量。为了避免这种情况,可以先声明本地变量,然后把函数赋值给这个变量,或者使用函数声明语句语法。
语句(statement)是代码运行时的基本单元:赋值、结构控制、函数调用、变量声明等。
一个chunk是一串代码。它们通常可以选择被分号隔开。chunk可以被用作匿名函数的函数体,所以在chunk里,可以声明局部变量,接受参数和返回值。
一个block像chunk一样,也是一串代码。通过下面的语句可以创建一个block,do block end
。这样可以限制变量的作用域,或者在其余block中加入return
或者break
语句。[13]
variable-list = expression-list
变量列表(variable-list)是用逗号隔开的一系列变量,表达式列表是一个或多个表达式。所有的表达式会在被赋值之前计算,所以a, b = b, a
会交换a和b的值。
local variable-list
local variable-list = expression-list
局部变量可以在一个block或者chunk中声明。上面的第一种声明形式,仅仅声明了变量,但并没有赋值,所以它们的值都是nil。第二种声明形式对变量进行了赋值。
需要注意的是,局部变量在声明之后才可见(visible)。所以像这样的声明 local x = x
,声明了一个局部变量叫x,给这个变量赋的值是外部名字空间的x的值。在包含这个局部变量的代码块结束之前,这个局部变量保持可见。
while exp do block end
只要exp表达式是true值,就会一直重复block内的内容。
repeat block until exp
直到exp运算出来的值是true之前,不断重复block的内容。
for name = exp1, exp2, exp3 do block end
for name = exp1, exp2 do block end
第一种for循环会声明一个名字叫name的局部变量,这个变量的初始值是exp1,每次循环都会加exp3到这个变量,直到它大于exp2。(如果exp3是负数正好相反)。exp3可以被省略,相当于是1。如果exp1,exp2,exp3其中之一是非数字值,例如nil
和false
,会抛出异常。所有的值都会被在循环开始之前提前计算。
除了变量var,limit,step不能被访问以外,这种for循环大体上相当于下面的代码
do local var, limit, step = tonumber( exp1 ), tonumber( exp2 ), tonumber( exp3 ) if not ( var and limit and step ) then error() end while ( step > 0 and var <= limit ) or ( step <= 0 and var >= limit ) do local name = var block var = var + step end end
需要注意,变量name对于这个代码块是局部变量。如果需要在循环后使用这个变量的值,需要赋值给循环外的变量。
for var-list in expression-list do block end
第二种for循环和迭代器(iterator)函数共同使用。像第一种形式一样,表达式只有循环开始之前会被计算一次。
除了变量func,static,var不能被访问以外,这种for循环和下面的大体上等同。
do local func, static, var = expression-list while true do local var-list = func( static, var ) var = var1 -- ''var1'' is the first variable in ''var-list'' if var == nil then break end block end end
注意,var-list中的变量对于代码块来说是局部变量。如果想在循环之外使用这些变量的值,需要赋值给循环外的变量。
通常,expression-list是一个返回三个值的函数调用,如果这个迭代器函数仅仅依靠传入的参数来写入的话,会更高效。如果不能的话,Programming in Lua建议使用一个闭包,来返回一个表作为静态变量,每次循环时刷新这个表的成员的值。
if exp1 then block1 elseif exp2 then block2 else block3 end
如果exp1为true,运行block1,否则,如果exp2为true时,运行block2,否则运行block3。else block3
部分可以被省略,elseif exp2 then block2
可以被省略或重复多次。
return expression-list
return语句用来从函数或者chunk(其实也是一个函数)返回值。expression-list是用逗号隔开的零个或更多个表达式。
Lua的尾调用[14]:如果expression-list包括恰好一个函数调用,这个函数调用时,当前的栈帧会被重用。这在处理调用栈的函数上有应用。例如getfenv()
和 debug.traceback()
函数。
return语句必须是block中最后一条语句。如果需要在代码中间需要return语句,可以使用代码块do return end
。
break
break语句用来跳出一个while、repeat、for循环,跳过循环内后面的语句。
break语句必须是代码块最后一个语句。如果需要在代码中间需要break语句,可以使用代码块do break end
。
函数调用可以作为语句。这时函数仅仅因为函数调用的副作用被调用(例如mw.log()中的),返回值会被忽略。
Lua提供了语法糖,可以使函数声明和函数实现更加自然。下面的语句等价。
-- 基本声明 function func( ''var-list'' ) ''[[#block|block]]'' end func = function ( ''var-list'' ) ''[[#block|block]]'' end
-- 本地函数声明 local function func( ''var-list'' ) ''[[#block|block]]'' end local func; func = function ( ''var-list'' ) ''[[#block|block]]'' end
-- 函数作为表的一个字段 function table.func( ''var-list'' ) ''[[#block|block]]'' end table.func = function ( ''var-list'' ) ''[[#block|block]]'' end
-- 函数作为表的一个方法 function table:func( ''var-list'' ) ''[[#block|block]]'' end table.func = function ( self, ''var-list'' ) ''[[#block|block]]'' end
注意,这里的冒号和函数调用时的冒号,都将叫做"self"的参数加入到函数的第一个参数里。
可以通过error()和assert()来抛出(throw/raise)异常。为了捕获(catch)异常,使用pcall() 或 xpcall()。需要注意,有些Scribunto内部异常不能在Lua代码中捕获。
Lua自动管理内存。这意味着你无需手动管理和释放内存。Lua通过时不时运行垃圾收集器(garbage collector),收集不再使用的对象,和只能通过弱引用来获取的对象。所有的内存对象都会自动内存管理:表,函数,字符串等。
垃圾自动进行收集,无法被Scribunto配置。
Lua标准库(standard library)提供了基本服务和对性能关键的函数。下面只记录了Scribunto可用的标准库部分。
这个变量持有一个当前全局变量的引用。全局变量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 } )
一个字符串,包括当前运行的Lua的版本。例如"Lua 5.1".
assert( v, message, ... )
如果v
是nil或者false,提交一个异常,这时,参数message
被用作error的错误文本(text):如果是nil(或未指定),错误文本是"assertion failed!",如果是一个字符串或者数字,错误文本即为该值;否则assert本身会抛出异常。
如果v
是其他值,assert会返回,包括v
和message
在内的所有参数。
在Lua常用做法是,通过函数的返回值来判断函数是否正常运行。如果返回值是"true"值,说明函数正常运行,未正常运行返回nil或者false作为第一个返回值,错误信息作为第二个返回值。错误检查可以通过函数调用来实现。
-- 下面的代码,不会检查函数是否运行错误 local result1, result2, etc = func( ... ) -- 下面的代码和上面的相同,但是会检查运行错误 local result1, result2, etc = assert( func( ... ) )
error( message, level )
提交一个异常,它的文本是message
。
error
通常会加入错误抛出地点的一些信息。如果level
是1或者被省略,那样这个信息是error
自己的位置。2是,信息是一个函数的位置,这个函数抛出了异常。以此类推。[15]level
为0,省略位置信息。
getfenv( f )
这个函数可能会失效,取决于allowEnvFuncs
工程配置。
返回一个全局表(global variable table)。f
用来指定:
getfenv
函数的变量环境(environment)。通常这个结果和_G相同。
标准库函数和Scribunto库函数中的函数的运行环境首刀保护。使用getfenv
函数获取它们的环境会返回nil。
getmetatable( table )
如果元表已有__metatable
字段,将会返回这个值,而不是这个表的元表。
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( table, key )
这个函数允许遍历(traversal)表的键。如果key
的值为0或者未指定,返回这个表的“第一个”键和它的值,否则,返回“下一个”键和它的值。如果所有的键都被迭代过,返回nil。通过表达式next( t ) == nil
可以判断一个表是否为空表。
注意,一个表的键按照什么顺序返回并没有指定。即使这个表的键都是数字。如果想按照数字顺序遍历表,使用numerical for 或 ipairs。
如果在使用next遍历时,给原本不存在的键赋值时,会产生未定义行为。但是,给一个已存在的键赋值,即使给赋nil值,也是允许的。
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( 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( a, b )
这个函数相当于a == b
,但是会忽略__eq元方法。
rawget( table, k )
这个函数相当于table[k]
,但是会忽略__index元方法。
rawset( table, k, v )
这个函数相当于 table[k] = v
,但是会忽略__newindex元方法。
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( table, metatable )
给一个表设置元表,metatable
可以为空,但是必须明确改名。
如果当前元表有__metatable字段,setmetatable
会抛出异常。
tonumber( value, base )
尝试将value
转为为数字。如果是数字或者可以转化为数字的字符串,那么tonumber
返回这个数字,否则返回nil。
可选参数base
(默认为10)指定进制。base
可以是2到36之间的数字,如果base大于10,字母'A'(大小写均可)表示10,'B'表示11,'Z'表示35,以此类推。
十进制下,value
可以小数部分,或用E记号表示,十六进制下,可以有前缀"0x"。在其他进制下,只能接受无符号整数。
tostring( value )
将value
转化为字符串。对于如何进行转化,详见Data types。
元方法__tostring可以改变这个函数的行为。这个元方法存在,会返回来自于__tostring( value )
的单个值。
type( value )
以字符串形式返回value
的类型。nil
, number
, string
, boolean
, table
, 或 function
.
unpack( table, i, j )
像这样返回指定表中的多个值,table[i], table[i+1], ···, table[j]
。如果参数是nil或未指定,i
默认为1,j
默认为#table
。
注意,如果table
不是序列,或者j
为nil或未指定,返回结果可能不确定,详见长度运算符。
xpcall( f, errhandler )
这个函数和pcall
很相似,只是会在异常信息返回之前,传递给errhandler
函数。
这个函数大致相当于下面的 伪码。
function xpcall( f, errhandler ) try return true, f() catch ( message ) message = errhandler( message ) return false, message end end
debug.traceback( message, level )
这个函数返回一个字符串,对函数的调用栈帧进行回溯。可选的message字符串会被加到输出结果最前面。可选的level
数字指定,开始回溯的栈高度。
math.abs( x )
返回x
的绝对值。
math.acos( x )
返回x
的反余弦值(弧度制)。
math.asin( x )
返回x
的反正弦值(弧度制)。
math.atan( x )
返回x
的反正切值(弧度制)。
math.atan2( y, x )
返回y/x
的反正切值(弧度制),通过参数的正负来确定返回值的象限。
math.ceil( x )
返回大于等于x
的最小整数(向上取整)。
math.cos( x )
返回x
的余弦值(弧度制)。
math.cosh( x )
返回x
的双曲余弦值。
math.deg( x )
将弧度制x
转化为角度制。
math.exp( x )
返回 <math>e^x</math>的值。
math.floor( x )
返回小于等于x
的最大整数(向下取整)。
math.fmod( x, y )
取余:返回x
除以y
后,向0方向取余数的结果。例如,math.fmod( 10, 3 )
结果是1
。[17]
math.frexp( x )
返回满足以下条件的m
和e
值。
x
非0有穷,<math>x = m \times 2*e</math>,其中,e
是整数,m
的绝对值在<math>[0.5, 1)</math>范围内。x
为0,m
和 e
均为0。x
是NaN或无穷大, m
is x
and e
未指定。这个值表示正无穷大,它大于等于其余数值。
math.ldexp( m, e )
返回 <math>m \times 2^e</math> (e
应为整数).
math.log( x )
返回 x
的自然对数值。
math.log10( x )
返回以10为底的 x
的对数值。
math.max( x, ... )
返回传入参数的最大值。
传入NaN的行为不确定。当前[18],如果第一个参数x
是NaN,会返回NaN,其余的NaN会忽略。
math.min( x, ... )
返回传入参数的最小值。
传入NaN的行为不确定。当前(同上),如果第一个参数x
是NaN,会返回NaN,其余的NaN会忽略。
math.modf( x )
返回两个值,分别是x
的整数部分和小数部分。例如,math.modf( 1.25 )
结果是1, 0.25
。
<math>\pi</math>的值。
math.pow( x, y )
相当于x^y
.
math.rad( x )
将角度值x
转化为弧度制。
math.random( m, n )
返回一个伪随机数。
m
和n
可以省略,但是它们必须是整数值。
math.randomseed( x )
将x
设置为伪随机数生成器的种子。
注意,相同的种子会导致函数math.random
生成相同的随机数序列。
math.sin( x )
返回x
的正弦值(弧度制)。
math.sinh( x )
返回x
双曲正弦值。
math.sqrt( x )
返回x
的平方根,相当于x^0.5
。
math.tan( x )
返回x
的正切值(弧度制)。
math.tanh( x )
返回x
的双曲正切值。
os.clock()
返回这个程序使用CPU的大致时间,以秒为单位。[19]
os.date( format, time )
返回一个包括时间和日期的字符串或表,通过format
确定格式。如果format
被省略或为nil,默认为"%c"。
这个函数会对给定的time
,进行格式转化。如果没有给定,会转化当前时间。
如果format
以'!'开头,时间会转化为UTC而不是用户所在时区的时间。如果format
是字符串"*t",会返回右以下字段的表。
如果format
不是"*t",这个函数会和C语言函数strftime遵循同样规则返回。[20]
os.difftime( t2, t1 )
返回从t1
到t2
两个时间之间的秒数。[21]
os.time( table )
返回一个数字表示当前时间的值。
如果该函数不带参数调用,返回当前时间。如果传入的是一个表,会返回这个表表示的时间。这个表必须有字段"year","month"和"day",也可以包括字段"hour"(默认为12),"min"(默认为0),"sec"(默认为0)和"isdst"。
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!'
这个表保存已被加载的包。键为包的名字,值为包被加载时的返回值。
这个表保存用来加载包的搜索器函数(searcher function)的序列。每个搜索器被调用时仅传入一个参数,是被加载的包的名字。如果包被找到,搜索器必须返回一个可用来加载这个包的函数,并把会被require会返回的值返回。否则,返回nil。
Scribunto提供两个搜索器:
package.preload[modulename]
搜索加载器函数。
注意,Lua标准中的加载器未被 提供。
这个表提供加载器函数,它们被Scribuntopackage.loaders第一个搜索器使用。
package.seeall( table )
将表table
的__index元方法设定为_G。
在所有的字符串函数中,第一个字符在位置 1,而不是像C,PHP,JavaScript一样在位置0.下标可以为负数,表示从字符串最后一个字符倒数。位置 -1表示倒数第一个字符,-2是倒数第二个。
Warning: string library假定字符串编码为1个字节,不应用来处理Unicode字符。如果处理Unicode字符,使用Scribunto Ustring library中的方法。
部分函数可能需要#Patterns为前置知识。
string.byte( s, i, j )
将字符串看作字节的数组,返回字节值s[i]
, s[i+1]
, ···, s[j]
。i
的默认值为 1;j的默认值为j
is i
。和mw.ustring.byte()相似。
string.char( ... )
接受0个或更多个整数。返回一个长度是参数个数的字符串,对应的字符的字节值为对应的参数。
local value = string.char( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21 ) -- value的值为'Hello!'
使用Unicode码点(codepoint)而不是字节值的类似的函数详见mw.ustring.char()。
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( formatstring, ... )
返回一个字符串。这个函数将其可变个的参数,按照第一个参数(必须是字符串)的指示,进行格式化处理。
这个函数格式化字符串使用printf
格式化说明符[24],但是有以下限制。
长度修饰符 'q' 类似于 's',可以转化字符串为,Lua解释器可以安全读取的形式:字符串会在双引号间写入,所有的双引号,换行符,嵌入的0和反斜杠会被转义。
字符串和数字,按照数据类型转化。其余类型不会自动转化为字符串。包含NUL('\0')的字符串(字节码0)不会被正确处理。[25]
string.gmatch( s, pattern )
返回一个迭代器函数,每次调用时,返回s
中,pattern
中的下一个捕获。如果pattern
中没有捕获,那么每次调用会返回整个匹配。
对于这个函数,在匹配模式中的最开始的'^
'不会解释为魔法字符,而会被看作为普通字符,因为这样会避免迭代。
对于匹配模式是真正按照描述的那样工作的,参见Ustring patterns章节中的mw.ustring.gmatch()。
string.gsub( s, pattern, repl, n )
返回s
的复制品,其中所有的(前n个,如果给定n的话)与pattern
匹配的匹配会被替换为repl
,它可以是一个字符串,表,或者函数。gsub
也会把匹配总数作为第二个参数返回。
如果repl
是一个字符串,则会把这个字符串用来替换。repl
中, %
作为转义字符。符合格式%n
的repl
子串,其中n是从1到9的数字,表示第n个被捕获的子串。%0
表示整个匹配,%%
表示单个 %
。
如果repl
是一个表,会在每次匹配时访问这个表,将第一个捕获作为键。如果匹配模式中没有捕获,则会把整个匹配用作键。
如果repl
是一个函数,这个函数会每次匹配时调用,所有的捕获会按照顺序作为参数传入。如果匹配模式没有捕获,会将整个匹配作为唯一的参数传入。
如果repl
的返回值是一个字符串或者数,会被用来字符串替换,否则,如果是false或nil,并不会发生替换,也就是说,原本的匹配会留在字符串。
对于Ustring patterns中类似函数,参见mw.ustring.gsub()。
string.len( s )
按照字节返回字符串的长度。这个函数不会被ASCII NUL字符干扰。相当于code style="white-space:nowrap">#s。
对于类似功能,使用Unicode码点而不是字节的函数,参见 mw.ustring.len() 。
string.lower( s )
返回字符串的复制,其中,其中所有的ASCII大写字母会被转化为小写字母。其余字符不会被转化。
对于类似功能的函数,详见mw.ustring.lower() ,其中Unicode定义的所有的大写字母都会转化为小写字母。
string.match( s, pattern, init )
寻找字符串中第一个匹配pattern
的陪陪。如果找到了一个,返回这个匹配的捕获。否则返回nil。如果匹配中无捕获,则返回整个匹配。
可选参数init
指定从哪里开始查找。这个值默认为1,可以为负数。
对于Ustring patterns中相似函数,详见mw.ustring.match()。其中init
下标是按照字符而不是字节计算。
string.rep( s, n )
返回一个字符串,是n
个s
连接在一起。与mw.ustring.rep()相同。
string.reverse( s )
返回一个字符串,是s
按字节倒转。
string.sub( s, i, j )
返回一个s
的子串,从位置i
开始j
结束。i
和j
都可以是负数。如果j
是nil或被省略,会以字符串末尾结束。
可以用string.sub(s,1,j)
,返回s
长度为j
的前缀。string.sub(s, -i)
返回长度为i
的s
的后缀。
对于相似函数,详见mw.ustring.sub()。其中下标马昭字符而不是字节计算。
string.upper( s )
返回字符串的复制,其中,其中所有的ASCII小写字母会被转化为大写字母。其余字符不会被转化。
对于类似功能的函数,详见 mw.ustring.upper(),其中Unicode定义的所有的小写字母都会转化为大写字母。
Lua的匹配和正则表达式很像,但是并不等同。尤其是注意Lua的匹配在以下方面和正则表达式和PCRE[26] 的不同。
%
), 而不是右斜杠(\
)。.
) 匹配所有的字符,包括换行符。|
运算符).*
, +
, ?
, 和 -
) 只能用于匹配单个字符或字符类(character class),不能用来捕获组。-
, 相当于PCRE的 *?
,{n,m}
。^
,$
, 和 %f[set]
。例如PCRE的\b
或者(?=···)
不存在。
也要注意,匹配模式中不能包括嵌入的零字节(ASCII NUL,\0
),应使用%z
。
对于相似的使用Unicode码的匹配模式匹配函数,详见Ustring patterns。
字符类(character class)用来表示一系列字符。允许用以下组合来描述一个字符类。
^$()%.[]*+-?
之一)表示字符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 item)可以是:
*
',匹配出现0次或更多次的字符。总是匹配更长的序列。+
',匹配出现1次或更多次的字符。总是匹配更长的序列。-
',匹配出现0次或更多次的字符。总是匹配更短的序列,和'*
'不同。?
',匹配出现0次或一次的字符。%n
,其中n是0到9的数字。匹配和第n个捕获匹配的子串(见下文)。%bxy
, 其中x和y是两个不同的字符。匹配以x开始以y结束,且平衡(balanced)的字符串。平衡的意思是,如果用一个计数器,从左到右遍历字符串,每次碰到x+1,每次碰到y-1,那么字符串会在计数器为0的那个y截止。例如,%b()
匹配平衡括号的表达式。%f[set]
,边界匹配。它会匹配一个在任意位置的空字符串,它的下一个字符属于set,前一个字符串不属于set。集合set如前所述。目标字符串的最开始和最末尾的位置也可能会被匹配,此时将它们看作字符 '\0'。
在Lua 5.1,已经出现了frontier pattern,但是没有被Lua文档记载,在5.2才被官方记载。 Lua 5.2.1 和5.1.0中的实现相同。
匹配模式(pattern)是匹配模式项的序列。
匹配模式最前面的'^
'匹配目标字符串的最开始,匹配模式最后面的'$
'匹配目标字符串的最尾端。出现在其余位置的'^
'和'$
无特殊含义,仅表示它们本身。
一个匹配模式可以包括被包含在括号之内的子匹配模式,或者叫做捕获(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.foreach()
,table.foreachi()
,table.getn()
,尽管它们可能可用。推荐使用for循环与 pairs()或ipairs()结合的方式,或者长度运算符。
table.concat( table, sep, i, j )
给定一个数组,其中所有的元素都是字符串或者数字,返回table[i] .. sep .. table[i+1] ··· sep .. table[j]
。
sep
的默认值是空字符串,i
的默认值是1,j
的默认值是表的长度。如果i
比j
大,返回空字符串。
table.insert( table, value )
table.insert( table, pos, value )
将value
插入到table
中的pos
位置,这个位置后面的元素向后顺延。pos
的默认值是表的长度+1,因此调用table.insert(t, x)
会在表t
的最后插入x
。
下标大于#table
的元素会被移动。如果表不是数组的可能后果详见长度运算符。
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, pos )
去除table
中在位置pos
的元素。会将这个位置后面的元素前移。返回被移出元素的值。pos
的默认值是表的长度,所以调用table.remove( t )
返回表中最后一个元素
下标大于#table
的元素会被移动。如果表不是数组的可能后果详见长度运算符。
table.sort( table, comp )
将表中从table[1]
到table[#table]
按照给定排序方法排序。如果指定了comp
,那么它一定是接受两个表作为参数的函数,如果第一个值比第二个值小,返回true。(这样排序过后,not comp(a[i+1],a[i])
会为true)。如果comp
未指定,会使用Lua运算符<
。
这个排序算法并不稳定。也就是说,同样大小的两个元素,在排序后相对位置可能会被破坏。
所有的Scribunto libraries都位于表mw
中。
mw.addWarning( text )
当预览编辑时,会在预览页面上方增加报错。text
被解析为维基代码。
mw.allToString( ... )
对于所有参数调用tostring(),然后把它们使用tab相连。
mw.clone( value )
创建一个值的深度复制(deep copy)。所有的表(和它们的元表)被重建,但是函数仍然会共享。
mw.getCurrentFrame()
返回当前框架对象,通常是来自于最近的#invoke
的框架对象。
mw.incrementExpensiveFunctionCount()
在"高性能解析函数"计数上加1,如果超出限制抛出异常。详见$wgExpensiveParserFunctionLimit|$wgExpensiveParserFunctionLimit
。
mw.isSubsting()
如果#invoke
被替换引用了,返回true,否则返回false。对于替换引用与未替换引用的讨论,详见Returning text。引用错误:无效<ref>
标签;未填name属性的引用必须填写内容
mw.loadData( module )
有时一个模块需要很大的数据表,例如,一个用来转换度量单位的通用模块,可能需要一个大表,包括单位及其转换系数。有时这些模块可能在同一个页面使用多次。每次{{#invoke:}}
解析这个大表可能会大量时间。为了避免这个问题,提供了函数mw.loadData()
。
mw.loadData
和require()
很相似,但是有以下的不同:
{{#invoke:}}
被解析,而是仅在每次加载页面时。package.loaded
。
mw.loadData()
返回的表具有一个元方法,这个远方吧提供对模块返回的表的只读访问。因为表中不提直接包含数据,所以pairs()
和ipairs()
可以正常使用,但是其余方法,例如#value
,next()
和 Table library中的函数,不会正常使用。
假设上文提到的单位转换模块的代码在模块"Module:Convert",它的数据在"Module:Convert/data",模块"Module:Convert"应该使用local data = mw.loadData( 'Module:Convert/data' )
高效加载数据。
mw.dumpObject( object )
将object
序列化为人类可读的表示,然后返回得到的字符串。
mw.log( ... )
将所有参数传递给mw.allToString(),然后把得到的字符串附加到日志缓冲区(log buffer)。
在debug控制台下,函数print()
可看做是这个函数的别名。
mw.logObject( object )
mw.logObject( object, prefix )
调用函数mw.dumpObject(),然后将结果附加到日志缓冲区。如果给定了prefix
,它会被附加到序列化字符串的前面(日志文档将会是"prefix = object-string")。
框架对象(frame object,或帧对象),是一个对{{#invoke:}}
传递的参数,和解析器的接口。
需要注意,没有frame library。也没有名字为frame
的全局变量。框架对象通常包含从{{#invoke:}}
传入的参数,可以被mw.getCurrentFrame()
函数获取。
一个表,可以获取被传入框架的参数。例如,下面是一个从维基文本调用的模块。
{{#invoke:module|function|arg1|arg2|name=arg3}}
frame.args[1]
会返回arg1
,frame.args[2]
会返回arg2
,frame.args['name']
(或 frame.args.name
)会返回arg3
。也可以使用pairs( frame.args )
或 ipairs( frame.args )
迭代所有的参数。
然而,因为Lua执行表迭代的方式,像这样迭代参数会使得参数按照未指定的顺序返回,这样就无法得知它们在维基文本中原来的顺序。
注意,这个表的值都是字符串格式,可能需要tonumber()
来转化为数字。然后,键可以是数字,即使是调用时显式提供。例如,{{#invoke:module|function|1|2=2}}
,对应两个字符串值1
和2
,和两个数字键1
和2
。
在Mediawiki模板调用时,命名参数(named argument)会将名字和参数前后两端的空白部分去除,然后传入Lua,匿名参数(unnamed argument)会保留空白部分。
由于性能原因,frame.args
并不是直接包含所有传入参数的表,而是使用的元表。需要时,从MediaWiki请求获取参数值。这意味着大多数用于表的方法不能正常使用,包括#frame.args
, next( frame.args )
, 和Table library中的函数。
如果#invoke中包含了预处理语句,例如模板调用、三层括号参数,它们在传递给Lua时不会被展开,除非Lua请求获得它们的值。如果#invoke的参数包括一些特定的XML标记,例如<pre>
, <nowiki>
, <gallery>
和 <ref>
,这些标签(tag)会被转化为条状标记(strip marker)[27] ,在被#invoke返回后转化为HTML。
frame:callParserFunction( 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{ 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( name, content, args )
frame:extensionTag{ name = string, content = string, args = table_or_string }
这个函数和调用frame:callParserFunction() 函数,后者的name参数为
'#tag:' .. name
,content
加入到args
参数,等同。
-- 下面代码等同
frame:extensionTag{ name = 'ref', content = 'some text', args = { name = 'foo', group = 'bar' } }
frame:extensionTag( 'ref', 'some text', { name = 'foo', group = 'bar' } )
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', name = 'foo', group = 'bar'
} }
-- 下面代码等同
frame:extensionTag{ name = 'ref', content = 'some text', args = 'some other text' }
frame:callParserFunction{ name = '#tag:ref', args = {
'some text', 'some other text'
} }
frame:getParent
frame:getParent()
被{{#invoke:}}
创建的框架对象调用该函数时,返回一个框架对象,这个框架对象在页面上调用了{{#invoke:}}
。如果被前文提到的被返回对象调用该函数,返回nil。
例如,如果模板{{Example}}
包括代码{{#invoke:ModuleName}}
,一个页面嵌入了此模板,并传入此模板参数({{Example|arg1|arg2}}
),在Module:ModuleName中调用 mw.getCurrentFrame():getParent().args[1], mw.getCurrentFrame():getParent().args[2]
会返回"arg1", "arg2"
。
frame:getTitle
frame:getTitle()
将与此框架关联的标题作为字符串返回。对于被{{#invoke:}}
创建的框架,返回值是被调用的模块的标题。
frame:newChild
frame:newChild{ title = title, args = table }
- 注意 命名参数的使用.
生成一个新框架对象 。这是当前框架的子框架(child)有可选的参数和标题。
这主要在debug控制台下,用来测试被{{#invoke:}}
调用的测试函数。一次性创建的框架数被限制。
frame:preprocess
frame:preprocess( string )
frame:preprocess{ text = string }
这个函数用来在框架中增加维基文本,例如模板、解析器函数,和类似于{{{1}}}
这类的参数。一些特殊的,用XML格式写的标签(tag),例如<pre>
, <nowiki>
, <gallery>
and <ref>
等,会被换为[Special:MyLanguage/strip marker|条状标记]]" — ,在被#invoke返回后转化为HTML。
如果你想增加单个模板,使用frame:expandTemplate
,而不是尝试用构造一个维基文本字符串,传入到此方法之中。在参数包含pipe character或者其余维基标记时,前者更快,且出现错误倾向更少。
如果你想增加一个解析函数,因为和上面同样的原因,请使用frame:callParserFunction
。
frame:getArgument
frame:getArgument( arg )
frame:getArgument{ name = arg }
对于指定的参数,获取一个对象(object)。如果未给定参数,返回nil。
返回的对象有一个方法 object:expand()
,它返回对应参数的展开后维基文本。
frame:newParserValue
frame:newParserValue( text )
frame:newParserValue{ text = text }
返回一个有object:expand()
方法的对象,这个方法返回frame:preprocess( text )
的结果。
frame:newTemplateParserValue
frame:newTemplateParserValue{ title = title, args = table }
- 注意 命名参数的使用.
返回一个有object:expand()
方法的对象,这个方法返回对用给定的参数调用frame:expandTemplate
的结果。
frame:argumentPairs
frame:argumentPairs()
和pairs( frame.args )
相同。这个函数考虑到向后兼容性被包括在库中。
Hash library
mw.hash.hashValue
mw.hash.hashValue( algo, value )
使用指定的算法哈希(hash,或散列)一个字符串值。合法的算法可以通过mw.hash.listAlgorithms()获取。引用错误:无效<ref>
标签;未填name属性的引用必须填写内容
mw.hash.listAlgorithms
mw.hash.listAlgorithms()
返回一个支持的哈希算法序列,用作mw.hash.hashValue()中。
HTML library
mw.html
是一个从Lua创建复杂HTML代码的便利接口。一个mw.html对象可以用mw.html.create
创建。
下面文档中mw.html.name
在全局库(表)mw.html
中可用;mw.html:name
和html:name
是html对象的方法。 (详见mw.html.create
).
一个基本例子就像这样:
local div = mw.html.create( 'div' )
div
:attr( 'id', 'testdiv' )
:css( 'width', '100%' )
:wikitext( 'Some text' )
:tag( 'hr' )
return tostring( div )
-- Output: <div id="testdiv" style="width:100%;">Some text<hr /></div>
mw.html.create
mw.html.create( tagName, args )
创建一个HTML对象,包括tagName
类型的HTML元素。为了创建空mw.html对象,也可以传递空字符串或者nil作为tagName
。
args
可以是具有以下键的表。
args.selfClosing
: 强制当前标签是自闭合[28] 的,即使mw.html不认为它是自闭合的。
args.parent
: 当前html实例的父对象(用于内部使用)。
mw.html:node
html:node( builder )
在当前mw.html实例中加入一个子对象节点(builder
)。如果传入nil参数,则无操作(no-op/no operation)。builder
子节点是一个表示html元素的字符串。
mw.html:wikitext
html:wikitext( ... )
追加一组没有确定数量的维基文本字符串到对象中。
注意追加会在遇到第一个nil参数时停止。
mw.html:newline
html:newline()
在mw.html对象中加入新行。
mw.html:tag
html:tag( tagName, args )
在给定的tagName
中加入新子节点,返回一个mw.html实例代表新节点。args
参数和mw.html.create
中的参数一样。
mw.html:attr
html:attr( name, value )
html:attr( table )
以name
和value
作为名称和值为对象设置HTML属性。此外拥有 名称->值 对的属性表也可以传入。 在第一种形式中,value为nil会导致已经设置的name属性被撤掉。
mw.html:getAttr
html:getAttr( name )
获取先前使用html:attr()
和给定的名字设定过的对象的属性值。
mw.html:addClass
html:addClass( class )
给节点的类属性增加一个类名。如果传入的是nil,则无操作。
mw.html:css
html:css( name, value )
html:css( table )
以name
和value
作为名称和值为对象设置HTML属性。此外拥有 名称->值 对的属性表也可以传入。在第一种形式中,value为nil会导致已经设置的name属性被撤掉。
mw.html:cssText
html:cssText( css )
增加纯css
文本给节点的style属性。如果传入nil参数,则无操作。
mw.html:done
html:done()
返回创建当前节点的父节点。像jQuery.end一样,这是一个很方便的函数,允许将多个子节点的创建链接到一条语句中。
mw.html:allDone
html:allDone()
类似于 html:done()
, 但是会回溯到树节点的根部,将其返回。
Language library
语言代码详见 language code。[29] 许多MediaWiki的语言代码和 IETF language tags类似,但是并不是所有的维基语言代码都是IETF标签,反之亦然。
下面文档中mw.language.name
在全局库(表)mw.language
中可用; mw.language:name
和 lang:name
是语言对象(language object)的方法。(详见mw.language.new
或 mw.language.getContentLanguage
)。
翻译者梳理。一个语言代码是:
- 合法的(valid):语言代码合乎语法即可,无论这个语言是否存在。在mw.language.isValidCode返回true。
- 合法内置代码(be valid built-in code):1.是合法的。2.仅包含ASCII字母、数字和连字符,且至少两个字符长度。在mw.language.isValidCode返回true。
- 被支持的(supported):1.是合法的。2.不包括大写字母。3.在当前运行MediaWiki版本中有信息文件(message file)。在mw.language.isSupportedLanguage返回true。
- 已知的(known):1.合法内置代码。2.在mw.language.fetchLanguageNames返回非空字符串。在mw.language.isKnownLanguageTag中返回true。
mw.language.fetchLanguageName
mw.language.fetchLanguageName( code, inLanguage )
返回给定语言代码的全名:默认为语言自称[30] ,如果给定了inLanguage
,则转化为给定语言。
mw.language.fetchLanguageNames
mw.language.fetchLanguageNames()
mw.language.fetchLanguageNames( inLanguage )
mw.language.fetchLanguageNames( inLanguage, include )
获取Mediawiki已知(known)的语言的序列,返回值是一个表,将语言代码映射到语言名称上。
默认情况,语言名称是语言自称。传入inLanguage
参数使得返回的是所有在指定语言的名字。
默认情况下,只有Mediawiki已知的语言名字会被返回,return
中传入'all'
会返回所有可用的语言 (例如来自于 Extension:CLDR的语言)。如果传入'mwfile'
,返回结果会仅包括这样的语言,它们被MediaWiki内核或已安装扩展包括的自定义信息。如果想显示选择默认值,可以传递'mw'
。
mw.language.getContentLanguage
mw.language.getContentLanguage()
mw.getContentLanguage()
返回一个维基的默认文本语言的新建对象。
mw.language.getFallbacksFor
mw.language.getFallbacksFor( code )
返回包括MediaWiki对于指定代码的依赖语言(fallback language)的列表。[31]
mw.language.isKnownLanguageTag
mw.language.isKnownLanguageTag( code )
如果语言被MediaWiki"已知",返回true。
一个语言"已知"(be known),如果这个语言是"有效的内置代码"(在mw.language.isValidBuiltInCode
中返回true),且在 mw.language.fetchLanguageName
中返回一个非空字符串。
mw.language.isSupportedLanguage
mw.language.isSupportedLanguage( code )
检查该语言代码code
是否有任何本地化可用。
一个语言"受支持"(supported),如果它是一个"合法的"(valid)[32] 语言。不包括大写字母,并且在Mediaviki的当前运行版本存在消息文件。
有可能出现这种情况,一个语言的代码是"受支持"(supported)但是不是"已知的"(known),(例如,mw.language.isKnownLanguageTag
返回true的语言)。也需要注意,有些代码尽管在 mw.language.isValidBuiltInCode
返回false,但是还是"受支持"(supported)。
mw.language.isValidBuiltInCode
mw.language.isValidBuiltInCode( code )
如果语言代码是用于MediaWiki内部自定义的有效格式,返回true。
代码可能事实上不对应任何已知的语言。
一个语言是"合法的内置语言",如果它是一个合法的语言(在mw.language.isValidCode
中返回true),且仅包含ASCII字母数字和连字符,且至少两个字符长度。
注意,有些语言代码是"被支持的"(supported),尽管这个函数返回false。
mw.language.isValidCode
mw.language.isValidCode( code )
如果语言代码是合法格式,返回true,无论这个语言是否存在,包括MediaWiki名字空间中仅在本地化使用的语言。
语言代码可能不对应任何已知语言。
一个语言代码是合法的,如果它不包括不安全字符(逗号、单双引号、斜杠、反斜杠、尖括号、连字符和ASCII NUl),且允许出现在页面标题中。
mw.language.new
mw.language.new( code )
mw.getLanguage( code )
新建一个语言对象。语言对象不包括任何可公开或许的属性,但是具有下面列出的方法。
页面中使用的不同的语言代码数量可能有限制。超过限制会报错。
mw.language:getCode
lang:getCode()
返回这个语言对象的语言代码。
mw.language:getFallbackLanguages
lang:getFallbackLanguages()
返回包括MediaWiki对于指定代码的依赖语言(fallback language)的列表。相当于mw.language.getFallbacksFor( lang:getCode() )
mw.language:isRTL
lang:isRTL()
如果该语言从右到左书写返回true,从左到右书写返回false。
mw.language:lc
lang:lc( s )
尊重给定的语言的特别转化规则,将字符串转化为小写字母。
如果Ustring library被加载了,调用 mw.ustring.lower() 会按照mw.language.getContentLanguage():lc( s )
实现。
mw.language:lcfirst
lang:lcfirst( s )
将字符串第一个字符,按照和lang:lc()相同的方式,转化为小写字母。
mw.language:uc
lang:uc( s )
尊重给定的语言的特别转化规则,将字符串转化为大写字母。
如果Ustring library被加载了,调用 mw.ustring.upper() 会按照mw.language.getContentLanguage():uc( s )
.实现。
mw.language:ucfirst
lang:ucfirst( s )
将字符串第一个字符,按照和 lang:uc()相同的方式,转化为大写字母。
mw.language:caseFold
lang:caseFold( s )
将字符串转化为不区分大小写的比较形式,注意这样可能使展示的字符串无意义。
mw.language:formatNum
lang:formatNum( n )
lang:formatNum( n, options )
将给定的数字格式化,增加分组和小数点。给定123456.78,按照给定的语言和wiki设置,可能会转化为123,456.78", "123.456,78", 甚至"١٢٣٬٤٥٦٫٧٨" 。
option
是包含可选参数的表,其中可选参数可以是:
noCommafy
: 如果设置为true,会省略分隔符,使用隔点(.
)作为小数点。数字转化仍然存在,可能包括转化数字分隔符。
mw.language:formatDate
lang:formatDate( format, timestamp, local )
按照给定的格式化字符串(format参数)格式化一个时间。如果省略了timestamp
,默认是当前时间。local
的值必须是一个布尔类型或者nil。如果为true,时间会按照wiki's local time格式化,而不是按照UTC。
格式化字符串和timestamp
的可用值和 来自于 Extension:ParserFunctions的#time parser function 相同。注意,在Lua字符串字面量中,反斜杠可能重复量词,因为Lua使用反斜杠作为转义字符,尽管维基文本并不是。
-- 这个字符串包括一个新行,而不是两个字符"\n",这和{{#time:\n}}不等同。
lang:formatDate( '\n' )
-- 这个和{{#time:\n}}等同,不和 {{#time:\\n}}等同
lang:formatDate( '\\n' )
-- 这个和{{#time:\\n}}等同,不和 {{#time:\\\\n}}等同。
lang:formatDate( '\\\\n' )
mw.language:formatDuration
lang:formatDuration( seconds )
lang:formatDuration( seconds, allowedIntervals )
将一个秒数转化为更易读的方式。例如,12345会转化为 3 hours, 25 minutes and 45 seconds,作为字符串返回。
allowedIntervals
是一个可以给定的表,它的值命名了使用的时间单位,包括'millennia', 'centuries', 'decades', 'years', 'weeks', 'days', 'hours', 'minutes', 'seconds'等[33]
mw.language:parseFormattedNumber
lang:parseFormattedNumber( s )
接受一个被lang:formatNum()转化的数字作为参数,返回实际数字。这个大致相当于语言敏感的tonumber()
。
mw.language:convertPlural
lang:convertPlural( n, ... )
lang:convertPlural( n, forms )
lang:plural( n, ... )
lang:plural( n, forms )
按照给定的数字n
,从forms
(必须是一个表)或者...
中选择恰当的单词变形形式。例如,在英文,你可以使用代码n .. ' ' .. lang:plural( n, 'sock', 'socks' )
或 n .. ' ' .. lang:plural( n, { 'sock', 'socks' } )
来生成语法正确的文本,1 sock或200 socks。
序列中需要的值依照不同的语言不同,细节详见localization of magic words 和 translatewiki's FAQ on PLURAL。
mw.language:convertGrammar
lang:convertGrammar( word, case )
lang:grammar( case, word )
- 注意两个函数中,不同的参数顺序。
convertGrammar
matches the order of the method of the same name on MediaWiki's Language object, while grammar
matches the order of the parser function of the same name, documented at Special:MyLanguage/Help:Magic words#Localisation.
按照给定的屈折代码case
,返回word
的正确屈折变化[34]形式。
可用的word
或case
值依照不同的语言不同,细节详见Special:MyLanguage/Help:Magic words#Localisation 和 translatewiki:Grammar
mw.language:gender
lang:gender( what, masculine, feminine, neutral )
lang:gender( what, { masculine, feminine, neutral } )
按照what
选择对应的性[35],可以是"male","female"或一个注册用户名。
mw.language:getArrow
lang:getArrow( direction )
按照direction
返回一个Unicode箭头字符。
- forwards: "→"或 "←",按照该语言的方向性(directionality)。
- backwards:"←" 或 "→", 按照该语言的方向性。
- left: "←"
- right: "→"
- up: "↑"
- down: "↓"
mw.language:getDir
lang:getDir()
按照该语言的方向性,返回"ltr"或"rtl"。
mw.language:getDirMark
lang:getDirMark( opposite )
按照该语言的方向性和opposite
的true或false,返回一个包括 U+200E (从左到右标记)或 U+200F (从右到左标志)的字符串。
mw.language:getDirMarkEntity
lang:getDirMarkEntity( opposite )
按照该语言的方向性和opposite
的true或false,返回 "‎" 或 "‏"。
mw.language:getDurationIntervals
lang:getDurationIntervals( seconds )
lang:getDurationIntervals( seconds, allowedIntervals )
将一个秒数转化为更易读的方式。例如,12345会转化为 3 hours, 25 minutes and 45 seconds。返回一个表,从时间单位名字到数字的映射。
allowedIntervals
是一个可以给定的表,它的值命名了使用的时间单位,包括'millennia', 'centuries', 'decades', 'years', 'weeks', 'days', 'hours', 'minutes', 'seconds'等。
Message library
这个库是本地化消息(message)和MediaWiki名字空间的接口。
下面文档中mw.message.name
在全局库(表)mw.message
中可用,函数mw.message:name
和 msg:name
是消息对象的方法(详见 mw.message.new
)。
mw.message.new
mw.message.new( key, ... )
对于给定的消息key
,创建一个新的消息对象(message object)。
该消息对象没有属性,但是有下文所述方法。
mw.message.newFallbackSequence
mw.message.newFallbackSequence( ... )
按照给定的消息创建新的消息对象。(会使用参数中第一个存在的消息对象)。
该消息对象没有属性,但是有下文所述方法。
mw.message.newRawMessage
mw.message.newRawMessage( msg, ... )
使用给定的文本(text)直接生成一个消息对象,而不是从全局的(internationalized)消息中查找。其余参数会传递给新对象的params()
方法。
该消息对象没有属性,但是有下文所述方法。
mw.message.rawParam
mw.message.rawParam( value )
包装传入的值,这样它不会被msg:parse()
视为维基文本。
mw.message.numParam
mw.message.numParam( value )
包装传入的值,这样它会准备自动按照lang:formatNum()
格式化。注意,这个函数并不会依赖Language library库的可用与否。
mw.message.getDefaultLanguage
mw.message.getDefaultLanguage()
对于默认语言,返回一个语言对象。
mw.message:params
msg:params( ... )
msg:params( params )
在消息中加入参数,它们可以是单个参数或者一个序列表。参数必须输数字,字符串或者被mw.message.numParam()返回的值。如果使用的是序列表,则参数在表中直接可用,使用__index 元方法的引用不可用。
返回当前msg
对象,以便用来链式调用。
mw.message:rawParams
msg:rawParams( ... )
msg:rawParams( params )
像:params()一样,但是先将所有参数通过mw.message.rawParam() 进行转化。
返回当前msg
对象,以便用来链式调用。
mw.message:numParams
msg:numParams( ... )
msg:numParams( params )
像:params()一样,但是先将所有参数通过mw.message.numParam()进行转化。
返回当前msg
对象,以便用来链式调用。
mw.message:inLanguage
msg:inLanguage( lang )
指定一个在加工消息是使用的语言。lang
可以是一个字符串或者一个有 getCode()
的表(例如一个语言对象)
默认语言是被 mw.message.getDefaultLanguage()
所返回的语言。
返回当前msg
对象,以便用来链式调用。
mw.message:useDatabase
msg:useDatabase( bool )
指定是否从MediaWiki名字空间获取消息,还是仅仅使用MediaWiki分配的默认消息。
默认为true。
返回当前msg
对象,以便用来链式调用。
mw.message:plain
msg:plain()
替换参数,并且按照原样返回维基文本。模板调用和解析器函数完整保留。
mw.message:exists
msg:exists()
返回一个布尔值,表明是否存在消息键(message key)。
mw.message:isBlank
msg:isBlank()
返回一个布尔值,表明消息键是否为空。如果这个消息键不存在或者是空字符串,返回true。
mw.message:isDisabled
msg:isDisabled()
返回一个布尔值,表明是否消息键是不可用的。如果消息键不可用或者是空字符串或是字符串"-",返回true。
Site library
mw.site.currentVersion
一个保存当前MediaWiki版本的字符串。
mw.site.scriptPath
$wgScriptPath|$wgScriptPath
的值。
mw.site.server
$wgServer|$wgServer
的值。
mw.site.siteName
$wgSitename|$wgSitename
的值。
mw.site.stylePath
$wgStylePath|$wgStylePath
的值。
mw.site.namespaces
是一个来自于全部名字空间的表,按照数字索引。
可用数据为:[36]
- id: 名字空间编号.
- name: 本地名字空间名字.
- canonicalName: 规范名字空间。[37]
- displayName: 用于显示在0名字空间的名字(因为这个名字通常是空白字符串)。
- hasSubpages: 在此名字空间是否有可用的子页面。
- hasGenderDistinction: 该名字空间是否在不同的性(gender)下有多个别名。
- isCapitalized: 该名字空间下的页面,首字母是否大写。
- isContent: 是否这是一个内容名字空间。
- isIncludable: 该名字空间下的页面是否可以被嵌入。
- isMovable: 该名字空间下的页面是否可以被移动。
- isSubject: 该名字空间是否为主题(非讨论)名字空间。
- isTalk: 该名字空间是否为讨论名字空间。
- defaultContentModel: 返回该名字空间的默认内容类型,作为字符串。
- aliases: 该名字空间的别名的列表。
- subject: 相关的主名字空间的引用,
- talk: 相关的讨论名字空间的引用。
- associated: 相关的名字空间的引用。
由于元表的使用,也可以通过本地或规范名字来查找名字空间。例如, mw.site.namespaces[4]
和 mw.site.namespaces.Project
都会返回Project名字空间的信息。
mw.site.contentNamespaces
仅保存文本名字空间的表,按照数字索引。详见mw.site.namespaces。
mw.site.subjectNamespaces
是一个仅保存主名字空间的表,按照数字索引。详见mw.site.namespaces。
mw.site.talkNamespaces
是一个仅保存讨论页名字空间的表,按照数字索引。详见mw.site.namespaces。
mw.site.stats
保存网页站点数据的表。可用的数据如下。
- pages: wiki中的页面数。
- articles: wiki中的文章(article)数。
- files: wiki中的文件数。
- edits: wiki中的编辑数。
- users: wiki中的用户数。
- activeUsers: wiki中的活跃用户数。
- admins: 属于群组'sysop'的人数。
mw.site.stats.pagesInCategory
mw.site.stats.pagesInCategory( category, which )
- 这个函数是 性能消耗大的
获取分类中的数据。如果which
是未指定,nil,或者"*",返回一个具有以下属性的表。
- all: 总页面、文件和子类别。
- subcats: 子分类的个数。
- files: 文件个数。
- pages: 页面个数。
如果which
是上述的键之一,只有对应的值会被返回。
每次新类别查询增加高性能解析函数数。
mw.site.stats.pagesInNamespace
mw.site.stats.pagesInNamespace( ns )
返回给定名字空间(按照数字区分)的页面数。
mw.site.stats.usersInGroup
mw.site.stats.usersInGroup( group )
返回给定用户群组的用户数。
mw.site.interwikiMap
mw.site.interwikiMap( filter )
返回一个表,是用来保存可获取的 跨wiki链接(interwiki,或wiki内部链接)[38] 前缀的数据。如果filter
是字符串"local",仅返回"本地的"跨wiki前缀。如果filter
是字符串"!local",仅返回"非本地"跨wiki前缀。如果未指定filter
,所有的前缀数据都会返回。此处"本地的"前缀指的是在同一个项目的前缀。例如,在English Wikipedia,其余语言的Wikipedia是"本地的", 而Wiktionary之类的不是。
这个函数返回的表中的键都是跨wiki前缀,值是一个包含以下属性的表。
- prefix - 跨wiki前缀
- url - 该wiki指向的URL。页面名称作为参数$1.
- isProtocolRelative - 一个布尔值,表示这个URL是否是 协议相关。[39]
- isLocal - 该URL是否是当前项目下的。
- isCurrentWiki - 该URL是否是当前wiki下的
- isTranscludable - 使用这个跨wiki前缀的页面是否是被嵌入[40] 的。这需要跨wiki引用,在Wikimedia 维基上不可用。
- isExtraLanguageLink - 跨维基是否列举在
$wgExtraInterlanguageLinkPrefixes|$wgExtraInterlanguageLinkPrefixes
中
- displayText - 对于列举在$wgExtraInterlanguageLinkPrefixes中的链接,这个是展示在跨语言链接的文档。如果未指定则为nil。
- tooltip - 对于列举在$wgExtraInterlanguageLinkPrefixes中的链接,这个是当用户停留在在跨语言链接时的工具提示文本。如果未指定则为nil。
Text library
文档库(text library)提供String library和Ustring library中没有的,一些常见函数。这些函数对于UTF-8字符串安全。
mw.text.decode
mw.text.decode( s )
mw.text.decode( s, decodeNamedEntities )
如果布尔值decodeNamedEntities
被省略或为false,则仅仅命名的HTML实体'<', '>', '&', '"', and ' '被识别。否则,要识别的HTML5命名实体列表将从PHP的 get_html_translation_table
函数中加载。
mw.text.encode
mw.text.encode( s )
mw.text.encode( s, charset )
将字符串中的字符替换为HTML实体。字符 '<', '>', '&', '"'和不换行空格(non-breaking space)会被转化为恰当的命名实体。其余的字符转化为数字实体。
如果charset
被提供,它应该是一个,可以被放入Ustring pattern中的括号的字符串,即[set]
中的"set"。默认的charset是 '<>&"\' '
。(在最后出现的空格是不换行空格,U+00A0)
mw.text.jsonDecode
mw.text.jsonDecode( s )
mw.text.jsonDecode( s, flags )
解码一个JSON字符串。flags
是0,或者是由mw.text.JSON_PRESERVE_KEYS
和 mw.text.JSON_TRY_FIXING
(使用+
)组合而成。
通常,JSON的以0开始计数的数组会转化为Lua以1开始的序列。为避免此,可以传递mw.text.JSON_PRESERVE_KEYS
。
。并不推荐。
传递mw.text.JSON_TRY_FIXING
,可以放宽JSON的一些要求,例如数组或对象中没有结尾逗号[42] (terminal comma/trailing comma)
局限:
mw.text.JSON_PRESERVE_KEYS
。
mw.text.jsonEncode( value )
mw.text.jsonEncode( value, flags )
编码一个JSON字符串,如果传入的值不能被编码为JSON,会抛出异常。flags
是0,或者是由mw.text.JSON_PRESERVE_KEYS
和 mw.text.JSON_PRETTY
(使用+
)组合而成。
通常Lua以1开始的序列表会编码为一个JSON以0开始的数组。如果flags
中设置了mw.text.JSON_PRESERVE_KEYS
,以0开始的序列表会编码为JSON数组。
局限:
[]
),而不是空对象({}
)。__pairs
的一些技巧。[43]mw.text.JSON_PRESERVE_KEYS
。
mw.text.killMarkers( s )
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( s )
将字符串中一些字符替换为HTML实体,来避免它们被解读为维基文本,这包括:
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( s, pattern, plain )
返回一个迭代器函数,它迭代的子字符串,相当于调用mw.text.split()
得到的返回值。
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( s )
mw.text.trim( s, charset )
去除字符串开始和结尾的空白字符或其余字符。
如果charset
被提供,它应该是一个,可以被放入Ustring pattern中的括号的字符串,即[set]
中的"set"。默认的charset是是ASCII空格,"\t\r\n\f "
。
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( s )
将MediaWiki<nowiki>条状标记转化为对应的文本。其余种类的条状标记不变。
mw.text.unstrip( s )
相当于 mw.text.killMarkers( mw.text.unstripNoWiki( s ) )
.
它不会显示特殊页面嵌入后的HTML,<ref>标记等,就像Scribunto早期版本一样。
mw.title.equals( a, b )
Test for whether two titles are equal. Note that fragments are ignored in the comparison.
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()
Returns the title object for the current page.
mw.title.new( text, namespace )
mw.title.new( 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( 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.
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.
title.text
.title.text
.title.text
.mw.site.namespaces
.mw.site.namespaces
.mw.site.namespaces
.mw.title.makeTitle( title.namespace, title.baseText )
.mw.title.makeTitle( title.namespace, title.rootText )
.mw.title.makeTitle( mw.site.namespaces[title.namespace].talk.id, title.text )
, or nil if this title cannot have a talk page.mw.title.makeTitle( mw.site.namespaces[title.namespace].subject.id, title.text )
.mw.title.makeTitle( title.namespace, title.text .. '/' .. text )
.title.text
encoded as it would be in a URL.proto
may be specified to control the scheme of the resulting url: "http", "https", "relative" (the default), or "canonical".
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".
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:
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.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.
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( 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( s )
Encodes a string for use in a MediaWiki URI fragment.
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( 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( page, query )
Returns a URI object for the canonical URL for a page, with optional query string/table.
mw.uri.fullUrl( page, query )
Returns a URI object for the full URL for a page, with optional query string/table.
mw.uri.localUrl( page, query )
Returns a URI object for the local URL for a page, with optional query string/table.
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( 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.
The URI object has the following fields, some or all of which may be nil:
The following properties are also available:
tostring()
will give the URI string.
Methods of the URI object are:
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.
uri:clone()
Makes a copy of the URI object.
uri:extend( parameters )
Merges the parameters table into the object's query table.
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.
The maximum allowed length of a pattern, in bytes.
The maximum allowed length of a string, in bytes.
mw.ustring.byte( s, i, j )
Returns individual bytes; identical to string.byte().
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( ... )
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( 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( 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( format, ... )
Identical to string.format(). Widths and precisions for strings are expressed in bytes, not codepoints.
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( s, pattern )
Much like string.gmatch(), except that the pattern is extended as described in Ustring patterns.
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( s )
Returns true if the string is valid UTF-8, false if not.
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( 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( 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( s, n )
Identical to string.rep().
mw.ustring.sub( s, i, j )
Much like string.sub(), except that the offsets are characters rather than bytes.
mw.ustring.toNFC( s )
Converts the string to Normalization Form C. Returns nil if the string is not valid UTF-8.
mw.ustring.toNFD( s )
Converts the string to Normalization Form D. Returns nil if the string is not valid UTF-8.
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.
Patterns in the ustring functions use the same syntax as the String library patterns. The major difference is that the character classes are redefined in terms of Unicode character properties:
%a
: represents all characters with General Category "Letter".%c
: represents all characters with General Category "Control".%d
: represents all characters with General Category "Number, decimal digit".%l
: represents all characters with General Category "Lowercase Letter".%p
: represents all characters with General Category "Punctuation".%s
: represents all characters with General Category "Separator", plus tab, linefeed, carriage return, vertical tab, and form feed.%u
: represents all characters with General Category "Uppercase Letter".%w
: represents all characters with General Category "Letter" or "Decimal Number".%x
: adds fullwidth character versions of the hex digits.
Like in String library patterns, %A
, %C
, %D
, %L
, %P
, %S
, %U
Template:IntTemplate:Int%W
here represent the complementary set ("all characters without given General Category").
In all cases, characters are interpreted as Unicode characters instead of bytes, so ranges such as [0-9]
, patterns such as %b«»
, and quantifiers applied to multibyte characters will work correctly. Empty captures will capture the position in code points rather than bytes.
These libraries are not included by default, but if needed may be loaded using require()
.
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( ... )
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( x )
Returns the bitwise complement of x
.
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( ... )
Equivalent to bit32.band( ... ) ~= 0
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( 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( 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( 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( 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( 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( 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( 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.
This library contains methods useful when implementing Scribunto libraries. It may be loaded using
libraryUtil = require( 'libraryUtil' )
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( 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( 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( 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( 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
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.
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.
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.
Wikibase Client provides access to localizable structured data. See Extension:Wikibase Client/Lua. This is supported by Wikidata.
WikibaseLexeme provides access to Wikibase Lexeme entities. This is supported by Wikidata:Lexicographical data.
WikibaseMediaInfo provides access to Wikibase MediaInfo entities. See Extension:WikibaseMediaInfo/Lua. This is supported by Structured Data on Commons. See Commons:Structured data/Lua.
BCmath provides arbitrary-precision arithmetic to Lua modules. See BCmath documentation via "LDoc" link at Extension:BCmath#Usage.
Semantic Scribunto provides native support for the Scribunto extension to Semantic MediaWiki extension.
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.
Cargo provides a means to query its data store from Lua. See Extension:Cargo/Other features#Lua support.
CategoryToolbox provides a means to check from Lua if a certain page belongs to a category
FlaggedRevs provides a means to access the stability settings of a page from Lua.
TitleBlacklist provides a means to test and obtain information about blacklisted page naming entries from Lua.
ParserFunctions provides a means to evaluate a parser function expressions from Lua.
ArticlePlaceholder provides a means to override default Wikibase renderings from Lua. See Extension:ArticlePlaceholder/Module:AboutTopic.
以下的函数经过了调整:
以下包几乎全部被移除。仅列出的函数是可以使用的。
以下的函数和包不能使用:
{{#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()
.
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:
Existing libraries serve as a good example.
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.
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:
n
, the name of test n
, and a string that is the expected output for test n
.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:
The type controls the format of expect
and how func
is called. Included types are:
expect
is a table of return values, or a string if the test should raise an error. func
is simply called.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()
.There are (at least) two ways to run PHPUnit tests:
--filter
option may be used to run only your extension's tests.
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; }
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许可证。
^$()%.[]*+-?
。将会在#Patterns详细介绍。
{{#tag:}}
会被转化为\127'"`UNIQ--tagname-8 hex digits-QINU`"'\127
。
——来自于[9]。
mw.language.isValidCode
下返回true。