Plover-bot (talk | contribs) m (→top: bad link repair) |
No edit summary |
||
Line 1: | Line 1: | ||
− | {{ |
+ | {{Move|Project:Lua/PAGENAME|reason = This [[Special:ListAdmins|administration team]] will move this page to '''Project:Lua'''.}} |
This article gives coding conventions for the creation and management of [[Global Lua Modules|global Lua modules]]. For an introduction to [[w:Help:Lua|Lua]], please see our [[Lua templating/Getting started|getting started guide]]. |
This article gives coding conventions for the creation and management of [[Global Lua Modules|global Lua modules]]. For an introduction to [[w:Help:Lua|Lua]], please see our [[Lua templating/Getting started|getting started guide]]. |
||
Revision as of 12:56, 30 April 2021
Reason: This administration team will move this page to Project:Lua.
If you disagree with the rename, please explain why on the page's talk page or at Category talk:Requested moves. See Category:Requested moves for a full list of move requests.
This article gives coding conventions for the creation and management of global Lua modules. For an introduction to Lua, please see our getting started guide.
What is this?
This article is a style guide, a set of standards and best practices created to help developers write better code. It encourages consistency between modules, which makes them easier to read, test, and maintain. That said, you should always use your best judgement when coding, and avoid the cargo cult.
Documentation
Document all methods, and all potentially confusing parameters as well as the purpose of the module itself. There are multiple ways to document code inline such as using the conventions JSDoc conventions. Using Codedoc format is one possible alternative that has the benefit of coming with its own parser that can generate documentation on a page. Generally code should be documented for other developers inline, and separately for end-users on a documentation page and / or template.
-- Good:
--% Shows a listing of books
--@ books (string) A comma separated list of books
--: (string) A listing of all books
function showBooks(books)
-- Adds a suffix to the returned string
local suffix = "."
return books .. suffix
end
-- Bad (no description):
function showStuff(books)
local something = "."
return books .. something
end
Page structure
Each module (e.g. Module:Do something) should be accompanied by the following pages:
Full page name | Purpose |
---|---|
Global Lua Modules/Do Something | Documentation page for the module |
Module:Do something/testcases | Unit tests for the module |
Module talk:Do something/testcases | Results of said unit tests |
Code structure
Escaping wikitext
Did you know that modules are parsed for wikitext? For example, this innocent-looking bit of code...
function addCategory(name)
return '[[Category:' .. name .. ']]'
end
...will put its module in a bizarre category called ' .. name .. ' (quotes and all). To avoid this problem, always wrap your module in <nowiki>
, <pre>
, or <syntaxhighlight>
(a.k.a. <source>
) tags.
Indentation
Use four spaces per indentation level. Pressing the "tab" key in Fandom's code editor results in four spaces, so the only way to get a tab character is to paste it from somewhere else.
-- Good:
function helloWorld()
return 'Hello, World!'
end
-- Bad (two spaces):
function helloWorld()
return 'Hello, World!'
end
-- Bad (tab character):
function helloWorld()
return 'Hello, World!'
end
Line length
Each line should be no longer than 80 characters. If a single line would be too long, you can split a large statement over multiple lines with a hanging indent that aligns with the opening delimiter. For if statements, the conditions should be placed on the next line with an extra level of indentation.
-- Example:
hello = long_function_name(var_one, var_two,
var_three, var_four)
if (condition1 or condition2)
and condition3
and condition4 then
foo()
bar()
baz()
end
Semicolons
Don't use semicolons; they are completely optional in Lua, and only add visual clutter. As a corollary—use one expression per line.
-- Good:
doSomething()
if 1 then
foo()
bar()
else
baz()
end
bread()
eggs()
milk()
-- Bad:
doSomething();
if 1 then foo(); bar(); else baz(); end
bread(); eggs(); milk();
Parallel assignment
Avoid parallel assignment when defining variables. It is allowed when all values are nil
, when all values are returned from a single function, and when swapping variables. Parallel assignment is harder to read than separate assignment.
-- Good:
local foo = 'first value'
local bar = 'second value'
-- Okay:
local empty1, empty2
local value1, value2, value3 = multiReturn()
foo, bar = bar, foo
-- Bad:
local foo, bar = 'first value', 'second value'
Whitespace
Functions
Place one space after the keyword function
, but do not place any after the function name.
-- Good:
function doSomething()
-- Do something
end
return function ()
-- Do something else
end
-- Bad:
function doSomething ()
-- Do something
end
return function()
-- Do something else
end
Operators
Place one space on either side of operators.
-- Good:
if type(foo) == 'number' then
foo = foo + 1
end
-- Bad:
if type(foo)=='number' then
foo=foo+1
end
Bracketing characters
Do not place any space after [
, (
, and {
; or before ]
, )
, and }
.
-- Good:
function doSomething(arg1, arg2)
local myTable = {'one', 'two', 'three', 'four', 'five'}
return myTable[1 + 1]
end
-- Bad:
function doSomething( arg1, arg2 )
local myTable = { 'one', 'two', 'three', 'four', 'five' }
return myTable[ 1 + 1 ]
end
Comments
Comments should be indented to the same level as the underlying code, and may be separated by a blank new line if this makes the code more readable, but this is not a requirement.
Commas
Place one space after a comma.
-- Good:
function doSomething(arg1, arg2)
-- Do something
end
-- Bad:
function doSomething(arg1,arg2)
-- Do something
end
Blank lines
Place an empty line after every until
and end
keyword, unless the next line has less indentation. Empty lines should also be used to break the module into logical "paragraphs."
-- Good:
function first()
-- Do something
end
function second()
-- Do something else
if true then
-- Do a third thing
end
end
-- Bad:
function first()
-- Do something
end
function second()
-- Do something else
if true then
-- Do a third thing
end
end
Trailing whitespace
Remove extra whitespace from the end of each line.
Functions
Have descriptive function names that identify the action:
local p = {}
-- Bad:
function p.doStuff(frame)
-- Code goes here
end
-- Good:
function p.loadUsers(frame)
-- Code goes here
end
return p
Invoked functions
Make sure invoked function names are short, lower case, and descriptive.
Bad: {{#invoke:A_module_FOR_characters}} Good: {{#invoke:characters}}
Parameters
Avoid long lists of parameters for invoked functions, using fewer than 7 parameters whenever possible. Also, consider using named parameters.
Module structure
Separate utility functions from the main p table, especially those functions that will not need to be directly accessible from templates or articles. If there are too many utility functions, consider creating a new meta-module and storing them there to reduce complexity.
local p = {}
function getArgumentNames()
-- Code goes here
end
return p
Try not to have too many functions as the entry points for a module:
local p = {}
function p.loadtable(frame)
-- Code goes here
end
function p.main(frame)
-- Code goes here
end
function p.url(frame)
-- Code goes here
end
return p
Naming conventions
Define the entry method as simply unpacking the parameters from the frame, and then passing those through a function with the same name prefixed with a single underscore. This can be disregarded if the function is short and simple.
In the standard library, function names consisting of multiple words are simply put together (e.g. setmetatable
). camelCase is the preferred way to name functions, in order to avoid potential garden path function names. It might also be a good idea to follow some guide, e.g. a good guide to naming variables.
Whenever possible try to name the main entry point to invoke the package p.main
, e.g. {{#invoke:url|main}}
.
-- See https://en.wikipedia.org/w/index.php?oldid=540791109 for code
local p = {}
function p._url(url, text)
-- Code goes here
end
function p.url(frame)
-- Take parameters out of the frame and pass them to p._url(). Return the result.
-- Code goes here
return p._url(url, text)
end
return p
P.S. Avoid overly long names and being a citizen of the kingdom of nouns [1].