维基百科: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
710 字幕 字幕討論 711
828 模块 模块讨论 829
2300 小工具 小工具讨论 2301
2302 小工具定義頁 小工具定義頁讨论 2303
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中。