# Initiation au Lua avec Scribunto/L'objet Frame

Ce paragraphe étudie plus en détail l’objet frame que l’on peut considérer comme étant l'interface avec le programme. C'est l’objet frame qui reçoit les paramètres que l’on envoie au programme grâce à la commande #invoke.

## Nature de l’objet frame

Une remarque que l’on peut faire à propos de l’objet frame et de la façon de l’utiliser comme l'accès aux arguments frame.args[1], frame.args[2], etc. est la ressemblance avec les notations relatives aux tables. frame serait une table et frame.args que l’on pourrait aussi noter frame["args"] serait une table, indexée par la chaîne de caractères "args", se trouvant dans la table frame. Par contre frame.args serait une table à accès numérique. C'est pour cela que l’on note ses arguments frame.args[1], frame.args[2], etc.
En réalité, ce que l’on vient de dire n’est pas tout à fait vrai. À l'appel d'un module avec #invoke, la table frame n’est pas créée et remplie tel que l’on vient de le dire. Quand l’on fait appel à un élément de la table numérique frame.arg, une méta-méthode est activée pour demander l’objet souhaité au logiciel MediaWiki. La table frame est en réalité une méta-table remplie de méta-méthodes dont la fonction est de simuler l’existence d'une table qui contiendrait les éléments décrits plus haut alors, qu'en réalité, ils sont demandés au fur et à mesure des besoins au logiciel MediaWiki.
Comme "frame" n’est pas une vraie table, on n’est pas assuré que toutes les fonctions agissant sur les tables vont fonctionner correctement. Nous devons donc connaître la liste des fonctions qui fonctionnent correctement et la liste des fonctions qui ne fonctionnent pas correctement, ces deux listes étant susceptibles d’être modifiées au fil des versions de Lua et de Scribunto.
Les fonctions sur lesquelles, on peut compter actuellement sont ipairs et pairs.
Nous allons donc donner un exemple simple utilisant la fonction ipair.
Dans le Module:Frame, écrivons une fonction p.evalue qui compte combien il y a d'arguments contenant une valeur numérique et combien il y a d'arguments contenant une chaîne de caractères.
{{#invoke:Frame|evalue|Laura|54|76|Mouchoir|17|Schtroumpfs|11|2}}, nous donne : Il y a 5 nombres et 3 chaines de caractères.

## Arguments avec clé sous forme de chaîne de caratères

Jusqu'à maintenant, nous avons déclaré, dans la commande #invoke, les arguments à la suite les uns des autres comme on déclare les objets d'une table à clé numérique. Le premier argument s'associant automatiquement à la clé 1, le deuxième à la clé 2 et ainsi de suite. Toutefois, de même que l’on a vu que, dans les tables, il est possible de créer des clés sous forme de chaîne de caractères, nous allons voir qu’il en est de même pour la pseudo-table frame.args. Pour cela, il suffit de déclarer, dans la commande #invoke, les arguments avec clé sous forme de chaîne de caractères comme on le ferait pour une table.
Par exemple, on écrira : {{#invoke:''Module''|''fonction''|fleur=rose}}
Il est à noter que la déclaration : {{#invoke:''Module''|''fonction''|["fleur"]=rose}} n’est pas correcte car ["fleur"] sera interprété comme la chaîne de caractère "["fleur"]" (voir l'exemple ci-dessous avec ("personnage"]).
Écrivons un exemple pour voir si cela marche bien !
Dans le Module:Frame, écrivons une fonction p.renvoie qui nous renvoie les clés utilisés avec les objets correspondants.
{{#invoke:Frame|renvoie|prénom=Laura|nombre=54|76|Mouchoir|17|["personnage"]=Schtroumpfs|nombre premier=11|2}}, nous donne : À la clé 1, il y a l’objet : 76 À la clé 2, il y a l’objet : Mouchoir À la clé 3, il y a l’objet : 17 À la clé 4, il y a l’objet : 2 À la clé prénom, il y a l’objet : Laura À la clé nombre, il y a l’objet : 54 À la clé nombre premier, il y a l’objet : 11 À la clé ["personnage"], il y a l’objet : Schtroumpfs
Dans le programme précédent, nous avons utilisé la fonction pairs. Si nous avions utilisé la fonction ipairs, tous les objets dont la clé est une chaîne de caractères auraient été ignorés.

## Fonctions en relation avec l’objet frame

Tous les exemples de ce paragraphe se trouvent dans le Module:Frame.
Les fonctions que nous allons étudier dans ce paragraphe se trouvent dans l’objet frame. Nous commencerons donc par écrire une fonction p.visualisation permettant de les visualiser.
(Ici, contrairement aux paragraphes précédents, nous visualisons ce qui se trouve dans frame et pas ce qui se trouve dans frame.args.)
{{#invoke:Frame|visualise}} nous donne : À la clé newTemplateParserValue, on trouve un objet de type : function À la clé getParent, on trouve un objet de type : function À la clé argumentPairs, on trouve un objet de type : function À la clé extensionTag, on trouve un objet de type : function À la clé callParserFunction, on trouve un objet de type : function À la clé preprocess, on trouve un objet de type : function À la clé getTitle, on trouve un objet de type : function À la clé args, on trouve un objet de type : table À la clé newParserValue, on trouve un objet de type : function À la clé expandTemplate, on trouve un objet de type : function À la clé getArgument, on trouve un objet de type : function À la clé newChild, on trouve un objet de type : function
En dehors de la clé args qui référence la table contenant les arguments transmis par la commande #invoke, nous voyons que nous disposons de 11 fonctions que nous allons étudier en détail ci-dessous.
Une petite remarque que l’on peut faire ici est que la notation des fonctions diffère légèrement de ce que l’on avait mentionné auparavant. En effet, au lieu de noter, par exemple, la deuxième fonction de la liste frame.getParent (avec .), nous la noterons frame:getParent (avec :). Cette différence de notation tient au type de propriété à laquelle on accède. Le point permet d'accéder à la propriété définie dans l'objet frame tandis que le deux-points permet d'exécuter une fonction définie sur l'objet.
Autre remarque, les fonctions des librairies sont accessibles comme des propriétés. C'est pourquoi on utilise le point pour accéder à une fonction d'une librairie et non le deux-points car la librairie n’est pas instanciée (n'est pas un objet) : string.len(s). Quand on a à faire à un objet, l'appel à la méthode se fait par les deux-points : s:len.
Comme d'habitude, les fonctions ne seront pas étudiées dans l’ordre !

### frame:getParent

Cette fonction permet de connaître, à l'intérieur du module, les arguments du modèle qui a appelé le module où se trouve la fonction frame:getParent.
La fonction frame:getParent retourne une table contenant une table, indexée par la chaîne de caractère "args", qui contient tous les paramètres passés au modèle. Par exemple, si la fonction frame:getParent se trouve dans un module placé dans un modèle dont l'appel se fait ainsi :
Et si dans le module, nous avons l'instruction :
Alors model sera une table contenant la table model.args. La table model.args aura deux éléments : l'élément "stat" indexé par la chaîne de caractère "titre" et l'élément "ouvert" indexé par la chaîne de caractère "compte"
Si le modèle appelant possède un lien qui n’est pas renseigné, alors La table model.args retournera, à l'index correspondant, la chaîne vide "" (et pas nil).
À titre d'exemple, dans le Module:Frame nous écrivons la fonction p.Parent ainsi :
Nous créons ensuite un Modèle:Parents dans lequel nous écrivons :
Nous donnerons deux exemples.
Premier exemple :
nous donne :
Les arguments du présent modèle sont : À la clé 1, il y a l’objet : Grenouille À la clé 2, il y a l’objet : rouge À la clé 3, il y a l’objet : 4
Deuxième exemple :
nous donne :
Les arguments du présent modèle sont : À la clé nombre, il y a l’objet : 63 À la clé titre, il y a l’objet : Planing À la clé couleur, il y a l’objet : vert

### frame:newChild

Cette fonction permet d’utiliser des fonctions qui, normalement, attendent des arguments provenant d'une commande #invoke.
Dans l'exemple ci-dessous la fonction p.replique est rédigée comme si elle devait être utilisée grâce à l'appel {{#invoke:Frame|replique|jardin|maison}} par exemple. La fonction p.child fabrique un nouvel objet frame avec pour arguments "jeudi" et frame.args[2] et appelle la fonction p.replique sous la forme p.replique(newFrame), ce qui est alors équivalent à un appel du type {{#invoke:Frame|replique|jeudi|frame.args[2]}} que l’on n'aurait pas pu faire puisque nous ne pouvons pas utiliser la commande #invoke dans un module.
{{#invoke:Frame|child|3|Tulipe|7|janvier}} nous indique : Je renvoie Jeudi et Tulipe

### frame:preprocess

Nous avons déjà eu l’occasion d'étudier cette fonction qui permet d'interpréter les modèles avant qu’ils ne soient retournés (voir le chapitre sur la Gestion de l'environnement).
Dans l'exemple ci-dessous, nous n'avons pas retourné directement ce que donnait la fonction frame:preprocess, mais nous avons commencé par stocker le retour dans la variable reponse et nous avons ensuite retourné la variable reponse. Ceci montre que ce que retourne la fonction frame:preprocess peut éventuellement être mémorisé dans une variable et subir un éventuel traitement dans le programme.
{{#invoke:Frame|process}} nous indique : La fonction a retourné :
* Essai avec le modèle Attention

### frame:expandTemplate

La fonction "frame:expandTemplate" réalise à peu près la même chose que la fonction "frame:preprocess", mais uniquement pour les modèles. Par conséquent, pour les modèles, on préférera utiliser la fonction "frame:expandTemplate" car elle est plus rapide et moins sujette aux erreurs que la fonction "frame:preprocess".
Ci-dessous, nous donnons un exemple, réalisant la même chose, que celui donné pour la fonction "frame:preprocess".
{{#invoke:Frame|template}} nous indique :
* Essai avec le modèle Attention

### frame:argumentPairs

L'écriture frame:argumentPairs est strictement identique à l'écriture pairs( frame.args ) comme nous pouvons le constater dans l'exemple ci-dessous :
{{#invoke:Frame|pair|3|Tulipe|7|janvier}} nous indique : À la clé 1, il y a l’objet : 3 À la clé 2, il y a l’objet : Tulipe À la clé 3, il y a l’objet : 7 À la clé 4, il y a l’objet : janvier
En fait la fonction frame:argumentPairs n'existe que pour des raisons de compatibilité avec les versions antérieures de Scribunto.
Aujourd'hui, on préfèrera écrire pairs( frame.args ) à la place de frame:argumentPairs

### frame:callParserFunction

Cette fonction permet de faire appel à un des multiples parseurs (analyseurs) disponibles dans l'extension ParserFunctions. Ces fonctions permettent d'analyser des chaînes de caractères selon certains critères et de s'assurer qu'elles sont valides et utilisables.
{{#invoke:Frame|parser}} nous indique : La fonction a retourné : 2024-10-10 04:16:57 et son type est : string

### frame:extensionTag

Cette fonction permet de poser un tag autour d'un texte. Un exemple type est le tag <nowiki> interdisant à l'interpréteur de page d'exécuter un contenu. Ainsi, si un contenu renvoyé par une fonction est susceptible d'être interprété comme un modèle, un lien ou autre, on peut utiliser la fonction frame:extensionTag pour placer de manière automatique les balises <nowiki>.
Dans l’exemple suivant, on retourne le texte [[texte]] avec et sans l'utilisation de extensionTag.
Rendu avec extensionTag : {{#invoke:Frame|tag}} nous indique : La fonction a retourné : [[texte]] et son type est : string
Rendu sans extensionTag : {{#invoke:Frame|notag}} nous indique : La fonction a retourné : texte et son type est : string

### frame:getArgument

Cette fonction permet de récupérer un argument passé en paramètre au module. Il y a 2 signatures possibles :
* frame:getArgument(number) - où number représente l'index de l’argument à récupérer
* frame:getArgument(name) - où name représente le nom de la clé associée à l’argument à récupérer
La fonction retourne un objet offrant une méthode expand permettant de récupérer la valeur interprétée. Cette valeur est obtenu en appelant : objet:expand où objet est la variable dans laquelle a été stockée le résultat de l'exécution de la fonction.
Le type de l’objet étant une table, on peut en parcourir le contenu avec les fonctions pairs ou ipairs. La valeur obtenue sera alors brute, c'est-à-dire non interprétée.
{{#invoke:Frame|argument|3|fleur=Tulipe}} nous indique : La fonction a retourné : 3 et son type est : table
{{#invoke:Frame|namedArgument|3|fleur=Tulipe}} nous indique : La fonction a retourné : Tulipe et son type est : table

### frame:newParserValue

{{#invoke:Frame|parval|3|Tulipe|7|janvier}} nous indique : La fonction a retourné une variable de type : table qui contient :

### frame:newTemplateParserValue

{{#invoke:Frame|temparval|3|Tulipe|7|janvier}} nous indique : Erreur Lua dans mw.lua à la ligne 435 : frame:newTemplateParserValue: a title is required.

### frame:getTitle

Cette fonction renvoie le nom du module Lua invoqué.
{{#invoke:Frame|title}} nous indique : La fonction a retourné : Module:Frame et son type est : string

## Liens Connexes

* Manual de l'extension Scribunto (en)
| Librairies Scribunto | L'objet Title |