Fandom Developers Wiki
m (→‎top: bad link repair)
No edit summary
Line 1: Line 1:
{{Mbox/wikitext| text = This [[Special:ListAdmins|administration team]] will move this page to '''Project:Lua'''.}}
+
{{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].

References