维基百科: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可以转换数值的进位制:
{{#invoke:BaseConvert|convert|n=9|base=2}}
→ 1001{{#invoke:BaseConvert|convert|n=30|base=16}}
→ 1E
运行模块时的参数会自动以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
中,例如(假设):
- 模块:Example的内容为:
local p={} function p.x(frame) return frame:getParent().args["a"] end return p
- Template:Example中的内容为:
{{#invoke:Example|x}}
- 那么直接调用
{{#invoke:Example|x|a=Hello world}}
是得不到任何内容的。 - 但是使用
{{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|模組名稱}}
:
此模板使用Lua语言: |
之后这些模板会归入Category:Lua模板及其子分类中,你可以在这个分类中找到这些模板。请勿将模块归入此分类。
资源
文档
- Scribunto Lua 参考手册
- Lua编程
- Lua样式介绍
- About regex 基于Regex的Lua样式
指南
- 维基百科:Lua代码风格 – 通过连贯性改进可读性的标准
- "What do converted templates look like?" (slideshow)
- en:Help:Lua debugging – 调试Lua模块的指南
- en:Help:Lua for beginners
- en:Wikipedia:Lua string functions
- en:Wikipedia:Guide to Scribbling – 怎样用Scribunto/Lua编写模板
- en:Wikiversity:Lua – Lua指引
Lua相关文章
- en:Wikipedia:Lua speed – 比较模板和模块速度
- en:Wikipedia:Lua articles
- en:User:Dragons flight/Lua performance
- en:Wikipedia:Lua unit testing
- mw:User:Sumanah/Lua vs Javascript
- Roberto Ierusalimschy. Lua Performance Tips (PDF). lua.org.
模块链接列表
- ^ 也可以有多个输出值,但这类函数一般不用于#invoke中。