维基百科:Lua

命名空间
基本命名空间 讨论命名空间
0 主/条目 帮助 讨论 1
2 用户 帮助 用户讨论 3
4 维基百科 维基百科讨论 5
6 文件 帮助 文件讨论 7
8 MediaWiki MediaWiki讨论 9
10 模板 帮助 模板讨论 11
12 帮助 帮助讨论 13
14 分类 帮助 分类讨论 15
100 主题 主题讨论 101
102 维基专题 维基专题讨论 103
118 草稿 草稿讨论 119
126 格式手册快捷方式 PNS 格式手册快捷方式讨论 127
710 字幕 字幕讨论 711
828 模块 模块讨论 829
1728 活动 活动讨论 1729
2600 话题 帮助
虚拟命名空间
-1 特殊
-2 媒体

Lua编程语言目前通过MediaWiki上的解析器函数插件引入到中文维基百科当中使用。要在模板中嵌入Lua脚本,可加入解析器函数中的{{#invoke:}}功能。Lua源代码存放在“模块”页面中(如模块:Example),再以{{#invoke:}}来调用。模块页面本身不支持切换中文语言变体。

用法

运行模块

普通维基页面通过#invoke分析器函数来调用模块。#invoke的句法与一般模板相似,但有些许不同。最重要的是必须指定函数名称。函数会拿一组输入值,通过一系列指令,输出一个值。[1]这和模板很像:输入参数,模板运作后,输出一个值。Lua模块中可以有多个函数,但单个模板则只能有一个。

另外,模块不可以直接运行,而是有指定要运行的单个函数。模块是一组函数综合起来的装载体,自身并没有功能。只有指定要运行哪一个函数,该模块才会知道要运行哪一个函数。

最简单的模块运行方法如下:

{{#invoke:模块名稱|函數名稱}}

例如,Module:Example就可以如此运行,其含有一个叫做“hello”的函数。

运用参数

参数进入模块脚本的方式与进入模板一样。不过,在调用模块时第一个竖线之后必须要先指定函数名,第二个竖线之后才是正式参数。

{{#invoke:模块名称|函数名称|第一参数|第二参数|带名称的参数 = 值}}

例如Module:BaseConvert可以转换数值的进位制:

运行模块时的参数会自动以table(表)类型的形式写入对应模块的frame.args中,其中frame为函数的第一个参数。例如{{#invoke:BaseConvert|convert|n=30|base=16}}就会自动给运行时的模块临时写入frame.args的值类似于{["n"]="30";["base"]="16"},例如frame.args.n就会输出为30(字符串形式)。(注意:参数名称如果是数字,其frame.args中的参数名称也是数字,但参数值一定是一个字符串。这个args其实是使用了元表的。它的真正值为getmetatable({},{__index=函数名,__pairs=函数名,__ipairs=函数名}),因此如果需要制作一个纯粹的表以使用table.insert等函数,可以利用pairs进行迭代。)

此外,如果是引用调用了模块的页面,其引用时的值会写入模块的frame:getParent().args中,例如(假设):

  1. 模块:Example的内容为:
    local p={}
    function p.x(frame) return frame:getParent().args["a"] end
    return p
    
  2. Template:Example中的内容为:
    {{#invoke:Example|x}}
  3. 那么直接调用{{#invoke:Example|x|a=Hello world}}是得不到任何内容的。
  4. 但是使用{{Example|a=Hello world}}就可以得到Hello world的字符串。

Scribunto对参数的处理有些限制,可参考模块:Arguments以了解如何使用该模块对参数进行进一步处理。

关于Lua

Lua是一种利用多重编程范式的脚本语言,可用于分析资料,计算公式及添加格式等。虽然Lua脚本可以非常简单,但其功能强大,能够支持各种复杂结构,如表格、动态函数等。Lua同时也支持含有自我嵌套函数的递归过程。因此在设计Lua程序时,须注意不要加入过度复杂的组件,以免他人无法有效阅读脚本。以下脚本(如在Module:HelloWorld)可以输出Hello World!信息:

-- 維基百科上的Lua模組必須在開頭定義一個變數,使參數可從外面存取。
-- 變數的名稱可以含有資料。
local my_object = {};

-- 在該變數上運行函數。在維基百科中可以用#invoke指令調用這些函數。
-- 函數被調用時,維基百科會向函數發送資料。這一資料應包含在frame以內。
my_object.hello = function( frame ) 

    -- 定義局部變數。
    local str = "Hello World!"  

    -- 終止函數,並把str中的資料輸出到維基百科。
    -- 不可使用print函數,所以所有輸出要用return
    return str    

-- 函數結束。
end

-- 模組底部須用return把帶有函數的變數送回維基百科。
return my_object

-- 現在{{#invoke: HelloWorld | hello }}就可以調用以上函數了
-- #invoke指令先指定模組名稱,HelloWorld,再指定某一函數,hello

(注意:以上只是对模块用法的一个示例,如果要输入Hello World的字符串,最简单的用法如下:)

local p = {}
function p.hello()
     return "Hello World!"
end
return p

Lua脚本在内文中可以加在<syntaxhighlight lang="lua"></syntaxhighlight>里面来加上颜色标注。详见Lua条目。

在MediaWiki中使用Lua的教程,可见mw:Extension:Scribunto/Lua reference manual

单元测试

Module:UnitTests提供Lua脚本的单元测试。它可用一组指定输入值来运行特定脚本,并确认输出值符合预期。单元测试可以很快地找到改变脚本后所产生的新问题。

模块(如Module:Example)的单元测试应该放在其附页Module:Example/testcases里面,并在Module talk:Example/testcases上用{{#invoke:Example/testcases|run_tests}}运行。测试方法必须以“test”开头。以下是Module:Example/testcases的例子。

-- [[Module:Example]]的單元測試。進入討論頁可運行測試。
local p = require('Module:UnitTests')
 
function p:test_hello()
    self:preprocess_equals('{{#invoke:Example| hello}}', 'Hello, world!')
end
 
return p

Special:Whatlinkshere/Module:UnitTests页面列出所有进行单元测试的模块。

MediaWiki特有功能

{{#invoke:}}当中的输入值在进入Lua脚本时一定是字符串格式。Lua只能输出非包含及不含{{...}}的维基代码。所有Lua脚本的CPU运行时间都限制在10秒。相比一般的Lua,Scribunto的Lua版本少了多个函数(见:mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#Differences from standard Lua)。Scribunto也提供大量用于和MediaWiki对接的函数(mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#Scribunto libraries)。

Lua输入值限制

Lua脚本只在页面解析时才会运行。所以要对Lua输入参数,必须通过“编辑此页”,而不可在页面中加入一个输入框,作实时处理,也不可动态点击挑选函数功能。Lua可以接受的输入值包括任何“可包含”的文字页面。这并不包括图像文件(甚至.SVG文件都不可)和分类中的页面列表等。

维基代码

经“包含”的标题经常会有诸如“UNIQ5ae8f2aa414ff233-h-3--QINU”的隐藏文字(称为strip mark)。这些文字要去除之后才会有效解析。部分扩展标签也会转化为strip mark。

类似[[Wikipedia:Help|]]的维基链接在经Lua输出后是没有用的,必须完整地写成[[Wikipedia:Help|Help]]。其他保存前自动进行的转换,如~~~~替换为签名,都会在Lua输出时无法进行(但在Lua函数被特定条件下还是会执行)。

在Lua代码中隐藏文本(即进行注释,例如HTML中的<!--...-->)的方法是在要注释的文本前输入--(不能在字符串内)。也可使用 --[[开始大段注释,用]]结束。

Lua不能进行魔术字模板解析器函数的替换,否则会直接保留管道符和花括号(在Special:展开模板页面除外)。使用模板应该使用frame:expandTemplate{title = "模板名称(不含命名空间)", args = {"参数1", "参数2"}},其中frame为函数中传入的框架对象,亦可通过mw.getCurrentFrame()获得。解析器函数和魔术字在Lua都有自带的函数,例如{{FULLPAGENAME}}应该用tostring(mw.title.getCurrentTitle())或者mw.title.getCurrentTitle().fullText,具体用法参见mw:Special:MyLanguage/Extension:Scribunto/Lua_reference_manual

<ref><nowiki>等标签也不会在Lua程序当中处理。若要处理<nowiki>,则应该使用mw.text.nowiki("原文本")

使用Lua的模板

基于Lua语言编写的模板的文档页面应当加上{{lua|模組名稱}}

之后这些模板会归入Category:Lua模板及其子分类中,你可以在这个分类中找到这些模板。请勿将模块归入此分类。

资源

文档

指南

Lua相关文章

模块链接列表

  1. ^ 也可以有多个输出值,但这类函数一般不用于#invoke中。