Un module est un morceau de code source écrit en Lua. Son utilisation s'apparente à celle des modèles (dont le langage de programmation est différent). Les modules se trouvent dans l'espace de noms dédié Module:. Un module est invoqué par le code {{#invoke:nom_module|nom_fonction|arg1|arg2|…}} (et non {{nom_modèle|arg1|arg2|…}} comme les modèles).

Cette fonctionnalité est disponible depuis le 19 février 2013 sur Wikipédia en français.

Structure d'un module

modifier

Un module comporte une table locale qui doit être retournée (return) en fin de code. Toutes les fonctions exportées — c'est-à-dire utilisables à travers un #invoke — doivent être des éléments de cette table. Les fonctions exportées ne peuvent avoir qu'un paramètre déclaré, frame (voir l'objet frame), qui contient entre autres les paramètres passés lors de l'appel. D'autres fonctions (fonctions intermédiaires de traitement) peuvent être locales au module.

Un commentaire débute par deux tirets demi-cadratin  : --. Une telle ligne (ou partie finale de ligne) permet d'expliquer le code, elle n'est pas interprétée.

Exemple simple 1

modifier

Le titre de la page d'un module doit toujours commencer par « Module: » (contrairement aux modèles). Dans la page Module:Banane, le texte suivant a été écrit :

Note : le module suivant est le plus simple qu'il soit. Il ne possède aucun paramètre déclaré (frame).

-- Mon module très simple

-- création de la "table" correspondant au module, elle est vide au départ d'où le {}
local p = {} -- vous pouvez l'appeler comme vous voulez, pas obligatoirement "p". Il faut toutefois
             -- utiliser le même nom de table lors de la déclaration des fonctions (p.hello() plus bas)
             -- Par ailleurs "p" est devenu une « norme » courante.
 -- 
 -- définition de la fonction du module. 
 -- « hello » est le nom qui sera indiqué lors de l'appel au module ({{#invoke:Banane|hello}}). 
 -- Vous auriez pu appeler ce paramètre comme vous le souhaitez, pas nécessairement « hello » 
function p.hello() -- Ici, on se contente de retourner un texte 
-- (donc pas de frame comme dans exemple [[Module:Hello]]) 
    return "Hello, world!" -- ce qui est retourné est entre guillemets (c'est un texte)
end -- et c'est tout

-- obligatoire : on retourne la table du module (qui contient les fonctions)
return p

Dans une autre page qui ne soit pas dans l'espace de noms module, par exemple Modèle:Bac à sable, écrivez :

{{#invoke:Banane|hello}}

Note : si le module s'était appelé « truc », il aurait fallu écrire {{#invoke:truc|hello}}.

Ceci va appeler la fonction « hello » exportée par ce module. Le code {{#invoke:Banane|hello}} sera remplacé par le texte que cette fonction retourne, dans cet exemple « Hello, world! ».

C'est généralement une bonne idée d'« invoquer » un code Lua depuis une page de l'espace de noms « modèle: » plutôt que directement dans les pages destinées au grand public (articles, PdD, projet, , etc.). De cette façon, la syntaxe des pages courantes est constante, que le code ait été écrit en Lua ou en wikicode. Ainsi cela évite d'introduire une nouvelle syntaxe complexe dans ces pages-ci.

Exemple simple 2

modifier

Avec l'objet frame et un argument

Dans la page Module:Hello, le texte suivant a été écrit :

-- test Lua
-- utiliser {{#invoke:hello|helloworld}}
local p = {}

    function p.helloworld()
        return 'Hello World! Welcome to Lua!'
    end
    
-- utiliser {{#invoke:hello|hello|Monsieur X}}    
    function p.hello(frame) -- remarquez le frame
        
        return 'Hello ' .. frame.args[1] .. '!'
    end
return p

{{#invoke:hello|helloworld}} → Hello World! Welcome to Lua!


{{#invoke:hello|hello|Monsieur X}} → Hello Monsieur X!

L'objet frame correspond à l'appelant (l'endroit où le #invoke est fait) et contient entre autres les paramètres passés lors de l'appel, ici « Monsieur X ».

Exemple simple 3

modifier

Avec l'objet frame et les arguments

Voir Module:BananesArgs pour une explication par l'exemple des arguments.

Voir aussi Module:Module Factorielle.

Exemple plus complexe

modifier

Dans la page Module:ExempleParams, le texte suivant a été écrit :

-- Illustration du passage des paramètres dans les modules Lua
--    utilisation des itérations sur ipairs() et pairs()
local p = {}

function p.imprime_les_parametres(params)
	local x = ''
	local index, valeur
	local cle, val
	x = x.."'''Paramètres non nommés'''\n"
	for index,valeur in ipairs(params.args) do
		x = x..'* param['..index..'] = '..valeur..'\n'
	end
	x = x.."<br/>'''Paramètres non nommés et nommés'''\n"
	for cle,val in pairs(params.args) do
		x = x..'* param{'..cle..'} = '..val..'\n'
    end
	return x
	
end

return p


Voir les explications dans Module:ExempleParams.

Remarquer :

  • la table d'exportation de fonctions (ici « p ») contient déclaration et retour ; les fonctions exportées sont de la forme p.nomFonction() ;
  • le passage des paramètres aux fonctions exportées et leur récupération[1] (frame, pairs, ipairs) ;

Quand utiliser un module plutôt qu'un modèle

modifier

Les motivations ayant conduit à l'intégration de Lua dans MediaWiki (le logiciel qui fait tourner Wikipédia) sont :

  • élargir les possibilités de traitements, limitées dans les modèles par les parser-functions disponibles ;
  • avoir un vrai langage de programmation qui sépare contrôle et données (au contraire des modèles), avec comme avantages :
    • une capacité d'expression plus grande,
    • des structures de contrôle permettant des traitements plus simples et génériques (les boucles en particulier),
    • la possibilité de stocker de l'information durant le traitement (au sein d'un même appel), réduisant la répétition de code,
    • la structuration en modules et fonctions, permettant la réutilisation du code (au sein d'un même module ou depuis un autre module),
    • une mise en page libre (espaces, sauts de lignes, commentaires), favorisant la lecture et la compréhension du code ;
  • améliorer les performances, car dans les modèles :
    • chaque appel à un autre modèle ou parser-function génère une charge significative,
    • le code est souvent dupliqué en l'absence de capacité de mémorisation,
    • l'absence de structures de contrôle oblige à « étaler » le code (par exemple pour traiter un, ou deux, ou trois, ou plus de paramètres).

Un module devrait être utilisé lorsque le coût d'exécution d'un modèle est élevé. Le coût d'exécution d'un modèle est difficile à évaluer mais est proportionnel au nombre d'appels à des sous-modèles et parser-functions.

Un module devrait être également utilisé lorsque la complexité d'un modèle rend délicate sa compréhension et sa modification.

Un module devrait enfin être utilisé chaque fois que les fonctionnalités souhaitées ne peuvent être réalisées avec les parser-functions existantes.

Comment créer un module

modifier

Se référer aux documents suivants :

Comment documenter un module

modifier

La documentation du module nom_module se place dans la sous-page module:nom_module/Documentation.

Lorsqu'on lit une page de module ne possédant pas de documentation, un texte en début de page l'indique et fournit un lien permettant de créer directement la page de documentation. L'utilisation de ce lien pré-charge un modèle-guide de documentation pour définir les paramètres passés au modèle au cours de la confection de l'article avec l'éditeur visuel; Ce guide est en français, la séquence est logique et ne produit pas d'erreur de constitution de la table contenant la documentation.

Suivez le modèle pré-chargé de documentation. Il faut décrire chaque fonction exportée : son nom, son rôle, les paramètres (nommés et non nommés) attendus. Il est aussi conseillé de documenter les dépendances (autres modules utilisés, bibliothèques…) ainsi que les fonctions internes (rôle, paramètres…).

La documentation d'un module est une documentation d'utilisation, destinée aux personnes voulant utiliser le module, mais c'est aussi une documentation technique, destinée aux personnes voulant faire de la maintenance. Le ou les modèles qui utilisent ce module ont, eux, leur propre documentation d'utilisation, destinée aux personnes voulant utiliser ce(s) modèle(s) avec l'éditeur visuel ou l'éditeur de wikicode, basculables de l'un vers l'autre.

Note : Il ne faut pas insérer dans cette documentation le modèle {{Documentation}}. En effet l'insertion des éléments de documentation s'effectue directement par MediaWiki lors de la visualisation des pages.

Comment utiliser un module

modifier

On peut utiliser un module directement par l'appel à #invoke :

{{#invoke:nom-du-module|nom_de_la_fonction|paramètres…}}

Sans paramètre, cela donne :

{{#invoke:nom-du-module|nom_de_la_fonction}}

On peut aussi utiliser un module à travers un modèle. Dans ce cas le rédacteur fait appel à un modèle comme il a l'habitude de le faire, mais le modèle fait appel à une ou plusieurs fonctions dans un ou plusieurs modules avec la syntaxe #invoke.

Par exemple, dans un modèle : {{#invoke:nom-du-module|nom_de_la_fonction|{{{1}}}|{{{2}}}|paramètre 1={{{3|valeur par défaut}}}|paramètre 2=fr|…}}

Cette seconde approche doit être préférée à l'appel direct pour plusieurs raisons :

  • Cela limite les modifications dans les articles en cas de changements dans le module (seul le modèle est à modifier). Il a de plus été évoqué par les techniciens d'interdire l'utilisation de #invoke depuis l'espace encyclopédique.
  • Un module gère différemment les paramètres venant d'un appel de modèle et les paramètres venant d'un appel direct (#invoke). Gérer les deux cas complique la programmation des modules et peut conduire à des effets indésirables.
  • Une fonction générique d'un module peut avoir de nombreuses options, à charge du rédacteur de s'y retrouver. Passer par un modèle permet de simplifier la rédaction tout en permettant de construire plusieurs modèles différents exploitant des variantes de fonctionnement d'un même module (par exemple le choix de la langue décidé par le modèle et non par l'utilisateur du modèle, pour une fonction multi-langues).

Notes et références

modifier
  1. La récupération des paramètres s'effectue au moyen d'un mécanisme qui s'apparente à celui de getopt() (en)

Voir aussi

modifier