心百科:Lua

来自心百科,心灵的百科全书

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

用法

运行模块

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

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

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

{{#invoke:模块名称|函数名称}}

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

运用参数

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

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

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

  • 模板:Tlxm脚本错误:没有“BaseConvert”这个模块。
  • 模板:Tlxm脚本错误:没有“BaseConvert”这个模块。

运行模块时的参数会自动以table(表)类型的形式写入对应模块的frame.args中,其中frame为函数的第一个参数。例如模板:Tlxm就会自动给运行时的模块临时写入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. 那么直接调用模板:Tlxm是得不到任何内容的。
  4. 但是使用{{Example|a=Hello world}}就可以得到Hello world的字符串。

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

关于Lua

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

-- 维基百科上的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相关文章

  • 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.

模块链接列表

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