Initiation au Lua avec Scribunto/Librairies Scribunto
Les librairies Scribunto apporte un ensembles de fonctions spécialisées plus particulièrement adaptés aux projets de la fondation Wikimédia.
Présentation
modifierLes librairies Scribunto sont constituées d'ensembles d'objets, chacun des ensembles étant spécialisé dans un domaine particulier. Par exemple, la librairie frame est spécialisée dans l'interface entre l'utilisateur et le programme. La librairie Title sera spécialisée dans l'accès aux pages d'un Wiki, etc.
Les librairies Scribunto sont des ajouts qui ne font pas partie du Lua standard. Elles ont été écrites spécialement pour les projets Wikimédia. Elles permettent de faciliter l'écriture de programmes en Lua concernant la gestion des projets.
Toutes ces librairies sont constituées d'une table contenant principalement des fonctions mais pouvant aussi contenir d'autres objets comme des chaînes de caractères, des sous-tables, des booléens etc.
Toutes les librairies Scribunto se trouvent dans une table principale qui se nomme mw. Pour accéder à une librairie, il suffira donc de taper mw."nom de la librairie". Supposons que l’on veuille accéder à la fonction indexée par new se trouvant dans la librairie message, il nous suffira de taper mw.message.new(paramètres) (nous rappelons que new est en fait un index de la table mw.message, message étant lui même un index de la table mw)
Une particularité de la plupart des librairies Scribunto est de travailler sur une ou plusieurs tables fétiches de la librairie considérée. Ces tables porteront le nom d'objet suivi du nom de la librairie. par exemple la librairie Title travaillera sur des objets Title. Les tables constituant les objets fétiches d'une librairie contiennent, bien sûr, elles aussi, des fonctions ou autre chose (sous-tables, chaînes de caractères, booléens,etc.).
Supposons que, dans le cadre de la librairie message, on ait créé un objet message du nom de cocorico par exemple. Cet objet message va contenir tout un ensemble de fonctions parmi lesquelles se trouve la fonction indexée par plain. Il y a deux façons d'accéder à cette fonction. On a tout d’abord la façon habituelle, c'est-à-dire cocorico.plain(paramètres). Mais il existe une autre façon qui consiste à écrire mw.message:plain(paramètres). On remarque la présence de : dans mw.message:plain qui indique que l’on va chercher la fonction, non pas dans la table mw.message, mais dans un objet message dont le nom figure parmi les paramètres (ou pas, s'il n'y a pas de confusion possible sur l’objet visé comme l'objet frame de la librairie frame)
Nous venons de voir qu’il existe deux façons d'accéder à une fonction se trouvant dans un objet fétiche d'une librairie. Si l’on reprend l'exemple précédent, on a : cocorico.plain(paramètres) ou l’on a : mw.message:plain(paramètres). Par convention, pour différencier ces deux façons, nous dirons que la notation cocorico.plain désigne une fonction alors que la notation mw.message:plain désigne une méthode (même si une méthode n'est rien d’autre qu'une fonction). Comme, le plus souvent, on accède aux fonctions se trouvant dans les objets fétiches avec la notation méthode, on dira que les fonctions se trouvant dans les objets fétiches sont des méthodes. Si, par exemple, nous disons que dans la librairie langage, il y a 9 fonctions et 20 méthodes, nous voulons dire par là que 9 fonctions sont indexées directement dans la table mw.langage et 20 fonctions sont indexées dans un objet langage qui sera créé dans le cadre de cette librairie.
Ce que nous venons de dire est très théorique et comporte des exceptions. Nous verrons, par exemple, qu’il n'existe pas de librairie frame mais qu’il existe malgré tout un objet frame. Nous verrons aussi que les méthodes, dans la librairie HTML, n'apparaissent pas dans un objet html.
Fonctions et tables constituant les librairies Scribunto
modifierToutes les librairies Scribunto se trouvent dans la table mw
. Nous commencerons donc par visualiser le contenu de cette table grâce au programme suivant :
local p = {}
function p.visualisation(frame)
reponse = ""
for index, objet in pairs(mw) do
reponse = reponse.."<br />À la clé "..index..", on trouve un objet de type : "..type(objet)
end
return reponse
end
return p
{{#invoke:Scribunto|visualisation}} nous donne :
À la clé incrementExpensiveFunctionCount, on trouve un objet de type : function
À la clé log, on trouve un objet de type : function
À la clé addWarning, on trouve un objet de type : function
À la clé getLanguage, on trouve un objet de type : function
À la clé getCurrentFrame, on trouve un objet de type : function
À la clé loadJsonData, on trouve un objet de type : function
À la clé logObject, on trouve un objet de type : function
À la clé allToString, on trouve un objet de type : function
À la clé executeFunction, on trouve un objet de type : function
À la clé loadData, on trouve un objet de type : function
À la clé hash, on trouve un objet de type : table
À la clé title, on trouve un objet de type : table
À la clé uri, on trouve un objet de type : table
À la clé clone, on trouve un objet de type : function
À la clé text, on trouve un objet de type : table
À la clé language, on trouve un objet de type : table
À la clé message, on trouve un objet de type : table
À la clé wikibase, on trouve un objet de type : table
À la clé site, on trouve un objet de type : table
À la clé ustring, on trouve un objet de type : table
À la clé isSubsting, on trouve un objet de type : function
À la clé dumpObject, on trouve un objet de type : function
À la clé ext, on trouve un objet de type : table
À la clé html, on trouve un objet de type : table
À la clé getContentLanguage, on trouve un objet de type : function
Nous voyons que nous avons 9 tables constituant 9 librairies spécialisées, mais nous voyons aussi apparaître 12 fonctions. Nous allons étudier les 12 fonctions que nous désignerons sous le terme "fonctions de base" dans le paragraphe suivant. Nous présenterons ensuite les 9 tables constituant les 9 librairies spécialisées qui contiennent chacune des fonctions spécialisées. Dans ce chapitre, nous n'étudierons pas les 9 librairies spécialisées pour ne pas surcharger de façon colossale ce chapitre. Cette étude sera effectuée dans d'autres chapitres.
Fonctions de base
modifiermw.allToString
modifiermw.allToString( ... )
Appelle tostring() sur tous ses paramètres, puis concatène les résultats avec une tabulation comme séparateur.
mw.clone
modifiermw.clone( value )
Crée une copie de la valeur. Toutes les tables (et leurs méta-tables) sont reconstruites de zéro. Les fonctions restent partagées quoi qu’il en soit.
mw:executeFunction
modifiermw.getCurrentFrame
modifiermw.getCurrentFrame()
Retourne l'objet frame courant.
mw:getContentLanguage
modifiermw:getLanguage
modifier
mw.incrementExpensiveFunctionCount
modifiermw.incrementExpensiveFunctionCount()
Ajoute un au compteur des « parser-function coûteuses », et génère une exception si ce compteur dépasse la limite (voir $wgExpensiveParserFunctionLimit).
mw.isSubsting
modifiermw.isSubsting()
Renvoie true si le #invoke
courant est en train d’être « substé », false dans le cas contraire. Voir Retourner du texte plus haut pour connaitre la différence entre un #invoke
substé ou non.
mw.loadData
modifiermw.loadData( module )
Parfois un module a besoin de grandes tables de données. Par exemple, un module générique de conversion d'unités devrait avoir une grande table contenant toutes les unités connues et leurs facteurs de conversion. Et parfois ces modules vont être utilisés de nombreuses fois dans une même page. Interpréter de grandes tables de données pour chaque {{#invoke:}}
peut prendre un temps non négligeable. Pour éviter ce problème, la fonction mw.loadData()
existe.
mw.loadData
fonctionne comme require()
avec les différences suivantes :
- Le module n'est évalué qu'une fois par page, plutôt qu'une fois par appel à
{{#invoke:}}
. - Le module n’est pas enregistré dans
package.loaded
. - La valeur retournée par le module chargé doit être une table. Les autres types ne sont pas gérés.
- La table retournée (et ses sous-tables) peut contenir des booléens, des nombres, des chaînes et d'autres tables. Les autres types, en particulier les fonctions, ne sont pas autorisés.
- La table retournée (et toutes ses sous-tables) ne doit pas avoir de méta-tables.
- Toutes les clés de la table doivent être des booléens, des nombres ou des chaînes.
- La table réellement retournée par
mw.loadData()
a des méta-méthodes qui fournissent un accès en lecture seul à cette table. Dans la mesure où elle ne contient pas directement les données,pairs()
etipairs()
fonctionnent mais les autres méthodes, y comprisInitiation au Lua avec Scribunto/Fonctions basiques#value
,next()
, et les fonctions de la librairie Table, ne fonctionneront pas correctement.
Dans l'hypothétique module évoqué plus haut, le module pourrait être « Module:Convert » et les données pourraient être stockées dans « Module:Convert/data ». Le module utiliserait local data = mw.loadData( 'Module:Convert/data' )
pour charger efficacement les données.
mw.dumpObject
modifiermw.dumpObject( object )
Renvoie une représentation lisible par un humain de l’objet object
, sous forme de chaîne.
mw.log
modifiermw.log( ... )
Envoie ses paramètres à mw.allToString() puis ajoute le résultat au tampon des enregistrements (log).
Dans la console de debug, la fonction print()
est un alias de cette fonction.
mw.logObject
modifiermw.logObject( object )
mw.logObject( object, prefix )
Appelle mw.dumpObject() et concatène la chaîne résultante au « log buffer » (traduction ?). Si prefix
est renseigné, il sera ajouté au « log buffer » suivi d'un signe égal avant que la chaîne produite soit concaténée (i.e. le texte loggé sera "prefix = object-string").
Les tables constituant les librairies Scribunto
modifierLa table mw.html
modifierCette table héberge les éléments de la librairie HTML. Pour éviter de surcharger ce chapitre, l'étude de la librairie HTML sera faite dans le chapitre 15.
La table mw.language
modifierCette table héberge les éléments de la librairie Language. Pour éviter de surcharger ce chapitre, l'étude de la librairie langage sera faite dans le chapitre 16.
La table mw.text
modifierCette table héberge les éléments de la librairie Text. La librairie text fournit quelques fonctions utiles de traitement de texte absentes de la librairie String et de la librairie Ustring. Ces fonctions peuvent fonctionner avec les caractères UTF-8.
Les fonctions de cette librairie ont déjà été étudiées dans le chapitre 6 pour deux raisons : d'une part, pour alléger le présent chapitre qui est déjà volumineux et ensuite parce que ces fonctions agissent sur les chaînes de caractères, ce qui est l’objet du chapitre 6.
La table mw.ustring
modifierCette table héberge les éléments de la librairie Ustring. Les fonctions de cette librairie ont déjà été étudiées dans le chapitre 6 pour deux raisons : d'une part, pour alléger le présent chapitre qui est déjà volumineux et ensuite parce que ces fonctions agissent sur les chaînes de caractères, ce qui est l’objet du chapitre 6.
La table mw.message
modifierCette table héberge les éléments de la librairie Message. Pour éviter de surcharger ce chapitre, l'étude de la librairie message sera faite dans le chapitre 17
La table mw.site
modifierCette table héberge les éléments de la librairie Site. Pour éviter de surcharger ce chapitre, l'étude de la librairie site sera faite dans le chapitre 18
La table mw.title
modifierCette table héberge les éléments de la librairie Title. Pour éviter de surcharger ce chapitre, l'étude de l’objet Title sera faite dans le chapitre 13
La table mw.ext
modifierCette table semble n'avoir rien à voir avec notre propos. Si l’on regarde ce qu'elle contient, on y trouve les deux sous-tables :
- mw.ext.ParserFunctions
- mw.ext.TitleBlacklist
La table mw.uri
modifierCette table héberge les éléments de la librairie Uri. Pour éviter de surcharger ce chapitre, l'étude de l’objet URI sera faite dans le chapitre 14
L'objet Frame
modifierOn aurait pu s'attendre à voir apparaître une table mw.frame dans la table mw. Mais cela n’est pas arrivé. On peut admettre l’existence d'une table virtuelle mw.frame puisqu’il existe un objet frame. L'objet frame est l'interface des paramètres passés au {{#invoke:}}
, ainsi que l'interface au parseur.
Pour éviter de surcharger ce chapitre, l'étude de l’objet Frame sera faite dans le chapitre 12