Esta es la Guía para garabatear . Scribbling, también conocido como Luafication, es el acto de escribir una plantilla o convertir una plantilla para que utilice la extensión Scribunto para MediaWiki . La extensión Scribunto [a] fue desarrollada por Tim Starling y Victor Vasiliev y permite incorporar lenguajes de scripting en MediaWiki. Actualmente, el único lenguaje de programación compatible es Lua . Esta guía tiene como objetivo brindarle una descripción general amplia de Scribbling y sugerencias para obtener más información en varios lugares.
Las plantillas garabateadas vienen en dos partes: la plantilla en sí y uno o más módulos de back-end (en el Module:
espacio de nombres) que contienen programas que se ejecutan en los servidores wiki para generar el wikitexto al que se expande la plantilla. La plantilla invoca una función dentro de un módulo utilizando una nueva función de analizador denominada .{{#invoke:}}
La idea de Scribbling es mejorar el rendimiento del procesamiento de plantillas. Garabatear elimina cualquier necesidad de programar la función del analizador de plantillas utilizando funciones del analizador como {{#if}}
, {{#ifeq}}
y . En cambio, todo esto se hace en el módulo, en un lenguaje que en realidad fue diseñado para ser un lenguaje de programación, en lugar de un sistema de plantilla al que se le agregaron varias extensiones a lo largo del tiempo para intentar convertirlo en un lenguaje de programación. [b] Garabatear también elimina la necesidad de que las plantillas se expandan a más plantillas y potencialmente alcancen el límite de profundidad de expansión. Una plantilla completamente garabateada nunca debería necesitar transcluir otras plantillas. [C]{{#switch}}
{{#expr}}
El idioma en el que están escritos los módulos es Lua. A diferencia del sistema de funciones del analizador de plantillas, Lua en realidad fue diseñado no solo para ser un lenguaje de programación adecuado, sino también para ser un lenguaje de programación adecuado para lo que se conoce como secuencias de comandos integradas . Los módulos de MediaWiki son un ejemplo de scripts integrados. Hay varios lenguajes de secuencias de comandos integrados que podrían haberse utilizado, incluidos REXX y tcl ; y, de hecho, el objetivo original de Scribunto era ofrecer una selección de dichos idiomas. Por el momento, sin embargo, sólo está disponible Lua.
El manual de referencia oficial de Lua es Ierusalimschy, de Figueiredo & Celes 2006. Es una referencia, no un tutorial. Consúltalo si quieres conocer la sintaxis o semántica de algo. Para obtener un tutorial, consulte Ierusalimschy 2006 (Ierusalimschy 2003 también está disponible, aunque, por supuesto, está desactualizado) o Jung & Brown 2007. Las desventajas de estos libros son que muchas de las cosas que le cuentan tienen no tiene relación con el uso de Lua en los módulos de MediaWiki. No necesita saber cómo instalar Lua ni cómo integrar su intérprete en un programa o ejecutarlo de forma independiente. Los desarrolladores de MediaWiki han hecho todo eso. De manera similar, muchas de las funciones de la biblioteca Lua, por seguridad, no están disponibles en módulos. (Por ejemplo, no es posible realizar E/S de archivos o realizar llamadas al sistema operativo en los módulos de MediaWiki). Por lo tanto, mucho de lo que estos libros explican sobre las funciones y variables de la biblioteca estándar de Lua que vienen con el lenguaje es irrelevante o falso aquí. .
La especificación API original (las funciones y variables de la biblioteca estándar de Lua que se supone que están disponibles en módulos) se proporciona en MW:Extension:Scribunto/APIspecification. Sin embargo, incluso eso es falso. Lo que realmente tendrá disponible está documentado en el manual de referencia de MW:Extension:Scribunto/Lua, que es una versión reducida de la primera edición del manual de Lua que ha sido editado y modificado por Tim Starling para alinearlo más con el realidad del garabato. Sin embargo, nuevamente, este es un manual de referencia, no un tutorial.
Las cosas en Lua que más le preocuparán al escribir plantillas Scribbled son tablas , números de cadena , valores booleanos , ( generados ), (numéricos ) , expresiones y los distintos operadores ( incluidos , operadores aritméticos , , , , , y ), y las tablas globales , y (es decir, bibliotecas).nil
if … then … else … end
while … do … end
for … in … do … end
for
for … do … end
for
repeat … until
function … end
local
return
break
#
..
+
-
*
/
^
%
string
math
mw
Esto es simple. Su plantilla comprende una expansión de en el caso habitual. Aquí está {{ cita de Harvard }} , por ejemplo:{{#invoke:}}
<includeonly> {{ #invoke : Notas al pie | harvard_citation | bracket_left = ( | bracket_right = ) }}</ includeonly >< noinclude > {{ documentación }} <!-- Agregar categorías a la subpágina /doc, interwikis a Wikidata, no aquí --> </ noinclude >
Si desea utilizar otras plantillas dentro de su plantilla, o utilizar funciones del analizador de plantillas, o cualquier cosa que no sea posiblemente algunas variables como argumentos, entonces está utilizando el enfoque equivocado .{{#invoke:}}
Consideremos un módulo hipotético, Módulo: Población. (Consulte Módulo: Relojes de población para ver un módulo similar, pero más complejo). Puede estructurarse de dos maneras:
locales p = {}función p . India ( marco ) devolver "1,21,01,93,422 personas en (nominalmente) 2011-03-01 00:00:00 +0530"finvolver p
devolver { India = función ( marco ) devolver "1,21,01,93,422 personas en (nominalmente) 2011-03-01 00:00:00 +0530" fin}
La ejecución de un módulo por es en realidad doble:{{#invoke:}}
require()
{{#invoke:}}
{{#invoke:}}
El primer script Lua realiza la fase 1 de manera bastante explícita. Crea una variable local nombrada p
en la línea 1, inicializada en una tabla; construye y agrega una función (líneas 3 a 5), dándole a la función el nombre India
en la tabla nombrada por p
( es lo mismo que decir [d] ); y luego devuelve (en la línea 7) la tabla como última línea del script. Para expandir dicho script con más funciones (invocables), se agregan entre la declaración en la parte superior y la declaración en la parte inferior. ( Se pueden agregar funciones locales no invocables antes de la declaración). No es necesario nombrar la variable local . Podría denominarse cualquier nombre de variable Lua válido que desee. es simplemente convencional para este propósito y también es el nombre que puede usar para probar el script en la consola de depuración del editor de módulos.function p.India
p["India"] = function
local
return
local
p
p
El segundo guión de Lua hace lo mismo, pero de forma más "idiomática". En lugar de crear una variable con nombre como una tabla, crea una tabla anónima sobre la marcha, en medio de la return
declaración, que es la única declaración (ejecutada durante la primera fase) en el script. Las líneas 2 a 4 crean una función (también anónima) y la insertan en la tabla con el nombre . Para expandir dicho script con más funciones (invocables), se agregan como campos adicionales en la tabla. (Nuevamente, las funciones locales no invocables se pueden agregar antes de la declaración).India = function(frame) … end
India
return
En ambos casos, el código de plantilla que se escribe es para invocar la función nombrada del módulo Módulo: Población. También tenga en cuenta que construye una función, como un objeto, para ser llamada. No lo declara , como podría estar acostumbrado en otros lenguajes de programación, y la función no se ejecuta hasta que se llama.{{#invoke:Population|India}}
India
function
Por supuesto, se pueden hacer cosas más complejas que esto. Por ejemplo: se pueden declarar otras variables locales además de p
, para contener tablas de datos (como listas de idiomas o nombres de países) que utiliza el módulo. Pero esta es la estructura básica de un módulo. Haces una mesa llena de cosas y la devuelves.
Una función ordinaria en Lua puede tomar un número (efectivamente) arbitrario de argumentos. Sea testigo de esta función del Módulo: Wikitexto que se puede llamar con cualquier valor entre cero y tres argumentos:
función z . lista Oxford ( argumentos , separador , signo comercial )
Las funciones llamadas por son especiales. Esperan que se les pase exactamente un argumento, una tabla que se llama marco (y por eso convencionalmente se le da el nombre del parámetro en la lista de parámetros de la función). Se llama marco porque, desafortunadamente, los desarrolladores decidieron nombrarlo por conveniencia. Lleva el nombre de una estructura interna dentro del código de MediaWiki, que en cierto modo representa. [mi]{{#invoke:}}
frame
Este marco tiene una (sub)tabla dentro, llamada args
. También tiene un medio para acceder a su marco principal (nuevamente, llamado así por algo en MediaWiki). El marco principal también tiene una (sub)tabla dentro, también llamada args
.
frame
parámetro de la función, son los argumentos pasados dentro del wikitexto de su plantilla . Entonces, por ejemplo, si escribiera en su plantilla, la subtabla de argumentos del marco secundario sería (como está escrito en formato Lua) .{{#invoke:}}
{{#invoke:Population|India|a|b|class="popdata"}}
{ "a", "b", class="popdata" }
{{Population of India|c|d|language=Hindi}}
{ "c", "d", language="Hindi" }
Un modismo útil para programadores que puede usar, para hacer todo esto un poco más fácil, es tener variables locales nombradas (digamos) config
y args
en su función, que apunten a estas dos tablas de argumentos. Vea esto, del Módulo: WikidataCheck :
función p . wikidatacheck ( marco ) local pframe = marco : getParent () configuración local = marco . args : los argumentos pasados POR la plantilla, en el wikitexto de la propia plantilla local args = pframe . args : los argumentos pasados A la plantilla, en el wikitexto que transcluye la plantilla
Por lo tanto, todo lo que contiene config
es un argumento que usted ha especificado, en su plantilla, al que puede hacer referencia con código como y . Estas serán cosas que le indicarán a la función de su módulo su "configuración" (por ejemplo, un nombre de clase CSS que puede variar según la plantilla que se utilice).config[1]
config["class"]
Por lo tanto, todo lo que contiene args
es un argumento que el usuario de la plantilla ha especificado, donde se transcluyó, al que puede hacer referencia con código como y . Estos serán los argumentos normales de la plantilla, como se documenta en la página de su plantilla.args[1]
args["language"]
/doc
Consulte {{ otros lugares }} y {{ otros barcos }} para ver dos plantillas que lo hacen pero lo hacen con diferentes argumentos en lugar de , obteniendo así diferentes resultados de una única función común de Lua.{{#invoke:Other uses|otherX|x}}
x
Para ambos conjuntos de argumentos, el nombre y el valor del argumento son exactamente como en el wikitexto, excepto que se descuentan los espacios en blanco iniciales y finales en los parámetros con nombre. Esto tiene un efecto en su código si decide admitir o emplear nombres de argumentos de transclusión/invocación que no sean nombres de variables Lua válidos. En tales casos, no puede utilizar la forma de "punto" de búsqueda de tabla. Por ejemplo: es, como puede ver en la coloración de la sintaxis aquí, no una referencia a un argumento, sino una referencia a un argumento y una variable con el operador de resta en el medio. Para acceder a dicho argumento, utilice la forma de "corchete" de búsqueda en tabla: .args.author-first
|author-first=
|author=
first
args["author-first"]
Los argumentos con nombre se indexan en la args
tabla por sus cadenas de nombre, por supuesto. Los argumentos posicionales (ya sea como resultado de un explícito 1=
o no) se indexan en las args
tablas por número, no por cadena. no es lo mismo que , y este último efectivamente no se puede configurar desde wikitext. args[1]
args["1"]
Finalmente, tenga en cuenta que los módulos de Lua pueden diferenciar entre argumentos que se han utilizado en el wikitexto y simplemente se han configurado como una cadena vacía, y argumentos que no están en absoluto en el wikitexto. Estos últimos no existen en la args
tabla y cualquier intento de indexarlos se evaluará como nil
. Mientras que el primero existe en la tabla y se evalúa como una cadena vacía, ""
.
Dejemos una cosa clara desde el principio: el error de secuencia de comandos es un hipervínculo. Puede colocar el puntero del mouse sobre él y hacer clic.
Estamos tan condicionados por nuestras plantillas (no garabateadas) que muestran mensajes de error en rojo que pensamos que el mensaje de error "Error de secuencia de comandos" de Scribunto no es más que más de lo mismo. No lo es. Si tiene JavaScript habilitado en su navegador WWW, aparecerá una ventana emergente con los detalles del error, un seguimiento de la llamada e incluso hipervínculos que lo llevarán a la ubicación del código donde ocurrió el error en el módulo correspondiente.
Puede provocar un error llamando a la función. error()
Por razones que están fuera del alcance de esta Guía, [f] la args
subtabla de un marco no es como una tabla ordinaria. Comienza vacío y se completa con argumentos a medida que ejecuta el código que los busca. [g] (Es posible crear tablas que funcionen así en un programa Lua, usando cosas llamadas metatablas . Eso también está fuera del alcance de esta Guía).
Un desafortunado efecto secundario de esto es que algunos de los operadores normales de tablas de Lua no funcionan en una args
mesa. El operador de longitud, #
no funcionará, ni tampoco las funciones de la table
biblioteca de Lua. Estos sólo funcionan con tablas estándar y fallan cuando se presentan con la args
tabla especial. Sin embargo, las funciones y funcionarán, ya que los desarrolladores han agregado código para hacer posible su uso.pairs()
ipairs()
Un nombre en Lua es un acceso a una variable local o una búsqueda en una tabla. [3] math.floor
es una búsqueda de tabla (de la cadena "floor"
) en la math
tabla (global), por ejemplo. Las búsquedas de tablas son más lentas, en tiempo de ejecución, que las búsquedas de variables locales. Las búsquedas en tablas como la args
tabla con su "especialidad" son mucho más lentas.
Una función en Lua puede tener hasta 250 variables locales. [4] Así que haz un uso liberal de ellos:
math.floor
muchas veces, cópielo en una variable local y úselo en su lugar: [4] piso local = math.floor local a = piso (( 14 - fecha . lunes ) / 12 ) local y = fecha . año + 4800 - un local m = fecha . lun + 12 * a - 3 fecha de regreso . día + piso (( 153 * m + 2 ) / 5 ) + 365 * y + piso ( y / 4 ) - piso ( y / 100 ) + piso ( y / 400 ) - 2432046
args.something
Tabulador local = argumentos . pestaña
args
variable en sí es una forma de evitar buscar "args"
en la frame
tabla una y otra vez).Al copiar argumentos en variables locales, hay dos cosas útiles que puedes hacer a lo largo del camino:
or
operador de Lua para elegir el nombre de mayor prioridad que realmente se proporciona: Título local = argumentos . título o argumentos . enciclopedia o args . enciclopedia o argumentos . diccionario local ISBN = args . isbn13 o args . isbn o args . ISBN
nil
es el mismo en lo que false
a lo que or
a respecta.or
tiene lo que se conoce como semántica de "atajo". Si el operando de la izquierda se evalúa como algo que no es false
o nil
, ni siquiera se molesta en calcular el valor del operando de la derecha. (Entonces, si bien a primera vista puede parecer que el primer ejemplo realiza cuatro búsquedas, en el caso más común, cuando |title=
se usa con la plantilla, en realidad solo realiza una).nil
útil. Otras veces, sin embargo, no lo es y desea que el comportamiento de los argumentos faltantes sean cadenas vacías. Un simple al final de una expresión es suficiente:or ""
ID local = argumentos . identificación o argumentos . ID o argumentos [ 1 ] o ""
Si las variables locales son baratas y las búsquedas de tablas son caras, entonces la expansión de la plantilla está muy por encima de su rango de precios.
Evitar como la peste. Después de todo, estamos tratando de evitar la expansión de plantillas anidadas utilizando el preprocesador de MediaWiki. La mayoría de las cosas que harías con eso se hacen de manera más simple, más rápida y más fácil de mantener, con funciones simples de Lua.frame:preprocess()
De manera similar, evite cosas como usar w:Template:ISO 639 name aze ( eliminado en agosto de 2020 ) para almacenar lo que efectivamente es una entrada en una base de datos. Leerlo sería una llamada al analizador anidado con consultas concomitantes a la base de datos, todo para asignar una cadena a otra cadena. Coloque una tabla de datos sencilla y directa en su módulo, como las de Module:Language .