Alles auf einer Seite
Lua ist eine Skriptsprache, die 2013 in der deutschsprachigen Wikipedia verfügbar wurde.
Nachfolgend wird auf dieser Seite eine Zusammenstellung angeboten, die die auch als jeweils einzelne Hilfeseiten verfügbaren Informationen beispielsweise zur Textsuche zusammenfasst.
{{#invoke:}} in eine umgebende klassische Vorlage eingefügt und ergänzen diese um allgemeine Hilfsfunktionen, die bislang schwer zu realisieren waren.Die Darstellung auf diesen Hilfeseiten trifft dagegen im Prinzip auf jedes beliebige Wiki zu.
Wikisyntax: {{:}}
Aufruf (in der Regel innerhalb einer Vorlage):
{{#invoke: Modul-Titel | Funktionsname | Wert1 | Wert2 | NameX=Wert ... }}
Die Parameter können wie bei Vorlagen benannt oder unbenannt sein; es gelten prinzipiell analoge Regeln.
1=Wert1 wie bei Vorlagen (verschärftes Gleichheitszeichen-Problem; kann zum Syntaxfehler führen).<ref>, <pre>, <nowiki>, …). So würde eine direkte Ausgabe von {{Vorlage}} also nur zur Ausgabe des Textes {{Vorlage}} ohne die tatsächliche Vorlagenexpansion führen. Bei Bedarf kann das aber alles innerhalb der Modul-Programmierung erfolgen.#invoke zurückgesetzt. Eine direkte Übernahme von Variablen zwischen zwei Aufrufen ist nicht möglich.#invoke sequentiell und unter Verwendung der gleichen (nur wenig auswertbaren) Elternumgebung.Ein Aufruf von #invoke unmittelbar in einem enzyklopädischen Artikel oder einer allgemeinen Projektseite ist absolut unerwünscht. Diese Aufrufe sollen immer in Vorlagen verpackt sein; ausgenommen sind solche Projektseiten, die sich spezifisch mit Lua beschäftigen (WP:Lua/***).
Siehe auch: Hilfe:Vorlagenbeschränkungen.
#invoke, require() oder in geeigneten Fällen mw.loadData() kann eine komplette Modulseite geladen werden.Modul: können für die Auswertung benutzt werden.
.json deklarierter JSON-Code.Scribunto"./Doku..json am Schluss des Seitennamens.#invoke eingebunden sind, sondern durch require() usw. aufgerufen werden. Werkzeuge zählen etwa die Zahl der Einbindungen.Weiterleitungen von einer Modulseite zu einer anderen sind nicht direkt möglich. Lange Zeit war das Verschieben auf einen neuen Bezeichner auch kompliziert gewesen, wenn die Versionsgeschichte erhalten werden soll.
Inzwischen wird bei einer normalen Verschiebung ein neuer Seiteninhalt generiert:
return require [[Module:NeuerName]]
Anschließend kann mit der Auflösung aller bisherigen Nutzungen begonnen werden.
Siehe dazu: Hilfe:Lua/Quellcode und Vorschau
Das Speichern von syntaktisch fehlerhaften Lua-Modulen ist seit Oktober 2014 nicht mehr möglich.
Bis zu einer gewissen Maximalgröße der Seite werden die Syntaxelemente in unterschiedlichen Farben dargestellt. Seit 2021 werden auf Code-Seiten auch Zeilennummern angezeigt.
#L-1, #L-2, #L-3 usw.Die Maximalgröße von Seiten mit Syntaxhervorhebung, die eine farbige Auszeichnung bei zu großen Seiten unterbindet, verhindert dann auch die Generierung der Zeilennummern.
Auf Seiten mit Lua-Code können keine Vorlagen expandiert und keine Kategorisierungen wirksam werden. Wenn eine Modulseite gelöscht werden soll, bietet sich an:
Löschdiskussionen können über die /Doku-Seite initiiert werden.
Hallo, Welt! Dies ist Lua!Modul:Benutzerin:xxxxxxxxxxxxModul:Benutzer:xyxyxyxyxyxyAußerdem sind testwiki:, test2wiki: (mit dem eigenen SUL-Account) und auch de.wikipedia.beta (separater Account nötig) nutzbar. In der echten dewiki sollten dann erst halbwegs ausgereifte Produktiv-Versionen auftauchen.
Siehe dazu Hilfe:Lua/Programmierung mit den Spezialthemen
Zur Sprache Lua allgemein siehe die als Weblinks angegebenen Handbücher.
<syntaxhighlight lang="lua"> dargestellt werden.{{#tag:syntaxhighlight |{{Modul:Hello}}| lang=lua}}Die deutsche Wikipedia verwendet derzeit Lua 5.1 laut {{#invoke:Version|version}}.
Das gedruckte Buch s.u. beschreibt Lua 5.3 mit Hinweisen zu Unterschieden.
Aktuell ist Lua 5.5.0 (Stand Juni 2026).
Modul: (828) sind grundsätzlich der Quellcode zu je einem Lua-Modul. Dies wird nicht als Wikitext interpretiert. Das Content Model ist Scribunto./Doku endet, können Wikitext enthalten.#invoke schon deshalb nicht genutzt werden, weil der Namensraum dieser Anweisung intern vorangestellt wird. Auch ein require() ist nur auf Seiten möglich, deren Inhalt als Lua-Quellcode gespeichert ist („Content Model“).Modul: sollten nur nicht-selbstständigen Lua-Code enthalten:
mw.loadData() genutzte Datenmengen oder wenn eine solche Schnittstelle dokumentiert ist./test ausgegliederter unit test sein.Die Module sind bewusst so gestaltet, dass keinerlei Zugriff von einer Einbindung mit #invoke auf eine andere oder den Inhalt der umgebenden Seite möglich ist. Einige trickreiche Versuche, dies zu unterlaufen, wurden nach kurzer Zeit unterbunden.[1]
Ein Modul kann selbst keinerlei Veränderung an der Welt hervorrufen (sieht man davon ab, dass bei den „Links auf diese Seite“ durch Einbindung anderer Seiten ein Eintrag hinzukommen kann; oder dass es die Kategorie der Seiten mit Skriptfehlern bereichert). Es kann sich ausschließlich durch seinen Rückgabewert äußern, der letztlich in irgendeiner Weise auf eine Vorlagen-Einbindung oder sonstigen Seitentext wirken müsste.
Das Modul kann die Parameter der Vorlagen-Einbindung (oder einer sonstigen Seite, in der das #invoke vorkommt) auslesen. Ihm ist außerdem bekannt, wie die Gesamt-Seite heißt, die dem Benutzer dargestellt wird. Mehr kann das Modul über seine Umgebung (Elternumgebung) nicht herausfinden. Wie die Vorlage heißt, in der #invoke steht, lässt sich mit
frame:getParent():getTitle() auch noch ermitteln (siehe unten). seinen eigenen Namen kann das Modul seit Anfang 2014 ermitteln.
_G ist eine table, die standardmäßig die nachstehend aufgelisteten Komponenten enthält:
Im Handbuch auf Mediawiki heißt es:
Tatsächlich sind jedoch im Mai 2013 in _G aus allen mittels require() eingebundenen Modulen diejenigen Variablen versammelt, die dort nicht explizit als local deklariert wurden. Es ist aber davon auszugehen, dass dies nicht mehr lange der Fall sein wird; besser ist gemäß Export-table eine saubere Rückgabe.
Die letzte Zeile eines Moduls muss eine return-Anweisung mit einem Rückgabewert sein. Fehlt dies, wäre der Wert immer nil.
Der Datentyp dieses Rückgabewerts ist im Prinzip beliebig. Verbreitet wäre table, aber auch eine function wäre vorstellbar; letztlich auch eine zwangsläufig kaum variierbare Zeichenkette oder Zahl.
Der Rückgabewert ist in drei Fällen auszuwerten:
require().mw.loadData().#invoke die verfügbaren Funktionen zugreifbar.In die einbindende Seite wird mittels der Parserfunktion {{#invoke:M|fun|params}} eingebettet.
fun ist der Name einer Funktion, die Komponente in dem als table deklarierten Rückgabewert des Moduls M ist. Sie erhält als Parameter das Objekt frame des #invoke.
Die Parameterliste entspricht derjenigen bei Vorlagen. Verirrte Gleichheitszeichen im Wert eines unbenannten Parameters können Syntaxfehler auslösen. Bei von außen kommenden Werten sollte immer mittels vorangestellter laufender Nummer eine sichere Zuweisung erfolgen: |1={{{Text|}}}
In der Funktion steht die Parameterliste im Objekt frame als table frame.args zur Verfügung.
Im Unterschied zu Vorlagen ist auch die leere Zuweisung |x= | auswertbar; das heißt: Es lässt sich ohne besondere Konstrukte feststellen, dass x in der Parameterliste genannt wird, jedoch der leere Wert zugewiesen wurde.
Der Wert einer Komponente von frame.args ist ein string, wenn der Parameter im #invoke vorkommt, und nil ansonsten.
Wie auch bei Vorlagen gilt: Benannte Parameter werden getrimmt (Leerzeichen und Zeilenumbruch vor und nach dem Wert werden entfernt); unbenannte Parameter nicht.
Als Beispiel siehe das Modul:Hello.
Die Zuordnung lässt sich am besten aus folgendem Beispiel für ein Modul M mit Funktion f ablesen:
{{#invoke:M|f|1=ABC|FGH| LMN |benanntA=PQR|benanntB= TUV | HÖHE ÜBER NN= 32 | Leergut= }}
liefert
frame.args[ 1 ]
|
»ABC«
|
frame.args[ 2 ]
|
»FGH«
|
frame.args[ 3 ]
|
» LMN «
|
frame.args.benanntA
|
»PQR«
|
frame.args.benanntB
|
»TUV«
|
frame.args[ "HÖHE ÜBER NN" ]
|
»32«
|
frame.args.Leergut
|
»« |
frame.args.Unbekannt
|
nil
|
Der Rückgabewert der in #invoke genannten Funktion ersetzt als Zeichenkette den Bereich {{#invoke:}}.
Als Rückgabewert sollte man immer explizit eine Zeichenkette schaffen. Wenn der Rückgabewert von anderem Typ ist, wird dies durch Standard-Operationen in eine Zeichenkette umgewandelt. Dadurch kann in der Seite das Wort false oder nil lesbar sein oder die Programmierung zu falschen Schlüssen führen. Letzteres lässt sich vermeiden durch den Ausdruck:
return r or ""
Wenn r „etwas“ ist, wird r zurückgegeben, sonst "".
Mehrere Rückgabewerte oder ein aggregierter Datentyp würden für #invoke automatisch durch Verwendung der Funktion tostring() in Strings umgewandelt und dann ohne Trennzeichen aneinandergefügt. Dies sollte vermieden werden und kontrolliert eine Zeichenkette gebildet werden, die sich dann auch im Artikel sehen lassen kann.
Das Objekt frame gibt die Umgebung wieder. Grundsätzlich gibt es zwei Instanzen:
#invoke (Normalfall; standardmäßig immer mit frame bezeichnet)frame:getParent()frame.args der Vorlageneinbindung; alle Funktionen führen zum gleichen Ergebnis; erneutes frame:getParent() hilft nicht.Wenn über #invoke eine Funktion für die Vorlage genutzt wird, ist der Funktion gemäß Schnittstelle zur Vorlagenprogrammierung auch das Objekt frame dazu bekannt. Falls dies (als Bibliotheksfunktion) nicht übergeben wurde oder in tieferen Ebenen nicht durchgereicht wurde, kann es überall gebildet werden mit:
frame = mw.getCurrentFrame()
Unmittelbar nutzbar sind:
#invoke – nach frame:getParent() Vorlagenparameter der einbindenden Seite.frame.args nicht manipuliert werden können und auch die Anzahl nicht per length-Operator # festgestellt werden kann.number bei einem unbenannnten Vorlagenparameter; bzw. numerischer Angabestring sonstr = frame:callParserFunction( name, args )r = frame:expandTemplate{ title = s, args = args }title= wird in der Regel eine Zeichenkette mit dem Vorlagentitel sein; inzwischen ist aber auch ein Objekt mw.title möglich.r = frame:extensionTag( name, content, args )frameT = frame:getParent()#invoke generierten frame ist das der Name des eingebundenen Moduls selbst (einschließlich Modul: zu Beginn).#invoke, lässt sich so ermitteln: frame:getParent():getTitle()nil zurück.{{{1}}} werden ausgewertet.frame:preprocess( string )Nicht zwingend benötigt werden die nachstehenden drei Funktionen. Sie liefern jeweils ein object (table) zurück. Das object hat eine einzige Methode object:expand() – dies liefert den expandierten Wikitext in der jeweiligen Situation.
argument expandieren.frame:preprocess( text ).frame:expandTemplate() mit den genannten Argumenten.Mittels der Funktion mw.isSubsting() lässt sich herausfinden (boolean), ob die momentane Aktivität darauf hinauslaufen wird, dass das Ergebnis substituiert wird (mit {{subst: eingebunden wurde).
Anfang 2014 wird jedoch nur erkannt, ob die Parserfunktion #invoke unmittelbar Gegenstand einer Substituierung {{subst:#invoke:m|f}} ist; nicht aber, ob etwa eine Vorlage, in der dieses #invoke vorkäme, gerade substituiert wird.
Dadurch lassen sich Wartungskategorien in das Ergebnis einfügen, die bei einer unerwünschten Substituierung protestieren; oder umgekehrt bei fehlender Substituierung eine Einbindung bemängeln.
Ein frame-Objekt wird bei der Substituierung von #invoke nicht übergeben; über mw.getCurrentFrame() lässt es sich aber jederzeit beschaffen.
Die Funktion require() bindet ein anderes Modul ein.
Modul: ist voranzustellen."strict" löst eine besondere Funktion aus.
local deklariert werden; sie dürfen keine globale Hinterlegung oder Abfrage nicht bekannter Variablen bewirken. Ansonsten wird ein Skriptfehler ausgelöst.true wenn der Seitenname sonst existiert und als Lua-Quellcode verwaltet wird.Beispiel für eine sichere Einbindung:
local lucky, WillHaben = pcall( require, "Modul:WillHaben" )
if type( WillHaben ) == "table" then
r = WillHaben.WillHaben()
else
r = "<span class=\"error\">" .. WillHaben .. "</span>"
-- auto: "package.lua:80: module 'Modul:WillHaben' not found"
-- "Fehler * Modul:WillHaben nicht gefunden"
end
pcall() ist absturzsicher; der zweite Rückgabewert ist im Erfolgsfall der Rückgabewert des Moduls, sonst die Fehlermeldung von require().
Hinweis: Die Parserfunktion #iferror: greift nicht, wenn der Klassenname in Apostroph ' statt " eingeschlossen ist.
Ein Modul kann aus einer einzigen Zeile bestehen
return require( "Modul:NeuerName" )
und wirkt dann wie eine Weiterleitung; etwa nach einer Umbenennung.
Diese Funktion entspricht grundsätzlich dem require() mit zwei Besonderheiten:
#invoke innerhalb einer Gesamt-Seite beschleunigt werden.Vorgesehen ist dies für große Datenmengen, die dann auch separat von den Funktionen im Modul gepflegt werden können.
Die Standard-Aufgabe ist es, eine Vorlage mittels #invoke zu unterstützen. Konzeptionell gibt es die Möglichkeit, zusätzlich oder ausschließlich andere Lua-Module durch require() zu unterstützen. Dabei gibt es zwei Fälle:
#invoke beigegebenen Parameterwerte sind dann entsprechend zu interpretieren (parsen).Exportierte Funktionen werden mitsamt der table ihres definierenden Moduls angewendet. Diese heißt immer so wie das Modul selbst. Da die Namen der Module im Namensraum eindeutig sind, kann es nicht zu Namenskonflikten kommen. Damit ist auch sofort klar, woher eine Funktion stammt und wo die Dokumentation zu finden ist, wenn plötzlich im Quelltext ein unbekannter Funktionsaufruf angetroffen wird.
Das Modul:Hello gibt einen ersten Einstieg:
local p = {}
function p.hello(frame)
local name = frame.args[1]
if not name then
name = 'Welt'
end
return 'Hallo, ' .. name .. '! Dies ist Lua!'
end
return p
Der Aufruf würde erfolgen mittels
{{#invoke:Hello|hello}} (ergibt Hallo, Welt! Dies ist Lua!)oder
{{#invoke:Hello|hello|hier bin ich}} (ergibt Hallo, hier bin ich! Dies ist Lua!)Ein Modul mit zwei oder drei Funktionen nur für Vorlagen ist eher trivial.
Bei komplexeren Aufgaben ist etwas Strukturierung und Übersicht erforderlich.
p ist der Rückgabewert des gesamten Moduls. Dieser Name hat sich eingebürgert, und er stellt eine table dar.--[=[ DiesesBeispiel 2013-05-07
Dieser und jener Zweck
* service
]=]
-- Module globals
local messagePrefix = "lua-module-DiesesBeispiel-"
-- ...
-- ...
local function x( a )
-- ...
return r
end -- x()
-- ...
-- ...
-- Provide template access
local p = {}
p.service( frame )
-- ...
return x( u ) or ""
end -- .service()
return p
Die Funktion service wird zur Nutzung in einer Vorlage exportiert.
--[=[ DiesesBeispiel 2013-05-07
Dieser und jener Zweck
* service
* DiesesBeispiel()
]=]
-- Module globals
local messagePrefix = "lua-module-DiesesBeispiel-"
local DiesesBeispiel = { }
-- ...
-- ...
local function x( a )
-- ...
return r
end -- x()
DiesesBeispiel.service = function ( a )
-- ...
return x( u )
end -- DiesesBeispiel.service()
-- ...
-- ...
-- Provide external access
local p = {}
p.service( frame )
-- ...
return DiesesBeispiel.service( u ) or ""
end -- .service()
function p.DiesesBeispiel()
-- Retrieve function access for modules
-- Postcondition:
-- Return table with functions
return DiesesBeispiel
end -- .DiesesBeispiel()
return p
Wie vor, aber es wird zusätzlich die table DiesesBeispiel exportiert über die Funktion DiesesBeispiel().
DiesesBeispiel.service() steht danach auch anderen Modulen zur Verfügung.DiesesBeispiel.service() und die Funktion service für Vorlagen ruft diese Implementierung auf. Dabei sind die Parameter der Vorlageneinbindung (Zeichenketten in frame.args) geeignet zu interpretieren und ihr Typ ggf. geeignet zu konvertieren. Während der Rückgabewert von DiesesBeispiel.service() auch false oder nil sein mag, wird durch or "" die für Vorlagen geeignetere leere Zeichenkette zurückgegeben.--[=[ DiesesBeispiel 2013-05-07
Dieser und jener Zweck
* DiesesBeispiel.service()
]=]
-- Module globals
local messagePrefix = "lua-module-DiesesBeispiel-"
local DiesesBeispiel = { }
-- ...
-- ...
local function x( a )
-- ...
return r
end -- x()
DiesesBeispiel.service = function ( a )
-- ...
return x( u )
end -- DiesesBeispiel.service()
-- ...
-- ...
-- Provide external access
return DiesesBeispiel
Der Export von p mit der Tabelle für Vorlagen entfällt; es wird nur die table DiesesBeispiel direkt exportiert.
Diese Situation tritt beispielsweise bei ausgelagerten Unter-Modulen sowie Datentabellen bei mw.loadData() auf.
Versuche, die programmtechnisch im Prinzip vorhandene Elternumgebung zu ergründen, werden von Scribunto mit dem Ziel der Kapselung systematisch unterbunden. Darin unterscheidet sich „Lua im Wiki“ von allgemeinen Lua-Anwendungen.
Der einzig sinnvoll mögliche Zugriff ist auf die Parameter der unmittelbar einbindenden Seite möglich:frame:getParent().args
Innerhalb der unmittelbar umgebenden Seite (Vorlage) erfolgen die einzelnen Aufrufe von #invoke sequentiell und unter Verwendung der gleichen Umgebung.
Vor dem ersten Aufruf der Funktion math.random() ist der Zufallszahlengenerator stets mit dem Wert 0 initialisiert (zur Initialisierung siehe math.randomseed()). Ohne eigene Initialisierung wird also stets die gleiche Folge von Zufallszahlen generiert. Bei sequentieller Verarbeitung der Aufrufe von #invoke innerhalb der gleichen Vorlage wird der Zufallszahlengenerator allerdings zwischendurch nicht zurückgesetzt, so dass die Folge dort kontinuierlich fortgesetzt wird.
Startpunkt, wie sich ein Modul schreiben lässt, das genau eine Vorlage unterstützen soll. Das Gegenstück wären Bibliotheksmodule, die von beliebig vielen unterschiedlichen Vorlagen aufgerufen werden können.
Modul:Vorlage:Vorlagen-Titel{{#invoke:Vorlage:Vorlagen-Titel|f}}<noinclude>{{Dokumentation}}</noinclude>f (oder nach Belieben anders genannt) ist die einzige für Vorlagen verfügbare Schnittstelle.--[=[ 2013-05-19
Unterstützung für {{Vorlagen-Titel}}
f() test()
]=]
--
--
local function x( u )
local r
--
return r
end -- x()
local function main( a )
local r
--
r = x( u )
--
return r or ""
end -- main()
-- Export
local p = {}
function p.test( a )
local lucky, r = pcall( main, a )
return r
end
function p.f( frame )
local lucky, r = pcall( main, frame:getParent().args )
return r
end
return p
Die Funktion f übernimmt mittels getParent() die Parameter der Vorlageneinbindung.
Sie ruft die Haupt-Funktion in geschützter Ausführung auf.
Rückgabewert ist die von main() zurückgegebene Zeichenkette oder die von pcall() zugewiesene Zeichenkette der Fehlermeldung.
main() (oder nach Belieben anders genannt) ist die eigentliche Arbeitsfunktion.a, egal ob diese aus #invoke oder der Simulation stammen.frame wird nicht übergeben. Sollte das Objekt einmal benötigt werden, kann es mittels mw.getCurrentFrame() ermittelt werden. Es wäre das der Vorlageneinbindung oder aber das zwangsläufig irgendwo vorhandene #invoke der Simulation.main() muss als letzte aller lokalen Funktionen vereinbart sein.Der Aufruf der Haupt-Funktion wird jeweils in pcall() geschützt.
assert() oder error() ein Fehler ausgelöst, dann ist r die Fehlermeldung.Wenn es eine eng umgrenzte Gruppe von Vorlagen gibt (etwa Vorlage:Str*), bei denen sich der Aufwand für Einzelmodule nicht lohnen würde, können sie in einem gemeinsamen Modul untergebracht werden.
Beispiel anhand der Vorlage:Str len:
{{#invoke:Vorlage:Str|f|f=len}}mit einem einzigen Modul:Vorlage:Str für alle.
Die Funktion f ist dann wie folgt zu modifizieren:
function p.f( frame )
local a = frame:getParent().args
a.f = frame.args.f
local lucky, r = pcall( main, a )
return r
end
Während alle anderen Parameter der umgebenden Vorlage entstammen, wird f den Argumenten des #invoke entnommen.
Die Funktion test muss sich den Vorlagen-Namen in ihrer Simulation entsprechend vorgeben.
Die nachfolgenden Abschnitte stellen für Lua-Programmierer einige Besonderheiten der Sprache zusammen, die im Scribunto-Tutorial nicht oder nur verborgen dargestellt sind.
Außerdem gibt es eigene Hilfeseiten zu Sonderthemen:
mw und Hilfsbibliothekenmw (für MediaWiki) einige Wiki-spezifische Bibliotheken an, die auch gut mit der sonstigen Architektur eines Wiki-Servers kooperieren.mw.addWarning()Es gibt vier Ursachen für Skriptfehler:
Von sich aus gab Lua dabei bis zum Herbst 2014 immer nur eine einzige Fehlermeldung von sich: „Skriptfehler“. Das war langweilig und half niemandem bei der Beseitigung. Inzwischen wird der Name des Moduls, die Zeilennummer und eine konkrete Situationsanalyse in jeder einbindenden Seite angezeigt. Die Fehlermeldung ist verlinkt mit einer Popup-Box, die die Aufruffolge mit einzelnen Modulnamen und Zeilennummer wiedergibt.
Außerdem wird die Kategorie:Wikipedia:Seite mit Skriptfehlern mit allen einbindenden Seiten gefüllt – das sollte vermieden werden, sondern Laufzeitfehler sollten abgefangen und in Modul-spezifische Wartungskategorien geleitet werden.
Ein Syntaxfehler ist oft ein trivialer Schreibfehler. Dieser müsste eigentlich zur Folge haben, dass das Abspeichern der Modul-Seite unterbunden wird; es sei denn, man hätte bis zum Herbst 2014 dem Feld „⧼scribunto-ignore-errors⧽“ ein Häkchen gegeben. Das ist nicht länger möglich.
Beim Anzeigen der Seitenvorschau des Moduls erhält man eine möglichst qualifizierte Fehlermeldung mitsamt Zeilennummer. Bei schweren Syntaxproblemen kann das jedoch nicht geleistet werden und es kommt der lakonische „Skriptfehler“.
In der „Fehlerbereinigungskonsole“ lassen sich beim Bearbeiten differenziertere Hinweise zur Fehlersuche gewinnen.
Ein typischer qualifizierbarer Fehler wäre ein einzelner Punkt statt zwei zur Verkettung von Zeichenketten (PHP-Stil). Ohne konkrete Hilfestellung bleibt jedoch fehlendes then oder end und auch eine nicht geschlossene Zeichenkette.
Wenn es durch die Programmstruktur in einigen Fällen zu ungeeigneten Datentypen kommt, in manchen nicht, so ist das schwer zu finden. Wird dann etwa versucht, auf ein nil eine Zeichenketten-Funktion anzuwenden, gibt das den bekannten undefinierten Fehler. Für den Einbinder einer Vorlage ist das nicht aufzulösen. Möglichst alle Pfade sind deshalb auf Testseiten durchzuspielen, und die Voraussetzungen hinsichtlich Datentyp und Wertebereich sind in den Funktionen zu überprüfen.
Wenn eine Seite transcludiert wird, kann es sein, dass dieser Seitenname nicht existiert; insbesondere die erwartete Seite verschoben wurde oder beim Komponieren eines zusammengesetzten Namens ein Fehler auftrat. Um diese Situation auflösen zu können, wird eine präzise Information benötigt, welche Seite fehlt. LuaWiki.transclude() ermöglicht eine sichere Einbindung und sorgt für eine präzise Fehlermeldung.
Was immer die Vorlagenprogrammierer und Einbinder von Vorlagen an Parametern eingeben, muss analysiert und bei Problemen mit einer konkreten Nachricht versehen werden, damit eine Berichtigung möglich wird.
Defensives Programmieren ist ratsam.
#invoke wenigstens immer vom Typ string.fun mit Parameterliste args.e, v = pcall( fun, args )e im Fehlerfall false und v die Fehlermeldung.e den Wert true und v nebst allen folgenden Variablen sind die üblichen Rückgabewerte von fun.pcall steht für protected call.args ist eine Komma-getrennte Aufzählung von null bis beliebig vielen Parameterwerten.assert( v, message, ... )error(), jedoch nur, wenn die Bedingung v nicht erfüllt ist (also nil oder false ist).message sollte eine spezifische Fehlermeldung mitgegeben werden; es wäre sonst ein lapidares assertion failed! – zumindest wird aber immer die Zeilennummer des assert in der Meldung gezeigt, nebst dem Namen des Moduls.nil noch false ist, werden alle Argumente einschließlich v und message zurückgegeben.pcall() geschützten Umgebung sinnvoll; ansonsten wird bloß ein allgemeiner „Skriptfehler“ ohne nähere Einzelheiten ausgelöst.pcall() gesprungen; etwa die Schnittstelle zum #invoke. Damit erspart man sich das Durchreichen von besonderen Rückgabewerten von Funktion zu Funktion.error( message, level )pcall() geschützten Umgebung sinnvoll; ansonsten wird bloß ein allgemeiner „Skriptfehler“ ohne nähere Einzelheiten ausgelöst.pcall() ausgehenden Funktionsfolge wird die Fehlermeldung message zurückgegeben.level ist in der Original-Sprache Lua eine Aufruf-Folge oder stack, dessen anzuzeigende Tiefe vorgegeben werden kann.
allowEnvFuncs nicht zugelassen wird.level nicht angegeben oder ist Null oder zu groß, so wird keine Information zum Ort gezeigt.level immer mit 1 oder gar nicht anzugeben.assert().Anders als bei anderen Programmiersprachen gilt:
0 wie auch die leere Zeichenkette "" sind „etwas“.nil und false sind „nichts“.{} ist gleichbedeutend mit nil.Das ist vor allem für if-Abfragen wichtig.
Auf Werte und Funktionen als Komponenten einer table wird mit einem . als t.k zugegriffen, neben der Notation t["k+"] auch für Namen von Komponenten, die nicht rein alphanumerisch sind.
Die Elemente einer Tabelle können mit verschiedenen Iteratoren erfasst werden. Typisch sind folgende Universaliteratoren:
local Beispieltabelle = {"eins", "zwei", 3, "Quattro stagioni"}
for meinIndex, meinWert in ipairs(Beispieltabelle) do
...
end
iteriert durch die unbenannten Elemente einer Tabelle, während
local Beispieltabelle = {erster="eins", zweiter="zwei", dritter=3, vierter="Quattro stagioni"}
for meinSchlüssel, meinWert in pairs(Beispieltabelle) do
...
end
durch die benannten Werte der Tabelle iteriert.
Bei einem Objekt (einer Instanz, durch eine von Lua oder Scribunto angeboten Bibliothek) wird auf Eigenschaften ebenfalls mit einem . zugegriffen. Für Funktionen (Methoden) ist hingegen ein : zu verwenden. Beispiele siehe String-Funktionen.
Die Notation mit Doppelpunkt gilt nicht nur für Lua- und Scribunto-Objekte, sondern auch für benutzerdefinierte Objekte. Dabei erhält die Methode implizit einen zusätzlichen Parameter self, auf den innerhalb der Methode zugegrffen werden kann. Dieser repräsentiert die Instanz des Objekt-table, während die table einer „Klasse“ entspräche. Die beiden Anweisungen
function meinObjekt:f ( params ) body end
und
meinObjekt.f = function ( self, params ) body end
sind äquivalent.
Bei Funktionen in Objekten (Methoden) gibt es außerdem die Möglichkeit, benannte Argumente zu verwenden. Statt runder Klammern sind dann geschweifte Klammern {} zu benutzen. Dieses Format ist meist eine zusätzliche Option; in manchen Fällen wie bei frame:expandTemplate{} aber der einzige unterstützte Zugriff.
Die Vorlagenprogrammierung wird dadurch unterstützt, dass der or-Operator den links stehenden Disjunktionsausdruck zurückgibt, wenn dieser weder nil noch false ist, und sonst den Ausdruck auf der rechten Seite.
Damit lassen sich auch Datentypen bei fehlenden Angaben sichern:
saveString = frame.args.optional or ""
saveTable = getTable() or {}
Wenn der Wert leer und/oder dabei vom falschen Datentyp ist, wird mit dem richtigen Datentyp initialisiert.
Weil oft Bibliotheksfunktionen in bestimmten Situationen nil oder false zurückgeben, diese Zeichenketten aber nicht als Ergebnis der Vorlageneinbindung auftreten sollen, kann man etwa einen wirklich „leeren“ Wert mit der folgenden Anweisung sicherstellen:
return fun(x) or ""
Gibt fun(x) einen echten Wert zurück, wird dieser an das #invoke zurückgegeben; ist das nichts, greift das "".
Analog kann man den Wert 1 bei „nichts“ oder „etwas“ sicherstellen:
return fun(x) and "1" or ""
Weil diese Notation nicht sehr übersichtlich ist, sollte man es aber bei diesem Kniff bewenden lassen.
Die Reihenfolge lokaler Funktionen ist signifikant. Eine lokale Funktion muss in der physischen Abfolge der Definitionen definiert gewesen sein, bevor sie verwendet werden darf.
Bei einer Zählschleife
for v = e1, e2 do
werden die Argumente nur einmal zu Beginn ausgewertet; danach in interne Variablen überführt.
Es ist nicht möglich, innerhalb der Schleife die Endbedingung auszulösen, etwa durch e1=e2. Vielmehr ist eine break-Anweisung auszuführen.
Unbenannte Zeichenketten-Parameter sollten stets getrimmt werden, wenn sie aus Vorlagen stammen und Leerzeichen nicht signifikant wären. In der Vorlagenprogrammierung war dies nur mit Tricks möglich gewesen:
{{#if:trim|{{{1}}}}}In Lua wäre der Weg eine Bibliotheksfunktion, wenn gesichert ist, dass s eine Zeichenkette ist:
s = mw.text.trim( s )
Insbesondere während der Entwicklungsphase kann mit dem folgenden Statement möglichst früh in den ausführbaren Zeilen eine verschärfte Syntaxkontrolle angefordert werden.
require( "strict" )
Zurzeit bewirkt dies lediglich, dass gesichert wird, dass alle Variablenbezeichner auch explizit als local deklariert sein müssen.
local vereinbart sein (ausgenommen automatische lokale Variablen in Schleifen).Weil dies im produktiven Stadium Performance und Ressourcen kostet, sollte es in fertigen Versionen nicht mehr aktiv vorhanden sein.
Es wäre vermessen, Lua als objektorientierte Sprache anzusehen. Gleichwohl lassen sich über eine metatable einer table einige objektartige Eigenschaften geben.
Damit lassen sich spezifische Methoden definieren für:
Weil die table ohnehin Funktionen als Elemente enthalten kann, lassen sich nach Art eines selbstdefinierbaren Objekts Methoden und Eigenschaften darstellen und über eine Generierungsfunktion auch allen Instanzen einer „Klasse“ zuweisen; diese sogar geeignet vererben und überschreiben. Das traut man der schlichten Sprache auf den ersten Blick nicht zu.
Mittels der Funktion mw.addWarning( wikitext ) können im Kopfbereich der Seitenvorschau Warnungen angezeigt werden.
wikitext wird dabei noch geparset.error-54381975 generieren, der im Seitenkopf verlinkt und an der Einbindung verankert wird.Das Objekt mw (für MediaWiki) ist immer verfügbar. Es stellt zahlreiche nützliche Funktionen bereit.
Die Komponenten sind analog der Funktionen und Datenstrukturen auf dem Wiki-Server (in PHP) sowie dem Objekt mw in JavaScript gebildet, wo sich gleiche Aufgaben finden. Sofern möglich, stimmen Namen und Parameter überein.
Einige Funktionen sind direkt als Komponenten angebunden, bei anderen ist die Komponente eine Bibliothek, die die einzelnen Funktionen enthält.
Unmittelbare Funktionen
mw.addWarning()mw.allToString()mw.clone()mw.dumpObject()mw.getCurrentFrame()mw.incrementExpensiveFunctionCount()mw.isSubsting()mw.loadData()mw.loadJsonData()mw.log()mw.logObject()Funktionssammlungen
mw.ext – Erweiterungenmw.html – HTML-Elementmw.language – Formatieren in der aktuellen menschlichen Sprachemw.message – Systemnachrichtenmw.site – aktuelles Wiki-Projektmw.text – Zeichenkettenmw.title – Wiki-Seitenmw.uri – URLmw.ustring – Zeichenketten in Unicodemw.wikibase → mw:Extension:Wikibase Client/Luamw.extmw.ext.dataKomplexe Daten aus zentraler Struktur auslesen.
Data: bereitgestellt.s – Seitentitel in commons:Data:
.tab (als frei gestaltete Tabelle)slang – (optional) Sprachcode
"_" – Rohdatennil.
.data sind die lokalisierten Nutzdaten.Für Module, die in mehreren Sprachversionen vorliegen, eignet sich diese Funktion, um die Übersetzungen zentral an einem Ort in einer als Übersetzungswörterbuch dienenden Tabelle zu hinterlegen (vgl. commons:Data:I18n/Module:TNT.tab) und auszulesen. Änderungen an Übersetzungen oder Erweiterung um neue Sprachen benötigt dann keine Änderung des Moduls mehr.
mw.htmlDiese Methoden sind gut geeignet zur Synthese von HTML-Elementen.
Die Methodik ähnelt derjenigen, die in jQuery verwendet wird.
Ein neues html-Objekt lässt sich bilden mit
div.
args.selfClosing – Erzwingen eines unary Tag, auch wenn das für dieses Element nicht zu erwarten ist.args.parent – Verweis auf ein möglicherweise bekanntes Eltern-html-Objekt (nur für interne Zwecke vorgesehen)local el = mw.html.create( "div" )
Auf ein so gebildetes html-Objekt el können die folgenden Methoden angewendet werden.
Rückgabewert ist in der Regel das ursprüngliche Objekt selbst, weshalb die Methoden verkettet werden können.
class des Objekts hinzu.
html:done(), aber versucht jeweils noch zum nächsthöheren Elternknoten zu gelangen.style des Objekts hinzu.
style des Objekts hinzu.
jQuery().end() wird damit ermöglicht, mehrere verkettete Kind-Elemente gleichzeitig in einer einzigen Anweisung zu definieren. Ob die Einzel-Anweisung dann noch besonders übersichtlich und nachvollziehbar ist, steht dahin.\n an die Definition anhängen.... – Aufzählung von Zeichenketten oder Zahlen (unbestimmte Argumentanzahl)local div = mw.html.create( "div" )
div:attr( "id", "testdiv" )
:css( "width", "100%" )
:wikitext( "Some text" )
:tag( "hr" )
return tostring( div )
soll liefern:
<div id="testdiv" style="width:100%;">Some text<hr /></div>
Die nachfolgenden Abschnitte stellen die Unterstützung bei Weblinks und Wikilinks durch Scribunto-Standardbibliotheken dar.
Es sind
Wie bei Wikisyntax können Wiki-Seiten sowohl über URL wie auch über den Seitenbezeichner adressiert werden.
mw.titleDas title-Objekt repräsentiert einen Seitennamen, vor allem aber die Eigenschaften der entsprechenden Wiki-Seite.
Es sind etliche Informationen über die aktuelle (oberste) Seite und auch jede andere im Projekt verfügbar: Titel, Namensraum, Existenz, bis zum Inhalt.
mw.site.namespaces möglich ist.[2]curid generiert wird, ist der Rückgabewert nil, wenn eine solche Seite nicht existiert..getCurrentTitle() handelt und diese Seite auch nicht bereits geladen wurde.mw.site.namespaces möglich ist.[2]nil.mw.site.namespaces möglich ist.[2]lookupExistence() füllt die Eigenschaften exists, contentModel, id und isRedirect des title-Objekts der jeweiligen Seiten.getTitles() gibt eine table der title-Objekte der abgefragten Seitentitel zurück. Ungültige Seitentitel bekommen den Wert nil zugewiesen.true – wenn beide title-Objekte die gleiche Seite darstellen.-1, 0, oder 1, um anzuzeigen, ob title-Objekt a kleiner, gleich oder größer ist als title-Objekt b. Zunächst werden die Nummern der Namensräume verglichen, danach ggf. die (normalisierten) Seitentitel.Wie bei jedem Objekt kann, nachdem es erstellt wurde, das von ihm repräsentierte Gebilde näher untersucht werden.
Mit relationalen Operatoren können title-Objekte verglichen werden.
tostring( title ) ergibt title.prefixedText.Die meisten Eigenschaften lassen sich nur lesen, falls nicht anders angegeben (fragment).
curid oder 0, wenn die Seite nicht existiert."".""..text ansonsten..text ansonsten..text ansonsten.true wenn diese Seite eine Diskussionsseite haben kann (NR≥0).true – wenn diese Seite existiert.Media: ist dies ein Alias für .file.exists und wird entsprechend bewertet..getCurrentTitle() existiert die Seite immer (es sei denn, sie würde soeben erst mit dem Speichern erstellt); bei mw.title.makeTitle() wird dies erst ermittelt.false.
.exists
nil..height
.mimeType
.pages
.size
.width
. Obsolet; jetzt .file.exists
.filetrue – wenn es ein Inhalts-Namensraum ist.true – wenn die Seite als Begriffsklärungsseite deklariert ist.true – wenn es einen Interwiki-Präfix gibt.true – wenn es ein Projekt gleicher Art ist.true – wenn diese Seite als Weiterleitung gespeichert ist.true – wenn diese Seite eine Spezialseite sein kann (wenn sie im Namensraum Spezial: liegt und es ein gültiger Alias ist)true – wenn dies eine Unterseite einer anderen ist.true – wenn dies eine Diskussionsseite ist.nil, wenn die Seite nicht existiert.css, javascript, Scribunto (Modul), wikitext usw.mRestrictions sequence tablerestrictionssourcesnilwikitext ist, also insbesondere Programmiersprachen, ist meist en die Seitensprache. Dadurch wird ggf. lateinische Schrift von links nach rechts die Vorgabe.nil wenn es zu diesem title keine Diskussionsseite geben kann.true – wenn das aktuelle Objekt eine Unterseite von title ist.mw.site.namespaces möglich ist.[2]true – wenn das aktuelle Objekt im angegebenen Namensraum liegt.true – wenn das aktuelle Objekt in einem der angegebenen Namensräume liegt.mw.site.namespaces möglich ist.[2]true – wenn diese Seite selbst oder ihre Diskussionsseite im Inhalts-Namensraum namespace liegt.k=v sein oder eine Zeichenkette."relative" (Vorgabe des optionalen Wertes)"http""https""canonical"mw.uriDiese Methoden sind gut geeignet zur Synthese von URL und zur Analyse formal korrekter URL.
Bei unbekannt im Wikitext vorgefundenen Zeichenketten, die eine URL sein sollen, empfiehlt sich vorher eine vorsichtige Analyse auf formale Zulässigkeit mit URLutil, oder andere Mechanismen zum Abfangen von Fehlersituationen.
"QUERY") kann folgende Werte haben:
"QUERY" – Leerzeichen als + für query-Komponenten."PATH" – Leerzeichen als %20"WIKI" – Leerzeichen als _ (dies ist nicht vollständig umkehrbar, weil auch vorhandene _ ununterscheidbar werden)"QUERY") kann folgende Werte haben:
"QUERY" – ersetze + durch Leerzeichen"PATH" – Keine besondere Behandlung potentieller Leerzeichen."WIKI" – ersetze _ durch Leerzeichen& zu einer Zeichenkette.false für „leer“.&k=v in Elemente der table.
&k= erhalten den Wert false.mw.uri.new().Wie bei jedem Objekt kann, nachdem es erstellt wurde, das von ihm repräsentierte Gebilde näher untersucht werden.
Felder, von denen einige oder alle nil sein können:
mw.uri.parseQueryStringAußerdem sind die nachstehenden Eigenschaften vorhanden:
tostring() ergibt den (kanonischen) Text der URI.An Methoden sind vorhanden:
Die nachstehende Funktion versucht ein Link auf die Versionsgeschichte zurückzugeben, wobei die Seite über die Seitenkennnummer curid definiert ist. Programmierfehler und ungültige Zahlenwerte werden erkannt. Beide auf dieser Seite dargestellten Bibliotheken/Objekte werden verwendet.
function versionen( curid )
local r
if type( curid ) == "number" and curid > 0 then
local page = mw.title.new( curid )
if page then
local uri = mw.uri.fullUrl( page.prefixedText,
{ action = "history" } )
r = string.format( "[%s Versionen]", tostring( uri ) )
else
r = string.format( "Seite %d fehlt", curid )
end
else
r = "*BAD curid*"
end
return r
end
.id oder einer der Namen; zurzeit aber nicht die table selbst.
Die nachfolgenden Abschnitte stellen die Unterstützung in der momentanen Projekt-Umgebung durch Scribunto-Standardbibliotheken dar.
Es sind
mw.site – für allgemeine Informationen über das Wiki-Projektmw.language – für menschliche Sprachen, ihre Namen und Codesmw.message – für Systemnachrichtenos – Lua-Bibliothek für Betriebssystem-ZugriffeSiehe dazu auch Hilfe:Lua/Internationalisierung.
mw.siteAbfrage allgemeiner Informationen über das Wiki-Projekt und einige statistische Angaben.
1.47.0-wmf.15 (3f954f5) – {{CURRENTVERSION}}/w – {{SCRIPTPATH}}//de.wikipedia.org – {{SERVER}}Wikipedia – {{SITENAME}}dewiki/w/skins – {{STYLEPATH}}mw.site.namespaces.module.name ist Modulmw.site.namespaces[12].name ist Hilfemw.site.namespaces.wp.id ist 4nil oder "*" ist, wird eine table mit den folgenden Elementen zurückgegeben; ansonsten das Schlüsselwort erwartet.
all – Gesamtzahl der Seiten, Dateien und Unterkategorien.pagesfilessubcatsBenutzer.Project statt Wikipedia.(Artikel) oder (Seiten) oder (gallery)nil – in jedem Namensraum, dessen Name nicht leer ist.true – wenn Unterseiten für diesen Namensraum aktiviert sind.true – wenn dieser Namensraum unterschiedliche Aliasse für die Geschlechter hat (Benutzer und Benutzerin).true – wenn der erste Buchstabe des Seitentitels immer groß geschrieben wird (abweichend im Wiktionary).true – wenn es ein Inhaltsnamensraum ist (vereinfacht:[2] NR≥0)true – wenn Seiten eingebunden werden können (vereinfacht:[2] NR≥0)true – wenn Seiten verschoben werden können (vereinfacht:[2] NR≥0)true – wenn es Inhaltsseiten, aber keine Diskussionsseiten sind (vereinfacht:[2] NR≥0 und gerade)true – wenn es ein Diskussionsnamensraum ist (vereinfacht:[2] NR>0 und ungerade)nil – Das content model für den Namensraum.
wikitext – im Modul-Namensraum jedoch Scribunto und bei einzelnen Seiten etwa css oder javascript.nil, wenn keine Zuordnung definiert ist (NR<0[2]).nil, wenn keine Zuordnung definiert ist (NR<0[2]).nil, wenn keine Zuordnung definiert ist (NR<0[2]).
mw.languageSchwerpunkt ist die Analyse der momentanen Projektsprache getContentLanguage() sowie von Wiki-Projekten unterstützter menschlicher Sprachen.
Mit mw.language.new() lässt sich ein neues language-Objekt bilden.
mw (Vorgabe) – nur wenn die Sprache definiert in MediaWiki oder wgExtraLanguageNames istall – alle bekannten Sprachenmwfile – nur wenn die Sprache mw erfüllt und ein message file hat.deen als letztem Element."hsb" → { "dsb", "de", "en" }true – wenn code MediaWiki als IETF-Code bekannt ist.true – wenn für code in MediaWiki eine Lokalisierung vorhanden ist.true – wenn code formal geeignet wäre, eine interne Sonder-Lokalisierung zu definieren. Dabei muss code zu keiner bekannten Sprache gehören.true – wenn code formal korrekt ist; unabhängig davon, ob dies existiert. Dabei muss code zu keiner bekannten Sprache gehören.Ein neues Objekt für eine Sprache code lässt sich bilden mit
local lang = mw.language.new( code )
tostring( lang ) ergibt lang.codeAnschließend sind verfügbar:
de→"forwards" ergibt → bzw. ← (Vorgabe)"backwards" ergibt ← bzw. →"left" ergibt ←"right" ergibt →"up" rgibt ↑"down" rgibt ↓ltrrtl‎‏ bzw. durch lang:getDirMarkEntity( true )mw.messageSystemnachrichten aus dem translatewiki: oder dem MediaWiki-Namensraum.
Einige Funktionen wurden im Februar 2014 entfernt (gerrit:110983).
Ein neues Objekt für eine Systemnachricht lässt sich bilden mit den verschiedenen
local msg = mw.message.new( key )
Ein Teil der Methoden gibt das message-Objekt selbst zurück, um das Verketten der Aufrufe zu ermöglichen.
params kann eine sequence table sein, oder es ist die Liste einzelner string-Argumente.msg:title( title )
msg:parse()
#invoke Wikitext zurückgeben soll.msg:parseAsBlock()
<div>).msg:text()
msg:escaped()
true oder false je nach Existenz der Systemnachricht.true wenn der Bezeichner der Systemnachricht nicht existiert oder ihr Inhalt leer ist; sonst false.true wenn der Bezeichner der Systemnachricht nicht existiert oder ihr Inhalt leer ist oder die Zeichenkette "-"; sonst false.osEine Standardbibliothek in Lua ist os (operating system). Damit würden Zugriffe auf das Betriebssystem möglich. Auf den Wiki-Servern ist dies weitgehend unterbunden. Zu produktiven Zwecken ist das auch kaum sinnvoll praktisch nutzbar.
Die einzige Funktion, die bei der Entwicklung Anhaltspunkte liefern kann, ist os.clock(). Damit lassen sich Abschätzungen über den Zeitbedarf des Moduls treffen; siehe Lua #Begrenzungen.
Die Umrechnung in Sekunden (wohl seit 1. Januar 1970 00:00) ist für eine Wiki-Seite eher seltener von Interesse.
Die nachfolgenden Abschnitte geben
für Lua-Programmierer eine Kurzreferenz zum Umgang mit Zeichenketten in der Lua-Programmierung.
Die Wiki-Projekte sind in vollem Unicode geschrieben, Lua arbeitet jedoch nur mit 8-bit-Code (ISO 8859-1).
ustring-Funktionen für Unicode verarbeitet werden.siehe Scribunto (englisch):
Angegeben sind jeweils die Funktionen für ASCII und Unicode; letztere mit mw.ustring.*().
Die Parameter bedeuten:
-1: letztes Zeichen.
-1: bis zum SchlussDie Index-Zahlen gelten immer in Zeichen; das sind bei der ASCII-Version Bytes.
nil von den mw.ustring.* zurückgegeben. Das ist beim Wikitext nicht zu erwarten, wenn man ihn nicht vorher selbst ruiniert hatte.r1, r2, r3, r4 = s:byte( i, j )j, k = s:find( pattern )nil.printf)for-Schleife über jedes Zeichenfor-Schleifer, k = s:gsub( pattern, replace )return s:gsub( "X", "U" ) hängt unvermutet eine Zahl an die Zeichenkette des Rückgabewerts an.
%1 bis %9 eingefügt werden. %0 steht für die gesamte Fundstelle.nil oder false, dann wird nichts verändert.true wenn die UTF-8-Kodierung gültig ist.s:len() ist das Gleiche wie #sr1, r2, r3 = s:match( pattern )r1=smw.ustring.rep().-1 als Vorgabe.10000 (Mai 2013)2048000 (Mai 2013) und damit für alle darstellbaren Wiki-Quelltexte gerade hinreichendsiehe Scribunto (englisch)
Die beiden Funktionen
formatieren ihre Argumente p1, p2 usw.
Dabei ist
spec eine Zeichenkette aus den nachstehenden Spezifikatoren.
pi aus der Parameterliste gegenüberstehen.Die Formatierungs-Spezifizierung spec für die einzelnen Werte entspricht einer Teilmenge der Programmiersprache C (printf).
Die prinzipielle Struktur der Spezifikation für einen einzelnen Wert ist
% f w .p s c%% zur Darstellung eines einzelnen Prozentzeichens.Die Spezifikation beginnt also mit dem Prozentzeichen und endet mit dem Kennbuchstaben; die näheren Angaben dazwischen sind frei.
"%2$s") werden nicht unterstützt.c |
Kodierung als einzelnes Zeichen |
d |
Dezimalzahl |
i |
Dezimalzahl mit Vorzeichen; in Lua wie d
|
u |
Vorzeichenlose Dezimalzahl; in Lua wie d
|
o |
Oktalzahl |
x |
Hexadezimalzahl; kleine Buchstaben |
X |
Hexadezimalzahl; große Buchstaben |
e |
Exponentialnotation; kleines e |
E |
Exponentialnotation; großes E |
f |
Gleitkommazahl |
g |
Gleitkommazahl oder e nach Genauigkeit
|
G |
Gleitkommazahl oder E nach Genauigkeit
|
s |
Formatierung als Zeichenkette bestimmter Länge |
% |
Prozentzeichen |
q |
Lua-interne Repräsentation; wiedereinlesbar kodiert |
Der Kennbuchstabe ‘q’ entspricht ‘s’, formatiert jedoch die Zeichenkette auf eine Weise, die später vom Lua-Interpreter zurückgelesen werden kann: Eingeschlossen in " und im Inneren geeignet escaped.
Die Pattern entsprechen im Prinzip den verbreiteten regulären Ausdrücken mit einigen Besonderheiten:
% und so ebenfalls die Kennzeichnung der Spezifikatoren.* ? + - versehen werden. Bei in runde Klammern gesetzten Ausdrücken (captures) ist das nicht möglich.| (Pipe).. schließt Zeilenumbrüche mit ein (!).^ und $ – im Inneren jedoch als ganz normale Zeichen. Andere Begrenzer wie \b gibt es nicht.- (Bindestrich-Minus), die versucht, so wenig wie möglich Zeichen zu liefern.
"ababab" liefert "a.-b" nur "ab", während "a.*b" die ganze "ababab" ergeben würde.{n,m} für die Anzahl der Zeichen.%bxy gefunden werden, wobei x und y Zeichen sind. %b() greift beispielsweise, wenn die runden Klammern paarweise auftreten.%f[Liste] setzt die Position an jene Grenzstelle, deren vorangehendes Zeichen nicht der Liste entspricht und folgendes Zeichen der Liste entspricht. Dieses Pattern matcht keine Zeichen an sich, sondern die imaginäre leere Zeichenkette zwischen zwei Zeichen.
"DIES (IST) eiN BEIspiel-TEXT." liefert "%f[%a]%u+%f[%A]" alle großgeschriebenen Wörter "DIES", "IST" und "TEXT", während das Muster "%u+" auch "N" und "BEI" zurückgeben würde. Der Grund ist, dass "%f[%a]" den Übergang zwischen Nichtbuchstaben und Buchstaben matcht, d. h. Wortanfänge, "%f[%A]" Übergänge zwischen Buchstaben und Nichtbuchstaben, d. h. Wortenden, und "%u+" verlangt, dass alle diese Buchstaben zwischen Wortanfang bis Wortende Großbuchstaben sind.%1 bis %9 muss gleich dem entsprechend nummerierten vorangegangenen Ausdruck in runden Klammern sein.
Gleich ist der Zeichenbereich in eckigen Klammern [Liste] und dessen Negation [^Liste] sowie die Notation A-Z usw. für einen Bereich zwischen zwei Zeichencodes.
siehe Scribunto (englisch)
Die Zeichen sind in Klassen eingeteilt; jede hat einen Spezifikator. Damit wird jeweils ein ganzer Bereich beschrieben.
| Klasse | Bedeutung |
|---|---|
| x | ist das Zeichen selbst, wenn es nicht eines der Zeichen mit Sonderbedeutung ist: ^$()%.[]*+-?
|
. |
(Punkt) alle Zeichen, einschließlich Zeilenumbruch (!) |
%a |
alle ASCII-Buchstaben |
%c |
alle ASCII-Steuerzeichen (nur Tab und Zeilenumbruch im Wikitext) |
%d |
alle Ziffern |
%l |
alle ASCII-Kleinbuchstaben |
%p |
alle Sonderzeichen der Interpunktion |
%s |
aller ASCII-Whitespace |
%u |
alle ASCII-Großbuchstaben |
%w |
alle ASCII-alphanumerischen Zeichen |
%x |
alle Hexadezimalziffern |
%z |
ASCII NUL (zero byte) nicht im Wikitext |
%A |
alle Zeichen nicht in %a
|
%C |
alle Zeichen nicht in %c
|
%D |
alle Zeichen nicht in %d
|
%L |
alle Zeichen nicht in %l
|
%P |
alle Zeichen nicht in %p
|
%S |
alle Zeichen nicht in %s
|
%U |
alle Zeichen nicht in %u
|
%W |
alle Zeichen nicht in %w
|
%X |
alle Zeichen nicht in %x
|
%Z |
alle Zeichen nicht in %z
|
%x |
Wenn x kein alphanumerisches Zeichen ist, ist es das Zeichen x selbst. Somit ist dies der normale Weg, um die Zeichen mit Sonderbedeutung darzustellen. Eine Anwendung auf ein sonstiges Sonderzeichen ist unschädlich. |
siehe Scribunto (englisch)
Der wesentliche Unterschied zu einem ASCII-Pattern ist, dass die Zeichenklassen die Unicode-Eigenschaften wiedergeben.
| Klasse | General Category | |
|---|---|---|
%a |
Letter | |
%c |
Control | |
%d |
Decimal Number | |
%l |
Lowercase Letter | |
%p |
Punctuation | |
%s |
Separator | zuzüglich \t, \n, \r, \v, \f |
%u |
Uppercase Letter | |
%w |
Letter Decimal Number |
|
%x |
zuzüglich vollbreiter Versionen der Hex. |
Die Zeichen werden grundsätzlich als Unicode-Zeichen und nicht als Bytes interpretiert. Damit sind Bereiche wie [0-9] oder ein Pattern wie %b«» möglich, und Wiederholungszeichen arbeiten korrekt.
siehe Scribunto (englisch)
Eine weitere Hilfsbibliothek durch Scribunto, um kleine Manipulationen an Zeichenketten vornehmen zu können.
Unter „Zeichen“ wird hier Unicode verstanden.
"<>&\"' " mit geschütztem Leerzeichen am Ende.mw.text.JSON_PRESERVE_KEYS – Vermeiden, dass die zero-based Arrays in JSON auf Lua sequence tables abgebildet werden: Indizes beibehalten, Zählung bei 0 statt Lua-üblich 1 beginnen.mw.text.JSON_TRY_FIXING – Nicht empfohlen: Syntaxbeschränkungen ignorieren; etwa redundantes schließendes Komma in Array oder object.null enthält, kann es in Lua keine sequence table werden.null in einem JSON object erscheinen nicht.mw.text.JSON_PRESERVE_KEYS – Vermeiden, dass die sequence tables in Lua auf zero-based Arrays in JSON abgebildet werden: Indizes beibehalten, Zählung bei 1 statt JS-üblich 0 beginnen.mw.text.JSON_PRETTY – pretty printing (formatierte mehrzeilige Darstellung statt kompakter Abfolge).[] und nicht als leeres object {} generiert.nil zu erreichen, ist die metamethod __pairs erforderlich.table.concat().for analog zu mw.text.split()=false wird ein unary tag generiert.<ref> muss mit frame:extensionTag() generiert werden; andernfalls würde es nicht wirksam.mw.html – diese Bibliothek ist im Zweifelsfall votzuziehen und einheitlich darauf umzustellen.[set] stehen kann.
"\t\r\n\f "true verwendet wird, ist der Betrag von length die Gesamtlänge einschließlich ellipsis.mw.logObject() verwendet dieses Format.Die nachfolgenden Abschnitte stellen Möglichkeiten dar, bei der Programmierung von Lua-Modulen das Basis-Konzept einer Trennung von Programm und Daten umzusetzen.
Die Trennung von Programm und Daten gehört zum Stoff des ersten Semesters eines Informatikstudiums.
Vorteile:
Grundsätzlich werden Parameter mit konstanten Werten, welche eine zukünftig möglicherweise veränderliche Konfiguration abbilden, sowie sämtliche veränderlichen Textbausteine, die auch von menschlichen Sprachen abhängen, in der Strukturierung getrennt von den prozeduralen, algorithmischen Beziehungen.
Die Funktionen der Systembibliotheken liefern diverse global gepflegte Konfigurationsdaten über das aktuelle Wiki.
Im aktuellen Modul können Werte statisch zugewiesen werden, oder auch abhängig von der aktuellen Seite dynamisch ermittelt werden.
local-Zuweisungen sollten geschlossen zu Beginn des Quelltextes erfolgen, damit sie leicht und vollständig wiedergefunden und gepflegt werden können.#invoke oder externe Seiten überschrieben werden.Beispiel: Modul:TemplateData
Dies ist Mittel der Wahl für eine Programmierung, die in mehreren Wikis wiederverwendet werden soll.
mw.loadData() ermöglicht dann die Einbindung in andere Module.Vorteile
#invoke-Einbindungen wiederverwendet werden.Nachteile
function enthalten, sondern nur reine Daten: nil, boolean, number, string, tableBeispiel: Modul:URIutil/urn
Mittels require() kann ein anderes Modul eingebunden werden.
Vorteile
Nachteile
Beispiel: Modul:Vorlage:Runeberg/NF
Seit Oktober 2022 ist die Bibliotheksfunktion mw.loadJsonData() nutzbar.
.json-Seite genutzt werden, etwa geteilt mit Gadgets.Benutzung: tbl = mw.loadJsonData( seitenname )
Vorteile
Nachteile
Beispiel: Modul:JSTOR/config.json
Eine beliebige Seite in Wikitext kann ausgelesen, insbesondere aber transkludiert werden.
Vorteile
Nachteile
Beispiel: Vorlage:Seitenbewertung/Darstellung eingebunden durch Modul:Vorlage:Seitenbewertung
Vorteile
Nachteile
Im Namensraum Data:*.tab auf Wikimedia Commons können Seiten im JSON-Format hinterlegt werden, die alle Wikis lokal einbinden und auslesen können.
mw.ext.data.get() kann die Tabelle bezogen auf die Sprache des aktuellen Wikis oder für alle Sprachen abgerufen werden.Vorteile
Nachteile
.tab erlaubt keine Felder/Maps als Komponenten, sondern nur atomare Datenspalten. Allerdings gibt es den Typ „Lokalisiert“, der eine Tabelle für Zeichenketten nach Sprachcode erlaubt.Eine globale Zusammenstellung kann einmalig in mw.loadData() importiert und dort unter lokalen Bedingungen aufbereitet, gefiltert und einmalig vorverarbeitet werden.
Beispiel: commons:Data:ISO15924/rtl.tab
Aus Wikidata können beliebige Eigenschaften eines Items (oder auch anderer Objekte) ausgelesen werden; siehe mw:Extension:Wikibase Client/Lua.
Vorteile
Nachteile
Die nachfolgenden Abschnitte stellen Möglichkeiten dar, bei der Programmierung von Lua-Modulen andere Sprachen und Projekt-Konstellationen zu berücksichtigen.
Ein Nebeneffekt ist, dass durch bessere Strukturierung auch die Wartung und Pflege im eigenen Projekt einfacher und sicherer wird.
Einige grundsätzliche Möglichkeiten werden dargestellt und verglichen.
Textteile (in menschlicher Sprache) und potentiell veränderliche Konfigurationen (etwa die Namen von Seiten) sollen nie im Inneren des Codes versteckt werden.
Die momentane Konfiguration und Umgebung kann ausgelesen werden. So sind die Namen und Nummern zu den Namensräumen bekannt.
ns = mw.site.namespaces.Module.id
sT = mw.site.namespaces.Template.name
Die vorstehende Anweisung liest die momentane Nummer des Modul-Namensraums (828) und den deutschsprachigen Bezeichner des Vorlagen-Namensraums aus.
Siehe dazu allgemein: Hilfe:Lua/Umgebung.
Auch alle dort nicht angebotenen Parserfunktionen sind nach diesem Prinzip verfügbar, dann über frame:preprocess{} (siehe LuaWiki.getVariable()).
Alle möglicherweise anzupassenden Texte oder Zahlen werden in Variablen geschrieben. Die Wertzuweisung erfolgt in einem geschlossenen Block am Beginn des Moduls.
Vorteile
Nachteile
Für alle Sprachen, die unterstützt werden sollen, wird eine Tabelle angelegt. Es wird automatisch festgestellt, welche Sprache oder Projekt gerade aktiv ist, und das entsprechende Profil ausgewählt.
local l10nDef = { }
l10nDef[ "en" ] = {
msgA = "Message 'A'",
msgB = "Message 'B'"
}
l10nDef[ "de" ] = {
msgA = "Nachricht 'A'",
msgB = "Nachricht 'B'"
}
l10nDef[ "als" ] = l10nDef[ "de" ]
local l10n = l10nDef[ mw.language.getContentLanguage():getCode() ]
if not l10n then
l10n = l10nDef.en
end
say = l10n.msgA
Die Sprache des Inhalts getContentLanguage() ist für die Darstellung in den Seiten passend; nicht die Spracheinstellung der momentanen Bearbeiter.
Analog zur Sprachkonfiguration kann auch auf die Projekt-URL Bezug genommen werden:
local l10nDef = { }
l10nDef[ "//de.wikipedia.org" ] = {
nsDoc = 4, -- WPNR
warnTalk = "Diskussionsseite fehlt"
}
local l10n = l10nDef[ mw.site.server ]
if not l10n then
l10n = l10nDef[ "*" ] -- defaults; fallback
end
ns = l10n.nsDoc
Vorteile
Nachteile
Auf Commons sind mittlerweile Tabellen verfügbar bzw. können angelegt werden, die aus jedem Wiki ausgelesen werden können und Übersetzungslisten zu Schlüsselwörtern enthalten. tabData@Multilingual unterstützt dabei.
Die Textstücke können im MediaWiki-Namensraum abgelegt werden.
c = mw.language.getContentLanguage():getCode()
m = mw.message.new( "lua-module-MeinModul-" .. stored )
m:inLanguage( c )
say = m:plain()
Vorteile
Nachteile
Nur sinnvoll, wenn das #invoke lediglich in genau einer Vorlage vorkommt; das Modul also zur Unterstützung einer einzelnen Vorlage dient. Dann können die Textbausteine in die Parameterliste des #invoke eingeschlossen werden. Die Vorlage bleibt unter einem lokalen Namen für die allgemeine Benutzung mit einfacher Syntax verfügbar; #invoke und die angepassten Textstücke werden vor den Benutzern verborgen.
Vorteile
Nachteile
Die Textbausteine können auf eine beliebige Seite geschrieben werden, die unter Angabe des Schlüsselworts als Parameter eingebunden wird. Das ist mit der Funktion frame:expandTemplate{} möglich.
Vorteile
Nachteile
Ein geeignetes Unter-Modul für jede Sprache kann die Anpassung übernehmen, indem die zurückgegebene Tabelle die spezifischen Zeichenketten usw. enthält. Sie ist mit require() verfügbar, und die Namensgebung ist in eigener Hand. Auch mw.loadData() käme zur Effizienzsteigerung in Frage, falls die Tabelle keine Funktionen zurückgeben soll (die aber zur Generierung des Rückgabewerts benutzt werden können).
Vorteile
Nachteile
Weitgehend identisch mit einem Unter-Modul wäre eine Umsetzung als JSON.
mw.loadJsonData() bei gleichen Nebenwirkungen.Es muss immer damit gerechnet werden, dass externe Vereinbarungen oder die lokale Sprache nicht verfügbar sind.
In den nachfolgenden Abschnitten
wird beschrieben, wie sich in der Wiki-Umgebung Lua-Quellcode eingeben und testen lässt.
Bei den dafür vorgesehenen Seiten des Modul-Namensraums schaltet sich bei der Bearbeitung der Seite immer automatisch der CodeEditor zu.
Ähnlich wie bei Vorlagen gibt es (statt) der normalen Seitenvorschau zwischen Speichern und Änderungen zeigen im Feld darunter zusätzlich Vorschau zeigen zur Darstellung einer spezifizierten Seite, bei der der im Bearbeitungsfeld vorhandene Code so behandelt wird, als wäre das zugehörige Modul bereits gespeichert.
Das bietet sich insbesondere für die Testseite an:
Beispiele: URLutil und TemplatePar.
Damit kann der Lua-Quellcode auch nach und nach in der Seitenvorschau entwickelt werden, ohne jede einzelne Version speichern zu müssen.
Wenn man ein Modul mit existierendem Quellcode im Bearbeitungsfeld zum Bearbeiten geöffnet hat, erhält man im Fußbereich der Seite eine Fehlerbereinigungskonsole.
action=edit; auch hier jedoch nach der ersten Seitenvorschau als action=submit.= eingeben und die Taste Enter drücken.
pp (Variable oder Funktionsaufruf) eingetragen, ein Gleichheitszeichen vorangestellt und Enter gedrückt.mw.log(text) bleiben scheinbar wirkungslos; ausgenommen:
mw.log() und für ein Wiki nur innerhalb der Konsole möglich. Es ist gleichzeitig ein Alias für das Gleichheitszeichen.Bedienung:
Für die Gesamtwirkung der Modul-Ergebnisse ist die Vorschau-Funktion wichtiger, insbesondere mit der im vorigen Abschnitt dargestellten Testseite.
Während bei der Seitenvorschau der Modul-Einbindung die von mw.log() ausgeworfenen Meldungen in der Konsole sichtbar sind, erscheinen sie seit Juli 2014 in der normalen Seitenvorschau/Ansicht im Parser-Report. Dieser ist in der deutschsprachigen Wikipedia allerdings standardmäßig ausgeblendet.
In der Vorlagenspielwiese können Module analog zum Modul-Namensraum entwickelt werden.
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.