扩展:Scribunto/Lua参考手册

This page is a translated version of the page Extension:Scribunto/Lua reference manual and the translation is 75% complete.
Other languages:
Bahasa Indonesia • ‎Deutsch • ‎English • ‎Esperanto • ‎Tiếng Việt • ‎Türkçe • ‎asturianu • ‎català • ‎español • ‎français • ‎italiano • ‎magyar • ‎polski • ‎português do Brasil • ‎русский • ‎українська • ‎עברית • ‎ဖၠုံလိက် • ‎မြန်မာဘာသာ • ‎中文 • ‎日本語 • ‎한국어
快捷方式:
Lua manual
LUAREF

此手册记载Lua 的文档,它用于MediaWiki的Scribunto 扩展。 部分内容取自Lua 5.1参考手册,其许可协议为MIT许可证

介绍

入门

在已启用Scribunto的MediaWiki wiki上,以“Module:”前缀为标题创建一个页面,例如“Module:Bananas”。 进入该新页面,复制下列文本:

local p = {} --p代表一个包(package)

function p.hello( frame )
    return "Hello, world!"
end

return p

保存之后,另一个非模块的页面将会写入:

{{#invoke:Bananas|hello}}

除了你应该将“Bananas”替换成你需要调用的模块。这将会使“hello”函数被模块调用。{{#invoke:Bananas|hello}}将会被函数输出的结果替换,那么,“Hello, world!”

从模板的内容调用Lua代码确实是一个好办法。这意味着从调用页面的角度来说,语法不依赖与模板逻辑是否被Lua或者维基文本执行。这也避免了把复杂语法加到wiki内容页面中。

模块结构

模块本身必须返回一个包含能被{{#invoke:}}调用的函数的表(table)。一般来说,如上所示,先声明一个局部变量表,函数被写在这个表中,而且最终的模块代码中,返回(return)这个表。

若是没有加到这个表中的函数,无论是局部(变量)还是全局(变量),都不能被{{#invoke:}}关联,但是局部变量可能会被其他的用require()加载的模块关联。对于模块来说,最好将所有的函数和变量声明为局部变量。

从维基文本关联参数

{{#invoke:}}调用函数时,会将框架项目(frame object)作为调用函数时的参数(参数只有一个)。要关联被{{#invoke:}}通过的函数,代码通常会使用框架项目的args。也可以关联被包含{{#invoke:}}的模板参数,方法是使用frame:getParent() 然后关联到框架的args

框架项目也用来关联特定情况下的维基文本解析器,例如调用解析器函数扩展模板以及展开任意的(含模板或解析器函数的)维基文本字符串

返回文本

模块函数通常返回单个的字符串;无论返回什么值都会通过tostring()转换,然后连接在一起。这个字符串就是转化成维基文本代码{{#invoke:}}的结果。

在解析页面的这一点上,模板已经被展开,解析器函数和扩展标签都已经处理,而且预存的转换(例如签名的扩展以及pipe trick)都已经完成。因此,模块不能在输出文本中使用这些特性。例如,如果一个模块返回"你好,[[世界]]!{{欢迎}}",页面就会是“你好,世界!{{欢迎}}”。

另一方面,替换引用会在处理过程的早期就被处理,所以带有{{subst:#invoke:}}会尝试替换后的处理内容。因为失败的替换引用会保持为维基文本,它们都会被下一次编辑处理。这得要避免。

模块文档

Scruibunto允许模块可以被自动关联的模块维基文本页面关联文档;默认情况下,模块的“/doc”子页面是用来作为文档,并且会在模块页面的代码顶部显示其内容。例如,“模块:Bananas”的文档页面就是“模块:Bananas/doc”。

这也可以使用以下MediaWiki名字空间下的消息配置:

  • scribunto-doc-page-name(文档页面名称):设置用来作文档页面的名称。模块(除了模块:prefix)的名称会通过$1。如果在模块命名空间,这里的页面通常会视为维基文本而不是Lua代码,也不会被{{#invoke:}}使用。模块的页面通常是“Module:$1/doc”这样的模块/doc子页面。注意解析器函数等其他可扩展代码在这个消息中不被使用。
  • scribunto-doc-page-does-not-exist(文档页面不存在):消息会在文档页面不存在时显示。页面名称通常会通过$1。默认是空的。
  • scribunto-doc-page-show(文档页面显示):当文档页面存在时,消息就会显示。页面的名称通常会通过$1。默认是引用文档页面。
  • scribunto-doc-page-header(文档页面开头):当显示文档页面本身时,会显示开头。模块(包括模块:prefix)的开头会通过$1而作为文档。默认情况下会简单显示为斜体的表达句。

注意模块不可以被直接分类,也不可以直接添加跨维基链接。这些应该放在文档页面里面的<includeonly>...</includeonly>标签中,当文档页面引用到模块页面时,它们就会应用于模块中。

Lua语言

变量名称

Lua中的名称(Names)(也叫标识符(identifiers))通常可以是任何字母、数字和下划线的字符串,但不可以以数字开头。名称区分大小写;“foo”“Foo”和“FOO”都是不同的名称。

下列关键字是保留的,不能用作名称:

  • and
  • break
  • do
  • else
  • elseif
  • end
  • false
  • for
  • function
  • if
  • in
  • local
  • nil
  • not
  • or
  • repeat
  • return
  • then
  • true
  • until
  • while

名字的开头一个下划线大写字母是留给内部Lua全局变量。

下面这些文本也属于保留字:

  • #
  • %
  • (
  • )
  • *
  • +
  • ,
  • -
  • .
  • ..
  • ...
  • /
  • :
  • ;
  • <
  • <=
  • =
  • ==
  • >
  • >=
  • [
  • ]
  • ^
  • {
  • }
  • ~=

注释

注释在任何地方(除了字符串内)由--开始。如果--紧接着开放的中括号,注释就会一直延伸到下一个中括号;否则注释会延伸到这一行的结尾。

-- Lua的注释是由两个连字符(<code>-</code>)开始,延续到一行末尾。
--[[ 多行的字符串和注释
     可以被两层中括号括起来。]]
--[=[ 像这样的注释可以紧随其他--[[注释]]。]=]
--[==[ 像这样的注释可以有其他的
      --[===[ 修长的 --[=[注释]=] --跟随着
        ]===] 多次,即使它们所有
      --[[ 都没有用匹配的长括号分隔! ]===]
  ]==]

数据类型

Lua是动态类型语言,意味着变量和函数值都不会有种类,只有值会有。所有的值都有类型。

Lua有8个基本类型,然而只有6个是与Scribunto扩展相关。type()函数会返回值的类型。

tostring()能够将值转化为字符串(string)。tonumber()能够将值转化为数字(number)(如果可能的话),而其他情况则会返回空值(nil)。没有明确的函数能够将一个值转化为其他的数据类型。

凡是将与字符串(string)连接在一起的地方,数字(number)会自动转化为字符串。使用计算符号时,字符串会由tonumber()自动转化为数字辨识。当运算中需要将一个值作为布尔值(boolean)时,除了nil和false之外,所有的值都会视为true。

空值(nil)

“空值”是nil的数据类型,用来表示这个值不存在。

空值不一定作为一个表(table)中的域名(key),而且表中未指定的域名其实就是nil值的域名。

当空值转化为字符串时,其结果会是“nil”;转化为布尔值(boolean)时,空值会被视为false。

布尔值(boolean)

布尔值就是true(真)和false(假)。

当布尔值转化为字符串时,结果就是“true”或者“false”。

不像很多其他语言,布尔值不会直接转化为数字。而且只有false和nil作为布尔值时也会视为false;数字0和空字符串都是视为true。

字符串(string)

Lua字符串会视为一系列的8比特字节;这取决于应用程序以哪种特定的编码来解析。

字符串会记录在任何一组单双引号('")中;就像JavaScript而不像PHP,这两者(指的单引号和双引号)无区别。以下转义序列被辨识:

  • \a(响铃,字节7)
  • \b(退格,字节8)
  • \t(水平制表符,字节9)
  • \n(换行,字节10)
  • \v(纵向制表符,字节11)
  • \f(换页,字节12)
  • \r(回车,字节13)
  • \"(双引号,字节34)
  • \'(单引号,字节39)
  • \\(反斜线,字节92)

在字符串代码中直接换行,应该在前面加一个反斜线(\)。字节也可以通过转义序列'\ddd',这样ddd是0~255中的字节值。使用转义序列来代替Unicode字符,则为UTF-8的单个编码字节必须要指定;总的来说,直接输入Unicode字符会更加简单。

字符串也可以用长括号定义。 长括号之间可以夹杂着0个或更多个等号(两边的等号要等量),例如[[[=[[=====[。 开放的长括号必须被相应的闭合的长括号(或者说是结束标记)链接,例如]]]=]或者]=====].。 特殊情况下,开放的长括号紧跟着连续换行但未被包括的字符串,新一行只会持续到闭合长括号前。 由长括号定义的字符串不会处理转义序列。

-- 长字符串
foo = [[
bar\tbaz
]]

-- 等效于此引号分隔的字符串
foo = 'bar\\tbaz\n'

注意,在转化为布尔值时,所有的字符串都会视为true(真)。这不像其他的语言将空字符串视为false(假)。

数字(number)

Lua只有一种数字类型,就是典型的双精度浮点数。在这种格式,-9007199254740992到9007199254740992之间的数都会准确表达,更大的小数将会受到舍入的误差。

数字可以用点(.)来表示小数,例如123456.78。数字也可以用不带空格的科学计数法,例如1.23e-10123.45e20或者1.23E5。也可以用16进制表示整数,方法就是以0x开头,例如0x3A

虽然NaN和正负无穷大都可以正确地储存、处理,但是Lua不提供相应的直接文字表示方法。math.huge是正无穷大,相当于1/0,此外,像0/0这样的除法就可以生成NaN。

重申一遍,在转化为布尔值时,任何数字都会被视为true。这不像其他语言,数字0通常视为false。数字在转化为字符串时,数字都会被视为有限小数和科学计数;NaN是"nan"或者"-nan";无穷大就是"inf""-inf"

表(table)

Lua的表是关联数组,很像PHP的数组和JavaScript的object。

表要用一对花括号创建。空表是{}。创建有多个域的表时,逗号和分号可以分隔表中的各个域。表的内容可以用以下形式表示:

  • [表达式1] = 表达式2,意思是键为表达式1,它与值表达式2匹配。即表达式1的值是表达式2
  • 名称 = 表达式,它等价于["名称"] = 表达式
  • 表达式大致相当于[i] = 表达式,在这里i是在这个表中从1开始排序的正整数。如果最后一个字段和表达式有多个值,所有的值都会使用;否则只有第一个会保留。

表中的域用中括号关联,例如table[key]。字符串键(key)同样也可以用作点来表示的名字,例如table.key就与table['key']等价。这样的用点表示域的方法也可以用来调用函数,例如table:func( ... ),相当于table['func']( table, ... )或者table.func( table, ... )

序列从1到N的所有正整数且没有比N更大的正整数,且非空值的表。很多Lua函数仅按它的序列操作,忽略所有的非整数或小数的域名。

不像很多其他的语言(例如PHP或JavaScript),任何值(除了nil和NaN)都可以作为键,而且没有执行类型转换。参看下面的示例:

-- 创建表
t = {}
t["foo"] = "foo"
t.bar = "bar"
t[1] = "一"
t[2] = "二"
t[3] = "三"
t[12] = "数字十二"
t["12"] = "字符串十二"
t[true] = "true"
t[tonumber] = "是的,即使函数也可以用作表格键"
t[t] = "是的,表格也可以用作表格的键,即使是它本身。"

-- 这将创建一个大致相当于上面的表
t2 = {
    foo = "foo",
    bar = "bar",
    "one",
    "two",
    [12] = "数字十二",
    ["12"] = "字符串十二",
    "三",
    [true] = "true",
    [tonumber] = "是的,即使函数也可以用作表格键",
}
t2[t2] = "是的,表格也可以用作表格的键,即使是它本身。"

类似地,任何非nil的值都可以在表中储存为值。将表中存储nil相当于删除表中的对应的键,并且调用表中任何一个不存在的键都会返回nil。

注意,在Lua中,表从来不会复制出一个独立的新表;如果表作为一个参数传递到函数,那么函数能修改表中的键或值,这些变化在调用者(caller)的作用域中都会可见。

当转化为字符串时,结果通常是"table"(在Lua 5.3.1中),但使用__tostring元方法时,转化为字符串的值就会重写。作为布尔值时,即使是空的表也会视为真(true)。

函数(function)

Lua中的函数(又叫功能)是最好的(first-class)的值:它们可以匿名创建,作为参数传递,给变量赋值,等等。

函数通过function(“函数”的英文)关键字,并使用圆括号调用。有一些语法糖可以用来命名函数,局部函数,并且可以作为表中的一个域值。参看函数声明函数调用

Lua函数是闭包,这意味着它们维护对它们声明的范围的引用,并可以访问和操作该范围中的变量。

类似于表,如果函数一个函数被分配给另一个变量,或者作为参数传递给另一个函数,它仍然是相同的被调用的底层“函数对象”。

函数转化为字符串时,结果是"function"(在Lua 5.3.1中是如此)。

不支持的类型

用户数据(userdata)用来储存其他语言中的值;例如,一个用户数据可以用来储存C的指针或结构。使用Scribunto运行环境不允许使用用户数据。

线程数据类型代表协同处理,在Scribunto的沙盒中不可用。

元表

每个表可能都关联一个被称为元表的表。元表的每个域都被特定的操作符或函数调用,以使表发生不同的操作行为或回落到默认行为。元表通过getmetatable()方法获得,通过setmetatable()方法设定。

如果需要关联至元方法,需要在元表里面调用rawget()方法。

元表可以配置以下项目元素:

__index
使用这个时,t[]会返回nil。 如果值是表的域,输出就会在表中重复,例如__index[](会调用表的元表的__index)。 如果这个域的值是函数,函数就会像__index( t, )这样调用。 rawget()函数会绕过这个元方法。
__newindex
这个元方法用于将一个域名关联值一个表中,即t[域名]=,但是rawget( t, 域名 )会返回空值(nil)。 如果这个域的值是表,那么这个表就会重复赋值,例如__newindex[] = (会调用这个表的元表的__newindex)。 如果这个域的值是函数,那么函数就会像这样调用:__newindex( t, , )rawset()函数会绕过这个元方法。
__call
将这个表作为函数调用时,就会使用这种元表,t( ··· )。 这个值必须是函数,像__call( t, ··· )这样调用。
__mode
这用于使表保持弱引用(weak references)。 这个值一定是一个字符串。 默认情况下,任何一个值被作为表格中的键或值时是不会被垃圾回收的。 但如果元表域包含字母k,且没有弱引用,键会作为垃圾收集。而且如果包含v则值有可能也会作为垃圾收集;其他的情况,对应的键和值都会从表中移除。 注意,如果在表作为元表之后改变了域,这个域的行为就会未定义。

其他元表项目包括:

对于二元运算符,Lua首先检查左边的变量的元表(若有),如果左边变量的元方法不存在则使用右边的元方法。
对于关系运算符,只有在同样的函数在两个变量的元表定义时,元表才会被使用。不同的匿名函数,即使具有相同的主体和闭包,也不可能被认为是相同的。
* __metatable会同时影响getmetatable()setmetatable()

注意:在Lua中,所有的字符串都会共用一个单一的元表,__index会转到string表。在Scribunto中,这个元表不允许被关联,也不能被string表引用;对模块可用的string表是一个副本。

变量

变量是储存值的地方。Lua有三种变量:全局(global)变量、局部(local)变量和表(table)中的域(field)。

名称分为全局和局部变量(或者是函数变量,是局部变量的一种)。定义一个局部变量,可以使用关键词local。任何没有赋值的变量都会视为有nil值。

全局变量储存在叫做环境的Lua表中;这个表通常是作为全局变量_G的值。这个全局变量表也可以设置元表;__index和__newindex元方法都可以用于全局变量表,就像其他的表一样。

函数的环境可以使用getfenv()函数关联,使用setfenv()函数修改;在Scribunto中,这些函数如果全部可用,就会受到严重限制。

局部变量是词法性质的;参见局部变量定义了解详细信息。

表达式

表达式是有值的:常量(数字、字符串、布尔值(真假)、空)、匿名函数的声明、表构造函数、变量引用、函数调用、变量参数表达式、用括号括起来的表达式、一进制和二进制运算的表达式。

大多数表达式都有一个值;函数调用和变量参数表达式可以有任何数量个值。注意用括号括一个函数调用或变量参数表达式只能保留第一个值,其他的值会失去。

表达式列表是逗号分隔的表达式列表。除了最后一个表达式以外,所有的值都只能是一个值(如果表达式没有值,则丢弃附加值,或者使用nil);最后一个表达式的所有值都包含在表达式列表的值中。

算数运算符

Lua支持以下常见的算数运算符:加减乘除、模运算、幂和相反数。

当所有操作值为数字或字符串时,即使用tonumber()返回非nil时,这些操作符有他们通常的意义。

如果一个操作数是一个有合适的元方法的表,元方法就会被调用。

操作 函数(功能) 示例 元方法 注释
+ 加法 a + b __add
- 减法 a - b __sub
* 乘法 a * b __mul
/ 除法 a / b __div 除以零是错误的,会输出NaN或者无穷大
% 模运算 a % b __mod 定义为a % b == a - math.floor( a / b ) * b
^ 幂运算 a ^ b __pow 允许非整数指数
- 取相反数 -a __unm

关系运算符

Lua的关系运算符是==~=<><=>=。关系运算的结果一定是布尔值(boolean)。

等于号(==)首先比较两个值的种类;如果两个值是不同的种类,结果为假(false)。然后比较值:空值、布尔值、数字和字符串照常比较。对于函数,则是看两个函数是否引用同一个准确的函数对象;像这样检测两个不同的(但作用相同的)匿名函数function() end == function() end一定会返回假(false)。表也会默认像函数这样比较,但是可能会由于使用__eq元方法而改变结果。

不等号(~=)与等于号作用相反。

对于排序运算符,如果两者都是数字,或者两者都是字符串,则直接进行比较。其次检查元方法:

  • a < b使用__lt
  • a <= b使用__le如果可用,或者__lt可用,那么它等价于not ( b < a )
  • a > b等价于b < a
  • a >= b等价于b <= a

如果必需的元方法不可用,会产生错误。

逻辑运算符

逻辑运算是and(与)、or(或)和not(非)。在逻辑运算中,只有空值(nil)和falce被视为false,其他的都被视为true。

对于and,如果左边的操作数被视为假,那么它就会被返回,将右边的操作数忽略;否则右边的操作数会被返回。

对于or,如果左边的操作数视为真,那么它就会被返回,忽略右边的操作数;否则右边的操作数会被返回。

对于not,其结果一定是布尔值(true或false)。

注意andorshort circuit。例如,foo() or bar()只会调用bar(),除非foo()不是在它的返回false或nil。

连接运算符

连接运算符就是两个点(dot),比如a .. b。如果两个操作数都是数字或字符串,它们会被转化为字符串然后返回。但是如果__concat元方法可用,就会使用这样的元方法。如果它存在但无效,则会产生错误。

注意Lua的字符串不可以改变,而且Lua不提供任何的“字符串产生器”的排序,所以反复进行a = a .. b会必须为每次迭代创建一个新字符串,并最终收集旧字符串。如果许多字符串都需要连接,则使用string.format()或将所有的字符串添加到一个序列然后最后使用table.concat()

长度运算符

长度运算符是#,像#a这样使用。如果a是字符串,会返回字符串的比特数。如果a序列表,会返回序列的长度。

如果a是一个不是序列的表,#a会返回能够使“a[n]不是nil而a[N+1]是nil”成立的值N,即使更高的索引不是nil值(在Lua 5.1如此)。例如,

-- 这不是序列,因为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)>

函数调用

Lua的函数调用域其他的语言很类似:函数名称后面跟着被括号括起来的参数列表。

func( 表达式列表 )

和往常一样在Lua表达的列表,列表中的最后一个表达式可以提供多个参数值。

如果向函数传递的参数个数少于函数定义中的形参个数,则额外的形参将被赋值nil。如果函数表达式含有比形参更多的参数,则多余的参数会被丢弃。函数也可以接受可变个数的参数(也就是说,有时可以接受任意数量个参数),参见函数声明的细节。

Lua允许直接调用由函数返回的值,例如func()()。如果需要比变量访问更复杂的表达式来确定要调用的函数,则可以使用括号表达式来代替变量访问。

Lua的语法有两个常见的语法糖例子。第一个是当一个表被当做对象使用,并且这个对象有一个函数被调用,那么语法

table:name( 表达式 )

完全等同于

table.name( 表, 表达式 )

第二种常见的情况就是Lua通过含有名称至值的映射的表作为函数唯一参数实施已命名的参数的工具(直截了当说,就是将一个由花括号分割的表作为唯一参数)。这种情况下,包围着参数的括号可以省去。如果将一个(由引号或中括号分割的)字符串作为调用函数时的唯一参数,那么包围着这个参数的括号也可以省去。比如调用

func{ arg1 = exp, arg2 = exp }
func"string"

等同于

func( { arg1 = exp, arg2 = exp } )
func( "string" )

它们也可以被组合使用。以下使用是等价的:

table:name{ arg1 = exp, arg2 = exp }
table.name( table, { arg1 = exp, arg2 = exp } )

函数声明

方法的定义语法如下:

function ( var-list )
    block
end

对于这个函数,变量列表中的所有变量都是局部的,这些变量带有着函数调用的表达式列表。在这个代码段中,多余的局部变量会被忽略。

函数被调用时,代码段中的语句会在由参数列表创建与变量表对应的局部变量和指定值之后执行。如果执行到返回语句,代码段就会退出,返回的值则会在表达式中的调用函数时被返回语句给予。如果执行到代码段末尾,还没有返回语句,则函数调用返回的结果是0个值。

Lua函数是词法闭包。一个常见的习惯用法是在函数声明的范围内声明“私有静态”变量作为局部变量。比如,

-- 这会返回将它的参数增加一个数字的函数
function makeAdder( n )
    return function( x )
        -- 外面的这个n在这里是可以加到x中的
        return x + n
    end
end

local add5 = makeAdder( 5 )
mw.log( add5( 6 ) )
-- 输出11

函数可以声明接受可变数量的(即任何数量个)参数,通过将...作为变量列表的最后一项:

function ( var-list, ... )
    语句块(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”会指向函数外(通常是未定义的)变量。这个问题可以通过先声明一个局部变量然后再将它分配到后来的声明中,或者使用函数声明语句语法。

声明

语句是执行的基本单元:一个赋值、控制结构、函数调用、变量声明,等等。

代码块(chunk)是语句(statements)的序列,可以由分号分开。一个代码块基本上被考虑为匿名函数的主体,所以它可以声明局部变量,接受参数,并返回值。

语句块(block)也是语句序列,就像一个代码块(chunk)。语句块可以被分隔以创建单个语句(statement):do 语句块 end。这些通常用来限制局部变量的作用范围,或者在另一个块的中间加入returnbreak

赋值

变量列表 = 表达式列表

var-list是由逗号分隔的变量;表达式列表是由逗号分隔的一组一个或多个表达式。所有的表达式都会在赋值之前被求值,所以a, b = b, a会交换ab的值。

局部变量定义

local 变量列表

local 变量列表 = 表达式列表

局部变量可以在一个语句块代码块内任意地方声明。第一种形式,不需要表达式列表,声明变量但不赋值,所以这些变量都会将nil作为值二中形式,为局部变量赋值,参见上面的赋值

注意:局部变量显式声明于local关键字后面,形式为local 变量名。比如语句 local x = x 声明一个名为“x”的局部变量,并将全局变量“x”的值赋予这个变量。局部变量只在其声明的语句块结尾前的地方生效。

控制结构

while 表达式 do 语句块 end

表达式(视为)是true时,反复执行while声明。

repeat 代码段 until 表达式

反复执行语句块,直到表达式(视为)是true。在语句块内声明局部变量可以用于表达式中。

for 名称 = 表达式1, 表达式2, 表达式3 do 语句块 end
for 名称 = 表达式1, 表达式2 do 语句块 end

for循环的第一种形式会生命一个局部变量,然后从对于值exp1exp3的步长到exp2重复代码段。注意exp3可以省略,相当于1,但是非数字值比如nilfalse是错误的。循环开始前,所有的表达式都会被求值。

这种形式的for循环大致相当于

do
    local var, limit, step = tonumber( exp1 ), tonumber( exp2 ), tonumber( exp3 )
    if not ( var and limit and step ) then
        error()
    end
    while ( step > 0 and var <= limit ) or ( step <= 0 and var >= limit ) do
        local name = var
        block
        var = var + step
    end
end

不过变量var、limit和step在其他地方都不可访问。注意变量“name”是语句块的局部变量;如果要在循环以外用它的值,它必须被复制到一个循环外面定义的变量。

for 变量列表 in 表达式列表 do 语句块 end

第二种形式的for循环会与迭代函数一起作用。就像在第一种形式里,表达式列表会在开始循环之前就赋值了。

这种形式的for循环大致相当于

do
    local func, static, var = expression-list
    while true do
        local var-list = func( static, var )
        var = var1  -- ''var1''是''var-list''中的第一个变量
        if var == nil then
            break
        end
        block
    end
end

除了变量func、static和var在其他地方不能被获得。注意var-list中的变量在语句块中相当于局部变量;如要在循环外使用它们,需要复制到在循环之外声明的变量。

通常expression-list是返回3个值得一个函数调用。如果迭代器函数可以被写入(be written),那么只取决于传入的参数,这会更加有效。否则,在Lua中编程建议返回闭包比返回表更好,因为静止的变量在每次迭代更新其成员。

if 表达式1 then 语句块1 elseif 表达式2 then 语句块2 else 代码段3 end

表达式1返回true时执行代码段1,否则,当表达式2返回true时执行代码段2,否则执行代码段3else 代码段3部分可以省去,elseif 表达式2 then 代码段2部分可以重复,也可以省去。

return 表达式列表

返回声明用来返回从函数或者代码块(chunk)(只是一个函数)。expression-list是由逗号分隔开的零个或更多个表达式。

Lua实现尾调用(tail calls。如果表达式列表包含一个函数调用,对那个函数的调用会重新使用当前的堆栈项(stack frame)。这可用于处理调用堆栈的函数,比如getfenv()debug.traceback()

返回声明必须是语句块(block)的最后一个声明。如果某些原因语句块的中间需要返回,那么可能需要明显的语句块do return end

break

break语句用来中止一个while、rpeat的执行,或者对于循环,跳到循环后的下一个语句。

break声明必须是语句块(block)的最后一个声明。如果某些原因语句块的中间需要中断,那么可能需要明显的语句块do return end

函数调用作为语句

函数可以作为语句被调用,此时函数的副作用(例如mw.log()向日志输出信息)会发生,然而函数的返回值会被忽略。

函数声明语句

Lua提供了语法糖来使得函数的定义更加自然。以下几种定义相互等价。

-- 基本声明
function func( var-list ) 语句块 end
func = function ( var-list ) 语句块 end
-- 局部函数
local function func( var-list ) 语句块 end
local func; func = function ( var-list ) 语句块 end
-- 作为表中的域的函数
function table.func( var-list ) 语句块 end
table.func = function ( var-list ) 语句块 end
-- 作为表的方法的函数
function table:func( var-list ) 语句块 end
table.func = function ( self, var-list ) 语句块 end

注意,这里的冒号符号与函数调用的冒号符号相类似,在参数列表的开头添加了一个隐式参数,名为“self”。

错误处理

错误可以通过error()assert()“抛出”,使用pcall() 或者xpcall()可以“捕获”错误。注意,某些Scribunto的内部错误是不能被Lua层面的代码捕获处理。

垃圾回收

Lua能自动管理内存。这意味着你不需要关心新建对象时内存空间的申请,或者对象不需使用时内存空间的释放。Lua的内存管理会自动执行“垃圾回收”,将不会再被访问的死对象或者被弱引用保持的对象的内存空间收回。几乎所有Lua类型元素都能被回收,包括表、方法、字符串等。

垃圾回收是自动运行的,不能被Scribunto配置。

标准库

Lua标准库为Lua提供基本的性能和关键功能。只有Lua标准库再Scribunto启用的一部分内容会在此说明。

基本函数

_G

这个变量持有对当前全局变量表的引用;全局变量foo也会被关联到_G.foo。注意,然而,对_G本身并没有什么特别的;它可能被以同样的方式作为任何其他变量:

foo = 1
mw.log( foo ) -- 输出1
_G.foo = 2
mw.log( foo ) -- 输出2
_G = {}       -- _G不再指向全局变量表
_G.foo = 3
mw.log( foo ) -- 还是输出2

全局变量表可以当作普通的表来使用。例如,

-- 调用一个名称存储在变量中的函数
_G[var]()

-- 输出所有局部变量的名称和转化为字符串后的值
for k, v in pairs( _G ) do
   mw.log( k, v )
end

-- 输出新的局部变量的创建
setmetatable( _G, {
    __newindex = function ( t, k, v )
         mw.log( "Creation of new global variable '" .. k .. "'" )
         rawset( t, k, v )
    end
} )

_VERSION

包含正在运行的Lua语言版本的字符串,例如“Lua 5.1”。

assert

assert( v, message, ... )

如果v是空值(nil)或是假(布尔值false),就会产生错误,那么message就会用作错误的文本:如果nil(或者未指定),文字是“assertion failes!(声明失败!)”;如果是字符串或者数字,文字就是那个值;否则声明(assert)本身就会引发错误。

如果是任何其他的值,声明(assert)就会返回包括消息在内的全部变量。

在Lua的一个比较常见的惯用用法是一个函数返回正常操作时的true值,并在失败时返回0或false作为为第一个值,错误信息作为第二值。容易的错误检查可以通过调用函数assert来实现:

-- 这个不会检查错误
local result1, result2, etc = func( ... )

-- 这个作用相同,但是会查错
local result1, result2, etc = assert( func( ... ) )

error

error( message, level )

用文本message来发出一个错误。

error一般会提供出错的位置的信息。如果level是1或者省略,纳闷信息就是调用error本身的位置,2使用被调用错误的函数调用的位置,等等。0会省略位置信息。

getfenv

getfenv( f )

注意,这个函数可能会无效,取决于配置中的allowEnvFuncs

返回运行环境(全局变量),由f指定:

  • 如果1、nil或者未指定,返回调用getfenv函数的环境。通常这与_G相同。
  • 整数2~10返回更高一级的环境。例如,2返回被这一个函数调用的函数的环境,3返回调用这一个函数的函数的环境,以此类推。如果这个堆栈值越高,错误也会随之上升,否则这个堆栈级别会返回尾调用(tail call)。
  • 传递函数返回在调用该函数时将使用的环境。

通过所有的基本函数和Scribunto基本库函数使用的环境都被保护。尝试访问这些环境中使用getfenv将返回nil。

getmetatable

getmetatable( table )

返回这个元表。其他的类型都会返回nil。

如果元表拥有__metatable欄位,这个值就会直接返回,而不是返回对应的元表。

ipairs

ipairs( t )

返回3个值:迭代函数,表t和0。它是供for的迭代形式

for i, v in ipairs( t ) do
    -- process each index-value pair
end

它会迭代数对(1, t[1])、(2,t[2])等,直到t[i]是nil时。

如果__ipairsmetamethod存在,那么标准行为会被覆盖,调用会返回与__ipairs( t )的返回值一致的值。

next

next( table, key )

允许遍历表中的键。如果key是nil或者未指定,返回表中的第一个键和值,否则,返回下一个键和值。如果没有更多的键可以用,返回nil。可以通过使用next( t ) == nil来检查表是否是空的。

注意键被返回的顺序是没有指定的,即使表有数字的索引(indexes)。如要以数字顺序遍历表,使用数字的foripairs

如果遍历时使用next,任何不存在的键被赋给一个值,则行为未定义。给一个存在的域赋一个新的值(包括nil)是可以的。

pairs

pairs( t )

返回三个值:迭代器函数(next或者类似的)、表t和nil。这是用于for的迭代器形式

for k, v in pairs( t ) do
    -- 处理每个键值对
end

这会遍历t中的键值对,就像next做得那样。参考next的文档以了解遍历期间修改表的限制。

如果__pairs原方法存在,那么标准行为会被覆盖,调用会返回与__pairs( t )的返回值一致的值。

pcall

pcall( f, ... )

用指定的参数在“保护模式”下调用函数f。这意味着如果在调用f时一个错误发生,pcall会返回false与错误消息。如果没有错误发生,pcall会返回true与调用返回的所有值。

伪代码中,pcall的定义类似如下:

function pcall( f, ... )
    try
        return true, f( ... )
    catch ( message )
        return false, message
    end
end

rawequal

rawequal( a, b )

a == b相同,只是忽略了所有__eq元方法

rawget

rawget( table, k )

table[k]相同,只是忽略了所有__index元方法

rawset

rawset( table, k, v )

table[k] = v相同,只是忽略了所有__newindex元方法

select

select( index, ... )

如果index是数字,返回...后对应的位置的数。如果index是字符串"#",返回...中参数的个数。

也就是说,select有点像以下代码,只是即使当...包含nil值时也可以正常工作(参考#unpack以了解关于nil的问题)。

function select( index, ... )
    local t = { ... }
    if index == '#' then
        return #t
    else
        return unpack( t, index )
    end
end

setmetatable

setmetatable( table, metatable )

设置元表metatable可能是nil,但是必须是清楚地提供的。

如果当前的原表有一个__metatable域,setmetatable会报错。

tonumber

tonumber( value, base )

尝试将value转化为数字。如果已经是数字或者可以转化为数字的字符串,tonumber就会返回这个数字,否则会返回nil。

base是可选的,默认为10,指定解析数字的进位基数。这个基数可以是2到36之间的任何整数。对于大于10,字母A(大小写均可)代表10,B代表11,以此类推,Z代表35。

十进制下,值可以有小数部分,或者以科学计数法表示,而且甚至可以以“0x”开头以表示16进制。其他情况,只有纯整数是接受的。

tostring

tostring( value )

value转化为字符串。参考上方的数据类型以了解各种类型被转换时的细节。

对于表,标准的转换行为可以被__tostring元方法覆盖。如果这个元方法存在,那么调用tostring会返回由__tostring( value )返回的单个值。

type

type( value )

以字符串形式返回value的类型"nil""number""string""boolean""table""function"

unpack

unpack( table, i, j )

从给定的表返回值,像table[i], table[i+1], ···, table[j]这样的如果被写出会直接返回。ij如果没有给出或者是nil,取其默认值1和#table

注意如果table不是一个序列j是nil或未指定,则结果是不确定的,参考长度操作符以了解详细。

xpcall

xpcall( f, errhandler )

这个很像pcall,只是错误消息在返回之前传递到函数errhandler中。

伪代码中,xpcall的定义类似如下:

function xpcall( f, errhandler )
    try
        return true, f()
    catch ( message )
        message = errhandler( message )
        return false, message
    end
end

Debug库

debug.traceback

debug.traceback( message, level )

以字符串的形式返回调用栈。可选的message参数会被连接到调用栈信息的前面。可选的level参数表示返回多少层调用栈。

数学(math)库

math.abs

math.abs( x )

返回x的绝对值。

math.acos

math.acos( x )

返回x的反余弦值(以弧度表示)。

math.asin

math.asin( x )

返回x的反正弦值(以弧度表示)。

math.atan

math.atan( x )

返回x的反正切值(以弧度表示)。

math.atan2

math.atan2( y, x )

使用两个参数的符号(signs)以找到结果的象限,返回y/x的反正切值(弧度制)。

math.ceil

math.ceil( x )

返回不小于x的最小整数。

math.cos

math.cos( x )

返回x(以弧度表示)的余弦值。

math.cosh

math.cosh( x )

返回x的双曲余弦值。

math.deg

math.deg( x )

将弧度角x转化为角度。

math.exp

math.exp( x )

返回 

math.floor

math.floor( x )

返回小于或等于x的最大整数。

math.fmod

math.fmod( x, y )

返回x除以y的余数,并将商舍入到零。比如,math.fmod( 10, 3 )产生1

math.frexp

math.frexp( x )

返回像这样的两个值me

  • 如果x是无穷大且非零,那么 e是整数,m的绝对值在 区间内
  • 如果x是零,那么me都是0
  • 如果x是NaN(非数字)或无穷大,那么mxe不指定

math.huge

代表正无穷大的值;比任何其他数值都要大或与之相等。

math.ldexp

math.ldexp( m, e )

返回 e是整数)。

math.log

math.log( x )

返回x的自然对数。

math.log10

math.log10( x )

返回x的以10为底的对数。

math.max

math.max( x, ... )

返回其参数的最大值。

对于NaN的行为未指定。当前,如果x是NaN,那么会返回NaN,但是其他的NaN就会被忽略。

math.min

math.min( x, ... )

返回其参数的最小值。

对于NaN的行为未指定。当前,如果x是NaN,那么会返回NaN,但是其他的NaN就会被忽略。

math.modf

math.modf( x )

返回两个数字,x的整数部分和x的小数部分。比如,math.modf( 1.25 )产生1, 0.25

math.pi

 的值。

math.pow

math.pow( x, y )

x^y相同。

math.rad

math.rad( x )

将角度x转化为弧度角。

math.random

math.random( m, n )

返回伪随机数。

参数mn可省略,但是如果指定了,则必须能够转化为整数。

  • 没有参数时返回区间 内的实数。
  • 有一个参数时返回区间 内的整数。
  • 有两个参数时返回区间 内的整数。

math.randomseed

math.randomseed( x )

x作为伪随机数生成器的种子

注意使用同一个种子会导致math.random输出相同的数列。

math.sin

math.sin( x )

返回 x(以弧度表示)的正弦值。

math.sinh

math.sinh( x )

返回x的双曲正弦值。

math.sqrt

math.sqrt( x )

返回x的平方根。与x^0.5相同。

math.tan

math.tan( x )

返回x(以弧度表示)的正切值。

math.tanh

math.tanh( x )

返回x的双曲正切值。

操作系统库

os.clock

os.clock()

返回程序大约使用的CPU时间,以秒为单位。

os.date

os.date( format, time )

语言库的formatDate可以被用于更加全面的日期格式。

返回包含日期和时间的字符串或表,以format为格式。如果格式被省略或者是nil,则使用“%c”。

如果给定了time,则就是被格式化的时间(参考os.time()。否则使用当前的时间。

如果format以!开头,则日期按照UTC格式而不是服务器的本地时间。在这个可选字符之后,如果格式是字符串"*t",那么日期返回带有以下域的表。

  • year(完整的)
  • month(1~12)
  • day(1~31)
  • hour(0~23)
  • min(0~59)
  • sec(0~60)
  • wday(weekday,Sunday是1)
  • yday(一年的某一天)
  • isdst(夏令时,布尔值,信息不可用时可能不存在)

如果格式不是"*t",那么日期以字符串形式返回日期,按照和C函数strftime相同的规则格式化。

os.difftime

os.difftime( t2, t1 )

返回从t1t2两个时间的秒数。

os.time

os.time( table )

返回代表当前时间的数字。

调用且没有变量时,返回当前时间。若传入了表,则表中编码的时间就会被解析。表必须有years、month、days这几个域,并且可能也包括hour(默认为12)、min(默认为0)、sec(默认为0)和isdst。

包(package)库

require

require( 模块名 )

加载目标模块。

首先会检查package.loaded[模块名]以检查模块是否已被加载,如果是,返回package.loaded[模块名]

Otherwise, it calls each loader in the package.loaders sequence to attempt to find a loader for the module. If a loader is found, that loader is called. The value returned by the loader is stored into package.loaded[modulename] and is returned.

See the documentation for package.loaders for information on the loaders available.

例如,如果你有一个模块“模块:Giving”其中有如下代码:

local p = {}

p.someDataValue = '您好!'

return p

你可以用以下代码在其它模块载入此模块:

local giving = require( "Module:Giving" )

local value = giving.someDataValue --值现在等于 '您好!'

package.loaded

This table holds the loaded modules. The keys are the module names, and the values are the values returned when the module was loaded.

package.loaders

This table holds the sequence of searcher functions to use when loading modules. Each searcher function is called with a single argument, the name of the module to load. If the module is found, the searcher must return a function that will actually load the module and return the value to be returned by require. Otherwise, it must return nil.

Scribunto提供了两种搜索方式:

  1. Look in package.preload[modulename] for the loader function
  2. Look in the modules provided with Scribunto for the module name, and if that fails look in the Module: namespace. The "Module:" prefix must be provided.

注意标准的Lua加载器是包括的。

package.preload

This table holds loader functions, used by the first searcher Scribunto includes in package.loaders.

package.seeall

package.seeall( table )

table的__index元方法设置为_G

字符串(string)库

在所有字符串函数中,第一个字符是第1位,而不是像C、PHP、JavaScript中的那样第0位。索引(indexes)可以是负的,表示从字符串最末开始倒数,比如-1表示最后一个字符,-2表示倒数第二个,等等。

警告:字符串库假定单字节字符串编码。不能处理Unicode字符。要对Unicode字符进行操作,使用Scribunto Ustring库中对应的方法。

string.byte

string.byte( s, i, j )

如果字符串被考虑为字节的数组,返回s[i]s[i+1]、···、s[j]的字节值。i的默认值为1;j的默认值为i。等价于mw.ustring.byte()

string.char

string.char( ... )

接受零个或更多个整数。返回和长度与参数个数相同的字符串,每个字符的字节值等于其对应的参数。

local value = string.char( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21 ) --值现在是'Hello!'

参看mw.ustring.char()以了解使用Unicode codepoint而非字节值的类似函数。

string.find

string.find( s, pattern, init, plain )

寻找字符串s中第一个匹配的pattern。如果找到一个匹配,返回s中起止点的序列,否则返回nil。If the pattern has captures,then in a successful match the captured values are also returned after the two indices.

第三个参数init是可选的,指定从哪里开始搜索,默认值是1,可以是负数。第四个参数plain也是可选的,如果是true,则会关闭模式匹配机制,则函数做的只是简单地“找子串”操作,pattern中的字符就不会被看作魔法字符。

注意给了plain就必须给init

参考mw.ustring.find()以了解用于Ustring pattern的类似函数,而且init是按照字符而非字节。

string.format

string.format( formatstring, ... )

返回变量数字的参数将第一个参数(必须是字符串)格式化后的版本。

格式字符串使用printf格式指定器但有所限制。

  • “-”“+”“ ”“#”和“0”是被认可的。
  • 支持最多99个整数域。“*”不支持。
  • 支持最多99个整数精确度。“*”不支持。
  • 长度修改器不支持。
  • 认可c、d、i、o、u、x、X、e、E、f、g、G、s、%这些转换器,以及非标准的q。
  • 不支持像“%2$s”这样的位置指定器。

转换指定器q类似于s,但是会以特定的专用于表述字符串的格式来形成字符串;字符串会被写在双引号中,所有的双引号、新行、嵌入的零、反斜杠都会被转义。

数字和字符串之间的转换会像数据类型中说的那严格:其他类型不会自动转化为字符串。包含NUL字符的字符串(字节值0)不能被正常处理。

等同于mw.ustring.format()

string.gmatch

string.gmatch( s, pattern )

返回一个迭代器函数,每次被调用,都会从字符串s中的pattern返回下一个捕获。如果pattern不会指定捕获,则整个匹配都会在每次调用时产生。

对于这个函数,开始的^不是魔法字符,因为这个会避免迭代。它被看做是普通字符。

参看mw.ustring.gmath()以了解其类似函数,其匹配模式是被扩展的,参考Ustring匹配模式

string.gsub

string.gsub( s, pattern, repl, n )

将字符串s的所有(或者前n个)出现的pattern替换为由repl指定的替换,这个替换可以是字符串、表或者函数,然后返回替换后的字符串。gsub也会返回,作为第二个值,发生匹配的总次数。

如果repl是一个字符串,则其值直接用于替换。字符%用作转义符(escape character):repl中的任何%n形式的序列,n是1到9之间,代表第n个被捕获的子串。序列%0代表整个匹配(match),序列%%代表单个%

如果repl是表,则每次匹配查询这个表,其键(key)为第一个捕获(capture);如果匹配模式(pattern)不指定捕获,则整个匹配(match)用作键。

如果repl是函数,则每次匹配发生时调用这个函数,所有被捕获的子串都会依次被传入作为参数。如果匹配模式不指定捕获,则整个匹配会作为单个参数传入函数。

如果表格查询或者函数调用返回的值是字符串或者数字,则用作替换字符串,否则,如果是false或nil,则不会进行替换,也就是说原始匹配仍保留在字符串中。

参看mw.ustring.gsub()以了解其类似函数,其匹配模式是被扩展的,参考Ustring匹配模式

string.len

string.len( s )

返回字符串的字节长度。不会被ASCII NUL字符混淆。等同于#s

参看mw.ustring.len()以了解使用Unicode codepoint而非字节值的类似函数。

string.lower

string.lower( s )

将字符串的所有ASCII大写字符转为小写后返回。所有其他字符不改变。

参考mw.ustring.lower()以了解类似的函数,该函数可以将Unicode定义的所有的大写字母转化为小写字母。

string.match

string.match( s, pattern, init )

寻找字符串中pattern的第一个匹配,如果找到一个,则match返回从样式匹配中的捕获,否则返回nil。如果pattern不指定捕获,则返回整个字符串。

第三个参数init是可选的,用来表示从哪里开始搜索,其默认值为1,可以是负数。

参看mw.ustring.math()以了解其类似函数,其匹配模式是被扩展的,参考Ustring匹配模式

string.rep

string.rep( s, n )

返回字符串s重复n次并连接后的字符串。等价于mw.ustring.rep()

string.reverse

string.reverse( s )

返回字符串s被逆转后的字符串(按字节逆转)。

string.sub

string.sub( s, i, j )

返回s的从i开始持续到j的子串(substring);ij可以是负的。如果j是nil或未指定,则会一直到字符串末尾。

注意字符串是从索引1开始的。使用这个函数时,两边的所有索引都是包括的(inclusive)

特别地,调用string.sub(s,1,j)会返回字符串s的长度j的前缀,而string.sub(s, -i)会返回字符串s的长度为i的后缀。

参看mw.ustring.sub()以了解使用字符而非字节值的类似函数。

string.upper

string.upper( s )

将字符串的所有ASCII小写字符转为大写后返回。所有其他字符不改变。

参考$anchor以了解类似的函数,该函数可以将Unicode定义的所有的小写字母转化为大写字母。

模式匹配

注意Lua的样式匹配类似于正则表达式(regular expression),但是并不一样。特别地,注意正则表达式和PCRE之间的以下区别。

  • 用于引用的字符串是百分号(%)而非反斜杠(\)。
  • 点(.)总是匹配所有字符,包括新行。
  • 没有大小写不敏感模式。
  • 没有选择功能(|操作符)。
  • 量词(quantifier,*+?-)不能用于单独的字符或者字符类,不能捕获组。
  • 唯一非贪婪的量词是-,相当于PCRE的*?量词。
  • 没有广义的有限量词,比如PCRE中的{"n","m"}
  • 零宽的assertion是^$%f[set]frontier样式,像PCRE的\b(?=…)不可用。
  • 样式匹配本身不认识像'\"ddd"'这样的转义。然而,由于样式匹配是字符串,这一类转义或许可以用于在创建样式匹配字符串的文字。

注意样式匹配不能包含嵌入的零字节(ASCII NUL,"\0")。应该使用%z

参考Ustring样式匹配以了解使用Unicode字符的类似的样式匹配机制。

字符类

字符类是一组字符的集合。以下集合可以用于定义字符类。

  • x:(x不是魔法字符^$()%.[]*+-?之一)代表字符x自身。
  • .:(一个点)代表所有字符。
  • %a:代表所有ASCII字母。
  • %c:代表所有ASCII控制字符。
  • %d:代表所有数字。
  • %l:代表所有ASCII小写字母。
  • %p:代表所有标点字符。
  • %s:代表所有ASCII空白字符。
  • %u:代表所有ASCII大写字母。
  • %w:代表所有ASCII字母数字字符。
  • %x:代表所有十六进制数字。
  • %z:代表所有ASCII NUL,零字节。
  • %A:所有不在%a中的字符。
  • %C:所有不在%c中的字符。
  • %D:所有不在%d中的字符、
  • %L:所有不在%l中的字符。
  • %P:所有不在%p中的字符。
  • %S:所有不在%s中的字符。
  • %U:所有不在%u中的字符。
  • %W:所有不在%w中的字符。
  • %X:所有不在%x中的字符。
  • %Z:所有不在%z中的字符。
  • %x:(x不是字母数字字符)代表字符x。这是转义魔法字符的标准方式。任何标点字符)甚至是非魔法字符)都可以跟“%”,用以代表样式匹配中的自身。、
  • [set]:代表集合set中所有字符的组合。一系列字符可以通过用“-”分隔字符末尾来指定。上面讲到的所有的类%x都可以是集合set中的一部分。集合中所有其他字符代表其自身。比如,[%w_][_%w]代表所有字母数字字符加上下划线,[0-7]代表所有八进制数字,[0-7%l%-]代表所有八进制数字、小写字母和“-”字符。
    范围和类之间的交互是未定义的。因此,像[%a-z][a-%%]这样的样式匹配是无意义的。
  • [^set]:代表set的补集。
模式条目(pattern item)

一个模式条目可以是

  • 单个字符类,匹配类中的单个字符。
  • *前的单个字符类,匹配这个类中重复0次或者更多次的字符。这个重复项总是匹配可能的最长序列。
  • +前的单个字符类,匹配这个类中重复1次或者更多次的字符。这个重复项总是匹配可能的最长序列。
  • -前的单个字符类,匹配这个类中重复0次或者更多次的字符。不像*,这个重复项总是匹配可能的最短序列。
  • ?前的单个字符类,匹配这个类中0次或1次出现的字符。
  • %nn可以是1到9之间,匹配相当于第n个被捕获的子字符串(见下)。
  • %bxyxy是两个不同的字符,匹配从x开始、以y结尾的字符,且xy平衡的。也就是说,如果从左到右读,给x数+1,给y数-1,结束的y是计数到达0时的第一个y
  • %f[set],一个frontier pattern,这样的项匹配任何位置的空字符串,而下一个字符属于集合set,而前一个字符不属于set。集合set在前面已经有描述。子项目的开始和结束时按照字符'\0'处理的。
    注意frontier pattern存在但是没有在Lua 5.1的文档中解释,而是在Lua 5.2正式加入的。Lua 5.2.1的做法与5.1.0的无区别。
模式(pattern)

模式(pattern)是模式条目(pattern item)的序列。

模式开头的^会从字符串的开始处匹配,而模式末尾的$会匹配字符串的最末尾。其他地方的^$都代表自身,无特殊含义。

捕获

模式可以包括用小括号括起来的子模式(sub-patterns),描述了“捕获”。匹配成功时,字符串的匹配捕获的子字符串会被存储(被“捕获”)以备使用。捕获是根据左边的括号被标号的。比如,在模式(a*(.)%w(%s*))中,匹配a*(.)%w(%s*)的字符串部分被存储在第一个捕获(所以是第一项),匹配.的字符被捕获,记为第2项,匹配%s*的则是第3项。

捕获参考可以出现在字符串自身,而返回参考早前被捕获的文本。比如,([a-z])%1会匹配任何一对相同的小写字母,而([a-z])([a-z])([a-z])[a-z]%3%2%1会匹配任何7个字母的回文

特殊情况,空的捕获()会捕获当前的字符串位置(一个数字)。比如我们对字符串"flaaap"执行模式"()aa()",那么会有两个捕获:3和5。

表(table)库

这个库的大多数函数假设作为参数的表是序列

函数table.foreach()table.foreachi()table.getn()或许可用但是不推荐。应该使用pairs()的for循环、ipairs()的for循环和长度操作符。

table.concat

table.concat( table, sep, i, j )

给一个所有元素都是字符串或数字的数组,返回table[i] .. sep .. table[i+1] ··· sep .. table[j]

sep的默认值为空字符串,i的默认值为1,j的默认值为表的长度。如果i大于j,返回空字符串。

table.insert

table.insert( table, value )
table.insert( table, pos, value )

在表table的位置pos处插入元素value,会将其他元素的位置增加1以给这个元素提供插入空间。pos的默认值为表的长度加1,所以调用table.insert(t, x)会在表t的末尾插入x

大于#table的元素都会被提高,参考长度操作符以了解当表不是序列时的注意事项。

table.maxn

table.maxn( table )

返回给定的表的最大正数索引,或者表没有正数索引时返回零。

会遍历整个表,大致相当于

function table.maxn( table )
    local maxn, k = 0, nil
    repeat
        k = next( table, k )
        if type( k ) == 'number' and k > maxn then
            maxn = k
        end
    until not k
    return maxn
end

table.remove

table.remove( table, pos )

从表格table中移走位于pos处的元素,将后面的元素前移。pos的默认值为表的长度,所以调用table.remove( t )会移除表t的最后一个元素。

大于#table的元素都会被移动,参考长度操作符以了解当表不是序列时的注意事项。

table.sort

table.sort( table, comp )

table[1]table[#table],按照给定的次序给表的元素排序。如果给了comp,则它必须是接收两个表元素的函数,并且当第一个小于第二个时返回true(所以not comp(a[i+1],a[i])会在排序后为true)。如果没有给定comp,则使用标准的Lua操作符%lt;

排序算法并不稳定;也就是说,当两个元素按照给定的顺序被看作相等时,它们在排序后的相对位置可能会改变。

Scribunto库

所有Scribunto库位于表mw中。

基本函数

mw.addWarning

mw.addWarning( 文本 )

在预览编辑时加一个警告信息。text解析为维基文本。

mw.allToString

mw.allToString( ... )

对所有的参数调用tostring(),然后用制表符作为分隔符连接起来。

mw.clone

mw.clone( value )

深拷贝一个值。所有的表和它们的元表被重构,但是新表和旧表共用函数。

mw.getCurrentFrame

mw.getCurrentFrame()

返回目前的框架项目,通常是从最近的#invoke中的框架项目。

mw.incrementExpensiveFunctionCount

mw.incrementExpensiveFunctionCount()

使得“高开销解析器函数”计数器加一,并在其超过限制时抛出异常(参见$wgExpensiveParserFunctionLimit)。

mw.isSubsting

mw.isSubsting()

如果当前的#invoke替换引用时返回true,否则false。参见上方讨论的返回文本

mw.loadData

mw.loadData( module )

有时一个模块需要大量表格的数据,例如,用于转换计量单位的通用模块可能需要一张大表的已识别的单位及其转换系数。而且有时这些模块会在一页中使用多次。每次{{#invoke:}}都解析大表格的数据会用大量时间。为了避免这个问题,所以提供了mw.loadData()

mw.loadData类似于require(),但是有以下区别:

  • 加载的模块每页只会解析一次,而不是每次调用{{#invoke:}}就解析一次。
  • 加载的模块不会记录在package.loaded中。

从加载的模块返回的值必须是表。其他数据类型不支持。

  • 返回的表(以及其所有子表)智能包含布尔值、数字、字符串和其他表。其他的数据类型,比如函数,不允许。
  • 返回的表(和所有子表)不能有metatable元表。
  • 所有的表键必须是布尔值、数字、字符串。
  • mw.loadData()返回的表提供元方法,可以提供只读获取由模块返回的表。因为不能直接包含数据,pairs()ipairs()会起作用,但是像#valuenext()这样的函数和表库的函数不会起作用。

上述假定的单位转换模块可能将其代码存储在“Module:Convert”然后将其数据存储在“Module:Convert/data”,且“Module:Convert”会使用local data = mw.loadData( 'Module:Convert/data' )来有效地加载数据。

mw.dumpObject

mw.dumpObject( object )

object序列化为人类可读的字符串并返回。

mw.log

mw.log( ... )

将参数传递到mw.allToString(),然后将结果字符串加载控制台后。

在调试控制台,print()等价于这个函数。

mw.logObject

mw.logObject( object )
mw.logObject( object, prefix )

调用mw.dumpObject()然后将结果加到控制台输出的后面。如果给了prefix,则会被加到控制台输出并紧随一个等于号在序列化字符串之前,比如输出的字符串可以是"prefix = object-string"。

框架对象(Frame object)

框架(frame对象)是接口。通过框架来访问传递至{{#invoke:}}和解析器函数的参数。

注意没有框架库,也没有叫做frame的全局变量。框架项目通常为被{{#invoke:}}调用的函数的参数,当然也可以从mw.getCurrentFrame()获得。

frame.args

用来访问传递到frame的参数的表。例如,一个模块从如下的维基文本调用

{{#invoke:module|function|arg1|arg2|name=arg3}}

那么frame.args[1]会返回"arg1"frame.args[2]会返回"arg2"frame.args['name']frame.args.name会返回"arg3"。在参数列表迭代可以使用pairs( frame.args )ipairs( frame.args )。 然而基于Lua对迭代器的实现,迭代的顺序不确定,参数出现在维基文本中的顺序也无从得知。

注意这个表的值总是为字符串,tonumber()可以用于在需要时转化为数字。但是,键是数字,即使在调用时清楚提供:{{#invoke:module|function|1|2=2}}给予被数字键12索引的字符串值"1""2"

因为在MediaWiki模板调用中,命名的参数会在传递到Lua时移除名称和值的多余空格,而隐式参数不会移除空格。

考虑到性能,frame.args使用元表,而非直接包含参数。参数值会从MediaWiki被要求得到。这意味着大多数其他表格方法不会正常工作,包括#frame.argsnext( frame.args )表格库中的函数。

如果像模板调用和三层括号变量这样的预处理器(preprocessor)语法在#invoke的参数中被使用,那么这些不会被展开,而在传递到Lua之后,知道值被Lua获取。如果特定的特殊标签写成了XML标记形式,比如<pre><nowiki><gallery><ref>,被包括在需要调用的参数中,这些标签会被转化为strip marker——一种特殊字符串,由删除符(ASCII 127)开始,在从#invoke返回后转化为HTML。

frame:callParserFunction

frame:callParserFunction( name, args )
frame:callParserFunction( name, ... )
frame:callParserFunction{ name = string, args = table }

注意使用命名参数

调用解析器函数,返回适当的字符串。可能时,最好优先使用原生的Lua函数或Scribunto库函数。

以下调用与以下维基文本基本相同:

-- {{ns:0}}
frame:callParserFunction{ name = 'ns', args = 0 }

-- {{#tag:nowiki|some text}}
frame:callParserFunction{ name = '#tag', args = { 'nowiki', 'some text' } }
frame:callParserFunction( '#tag', { 'nowiki', 'some text' } )
frame:callParserFunction( '#tag', 'nowiki', 'some text' )
frame:callParserFunction( '#tag:nowiki', 'some text' )

-- {{#tag:ref|some text|name=foo|group=bar}}
frame:callParserFunction{ name = '#tag:ref', args = {
    'some text', name = 'foo', group = 'bar'
} }

注意,函数名称和参数不会在传递到解析器函数之前被预处理(preprocess),frame:expandTemplate()也是如此。

frame:expandTemplate

frame:expandTemplate{ title = title, args = table }

注意命名参数的使用。

这是嵌入包含。函数

frame:expandTemplate{ title = 'template', args = { 'arg1', 'arg2', name = 'arg3' } }

在Lua脚本中的行为大致和{{template|arg1|arg2|name=arg3}}在维基文本中的行为一样。如果页面名没有名字空间前缀,那么函数会认为页面在模板名字空间内。

注意标题与参数在传递到模版之前并未预处理:

-- 这与维基文本{{template|{{!}}}}基本相同
frame:expandTemplate{ title = 'template', args = { '|' } }

-- 这与维基文本{{template|{{((}}!{{))}}}}基本相同
frame:expandTemplate{ title = 'template', args = { '{{!}}' } }

frame:extensionTag

frame:extensionTag( name, content, args )
frame:extensionTag{ name = string, content = string, args = table_or_string }

这大致相当于调用frame:callParserFunction(),其函数名称为'#tag:' .. 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}},而另一页嵌入包含(transclude)那个页面并给{{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 }

注意命名参数的使用。

创建当前框架的子框架项目,可以有可选的参数和标题。

这个主要用于测试函数要被{{#invoke:}}调用时的调试。任何一次创建的框架的数量是受限制的。

frame:preprocess

frame:preprocess( string )
frame:preprocess{ text = string }

会在当前框架环境下展开维基文本,比如,模板、解析器函数以及像code>{{{1}}}这样的参数都会展开。某些特殊的写成XML格式的标记,比如<pre><nowiki><gallery><ref>都会被替换为“strip marker”——一类特殊的字符串,由删除符(ASCII 127)开头,在从#invoke返回后被替换成HTML。

如果你使用单个模板,使用frame:expandTemplate而非尝试建造维基文本以使用这个方法。这样更快并且不容易出错,尤其是参数包含管道符或其他维基标记时。

同理,展开单个解析器函数时应使用frame:callParserFunction

frame:getArgument

frame:getArgument( arg )
frame:getArgument{ name = arg }

获得特定参数的对象,或者没有提供参数时返回nil。

返回的对象有一个方法,object:expand(),可以返回对应参数的展开后的维基文本。

frame:newParserValue

frame:newParserValue( text )
frame:newParserValue{ text = text }

返回有一个方法object:expand()的对象,该方法可以返回frame:preprocess( text )的结果。

frame:newTemplateParserValue

frame:newTemplateParserValue{ title = title, args = table }

注意命名参数的使用。

返回有一个方法object:expand()的对象,该方法可以返回使用给定的参数调用frame:expandTemplate的结果。

frame:argumentPairs

frame:argumentPairs()

等同于pairs( frame.args )。考虑到向后兼容。

哈希库

mw.hash.hashValue

mw.hash.hashValue( algo, value )

按照指定的算法算出字符串的哈希值。有效地算法可以通过mw.hash.listAlgorithms()获得。

mw.hash.listAlgorithms

mw.hash.listAlgorithms()

返回支持的哈希算法的列表,以用于mw.hash.hashValue()

HTML库

mw.html是用于在Lua中构建复杂HTML树的友好接口。使用mw.html.create方法来创建mw.html对象。

被记为mw.html.name在全局mw.html表是可用的,被记为mw.html: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 )

创建一个新的mw.html对象,包含标签名称tagName的HTML元素。你可以传递一个空的字符串或nil作为tagName,以便于创建一个新的mw.html对象。

args可以是有以下键的表:

  • args.selfClosing:强制当前标签自我闭合,即使mw.html不认可其自我闭合
  • args.parent:当前mw.html实例的上级对象(用于内部使用)

mw.html:node

html:node( builder )

向当前的mw.html实例附加mw.html(builder)子元素。如果传递nil,那么函数不做任何事。(builder)参数代表要创建的HTML元素的种类。

mw.html:wikitext

html:wikitext( ... )

给mw.html对象加上不定数量的维基文本字符串。

注意遇到第一个nil项就会停。

mw.html:newline

html:newline()

给mw.html对象加新行。

mw.html:tag

html:tag( tagName, args )

给mw.html对象添加一个新的节点,其标签名称为tagName,返回代表这个新的节点的mw.html实例。args参数和mw.html.create的参数是一样的。

mw.html:attr

html:attr( name, value )
html:attr( table )

将节点的HTML属性的name属性的值设为value。也可以选择使用表,其键值对即为属性名称-值对。第一种形式中,如果值为nil,会导致这个给定名称的已被设置属性设为未被设置。

mw.html:getAttr

html:getAttr( name )

获得已经通过html:attr()设置的属性name的值。

mw.html:addClass

html:addClass( class )

给节点的类(class)属性添加一个类名称(class name)。如果参数为nil,则无效。

mw.html:css

html:css( name, value )
html:css( table )

使用给定的namevalue给节点设置CSS属性。也可以选择使用表,其键值对即为CSS名称-值对。第一种形式中,如果值为nil,会导致这个给定名称的已被设置的CSS设为未被设置。

mw.html:cssText

html:cssText( css )

给节点的属性添加一些纯css文本。如果参数为nil,则无效。

mw.html:done

html:done()

返回当前节点被创建时所在的上级节点。类似于jQuery.end,这是个方便地函数可以允许创建多个子节点,而由一个语句串在一起。

mw.html:allDone

html:allDone()

类似于html:done(),但是会遍历直到树节点的根部再返回。

语言库

语言代码在语言代码中由描述。很多MediaWiki的语言代码类似于IETF语言标签,但不是所有MediaWiki语言代码都是有效的IETF标签,反之亦然。

被记为mw.language.name在全局mw.language表是可用的,被记为mw.language:namelang:name是一个语言对象的方法(参见mw.language.newmw.language.getContentLanguage)。

mw.language.fetchLanguageName

mw.language.fetchLanguageName( code, inLanguage )

The full name of the language for the given language code: native name (language autonym) by default, name translated in target language if a value is given for inLanguage.

mw.language.fetchLanguageNames

mw.language.fetchLanguageNames()
mw.language.fetchLanguageNames( inLanguage )
mw.language.fetchLanguageNames( inLanguage, include )

Fetch the list of languages known to MediaWiki, returning a table mapping language code to language name.

By default the name returned is the language autonym; passing a language code for inLanguage returns all names in that language.

By default, only language names known to MediaWiki are returned; passing 'all' for include will return all available languages (e.g. from Extension:CLDR ), while passing 'mwfile' will include only languages having customized messages included with MediaWiki core or enabled extensions. To explicitly select the default, 'mw' may be passed.

mw.language.getContentLanguage

mw.language.getContentLanguage()
mw.getContentLanguage()

Returns a new language object for the wiki's default content language.

mw.language.getFallbacksFor

 
Fallback chains

mw.language.getFallbacksFor( code )

Returns a list of MediaWiki's fallback language codes for the specified code.

mw.language.isKnownLanguageTag

mw.language.isKnownLanguageTag( code )

Returns true if a language code is known to MediaWiki.

A language code is "known" if it is a "valid built-in code" (i.e. it returns true for mw.language.isValidBuiltInCode) and returns a non-empty string for mw.language.fetchLanguageName.

mw.language.isSupportedLanguage

mw.language.isSupportedLanguage( code )

Checks whether any localisation is available for that language code in MediaWiki.

A language code is "supported" if it is a "valid" code (returns true for mw.language.isValidCode), contains no uppercase letters, and has a message file in the currently-running version of MediaWiki.

It is possible for a language code to be "supported" but not "known" (i.e. returning true for mw.language.isKnownLanguageTag). Also note that certain codes are "supported" despite mw.language.isValidBuiltInCode returning false.

mw.language.isValidBuiltInCode

mw.language.isValidBuiltInCode( code )

Returns true if a language code is of a valid form for the purposes of internal customisation of MediaWiki.

The code may not actually correspond to any known language.

A language code is a "valid built-in code" if it is a "valid" code (i.e. it returns true for mw.language.isValidCode); consists of only ASCII letters, numbers, and hyphens; and is at least two characters long.

Note that some codes are "supported" (i.e. returning true from mw.language.isSupportedLanguage) even though this function returns false.

mw.language.isValidCode

mw.language.isValidCode( code )

Returns true if a language code string is of a valid form, whether or not it exists. This includes codes which are used solely for customisation via the MediaWiki namespace.

The code may not actually correspond to any known language.

A language code is valid if it does not contain certain unsafe characters (colons, single- or double-quotes, slashs, backslashs, angle brackets, ampersands, or ASCII NULs) and is otherwise allowed in a page title.

mw.language.new

mw.language.new( code )
mw.getLanguage( code )

Creates a new language object. Language objects do not have any publicly accessible properties, but they do have several methods, which are documented below.

There is a limit on the number of distinct language codes that may be used on a page. Exceeding this limit will result in errors.

mw.language:getCode

lang:getCode()

Returns the language code for this language object.

mw.language:getFallbackLanguages

lang:getFallbackLanguages()

Returns a list of MediaWiki's fallback language codes for this language object. Equivalent to mw.language.getFallbacksFor( lang:getCode() ).

mw.language:isRTL

lang:isRTL()

Returns true if the language is written right-to-left, false if it is written left-to-right.

mw.language:lc

lang:lc( s )

Converts the string to lowercase, honoring any special rules for the given language.

When the Ustring library is loaded, the mw.ustring.lower() function is implemented as a call to mw.language.getContentLanguage():lc( s ).

mw.language:lcfirst

lang:lcfirst( s )

Converts the first character of the string to lowercase, as with lang:lc().

mw.language:uc

lang:uc( s )

Converts the string to uppercase, honoring any special rules for the given language.

When the Ustring library is loaded, the mw.ustring.upper() function is implemented as a call to mw.language.getContentLanguage():uc( s ).

mw.language:ucfirst

lang:ucfirst( s )

Converts the first character of the string to uppercase, as with lang:uc().

mw.language:caseFold

lang:caseFold( s )

Converts the string to a representation appropriate for case-insensitive comparison. Note that the result may not make any sense when displayed.

mw.language:formatNum

lang:formatNum( n )
lang:formatNum( n, options )

Formats a number with grouping and decimal separators appropriate for the given language. Given 123456.78, this may produce "123,456.78", "123.456,78", or even something like "١٢٣٬٤٥٦٫٧٨" depending on the language and wiki configuration.

The options is a table of options, which can be:

  • noCommafy: Set true to omit grouping separators and use a dot (.) as the decimal separator. Digit transformation may still occur, which may include transforming the decimal separator.

mw.language:formatDate

lang:formatDate( format, timestamp, local )

Formats a date according to the given format string. If timestamp is omitted, the default is the current time. The value for local must be a boolean or nil; if true, the time is formatted in the wiki's local time rather than in UTC.

The format string and supported values for timestamp are identical to those for the #time parser function from 扩展:解析器函数 . Note however that backslashes may need to be doubled in a Lua string literal, since Lua also uses backslash as an escape character while wikitext does not:

-- This string literal contains a newline, not the two characters "\n", so it is not equivalent to {{#time:\n}}.
lang:formatDate( '\n' )

-- This is equivalent to {{#time:\n}}, not {{#time:\\n}}.
lang:formatDate( '\\n' )

-- This is equivalent to {{#time:\\n}}, not {{#time:\\\\n}}.
lang:formatDate( '\\\\n' )

mw.language:formatDuration

lang:formatDuration( seconds )
lang:formatDuration( seconds, allowedIntervals )

Breaks a duration in seconds into more human-readable units, e.g. 12345 to 3 hours, 25 minutes and 45 seconds, returning the result as a string.

allowedIntervals, if given, is a table with values naming the interval units to use in the response. These include 'millennia', 'centuries', 'decades', 'years', 'weeks', 'days', 'hours', 'minutes', and 'seconds'.

mw.language:parseFormattedNumber

lang:parseFormattedNumber( s )

This takes a number as formatted by lang:formatNum() and returns the actual number. In other words, this is basically a language-aware version of tonumber().

mw.language:convertPlural

lang:convertPlural( n, ... )
lang:convertPlural( n, forms )
lang:plural( n, ... )
lang:plural( n, forms )

This chooses the appropriate grammatical form from forms (which must be a sequence table) or ... based on the number n. For example, in English you might use n .. ' ' .. lang:plural( n, 'sock', 'socks' ) or n .. ' ' .. lang:plural( n, { 'sock', 'socks' } ) to generate grammatically-correct text whether there is only 1 sock or 200 socks.

The necessary values for the sequence are language-dependent, see localization of magic words and translatewiki's FAQ on PLURAL for some details.

mw.language:convertGrammar

lang:convertGrammar( word, case )
lang:grammar( case, word )

Note the different parameter order between the two aliases. 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.

This chooses the appropriate inflected form of word for the given inflection code case.

The possible values for word and case are language-dependent, see Special:MyLanguage/Help:Magic words#Localisation and translatewiki:Grammar for some details.

mw.language:gender

lang:gender( what, masculine, feminine, neutral )
lang:gender( what, { masculine, feminine, neutral } )

Chooses the string corresponding to the gender of what, which may be "male", "female", or a registered user name.

mw.language:getArrow

lang:getArrow( direction )

Returns a Unicode arrow character corresponding to direction:

  • forwards: Either "→" or "←" depending on the directionality of the language.
  • backwards: Either "←" or "→" depending on the directionality of the language.
  • left: "←"
  • right: "→"
  • up: "↑"
  • down: "↓"

mw.language:getDir

lang:getDir()

根据语言的书写方向,返回"ltr"(从左至右)或"rtl"(从右至左)。

mw.language:getDirMark

lang:getDirMark( opposite )

Returns a string containing either U+200E (the left-to-right mark) or U+200F (the right-to-left mark), depending on the directionality of the language and whether opposite is a true or false value.

mw.language:getDirMarkEntity

lang:getDirMarkEntity( opposite )

Returns "&lrm;" or "&rlm;", depending on the directionality of the language and whether opposite is a true or false value.

mw.language:getDurationIntervals

lang:getDurationIntervals( seconds )
lang:getDurationIntervals( seconds, allowedIntervals )

Breaks a duration in seconds into more human-readable units, e.g. 12345 to 3 hours, 25 minutes and 45 seconds, returning the result as a table mapping unit names to numbers.

For example, { ['hours'] = 3, ['minutes'] = 25, ['seconds'] = 45 }

allowedIntervals, if given, is a table with values naming the interval units to use in the response. These include 'millennia', 'centuries', 'decades', 'years', 'days', 'hours', 'minutes', and 'seconds'.

The unit names in allowedIntervals may be specified in any order (currently in English only, indendantly of the language object used, and with their plural unabbreviated form only like in the returned table, where unit names are symbolic but still not translated and not grammatically changed according to their assigned value). If the input table contains only unsupported unit names, the returned table will be empty. If the input table is not specified, is nil, or is empty, a static table for any supported units (including 'seconds' for the shortest unit) will be used by default.

The specified duration in seconds is first rounded down to an integer number of the shortest desired unit. The number of members in the returned array is variable, and only unit names mapped to a non-zero value are kept in the returned table if the rounded number of seconds is strictly positive. Otherwise only the member for the shortest desired unit name ('seconds' by default) will be set to the rounded down duration.

系统消息库

这个库是对本地化消息和MediaWiki:名字空间的界面。

被记为mw.message.name在全局mw.message表是可用的,被记为mw.message:namemsg:name是一个消息对象的方法(参见mw.message.new)。

mw.message.new

mw.message.new( key, ... )

创建一个给定消息key的新消息对象。 剩下的参数传递到新的对象的params()的方法。

消息对象没有属性,但是有下面列出的几个方法。

mw.message.newFallbackSequence

mw.message.newFallbackSequence( ... )

创建给定的消息的新的消息对象(存在的第一个会被使用)。

消息对象没有属性,但有下面列出的几种方法。

mw.message.newRawMessage

mw.message.newRawMessage( msg, ... )

创建新的消息对象,使用给定的文本,而不是查找国际化的(internationalized)消息。剩下的参数会传递到新对象的params()方法中。

消息对象没有属性,但是有下面列出的几个方法。

mw.message.rawParam

mw.message.rawParam( value )

包装(wrap)该值使之不会被msg:parse()解析为维基文本。

mw.message.numParam

mw.message.numParam( value )

包装(wrap)该值使之自动被格式化为lang:formatNum()。注意这不依赖事实上有效的语言库

mw.message.getDefaultLanguage

mw.message.getDefaultLanguage()

返回默认语言的语言对象。

mw.message:params

msg:params( ... )
msg:params( params )

给消息添加参数,参数可以一被传递为独立的参数或者作为一个序列表。参数必须是数字、字符串或由mw.message.numParam()mw.message.rawParam()返回的特殊的值。如果使用序列表,参数必须是直接出现在表中,使用__index元方法的参考不起作用。

返回msg对象,允许串起来调用。

mw.message:rawParams

msg:rawParams( ... )
msg:rawParams( params )

:params(),但是会先通过mw.message.rawParam()传递所有的参数。

返回msg对象,允许串起来调用。

mw.message:numParams

msg:numParams( ... )
msg:numParams( params )

:params(),但是会先通过mw.message.numParam()传递所有的参数。

返回msg对象,允许串起来调用。

mw.message:inLanguage

msg:inLanguage( lang )

指定一个语言,以在加工消息时使用。lang可以是字符串,或者带有getCode()元表的表(比如语言对象)。

默认的语言是由mw.message.getDefaultLanguage()返回的。

返回msg对象,允许串起来调用。

mw.message:useDatabase

msg:useDatabase( bool )

指定是否在MediaWiki:名字空间查找消息(比如在数据库中查找),或者只是使用MediaWiki分配的默认消息。

默认为true。

返回msg对象,允许串起来调用。

mw.message:plain

msg:plain()

替换参数按原样返回消息维基文本。模板调用和解析器函数都是完整的。

mw.message:exists

msg:exists()

返回表示消息键是否存在的布尔值。

mw.message:isBlank

msg:isBlank()

返回表示消息键是否有内容的布尔值。当消息键不存在或者消息是空字符串时返回true。

mw.message:isDisabled

msg:isDisabled()

返回表示消息键是否被禁用的布尔值。如果消息键不存在,或者消息是空字符串,或者是字符串"-"则返回true。

站点信息库

mw.site.currentVersion

包含当前MediaWiki版本信息的字符串值。

mw.site.scriptPath

$wgScriptPath的值。

mw.site.server

$wgServer的值。

mw.site.siteName

$wgSitename的值。

mw.site.stylePath

$wgStylePath的值。

mw.site.namespaces

包含所有名字空间数据的表,由数字索引。

可用的数据为:

  • id:名字空间数字。
  • name:本地名字空间名称。
  • canonicalName:名字空间名字的规范形式。
  • displayName:名字空间0的集合,用于显示的名字空间(因为这个名字通常是空白字符串)。
  • hasSubpages:这个名字空间是否允许启用子页面(subpages)。
  • hasGenderDistinction:这个名字空间在不同的词性是否有不同的别称(aliases)。
  • isCapitalized:这个名字空间的页面的第一个字母是否会转化为大写。
  • isContent:这个名字空间是否为内容名字空间。
  • isIncludable:这个名字空间的页面是否可以被嵌入包含。
  • isMovable:这个名字空间的页面是否可以移动。
  • isSubject:这个名字空间是否为一个项目名字空间(subject namespace)。
  • isTalk:这个名字空间是否为讨论页。
  • defaultContentModel:这个名字空间的默认内容模型(字符串)。
  • aliases:这个名字空间的别称的列表。
  • subject:对应项目名字空间的数据。
  • talk对应讨论页名字空间的数据。
  • associated与之有关联的名字空间的数据。

设置了元表以便于按照名称(本地化的或者规范的)查找名字空间。比如,mw.site.namespaces[4]mw.site.namespaces.Project都会返回关于Project名字空间的信息。

mw.site.contentNamespaces

只包含内容名字空间的表,按数字索引。参考mw.site.namespaces以了解详细内容。

mw.site.subjectNamespaces

只包含项目名字空间的表,按数字索引。参考mw.site.namespaces以了解详细内容。

mw.site.talkNamespaces

只包含讨论名字空间的表,按数字索引。参考mw.site.namespaces以了解详细内容。

mw.site.stats

包含站点统计的表。可用的统计有:

  • pages:wiki的页面数量。
  • articles:wiki的文章数量。
  • files:wiki的文件数量。
  • edits:wiki的编辑次数。
  • users:wiki的用户数量。
  • activeUsers:wiki的活跃用户数量。
  • admins:wiki中sysop用户组的用户数量。

mw.site.stats.pagesInCategory

mw.site.stats.pagesInCategory( category, which )

这个函数是高开销函数

获得关于分类的统计数据。如果which未指定,或者是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前缀的数据的表。如果filter是字符串"local",则只会返回关于本地跨wiki前缀的数据。如果filter是字符串"!local",则只会返回非本地跨wiki前缀的数据。如果没有指定filter,则所有的前缀的数据都会返回。这个"local"前缀是同一个项目的。比如在英文维基百科,其他语言的维基百科都会考虑为本地的(local),而维基词典不会。

这个函数返回的表的键是跨wiki前缀,值是带有以下属性的子表:

  • prefix——跨wiki前缀。
  • url——跨wiki指向的URL。页面名称由参数$1体现。
  • isProtocalRelative——布尔值,显示URL是否为URL
  • isLocal——这个URL是否是当前wiki的站点的。
  • isCurrentWiki——这个URL是否是为当前wiki的。
  • isTranscludable——使用这个跨wiki前缀的页面能否嵌入包含。这个要求scary transclusion,而这在维基媒体的wiki是禁用的。
  • isExtraLanguageLink——跨wiki是否列举在了$wgExtraInterlanguageLinkPrefixes
  • displayText——对于列举在$wgExtraInterlanguageLinkPrefixes中的链接,跨语言链接显示的文本。未指定时为nil。
  • tooltip——对于列举在$wgExtraInterlanguageLinkPrefixes的链接,当用户悬浮在跨语言链接上时显示的浮窗提示文本。未指定时为nil。

文本库

文本库提供了一些常见的文本处理函数,这些函数来自字符串库Ustring库,并且可用于UTF-8字符串。

mw.text.decode

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

将字符串中的HTML元素替换为对应的字符。

如果布尔值decodeNameEntities被省略或者为false,则只有被命名的实体“&lt;”“&gt;”“&amp;”“&quot;”和“&nbsp;”会被认可。否则,认可的HTML5命名实体的列表会从PHP的get_html_translation_table函数中加载。

mw.text.encode

mw.text.encode( s )
mw.text.encode( s, charset )

使用HTML实体替换字符串中的字符。字符“<”“>”“&”“"”和非换行空格会被适当的命名实体替换,所有其他的都会被替换为数字实体。

如果提供了charset,则它应该是合适的字符串,且被Ustring模式的括号括住,比如[set]中的“set”。默认的charset是'<>&"\' '(末尾的空格为非换行空格,U+00A0)。

mw.text.jsonDecode

mw.text.jsonDecode( s )
mw.text.jsonDecode( s, flags )

解析JSON字符串。flags是0或flagsmw.text.JSON_PRESERVE_KEYSmw.text.JSON_TRY_FIXING的组合(使用+)。

通常JSON的数组会被重组到Lua的有键的序列表,如果要避免这个,可以传入mw.text.JSON_PRESERVE_KEYS

如果要降低JSON的特定需求,比如数组或对象不应有结尾的逗号,可传入mw.text.JSON_TRY_FIXING。不推荐这样做。

限制:

  • 如果数组含有null值,解析的JSON数组可能不是Lua序列。
  • JSON对象会丢弃含有null值得键。
  • 不能直接分辨带有序列整数键的是JSON数组还是JSON对象。
  • 带有序列整数键从1开始的的JSON对象会被解析到作为有相同值的JSON数组的相同的表结构,尽管这些不一定总是相等,除非使用了mw.text.JSON_PRESERVE_KEYS

mw.text.jsonEncode

mw.text.jsonEncode( value )
mw.text.jsonEncode( value, flags )

编码JSON字符串。如果传入的值不能被JSON编码则会报错。flags是0或flagsmw.text.JSON_PRESERVE_KEYSmw.text.JSON_PRETTY的组合(使用+)。

通常Lua的带有键的序列表会被编码称JSON的不带键的序列;如果flags中设置了mw.text.JSON_PRESERVE_KEYS,不带键的序列表会被编码为JSON数组。

限制:

  • 空的表总是会被编码为空的数组([]),而不是空的对象({})。
  • 如果没有加入无效(dummy)元素,序列表不能被编码为JSON对象。
  • 如果要产生带有nil值得对象,需要设置__pairs元方法。
  • 带有从0开始的序列整数键的Lua表会被编码为JSON数组,带有从1开始的整数键的Lua表也是如此,除非使用了mw.text.JSON_PRESERVE_KEYS
  • 如果同一个表中,既使用了数字,又使用了代表那个数字的字符串作为键,则行为未指定。

mw.text.killMarkers

mw.text.killMarkers( s )

除去字符串中所有的strip marker

mw.text.listToText

mw.text.listToText( list )
mw.text.listToText( list, separator, conjunction )

使用自然语言组合一个列表,类似于table.concat(),但是最后一项前面的分隔符不同。

默认的分隔符取自wiki内容语言的MediaWiki:comma-separator,默认的连词取自由MediaWiki:word-separator连接的MediaWiki:and

比如,对消息使用默认值:

 -- 返回空字符串
 mw.text.listToText( {} )
 
 -- 返回"1"
 mw.text.listToText( { 1 } )
 
 -- 返回"1和2"(如果wiki的语言设置为“中文”,下同)
 mw.text.listToText( { 1, 2 } )
 
 -- 返回"1、2、3、4和5"
 mw.text.listToText( { 1, 2, 3, 4, 5 } )
 
 -- 返回"1; 2; 3; 4 or 5"
 mw.text.listToText( { 1, 2, 3, 4, 5 }, '; ', ' or ' )

mw.text.nowiki

mw.text.nowiki( s )

使用HTML实体替换字符串中的多种字符,以避免被解析为维基文本。包括:

  • 以下字符:'"', '&', "'", '<', '=', '>', '[', ']', '{', '|', '}'
  • 字符串开头或新行后面的的以下字符:'#', '*', ':', ';'、空格、制表符('\t')
  • 空行会有关联的新行或返回转义的字符(Blank lines will have one of the associated newline or carriage return characters escaped)
  • 字符串开始处或新行后的的"----"会使得第一个'-'被转义
  • "__"会使一个下划线被转义
  • "://"会使冒号被转义
  • ISBN、RFC或PMID后的空白字符会被转义

mw.text.split

mw.text.split( s, pattern, plain )

在匹配了Ustring模式pattern的地方分割字符串。如果指定了plain且为true,则pattern会被解释为纯字符串而不是Lua模式(就像mw.ustring.find()的这个参数一样)。返回包含子字符串的表。

比如,mw.text.split( 'a b\tc\nd', '%s' )会返回表{ 'a', 'b', 'c', 'd' }

如果pattern匹配空字符串,s会被分割成单个字符。

mw.text.gsplit

mw.text.gsplit( s, pattern, plain )

返回会迭代子字符串的迭代器函数,返回的相当于调用mw.text.split()

mw.text.tag

mw.text.tag( name, attrs, content )
mw.text.tag{ name = string, attrs = table, content = string|false }

使用具名参数的说明.

生成name的HTML样式的标签。

如果指定了attrs,则必须是带有字符串键的表。字符串和数字值都会被使用为属性的值,布尔值的true会被输出为HTML5的无值参数,布尔值的false会跳过这个键,其他的都会错误。

如果没有给出content(或者是nil),只会返回开始标签。如果content是布尔值false,则会返回自我闭合标签。否则它必须是字符串或数字,这样内容就会被开始标签和结束标签包围。注意内容不会自动被编码为HTML,如有需要,使用mw.text.encode()

对于返回扩展标签的属性,比如<ref>,应该使用frame:extensionTag()

mw.text.trim

mw.text.trim( s )
mw.text.trim( s, charset )

从字符串的开始和结尾移除空白字符或其他字符。

如果提供了charset,则它应该是合适的字符串,且被Ustring模式的括号括住,比如[set]中的“set”。默认的charset是ASCII空白字符,"\t\r\n\f "

mw.text.truncate

mw.text.truncate( text, length )
mw.text.truncate( text, length, ellipsis )
mw.text.truncate( text, length, ellipsis, adjustLength )

将文本text裁剪到指定的长度,如果执行了参见,加入ellipsis。如果长度为正,则字符串末尾被裁剪,如果为负,则字符串的开头会被裁剪。如果给定了adjustLength且为true,则包含省略号的字符串不会长于指定的长度。

ellipsis的默认值取自wiki的内容语言的MediaWiki:ellipsis

例如,使用默认的“...”省略号:

-- 返回"foobarbaz"
mw.text.truncate( "foobarbaz", 9 )

-- 返回"fooba..."
mw.text.truncate( "foobarbaz", 5 )

-- 返回"...arbaz"
mw.text.truncate( "foobarbaz", -5 )

-- 返回"foo..."
mw.text.truncate( "foobarbaz", 6, nil, true )

-- 返回"foobarbaz",因为比"foobarba..."更短
mw.text.truncate( "foobarbaz", 8 )

mw.text.unstripNoWiki

mw.text.unstripNoWiki( s )

将MediaWiki的<nowiki> strip marker替换为对应的文本。其他类型的strip marker不会改变。

mw.text.unstrip

mw.text.unstrip( s )

等同于mw.text.killMarkers( mw.text.unstripNoWiki( s ) )

这个不在显示特殊页面嵌入包含、<ref>后的HTML,就像Scribunto早期版本的那样。

标题库

mw.title.equals

mw.title.equals( a, b )

检测两个标题是否相等。注意比较时忽略碎片(fragments)。

mw.title.compare

mw.title.compare( a, b )

返回-1、0、1,表示标题a是否小于、等于或大于标题b

这会按照作为字符串的跨wiki前缀(如果有)比较,然后按名字空间数字,然后按照作为字符串的未加前缀的标题文本比较。字符串比较使用Lua标准的<操作符。

mw.title.getCurrentTitle

mw.title.getCurrentTitle()

返回当前页面的标题对象。

mw.title.new

mw.title.new( text, namespace )
mw.title.new( id )

用ID调用时该函数是高开销函数

创建新的标题对象。

如果给了id,则那个带有那个page_id的页面的对象会被创建。引用的标题会被认为链接到了当前页面。如果page_id不存在,返回nil。如果创建的标题对象不是对于已经加载的标题,则高开销函数数量会被增加。

然而,如果给了字符串text,那么那个标题的对象就会被创建(即使那个页面不存在)。如果文本字符串不指定名字空间,则使用namespace(可以在mw.site.namespaces的任何键中找到)。如果文本不是有效的标题,则会返回nil。

mw.title.makeTitle

mw.title.makeTitle( namespace, title, fragment, interwiki )

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.

  • 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.
  • cascadingProtection: The cascading protections applicable to the page. This is a table with keys "restrictions" (itself a table with keys like protectionLevels has) and "sources" (an array listing titles where the protections cascade from). If no protections cascade to the page, "restrictions" and "sources" will be empty. 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 "嵌入", and accessing the title object's file or fileExists fields records it as a "文件链接".

文件元数据

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.
高开销属性

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库

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对象

URI对象有以下域,其中的部分或全部可能是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库

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
     -- 语句块
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 )

等同于string.format()

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 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和⧼word-separator⧽%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().

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.

扩展库

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的不同之处

改变的函数

The following functions have been modified:

setfenv()
getfenv()
May not be available, depending on the configuration. If available, attempts to access parent environments will fail.
getmetatable()
Works on tables only to prevent unauthorized access to parent environments.
tostring()
Pointer addresses of tables and functions are not provided. This is to make memory corruption vulnerabilities more difficult to exploit.
pairs()
ipairs()
Support for the __pairs and __ipairs metamethods (added in Lua 5.2) has been added.
pcall()
xpcall()
Certain internal errors cannot be intercepted.
require()
Can fetch certain built-in modules distributed with Scribunto, as well as modules present in the Module namespace of the wiki. To fetch wiki modules, use the full page name including the namespace. Cannot otherwise access the local filesystem.

Removed functions and packages

The following packages are mostly removed. Only those functions listed are available:

package.*
Filesystem and C library access has been removed. Available functions and tables are:
package.loaded
package.preload
package.loaders
Loaders which access the local filesystem or load C libraries are not present. A loader for Module-namespace pages is added.
package.seeall()
os.*
There are some insecure functions in here, such as os.execute(), which can't be allowed. Available functions are:
os.clock()
os.date()
os.difftime()
os.time()
debug.*
Most of the functions are insecure. Available functions are:
debug.traceback()

The following functions and packages are not available:

collectgarbage()
module()
coroutine.*
No application is known for us, so it has not been reviewed for security.
dofile()
loadfile()
io.*, file.*
Allows local filesystem access, which is insecure.
load()
loadstring()
These were omitted to allow for static analysis of the Lua source code. Also, allowing these would allow Lua code to be added directly to article and template pages, which was not desired for usability reasons.
print()
This was discussed on wikitech-l and it was decided that it should be omitted in favour of return values, to improve code quality. If necessary, mw.log() may be used to output information to the debug console.
string.dump()
May expose private data from parent environments.

Additional caveats

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().

在其他扩展中的测试样例

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 Gerrit change 56570 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.

参见

许可

This manual is derived from the Lua 5.1 reference manual, which is available under the MIT license.

This derivative manual may also be copied under the terms of the same license.