Guidelines:Modules: Difference between revisions
Jump to navigation
Jump to search
no edit summary
PhantomCaleb (talk | contribs) (intro) |
PhantomCaleb (talk | contribs) No edit summary |
||
Line 2: | Line 2: | ||
{{Big|Overview|3}}<br> | {{Big|Overview|3}}<br> | ||
'''Modules''' are {{Wp|Lua (programming language)|Lua}} scripts for making [[Help:Templates|templates]] using a full-fledged programming language. | '''Modules''' are {{Wp|Lua (programming language)|Lua}} scripts for making [[Help:Templates|templates]] using a full-fledged programming language. You can ask questions about Zelda Wiki modules in the <code>#modules</code> [{{Discord}} Discord] channel. | ||
== | ==Getting Started== | ||
<!-- | In order to contribute to modules, you'll need to learn basic programming in Lua. You'll also need to know the specifics of Lua scripting on MediaWiki. | ||
===Lua=== | |||
====Beginners==== | |||
====Developers==== | |||
If you already have some programming experience in other languages, note the following particularities of Lua. | |||
{| class="wikitable" | |||
! Particularities | |||
! Further reading | |||
|- | |||
| <code>table</code>s are the only built-in object type. Any use of the term "array" actually refers to a table with integer keys. | |||
The language offers prototype-based inheritance through '''metatables'''. | |||
| | |||
* [https://www.lua.org/pil/2.5.html Tables] | |||
* [https://www.lua.org/pil/2.5.html Metatables and Metamethods] | |||
|- | |||
| Generally tables are 1-indexed as opposed to 0-indexed. | |||
<syntaxhighlight lang="lua"> | |||
local tbl = {"foo"} | |||
tbl[1] | |||
> "foo" | |||
</syntaxhighlight> | |||
| | |||
* [https://www.lua.org/pil/11.1.html Arrays] | |||
|- | |||
| | |||
* The <code>ipairs</code> iterator is for <u>integer</u> key-value pairs in a table. | |||
* The <code>pairs</code> iterator is for <u>all</u> key-value pairs, integer or otherwise. | |||
| | |||
* [https://www.lua.org/pil/4.3.5.html Generic <code>for</code>] | |||
* [https://www.lua.org/pil/4.3.4.html Numeric <code>for</code>] | |||
|- | |||
| The length operator for a table is <code>#</code>. | |||
<code>#</code> replaces the <code>table.getn</code> seen in the online version of ''Programming in Lua'', which is for Lua 5.0. <code>getn</code> won't work here as the wiki is on Lua 5.1 (at the time of writing). | |||
<code>table.setn</code> was also deprecated and is unusable in 5.1. Unfortunately, the alternative <code>__len</code> field is only available in Lua 5.2. | |||
| | |||
|- | |||
| Tables, <code>nil</code>, and the <code>#</code> operator don't interact the way similar constructs do in other languages. | |||
<syntaxhighlight lang="lua"> | |||
#{ nil, nil, "foo" } | |||
> 3 | |||
local tbl = {} | |||
tbl[3] = "foo" | |||
#tbl | |||
> 0 | |||
tbl[1] = "bar" | |||
#tbl | |||
> 1 | |||
tbl[2] = "baz" | |||
#tbl | |||
> 3 | |||
</syntaxhighlight> | |||
| | |||
|} | |||
===Scribunto=== | |||
:''For a broader, more in-depth guide, see [[gphelp:Extension:Scribunto|Gamepedia Help Wiki]].'' | |||
:''See also the full {{Mediawiki|Extension:Scribunto/Lua reference manual|Scribunto/Lua reference manual}}.'' | |||
'''Scribunto''' is the name of the extension that enables modules. It is the term used for concepts that are Lua-related but specific to MediaWiki. | |||
The Lua on you see on MediaWiki is almost the same as standard Lua except for {{Mediawiki|Lua reference manual#Differences from standard Lua|some changes}} to library functions and packages. The main difference is in how Lua scripts are invoked. | |||
====<code>#invoke</code>==== | |||
The <code>#invoke</code> {{Mediawiki|Help:Extension:ParserFunctions|parser function}} is what bridges the gap between templates and module scripts.{{Note|It is possible to invoke a module from any page, but it is almost always best to wrap the invocation in a template.}} For example, the {{Mediawiki|Transclusion|transcluded}} content of [[Template:Figurine]] is as follows: | |||
<pre> | |||
{{#invoke:Figurine|Main}} | |||
</pre> | |||
This invokes [[Module:Figurine]], which looks be something like: | |||
<syntaxhighlight lang="lua"> | |||
local p = {} | |||
local h = {} | |||
local utilsGame = require("Module:UtilsGame") | |||
... | |||
function p.Main(frame) | |||
local args = frame:getParent().args | |||
local result = h.getFigurine(args[1], args[2]) | |||
return result | |||
end | |||
function h.getFigurine(game, name) | |||
... | |||
end | |||
return p | |||
</syntaxhighlight> | |||
A page can invoke any function that is a field on the module's '''export table'''. The export table is the <code>table</code> object returned by the module, which is always named <code>p</code> by convention. In this case, <code>Main</code> is the only function in the export table. | |||
====<code>args</code>==== | |||
Functions called via <code>#invoke</code> are passed a {{Mediawiki|Extension:Scribunto/Lua reference manual#Frame object|Frame object}}. <code>frame.args</code> is a <code>table</code> of the arguments to <code>#invoke</code>—there are none in the above example. However, <code>frame:getParent().args</code> represents the ''template'' arguments. For example, if a page has <code><nowiki>{{Figurine|TMC|Minish Ezlo}}</nowiki></code>, then <code>frame:getParent().args[1]</code> evaluates to the string <code>TMC</code> in that invocation. | |||
The <code>#</code> operator and most other table functions don't work on <code>frame.args</code>. | |||
====<code>mw</code>==== | |||
Scribunto adds several libraries that are pre-loaded on all modules as the <code>mw</code> object. The following libraries are of note, in addition to the {{Mediawiki|Extension:Scribunto/Lua reference manual#Base functions|base functions}}: | |||
{| class="wikitable" | |||
! Library | |||
! Usage example | |||
|- | |||
|<code>{{Mediawiki|Extension:Scribunto/Lua reference manual#Text library|mw.text}}</code> | |||
|[[Module:List]] | |||
|- | |||
|<code>{{Mediawiki|Extension:Scribunto/Lua reference manual#Title library|mw.title}}</code> | |||
|[[Module:Subpage List]] | |||
|- | |||
|<code>{{Mediawiki|Extension:Scribunto/Lua reference manual#HTML library|mw.html}}</code> | |||
|[[Module:Infobox2]] | |||
|} | |||
====<code>require</code>==== | |||
A module can import another module and use its exported functions. This is done with the <code>require</code> function, as shown in the above example with [[Module:UtilsGame]]. | |||
===Utility Modules=== | |||
A utility module is a library-type module meant to be used by other modules, rather than being invoked by a template. Most template-facing modules use at least one of these: | |||
* [[Module:UtilsGame]] | |||
* [[Module:UtilsMarkup]] | |||
* [[Module:UtilsTable]] | |||
A complete list of utility modules can be found [https://zelda.gamepedia.com/Special:PrefixIndex?prefix=Utils&namespace=828 here]. | |||
====Higher-Order Functions==== | |||
In utility modules such as [[Module:UtilsTable]], you'll often see functions like these: | |||
<syntaxhighlight lang="lua"> | |||
utilsTable.isEqual({})({}) | |||
> true | |||
</syntaxhighlight> | |||
You might've expected the usual function syntax <code>utilsTable.isEqual({}, {})</code> instead. The above is an example of a '''higher-order function'''—a function that returns a function. The function call above is shorthand for: | |||
<syntaxhighlight lang="lua"> | |||
local isEmpty = utilsTable.isEqual({}) | |||
isEmpty({}) | |||
> true | |||
</syntaxhighlight> | |||
Functions are written this way for increased reusability. They are often composed with the other type of higher-order function—one that accepts a function as an argument: | |||
<syntaxhighlight lang="lua"> | |||
local isEmpty = utilsTable.isEqual({}) | |||
local notEmpty = utilsFunction.negate(isEmpty) | |||
local magicWords = utilsTable.filter(notEmpty)({ {}, {}, {"Kooloo"}, {"Limpah"} }) | |||
utilsTable.flatten(magicWords) | |||
> { "Kooloo", "Limpah" } | |||
</syntaxhighlight> | |||
==Exercise== | |||
{{Notes}} | |||
{{Guidelines Nav}} | {{Guidelines Nav}} |