Hilfe:Lua/*
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.
Einstieg
[Bearbeiten | Quelltext bearbeiten]
- Die Funktionen werden über eine neue Parserfunktion
{{#invoke:}}
in eine umgebende klassische Vorlage eingefügt und ergänzen diese um allgemeine Hilfsfunktionen, die bislang schwer zu realisieren waren. - Gegenüber Wikisyntax-Vorlagenprogrammierung bietet Lua vor allem bislang kaum mögliche Techniken im Zusammenhang mit Zeichenketten und größeren Mengen an numerischen Daten; nebst Analyse des Wikitextes der dargestellten Seite.
- In MediaWiki wird sie über die mw:Extension:Scribunto angebunden, die auch weitere Skriptsprachen ermöglichen würde.
Die Darstellung auf diesen Hilfeseiten trifft dagegen im Prinzip auf jedes beliebige Wiki zu.
Vorlagenprogrammierung
[Bearbeiten | Quelltext bearbeiten]Wikisyntax: {{:}}
- Pflicht: 1 2
- Optional: <beliebig>
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.
- Bei unbekannt von außen kommenden Inhalten sollten keine unbenannten Parameter verwendet werden, bzw.
1=Wert1
wie bei Vorlagen (verschärftes Gleichheitszeichen-Problem; kann zum Syntaxfehler führen). - Der Rückgabewert der aufgerufenen Funktion ist eine Zeichenkette mit Wikitext, der entsprechend an dieser Stelle in den Artikel eingebettet wird.
- Beispiel: Modul:Hello – Demonstration: Hallo, Welt! Dies ist Lua!
- Zum Zeitpunkt des Funktionsaufrufes hat der Parser mehrere wichtige Schritte bereits abgeschlossen, insbesondere die Vorlagenexpansion und die Verarbeitung von Extension-Tags (
<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. - Die Ausführungsumgebung wird bei jedem Aufruf von
#invoke
zurückgesetzt. Eine direkte Übernahme von Variablen zwischen zwei Aufrufen ist nicht möglich. - Innerhalb der aufrufenden Vorlage erfolgen die einzelnen Aufrufe von
#invoke
sequentiell und unter Verwendung der gleichen (nur wenig auswertbaren) Elternumgebung. - Verschiedene Einbindungen der Vorlage selbst (z. B. in einem Artikel) werden dagegen parallel abgearbeitet und teilen auch keine 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/***).
Begrenzungen
[Bearbeiten | Quelltext bearbeiten]- Schachtelungstiefe und Größe (Expansion) werden durch Lua zwangsläufig reduziert. Seiten, die bislang nicht dargestellt werden konnten, lassen sich nun ohne Sprengung der Limits anzeigen.
- Der Zeitverbrauch für die Gesamtdarstellung einer Seite mit Nutzung komplexer Vorlagenprogrammierung lässt sich auf etwa ein Drittel reduzieren, wenn die Vorlagensyntax durch gleichwertige Lua-Module ersetzt wird.
- Bei einer Seite mit vielen sehr einfachen Vorlagen könnte die Performance dagegen verschlechtert werden, falls jede einfache Vorlage durch eine Lua-Benutzung ersetzt würde: Jeder Start einer Lua-Funktion kostet ein gewisses Eintrittsgeld, das durch Ersatz einer bisher komplizierten Vorlagenprogrammierung erst einmal erwirtschaftet werden muss. Wird nur eine einfache Vorlage ersetzt, so war diese möglicherweise effizienter gewesen.
- Alle Lua-Module einer Seite sind auf eine kumulierte Prozessor-Zeit von 10 Sekunden begrenzt. Diese Zeit wird wie die Nutzung anderer Ressourcen im HTML-Quellcode als PP-Report des Präprozessors ausgewiesen. In Zeiten hoher Serverbelastung kann die Ausführungszeit bis auf das Vierfache steigen. Deshalb sollte, wenn in günstigen Zeiten eine Gesamtzeit von 2 Sekunden erreicht wird, eine Code-Optimierung (kaum signifikant zu erwarten) oder eine Aufteilung übergroßer Seiten überlegt werden.
- Ein weiterer Flaschenhals können die „teuren“ Funktionen sein. Ihre Anzahl pro dargestellter Gesamt-Seite ist auf 500 begrenzt. Dazu zählt unter anderem die Abfrage nach der Existenz von Seiten und Dateien.
Siehe auch: Hilfe:Vorlagenbeschränkungen.
Modul-Namensraum
[Bearbeiten | Quelltext bearbeiten]Organisation der Seiten
[Bearbeiten | Quelltext bearbeiten]- Die Quellcodes stehen in einem eigenen Namensraum Modul: auf Seiten, die „Modul“ genannt werden.
- Jedes Modul enthält eine oder mehrere Funktionen in Lua.
- Mittels
#invoke
,require()
oder in geeigneten Fällenmw.loadData()
kann eine komplette Modulseite geladen werden.
- Ausschließlich Seiten aus dem Namensraum
Modul:
können für die Auswertung benutzt werden.- Benutzer-Unterseiten sind nicht möglich; ausgenommen solche in Hierarchie der Vorlagenspielwiese.
- Auch alle Unterseiten im Modul-Namensraum gelten als Lua-Quellcode und werden nicht als Wikitext dargestellt. Nur die Unterseiten gemäß dem vereinbarten Schema für die Dokumentation gelten als Wikitext.
- Eine Seite mit Lua-Quellcode hat das Content Model "
Scribunto
".
- An jede Quellcode-Seite ist eine Dokumentationsseite angebunden, die auch genutzt werden soll. Sie bildet sich aus dem Seitennamen als Unterseite
/Doku
. - Seit Oktober 2022 sind auch JSON-Seiten möglich; typischerweise mit
.json
am Schluss des Seitennamens. - Vorlagen sind im Lua-Quellcode nicht wirksam; SLA müssten auf WP:A/A gestellt werden oder mit Verweis auf die Oberseite (Modul) in der Dokumentationsseite. Eine unmittelbare Kategorisierung ist ebenfalls nicht möglich.
- Module werden verwaltet wie Vorlagen (Einbindung von Seiten). Sie erscheinen auch unter „Links auf diese Seite“, selbst wenn sie nicht mittels
#invoke
eingebunden sind, sondern durchrequire()
usw. aufgerufen werden. Werkzeuge zählen etwa die Zahl der Einbindungen.
Weiterleitungen und Verschiebungen
[Bearbeiten | Quelltext bearbeiten]Weiterleitungen von einer Modulseite zu einer anderen sind nicht möglich. Eine „Weiterleitung“ würde Wikisyntax statt Lua-Quellcode erzeugen und (anders als im Fall von Vorlagen) alle Einbindungen und require()
des Moduls zum Auswerfen von Syntaxfehlern bringen; deshalb könnte eine Weiterleitung noch nicht einmal ohne Weiteres abgespeichert werden.
Wenn der Name eines Moduls nicht mehr geeignet erscheint, muss die Existenz von Lua-Quellcode unter den programmierten Namen gesichert bleiben. „Normale“ Verschiebungen sind nicht möglich. Bei produktiv genutzten Modulen, die bereits von sehr vielen Seiten eingebunden sind, ist die Prozedur recht umständlich; insbesondere wenn bereits mehrere Entwickler mitgewirkt hatten.
- Zuerst ist ein neues Modul unter dem künftigen Namen anzulegen und mit dem Quellcode zu füllen.
- Wenn mehrere Benutzer an der Programmierung beteiligt waren, ist auf WP:IMP Versionsimport innerhalb desselben Projekts zu beantragen.
- Dann sind alle Nutzungen auf den neuen Namen umzusetzen.
- Die Verwendung in den dargestellten Seiten einschließlich
require()
wird auf Spezial:Linkliste angezeigt. Diese Liste muss schließlich leer sein. - Zuletzt ist das veraltete Modul zu löschen.
Allerdings kann bis zur Auflösung aller Nutzungen eine einheitliche Funktionalität erreicht werden, indem als einzige Zeile vorgehalten wird: return require( "Modul:NeuerName" )
Solange das Modul noch nicht produktiv genutzt wird, kann es jedoch einfach verschoben werden.
Seiten-Bearbeitung
[Bearbeiten | Quelltext bearbeiten]- Bei Bearbeitung der Quellcode-Seite wird der CodeEditor zugeschaltet.
- Eine Debugging-Konsole wird angezeigt.
- Module können in einer Vorlagen-Umgebung (innerhalb einer anderen Seite) getestet werden.
Siehe dazu: Hilfe:Lua/Quellcode und Vorschau
Das Speichern von syntaktisch fehlerhaften Lua-Modulen ist seit Oktober 2014 nicht mehr möglich.
Syntaxhervorhebung und Zeilennummern
[Bearbeiten | Quelltext bearbeiten]Bis zu einer gewissen Maximalgröße der Seite werden die Syntaxelemente in unterschiedlichen Farben dargestellt. Seit Anfang 2021 werden auf Code-Seiten auch Zeilennummern angezeigt.
- Eine Verlinkung auf eine bestimmte Zeile ist möglich mit dem Fragmentbezeichner
#L-1
,#L-2
,#L-3
usw. - Ein Klick auf die Zeilennummer hebt die aktuelle Zeile hervor, und in der Adresszeile des Browsers wird die geeignete Verlinkung auf diese Zeile dargestellt.
- In aktuellen Diskussionen kann auf die momentane Version verlinkt werden.
- Weil sich der vorangehende Code im Lauf der Zeit ändern kann, wäre ggf. ein PermaLink ratsam.
Die Maximalgröße von Seiten mit Syntaxhervorhebung, die eine farbige Auszeichnung bei zu großen Seiten unterbindet, verhindert dann auch die Generierung der Zeilennummern.
Erprobung
[Bearbeiten | Quelltext bearbeiten]- Spielwiese
- Freies Ausprobieren kleiner Code-Fragmente auf kurze Zeit.
- Für größere Entwicklungsarbeiten ermöglicht die Vorlagenspielwiese auch Quelltext-Module auf eigenen Benutzerseiten.
- Hello
- Demonstrationsmodul (Hallo, Welt!) –
Hallo, Welt! Dies ist Lua!
- Alle Benutzer
- zum Beta-Testen durch mehrere Anwender mit
Modul:Benutzerin:
xxxxxxxxxxxxModul:Benutzer:
xyxyxyxyxyxy- Unterseiten für Benutzer-Module sind möglich.
- Seite muss auch dort angelegt werden.
- Vorlagenspielwiese
- Alle Benutzer können mittels der Vorlagenspielwiese auf ihren Benutzerseiten eigene Module zum Testen verwalten. Mittels des Benutzerskriptes editorContent steht dann auch der CodeEditor zur Verfügung.
Auß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.
Programmieren in Lua
[Bearbeiten | Quelltext bearbeiten]Siehe dazu Hilfe:Lua/Programmierung mit den Spezialthemen
- Modul im Wiki – Modul im Kontext einer Wiki-Seite
- Modul für eine bestimmte Vorlage
- Zeichenketten
- mw-Objekt – Funktionsbibliotheken
- Links – Seiten und URL
- Umgebung – aktuelles Wiki-Projekt
- Konzept der Trennung von Programm und Daten
- Internationalisierung
Zur Sprache Lua allgemein siehe die als Weblinks angegebenen Handbücher.
Darstellung von Quellcode
[Bearbeiten | Quelltext bearbeiten]- Quellcode kann in Textseiten mittels
<syntaxhighlight lang="lua">
dargestellt werden. - Der Inhalt eines ganzen Moduls kann farbig angezeigt werden mit:
{{#tag:syntaxhighlight |{{Modul:Hello}}| lang=lua}}
Weitere Informationen
- Ursprüngliches Lua-Handbuch; enthält Teile, die auf einem Wiki-Server nicht möglich sind:
- Lua 5.1 Reference Manual – lua.org (englisch, portugiesisch)
- deutsche Übersetzung der Version 5.1 des Handbuchs
- Coding conventions – Kodierungsstandard (englisch)
- Lua vs Javascript – Warum wurde Lua und nicht JavaScript gewählt? (englisch)
- Code-Beispiele:
- lua-users.org (englisch)
- ELUA/* – Implementierung auf dem Wiki-Server
Quelltext und Seiten
[Bearbeiten | Quelltext bearbeiten]- Alle Seiten im Namensraum
Modul:
(828) sind grundsätzlich der Quellcode zu je einem Lua-Modul. Dies wird nicht als Wikitext interpretiert. Das Content Model istScribunto
. - Nur Seiten, deren Name das Schema für Dokumentationen erfüllt, in der deutschsprachigen Wikipedia also auf
/Doku
endet, können Wikitext enthalten. - Darüber hinaus gibt es die Möglichkeit, in bestimmten Unterseiten der Benutzer-Spielwiese im Rahmen der Vorlagenspielwiese Lua-Module wirksam werden zu lassen.
- Seiten anderer Namensräume können mit
#invoke
schon deshalb nicht genutzt werden, weil der Namensraum dieser Anweisung intern vorangestellt wird. Auch einrequire()
ist nur auf Seiten möglich, deren Inhalt als Lua-Quellcode gespeichert ist („Content Model“). - Sonstige Unterseiten im Namensraum
Modul:
sollten nur nicht-selbstständigen Lua-Code enthalten:- Keine Vorlage oder ein anderes Modul sollte unaufgefordert derartige Seiten verwenden; ausgenommen durch
mw.loadData()
genutzte Datenmengen oder wenn eine solche Schnittstelle dokumentiert ist. - In der Regel ist es aus dem selbstständigen Modul ausgegliederter Code, wofür es unterschiedliche gute Gründe geben kann.
- Es könnte auch ein unter dem Namen
/test
ausgegliederter unit test sein.
- Keine Vorlage oder ein anderes Modul sollte unaufgefordert derartige Seiten verwenden; ausgenommen durch
Kapselung
[Bearbeiten | Quelltext bearbeiten]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.
Die globale Variable _G
[Bearbeiten | Quelltext bearbeiten]_G ist eine table, die standardmäßig die nachstehend aufgelisteten Komponenten enthält:
- _G _VERSION assert debug error getmetatable ipairs math mw next os package pairs pcall rawequal rawget rawset require select setmetatable string table tonumber tostring trim type unpack xpcall
Im Handbuch auf Mediawiki heißt es:
- Note that every required module is loaded in its own sandboxed environment, so it cannot export global variables as is sometimes done in Lua 5.1. Instead, everything that the module wishes to export should be included in the table returned by the module.
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.
Rückgabewert des Moduls
[Bearbeiten | Quelltext bearbeiten]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:
- Als Wert des Aufrufs von
require()
. - Als Wert von
mw.loadData()
. - Wenn es eine table ist, macht sie für
#invoke
die verfügbaren Funktionen zugreifbar.
Schnittstelle zur Vorlagenprogrammierung
[Bearbeiten | Quelltext bearbeiten]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|}}}
Auswertung in der Funktion
[Bearbeiten | Quelltext bearbeiten]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
|
Rückgabewert einer Funktion für Vorlagen
[Bearbeiten | Quelltext bearbeiten]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.
Objekt frame
[Bearbeiten | Quelltext bearbeiten]- → Scribunto-Dokumentation (englisch)
Das Objekt frame gibt die Umgebung wieder. Grundsätzlich gibt es zwei Instanzen:
- Aufruf des
#invoke
(Normalfall; standardmäßig immer mitframe
bezeichnet) - Aufruf der einbindenden Seite (meist Vorlage).
- Erhältlich mittels
frame:getParent()
- Einziger nutzbarer Unterschied sind die Argumente
frame.args
der Vorlageneinbindung; alle Funktionen führen zum gleichen Ergebnis; erneutesframe:getParent()
hilft nicht.
- Erhältlich mittels
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()
Komponenten
[Bearbeiten | Quelltext bearbeiten]Unmittelbar nutzbar sind:
- frame.args
- Angegebene Parameter als table.
- In der Regel Parameter des
#invoke
– nach frame:getParent() Vorlagenparameter der einbindenden Seite.
- In der Regel Parameter des
- Aus Performance-Gründen wird das frame-Objekt als metatable organisiert. Das bedeutet, dass insbesondere die
frame.args
nicht manipuliert werden können und auch die Anzahl nicht per length-Operator#
festgestellt werden kann. - Der Datentyp des Bezeichners ist:
number
bei einem unbenannnten Vorlagenparameter; bzw. numerischer Angabestring
sonst
- frame:callParserFunction()
- Ausführung einer Parser-Funktion.
r = frame:callParserFunction( name, args )
- Verschiedene Formen sind für die Argumentenliste möglich.
- Die Argumente werden unverarbeitet an die Parser-Funktion übergeben.
- Der Doppelpunkt gehört nicht zum Funktionsnamen.
- Wo es möglich ist, sollten Lua-interne Funktionen bevorzugt werden.
- frame:expandTemplate()
- Einbinden einer anderen Seite.
r = frame:expandTemplate{ title = s, args = args }
- Es ist nur dieses Format mit benannten Parametern und geschweiften Klammern möglich.
title=
wird in der Regel eine Zeichenkette mit dem Vorlagentitel sein; inzwischen ist aber auch ein Objektmw.title
möglich.- frame:extensionTag()
- Analog zu frame:callParserFunction() mit dem von Tags umschlossenen Inhalt.
r = frame:extensionTag( name, content, args )
- Verschiedene Formen sind für die Argumentenliste möglich.
- frame:getParent()
- Objekt frame für die einbindende Seite (Elternumgebung).
frameT = frame:getParent()
- frame:getTitle()
- Gibt den Seitentitel zum frame-Objekt zurück.
- Für den mittels
#invoke
generierten frame ist das der Name des eingebundenen Moduls selbst (einschließlichModul:
zu Beginn). - Das Modul kennt dadurch seinen eigenen Namen (Pfad).
- Das kann eingesetzt werden, um die Produktivversion von einer Testkopie im BNR zu unterscheiden.
- Maximal die einbindende Wikitext-Seite, in der Regel also die Vorlage mit dem
#invoke
, lässt sich so ermitteln:frame:getParent():getTitle()
- Von der einbindenden Wikitext-Seite (Vorlage) aus ist keine Steigerung mehr im Sinne eines Aufruf-Stack möglich; die übergeordneten Aufrufe liefern
nil
zurück. - frame:preprocess()
- Expandieren eines komplexen Wikitexts.
- Vorlagen, Parserfunktionen und Parameter wie
{{{1}}}
werden ausgewertet. - Eine einzelne Vorlage sollte statt dessen mit frame:expandTemplate() expandiert werden.
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.
- frame:getArgument( argument )
- frame:getArgument{ name = argument }
- Lässt
argument
expandieren. - frame:newParserValue( text )
- frame:newParserValue{ text = text }
- Zugriff auf
frame:preprocess( text )
. - frame:newTemplateParserValue{ title = title, args = table }
- Benannte Argumente erforderlich.
- Zugriff auf
frame:expandTemplate()
mit den genannten Argumenten.
Substituierung
[Bearbeiten | Quelltext bearbeiten]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.
Mehrere Module
[Bearbeiten | Quelltext bearbeiten]Einbindung
[Bearbeiten | Quelltext bearbeiten]
Die Funktion require()
bindet ein anderes Modul ein.
- Parameter ist eine Zeichenkette mit dem Namen des Moduls.
- Der Namensraum
Modul:
ist voranzustellen.
- Der Namensraum
- Es ergeben sich folgende Werte:
- table oder string, wenn dies Rückgabewert war.
true
wenn der Seitenname sonst existiert und als Lua-Quellcode verwaltet wird.- Skriptfehler und Abbruch, wenn der Seitenname nicht existiert oder der Inhalt nicht als Lua-Quellcode gilt oder ein globaler Syntaxfehler in der Seite vorliegt (kein gültiger content).
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.
Weiterleitung
[Bearbeiten | Quelltext bearbeiten]Ein Modul kann aus einer einzigen Zeile bestehen
return require( "Modul:NeuerName" )
und wirkt dann wie eine Weiterleitung; etwa nach einer Umbenennung.
mw.loadData()
[Bearbeiten | Quelltext bearbeiten]Diese Funktion entspricht grundsätzlich dem require()
mit zwei Besonderheiten:
- Die Elemente des Rückgabewerts können nur Basis-Datentypen enthalten (vor allem Zeichenketten und Zahlen); nicht aber Funktionen.
- Die erfolgte Einbindung wird vorgemerkt, so dass mehrfache
#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.
Export für andere Module
[Bearbeiten | Quelltext bearbeiten]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:
- Sowohl Vorlagen als auch Module werden durch jeweils angepasste Funktionen gleicher Zielsetzung unterstützt.
- Es bietet sich an, die Funktionen mit gleichem Namen in beiden Zugriffsarten anzubieten.
- Die generische Funktion ist dann die Version für Lua-Aufruf.
- Die Variante für die Vorlagenprogrammierung setzt nur noch die Eingabeparameter um, ruft die generische Funktion auf und stellt das für Vorlagen geeignete Resultat sicher.
- Bei der Vorlagenprogrammierung sind ausschließlich Zeichenketten als Parameter möglich, während die generische Funktion auch andere Typen wie numerische Werte oder table zulässt. Die beim
#invoke
beigegebenen Parameterwerte sind dann entsprechend zu interpretieren (parsen).
- Beispiel: siehe unten
- Es bietet sich an, die Funktionen mit gleichem Namen in beiden Zugriffsarten anzubieten.
- Es werden ausschließlich Funktionen für Lua-Module angeboten; die Aufgabenstellung passt nicht zu Vorlagen.
- Beispiele:
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.
Einfaches Modul für Vorlagen
[Bearbeiten | Quelltext bearbeiten]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}}
(ergibtHallo, Welt! Dies ist Lua!
)
oder
{{#invoke:Hello|hello|hier bin ich}}
(ergibtHallo, hier bin ich! Dies ist Lua!
)
Strukturierung eines komplexeren Moduls
[Bearbeiten | Quelltext bearbeiten]Ein Modul mit zwei oder drei Funktionen nur für Vorlagen ist eher trivial.
Bei komplexeren Aufgaben ist etwas Strukturierung und Übersicht erforderlich.
- An Beginn sollte auch ein Datum vermerkt sein.
- Weil Versionen des Quellcodes nicht ausschließlich über die produktive Seite generiert werden, ist die normale Versionsgeschichte einer Seite nicht hinreichend für die Verfolgung der Varianten. Vielmehr werden Versionen auch aus einem Testwiki oder von einer gesonderten Erprobungsseite oder aus einem fremden Wiki-Projekt mit der Mutterversion einkopiert; und wieder dorthin zurück.
- Es empfiehlt sich eine Ultrakurzbeschreibung der Funktionalität.
- Am Schluss stehen die Funktionen, die für den Export bestimmt sind.
p
ist der Rückgabewert des gesamten Moduls. Dieser Name hat sich eingebürgert, und er stellt eine table dar.
Funktionen nur für Vorlagen, sowie innere Hilfsfunktionen
[Bearbeiten | Quelltext bearbeiten]--[=[ 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.
Funktionen für Vorlagen und zusätzlich Lua-Zugriff
[Bearbeiten | Quelltext bearbeiten]--[=[ 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()
.
- Die Funktion
DiesesBeispiel.service()
steht danach auch anderen Modulen zur Verfügung. - Die eigentliche Implementierung der Funktionalität erfolgt in
DiesesBeispiel.service()
und die Funktionservice
für Vorlagen ruft diese Implementierung auf. Dabei sind die Parameter der Vorlageneinbindung (Zeichenketten inframe.args
) geeignet zu interpretieren und ihr Typ ggf. geeignet zu konvertieren. Während der Rückgabewert vonDiesesBeispiel.service()
auchfalse
odernil
sein mag, wird durchor ""
die für Vorlagen geeignetere leere Zeichenkette zurückgegeben.
Funktionen ausschließlich für Lua-Zugriff, nicht für Vorlagen
[Bearbeiten | Quelltext bearbeiten]--[=[ 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.
Elternumgebung
[Bearbeiten | Quelltext bearbeiten]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.
- Verschiedene Einbindungen der Vorlage selbst (z. B. in einem Artikel) werden dagegen parallel abgearbeitet und teilen auch keine Elternumgebung.
math.random()
[Bearbeiten | Quelltext bearbeiten]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.
Modul für eine bestimmte Vorlage
[Bearbeiten | Quelltext bearbeiten]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.
Grundprinzip vorlagenspezifisher Module
- Das Modul erhält den Namen
Modul:Vorlage:
Vorlagen-Titel
- Damit ist die Zuordnung leicht nachzuvollziehen.
- Die Arbeit der Vorlage wird ausschließlich durch das Modul vorgenommen.
- Die Vorlage enthält in der Regel nur eine einzige Zeile:
{{#invoke:Vorlage:
Vorlagen-Titel|f}}<noinclude>{{Dokumentation}}</noinclude>
- Die Vorlage enthält in der Regel nur eine einzige Zeile:
- Die Funktion
f
(oder nach Belieben anders genannt) ist die einzige für Vorlagen verfügbare Schnittstelle. - Parameter der Vorlageneinbindung müssen nicht weitergereicht werden; sie können besser und vollständiger innerhalb des Moduls ermittelt werden.
- Innerhalb eines Wiki-Projektes sind keine anderen Parameter erforderlich; Sonderfälle wären Mehrere Vorlagen oder Internationalisierung.
Muster für eine Einzelvorlage
--[=[ 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
Vorlagen-Schnittstelle
[Bearbeiten | Quelltext bearbeiten]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.
Test-Schnittstelle
[Bearbeiten | Quelltext bearbeiten]- Für automatisierte Tests können von einem entsprechenden Lua-Modul aus eine größere Serie von Parameter-Sätzen vorgegeben und mit den erwarteten Ergebnissen verglichen werden.
- Die Parameter-Sätze werden in gleicher Weise formatiert, wie sie bei der Vorlageneinbindung benutzt würden.
- Die Haupt-Funktion wird genau analog aufgerufen.
Haupt-Funktion
[Bearbeiten | Quelltext bearbeiten]- Die Funktion
main()
(oder nach Belieben anders genannt) ist die eigentliche Arbeitsfunktion. - Sie erhält alle Parameterzuweisungen als
a
, egal ob diese aus#invoke
oder der Simulation stammen. - Der Rückgabewert ist die für Vorlagen passende Zeichenkette; und dies identisch für die Vorlageneinbindung und die Simulation, damit die Ergebnisse vergleichbar sind.
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.- Die lokale Funktion
main()
muss als letzte aller lokalen Funktionen vereinbart sein.
Geschützte Ausführung
[Bearbeiten | Quelltext bearbeiten]Der Aufruf der Haupt-Funktion wird jeweils in pcall()
geschützt.
- Kommt es nun zu einem Laufzeitfehler, oder wird durch das eigene Modul mittels
assert()
odererror()
ein Fehler ausgelöst, dann istr
die Fehlermeldung. - Damit wird das notorisch unspezifische „Skriptfehler“ vermieden.
Mehrere Vorlagen
[Bearbeiten | Quelltext bearbeiten]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.
Programmierung
[Bearbeiten | Quelltext bearbeiten]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:
- Modul im Wiki – Integration des Lua-Codes in den Wiki-Kontext
- frame-Objekt – Schnittstelle zur Vorlagenprogrammierung
- Modul für eine bestimmte Vorlage – Einzelne Vorlage unterstützen
- Zeichenketten – String-Funktionen, Pattern (regulärer Ausdruck) und Text-Elemente
- mw – Objekt
mw
und Hilfsbibliotheken - Links
- Umgebung – aktueller Wiki-Server und seine Ausstattung
- Internationalisierung
- Tutorial
Bibliotheken
[Bearbeiten | Quelltext bearbeiten]- Bestandteil der Sprache Lua sind einige Standardbibliotheken. Soweit sie im Kontext der Wiki-Seiten sinnvoll sind, werden sie unterstützt.
- Außerdem bieten Scribunto als Objekt
mw
(für MediaWiki) einige Wiki-spezifische Bibliotheken an, die auch gut mit der sonstigen Architektur eines Wiki-Servers kooperieren.
- Lua-Basissprache
- debug
- debug.traceback
- math – Mathematische Funktionen → Scribunto
- os
- package – Laden von Modulen → Scribunto
- string – Zeichenketten
- table → Scribunto
- mw (für „MediaWiki“) – Scribunto-Bibliotheken
-
mw.addWarning()
- mw.allToString()
- mw.clone()
- mw.getCurrentFrame()
- mw.incrementExpensiveFunctionCount()
- mw.isSubsting()
- mw.loadData()
- mw.log()
- mw.logObject()
- frame-Objekt – Schnittstelle zur Vorlagenprogrammierung
- mw.html – HTML-Element
- mw.language – Formatieren in der aktuellen menschlichen Sprache
- mw.message – Systemnachrichten
- mw.site – aktuelles Wiki-Projekt
- mw.text – Zeichenketten
- mw.title – Wiki-Seiten
- mw.uri – URL
- mw.ustring – Zeichenketten in Unicode
- mw.wikibase → mw:Extension:Wikibase Client/Lua
- Ladbare Bibliotheken
-
- Eher seltener erforderlich → Scribunto
- bit32
- libraryUtil
- luabit
- ustring
Fehlermeldungen
[Bearbeiten | Quelltext bearbeiten]Es gibt vier Ursachen für Skriptfehler:
- Syntaxfehler
- Programmierfehler zur Einbindung
- Fehlende Seite
- Anwenderfehler bei Einbindung
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.
Syntaxfehler
[Bearbeiten | Quelltext bearbeiten]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.
Programmierfehler zur Einbindung
[Bearbeiten | Quelltext bearbeiten]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.
Fehlende Seite
[Bearbeiten | Quelltext bearbeiten]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.
Anwenderfehler bei Einbindung
[Bearbeiten | Quelltext bearbeiten]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.
- Alle Eingabewerte sind als möglicherweise fehlend oder syntaktisch falsch anzusehen, bis das Gegenteil festgestellt wurde.
- Allerdings sind vorhandene Parameter im
#invoke
wenigstens immer vom Typ string.
Hilfsfunktionen
[Bearbeiten | Quelltext bearbeiten]- pcall()
- Absturzsicheres Ausführen einer Funktion
fun
mit Parameterlisteargs
. e, v = pcall( fun, args )
- Dabei ist
e
im Fehlerfallfalse
undv
die Fehlermeldung. - Wenn kein Problem auftrat, hat
e
den Werttrue
undv
nebst allen folgenden Variablen sind die üblichen Rückgabewerte vonfun
. pcall
steht für protected call.- Das entspricht einem catch.
- assert()
assert( v, message, ... )
- Löse einen Skript-Abbruch mit einer qualifizierten Fehlermeldung aus, wenn eine Bedingung nicht eingehalten wird.
- Entspricht in etwa der von
error()
, jedoch nur, wenn die Bedingung v nicht erfüllt ist (alsonil
oderfalse
ist). - Als
message
sollte eine spezifische Fehlermeldung mitgegeben werden; es wäre sonst ein lapidares assertion failed! – zumindest wird aber immer die Zeilennummer desassert
in der Meldung gezeigt, nebst dem Namen des Moduls. - Wenn v weder
nil
nochfalse
ist, werden alle Argumente einschließlich v und message zurückgegeben. - Der Aufruf ist nur innerhalb einer durch
pcall()
geschützten Umgebung sinnvoll; ansonsten wird bloß ein allgemeiner „Skriptfehler“ ohne nähere Einzelheiten ausgelöst. - Sinn der Angelegenheit ist, in einer tieferen Ebene der Funktions-Hierarchie für v eine Funktion anzugeben, die die Gültigkeit der ihr übergebenen Werte prüft. Beim Versagen wird direkt in die Ebene mit
pcall()
gesprungen; etwa die Schnittstelle zum#invoke
. Damit erspart man sich das Durchreichen von besonderen Rückgabewerten von Funktion zu Funktion. - Die Funktion entspricht einem throw.
- error()
- Diese Funktion soll einen Skript-Abbruch mit einer qualifizierten Fehlermeldung ermöglichen.
error( message, level )
- Der Aufruf ist nur innerhalb einer durch
pcall()
geschützten Umgebung sinnvoll; ansonsten wird bloß ein allgemeiner „Skriptfehler“ ohne nähere Einzelheiten ausgelöst. - Innerhalb der von
pcall()
ausgehenden Funktionsfolge wird die Fehlermeldungmessage
zurückgegeben. - Der optionale Parameter
level
ist in der Original-Sprache Lua eine Aufruf-Folge oder stack, dessen anzuzeigende Tiefe vorgegeben werden kann.- Zurzeit werden in Scribunto nur der Name des Moduls und die Zeilennummer angezeigt, und dies nur auf einer Ebene. Das ist möglicherweise eine noch unvollendete Situation. Der Aufbau von Wiki-Seiten und die sonstige Handhabung der Lua-Dateien unterscheiden sich etwas. Es hängt offenbar damit zusammen, dass in Scribunto
allowEnvFuncs
nicht zugelassen wird. - Wird
level
nicht angegeben oder ist Null oder zu groß, so wird keine Information zum Ort gezeigt. - Es empfiehlt sich momentan,
level
immer mit1
oder gar nicht anzugeben.
- Zurzeit werden in Scribunto nur der Name des Moduls und die Zeilennummer angezeigt, und dies nur auf einer Ebene. Das ist möglicherweise eine noch unvollendete Situation. Der Aufbau von Wiki-Seiten und die sonstige Handhabung der Lua-Dateien unterscheiden sich etwas. Es hängt offenbar damit zusammen, dass in Scribunto
- Die Grundidee ähnelt der von
assert()
. - Die Funktion entspricht einem throw.
- LuaWiki.*
- Aufrufe der Wiki-Umgebung.
- Diese Funktionen analysieren die übergebenen Parameter und sorgen für eine präzise Fehlermeldung.
Leere Werte
[Bearbeiten | Quelltext bearbeiten]Anders als bei anderen Programmiersprachen gilt:
- Sowohl die Zahl
0
wie auch die leere Zeichenkette""
sind „etwas“. - Nur
nil
undfalse
sind „nichts“. - Eine leere table
{}
ist gleichbedeutend mitnil
.
Das ist vor allem für if
-Abfragen wichtig.
Table und Objekt
[Bearbeiten | Quelltext bearbeiten]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.
or: Von links nach rechts
[Bearbeiten | Quelltext bearbeiten]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.
Reihenfolge lokaler Funktionen
[Bearbeiten | Quelltext bearbeiten]Die Reihenfolge lokaler Funktionen ist signifikant. Eine lokale Funktion muss in der physischen Abfolge der Definitionen definiert gewesen sein, bevor sie verwendet werden darf.
Zählschleife
[Bearbeiten | Quelltext bearbeiten]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.
Zeichenketten-Parameter trimmen
[Bearbeiten | Quelltext bearbeiten]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 )
Benutzerdefinierte Objekte
[Bearbeiten | Quelltext bearbeiten]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:
- Zugriff auf Element, neues Element, Vereinigung, Länge, Vergleich, arithmetische Operationen.
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.
Fehlermeldungen im Kopf der Seitenvorschau
[Bearbeiten | Quelltext bearbeiten]Mittels der Funktion mw.addWarning( wikitext )
können im Kopfbereich der Seitenvorschau Warnungen angezeigt werden.
wikitext
wird dabei noch geparset.- Mehrfache identische Meldungen werden nur einmal gezeigt.
- Problem: Zunächst besteht kein Zusammenhang zwischen der Warnmeldung im Seitenkopf und der aufrufenden Stelle in der Seite, wo das Problem auftritt. Bei sehr langen Seiten – und wenn dann auch noch keine Fehlermeldung in der Seitenvorschau sichtbar ist – wird die Meldung sinnfrei, weil die Autoren sie nicht der Ursache zuordnen können.
- Mit dem Zufallszahlengenerator math.random() ließe sich ein temporärer Fragmentbezeichner wie
error-54381975
generieren, der im Seitenkopf verlinkt und an der Einbindung verankert wird. - Die unterschiedlichen Einbindungen in der Seite haben keine Kenntnis voneinander.
mw-Objekt
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.
Alle Komponenten
[Bearbeiten | Quelltext bearbeiten]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/Lua
mw.ext
[Bearbeiten | Quelltext bearbeiten]mw.ext.data
[Bearbeiten | Quelltext bearbeiten]Komplexe Daten aus zentraler Struktur auslesen.
- Werden für alle Wikis auf Commons im Namensraum
Data:
bereitgestellt. - Im Gegensatz zu den Daten in Form eines Semantic Web / Graphen auf Wikidata können hiermit tabellarische Daten und Kartendaten abgelegt werden.
- Jedes Datenobjekt trägt eine Lizenzerklärung.
- Der Quelltext ist in JSON notiert.
- Mehr: mw:Help:Tabular Data, auch mw:Help:Map Data
- mw.ext.data.get( s, lang )
-
s
– Seitentitel incommons:Data:
- Endet auf
.tab
- Endet auf
lang
– (optional) Sprachcode- Vorgabe: eigene Projektsprache
"_"
– Rohdaten- Lizenzinformationen werden sprachlich konvertiert.
- Gibt table zurück, sonst
nil
.- table
.data
sind die lokalisierten Nutzdaten. - Vermutlich mit schreibschützender metatable.
- table
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.html
[Bearbeiten | Quelltext bearbeiten]Diese 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
- mw.html.create( name, args )
-
- name – Name des gewünschten Elements; etwa
div
.- name kann auch eine leere Zeichenkette sein; dann wird ein leeres Objekt zurückgegeben.
- args – optionale table mit folgenden Feldern:
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)
- name – Name des gewünschten Elements; etwa
html-Objekt
[Bearbeiten | Quelltext bearbeiten]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.
- el:addClass( access )
- Fügt einen Klassennamen zum Attribut
class
des Objekts hinzu.- access – Zeichenkette mit zusätzlichem Klassen-Bezeichner
- el:allDone( )
- Ermittelt den obersten Elternknoten, unter den dieses html-Objekt eingefügt ist.
- Wie
html:done()
, aber versucht jeweils noch zum nächsthöheren Elternknoten zu gelangen. - el:attr( name, value )
- el:attr( table )
- HTML-Attribut zuweisen.
- name – Zeichenkette mit dem Namen des Attributs (Zahl ist formal zugelassen, wäre aber ungültiges HTML)
- value – Zeichenkette oder Zahl mit dem Wert des Attributs
- table – Tabelle mit Zuweisungen name→value
- el:css( property, value )
- el:css( table )
- Fügt eine oder mehrere Stildefinitionen zum Attribut
style
des Objekts hinzu.- property – Zeichenkette mit dem Namen der Eigenschaft
- value – Zeichenkette oder Zahl mit dem Wert der Eigenschaft
- table – Tabelle mit Zuweisungen property→value
- el:cssText( string )
- Füge formatierte Stildefinitionen zum Attribut
style
des Objekts hinzu.- string – Zeichenkette mit Definitionen
- el:done( )
- Ermittelt den unmittelbaren Elternknoten, unter den dieses html-Objekt eingefügt ist.
- Wenn kein Elternknoten vorhanden ist, wird dieses html-Objekt selbst zurückgegeben.
- Wie bei
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. - el:getAttr( attr )
- Frage einen Attributwert ab.
- attr – Zeichenkette mit dem Namen des Attributs
- Der Rückgabewert ist der Attributwert; in der Regel eine Zeichenkette.
- el:newline()
- Zeilenumbruch-Zeichen
\n
an die Definition anhängen. - el:node( builder )
- Kind-Knoten an das Objekt anbinden.
- builder – Zeichenkette oder anderes html-Objekt
- Voraussetzung: Es darf sich beim aktuellen Objekt nicht um ein zwingendes unary Element handeln.
- el:tag( art, args )
- An das aktuelle Objekt wird ein neu gebildetes html-Objekt angehängt.
- Die Parameter entsprechen denen von mw.html.create().
- Der Rückgabewert ist das neu gebildete html-Objekt.
- el:wikitext( … )
- Anhängen einer beliebigen Anzahl von Kind-Knoten.
...
– Aufzählung von Zeichenketten oder Zahlen (unbestimmte Argumentanzahl)
Beispiel für ein HTML-Element
[Bearbeiten | Quelltext bearbeiten]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>
Weblinks und Wikilinks
[Bearbeiten | Quelltext bearbeiten]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.title
[Bearbeiten | Quelltext bearbeiten]Das 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.
Bibliotheksfunktionen und Konstruktoren
[Bearbeiten | Quelltext bearbeiten]- mw.title.getCurrentTitle()
- title-Objekt für die aktuelle (oberste) Seite.
- mw.title.makeTitle( namespace, title, fragment, interwiki )
- title-Objekt für die spezifizierte Seite.
- namespace kann alles sein, was unter
mw.site.namespaces
möglich ist.[2] - title ist natürlich eine Pflichtangabe.
- Ein nachgestelltes Fragment und eine Interwiki-Präfix-Gruppe (Sprache, Projekt) sind optional.
- Diese Funktion ist „teuer“.[3]
- mw.title.new( text, namespace )
- mw.title.new( id )
- Erschafft ein neues title-Objekt.
- Wenn das erste Argument vom Typ number ist und somit für die id entsprechend
curid
generiert wird, ist der Rückgabewertnil
, wenn eine solche Seite nicht existiert. - Ein Seitenname text muss erlaubt sein; darf insbesondere kein Prozent-Encoding enthalten.
- Diese Funktion ist „teuer“,[3] sofern es sich nicht um die aktuelle Seite im Sinne von
.getCurrentTitle()
handelt und diese Seite auch nicht bereits geladen wurde. - Wenn das erste Argument vom Typ string ist und somit ein text übergeben wurde, wird bei gültigem Wert selbst dann ein Objekt zurückgegeben, wenn diese Seite nicht existiert.
- Wenn im text kein Namensraum enthalten ist, wird namespace benutzt. namespace kann alles sein, was unter
mw.site.namespaces
möglich ist.[2] - Wenn text kein syntaktisch gültiger Seitenname ist, ist der Rückgabewert
nil
.
- Wenn im text kein Namensraum enthalten ist, wird namespace benutzt. namespace kann alles sein, was unter
- mw.title.equals( a, b )
true
– wenn beide title-Objekte die gleiche Seite darstellen.- Fragmente werden beim Vergleich ignoriert.
- mw.title.compare( a, b )
- Rückgabewerte sind
-1
,0
, oder1
, 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.
title-Objekt
[Bearbeiten | Quelltext bearbeiten]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
.
Eigenschaften
[Bearbeiten | Quelltext bearbeiten]Die meisten Eigenschaften lassen sich nur lesen, falls nicht anders angegeben (fragment).
- .id
curid
oder0
, wenn die Seite nicht existiert.- .interwiki
- Interwiki-Präfix-Gruppe (Sprache, Projekt), oder
""
. - .namespace
- Namensraum-Nummer.
- .fragment
- Das fragment, oder
""
. - Kann gesetzt werden.
- .nsText
- Der kanonische Name des Namensraums
- .subjectNsText
- Namensraum-Name der Inhaltsseite (Gegenstück zur Diskussionsseite)
- .talkNsText
- Namensraum-Name der Diskussionsseite (Gegenstück zur Inhaltsseite)
- .text
- Seitentitel, ohne Namensraum und Interwiki-Präfix
- .prefixedText
- Seitentitel, mit Namensraum und Interwiki-Präfix
- .fullText
- Seitentitel, mit Namensraum und Interwiki-Präfix und Fragment.
- .rootText
- Auf einer Unterseite der Titel der obersten Basis-Seite;
.text
ansonsten. - .baseText
- Auf einer Unterseite der Titel der unmittelbar übergeordneten Basis-Seite;
.text
ansonsten. - .subpageText
- Auf einer Unterseite der Titel des letzten Namens-Elementes;
.text
ansonsten. - .canTalk
true
wenn diese Seite eine Diskussionsseite haben kann (NR≥0).- .exists
true
– wenn diese Seite existiert.- Bei Dateien und
Media:
ist dies ein Alias für.file.exists
und wird entsprechend bewertet. - Ansonsten geht dies nicht erneut in die Zählung „teurer“[3] Funktionen ein.
- Bei Bildung durch
.getCurrentTitle()
existiert die Seite immer (es sei denn, sie würde soeben erst mit dem Speichern erstellt); beimw.title.makeTitle()
wird dies erst ermittelt. - .file
- table, falls in den Namensräumen der Mediendateien, sonst
false
.- Dies ist doppelt teuer,[3] weil auch auf Commons nachgefragt werden könnte.
- Komponenten:
.exists
- Wenn nicht existent, sind alle weiteren Komponenten
nil
.
- Wenn nicht existent, sind alle weiteren Komponenten
.height
- Höhe in Pixeln; falls paged media, dann der ersten Seite.
.mimeType
.pages
- table, falls paged media; darin eine table pro Seite, mit Höhe und Breite.
.size
- Größe in Bytes.
.width
- Breite in Pixeln; falls paged media, dann der ersten Seite.
- .fileExists
. Obsolet; jetzt .file.exists
.getFileInfo()- abgelöst durch
.file
- .isContentPage
true
– wenn es ein Inhalts-Namensraum ist.- .isExternal
true
– wenn es einen Interwiki-Präfix gibt.- .isLocal
true
– wenn es ein Projekt gleicher Art ist.- Für die deutschsprachige Wikipedia ist jede Wikipedia „lokal“, Wiktionary und Meta sind es nicht.
- Mit einem lokalen Projekt kann über Interlanguage verbunden werden.
- .isRedirect
true
– wenn diese Seite als Weiterleitung gespeichert ist.- .isSpecialPage
true
– wenn diese Seite eine Spezialseite sein kann (wenn sie im NamensraumSpezial:
liegt und es ein gültiger Alias ist)- .isSubpage
true
– wenn dies eine Unterseite einer anderen ist.- .isTalkPage
true
– wenn dies eine Diskussionsseite ist.- .categories
- sequence table mit Kategorietiteln
- .content
- Zeichenkette mit dem unveränderten Quelltext (Wikitext oder andere Ressource) des title-Objekts; bzw.
nil
, wenn die Seite nicht existiert. - .contentModel
- „Content Model“ für diese Seite, als Zeichenkette:
css
,javascript
,Scribunto
(Modul),wikitext
. - .protectionLevels
mRestrictions
sequence table- .pageLang
- mw.language-Objekt zur Seiteninhaltssprache.
- In mehrsprachigen Wikis können bestimmten Seiten eigene Sprachen zugewiesen sein; ansonsten ist für alle Seiten deren Sprache zunächst gleich der Projektsprache.
- Bei Seiten, deren „Content Model“ nicht
wikitext
ist, also insbesondere Programmiersprachen, ist meisten
die Seitensprache. Dadurch wird ggf. lateinische Schrift von links nach rechts die Vorgabe. - .basePageTitle
- Wirkungsgleich zu mw.title.makeTitle( title.namespace, title.baseText )
- .rootPageTitle
- Wirkungsgleich zu mw.title.makeTitle( title.namespace, title.rootText )
- .talkPageTitle
- Wirkungsgleich zu mw.title.makeTitle( mw.site.namespaces[title.namespace].talk.id, title.text )
nil
wenn es zu diesem title keine Diskussionsseite geben kann.- .subjectPageTitle
- Wirkungsgleich zu mw.title.makeTitle( mw.site.namespaces[title.namespace].subject.id, title.text )
Methoden (Funktionen)
[Bearbeiten | Quelltext bearbeiten]- :isSubpageOf( title )
- Parameter: title, ein title-Objekt
- Rückgabe:
true
– wenn das aktuelle Objekt eine Unterseite von title ist. - :inNamespace( namespace )
- Parameter: namespace. namespace kann alles sein, was unter
mw.site.namespaces
möglich ist.[2] - Rückgabe:
true
– wenn das aktuelle Objekt im angegebenen Namensraum liegt. - :inNamespaces( ns1, ns2, … )
- Parameter: mehrere Namensräume
- Rückgabe:
true
– wenn das aktuelle Objekt in einem der angegebenen Namensräume liegt. - :hasSubjectNamespace( namespace )
- Parameter: namespace. namespace kann alles sein, was unter
mw.site.namespaces
möglich ist.[2] - Rückgabe:
true
– wenn diese Seite selbst oder ihre Diskussionsseite im Inhalts-Namensraum namespace liegt. - :subPageTitle(text)
- Wirkungsgleich zu mw.title.makeTitle( title.namespace, title.text .. "/" .. text )
- :partialUrl()
- Parameter: keine
- Rückgabe: Die Eigenschaft .text mit dem URL-Encoding wie in einer URL.
- :localUrl( query )
- Parameter: Die optionale query wie .fullUrl()
- Rückgabe: URL des Objekts relativ zur Projekt-Domain
- :fullUrl( query, proto )
- Rückgabe: Volle URL zum aktuellen Objekt.
- Parameter: Die optionale query gibt weitere URL-Parameter an und kann ein table
k=v
sein oder eine Zeichenkette. - proto kann einen der folgenden Werte annehmen:
"relative"
(Vorgabe des optionalen Wertes)"http"
"https"
"canonical"
- :canonicalUrl( query )
- Parameter: Die optionale query wie .fullUrl()
- Rückgabe: Kanonische URL des Objekts (standardisiertes Format mit Protokoll)
- :getContent()
- Parameter: keine
- Rückgabe: Zeichenkette mit dem unveränderten Quelltext; veraltet, seit Herbst 2024 .content
mw.uri
[Bearbeiten | Quelltext bearbeiten]Diese 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.
- mw.uri.encode( s, enctype )
- Encoding der Zeichenkette s (Prozent).
- Der optionale enctype (Vorgabe:
"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)
- mw.uri.decode( s, enctype )
- Prozent-Dekodierung von s
- Der optionale enctype (Vorgabe:
"QUERY"
) kann folgende Werte haben:"QUERY"
– ersetze+
durch Leerzeichen"PATH"
– Keine besondere Behandlung potentieller Leerzeichen."WIKI"
– ersetze_
durch Leerzeichen
- mw.uri.anchorEncode( s )
- Encoding von s, so dass dieser als Fragment in einer Wiki-URL benutzt werden kann (Punkt statt Prozent).
- mw.uri.buildQueryString( table )
- Wandle den Inhalt einer table in eine Folge von Zuweisungen k=v und verkette durch
&
zu einer Zeichenkette. - Die k in table sollen Zeichenketten sein.
- Die v in table können sein: string, number, sequence table für mehrfaches Auftreten,
false
für „leer“. - mw.uri.parseQueryString( s )
- Wandle eine Zeichenkette s um in eine table und löse die
&
k=v in Elemente der table.- Leere Zuweisungen
&
k= erhalten den Wertfalse
. - Wiederholte Zuweisungen mit gleichem k werden als sequence table abgelegt.
- Alle anderen v werden Zeichenketten.
- Leere Zuweisungen
- mw.uri.localUrl( page, query )
- uri-Objekt für die lokale URL (bezogen auf die Domain) einer Wiki-Seite page oder einfache Zeichenkette.
- Optional mit query als fertige Zeichenkette oder table mit Spezifikationen k=v.
- mw.uri.fullUrl( page, query )
- uri-Objekt für die vollständige URL (aber ohne Protokoll) einer Wiki-Seite page oder einfache Zeichenkette.
- Optional mit query als fertige Zeichenkette oder table mit Spezifikationen k=v.
- mw.uri.canonicalUrl( page, query )
- uri-Objekt für die kanonische URL (mit aktuellem Protokoll) einer Wiki-Seite page oder einfache Zeichenkette.
- Optional mit query als fertige Zeichenkette oder table mit Spezifikationen k=v.
- mw.uri.new( s )
- mw.uri.new( table )
- uri-Objekt bilden durch Parsen einer Zeichenkette s oder Befüllen der Felder in table.
- mw.uri.validate( s )
- mw.uri.validate( table )
- Überprüfe die Verwendbarkeit einer Zeichenkette s oder der Felder in table für
mw.uri.new()
. - boolean für Verwendbarkeit, Zeichenkette mit Fehlermeldung sonst.
uri-Objekt
[Bearbeiten | Quelltext bearbeiten]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:
- .protocol
- (string) protocol/scheme
- .user
- (string) user
- .password
- (string) password
- .host
- (string) host name
- .port
- (number) port
- .path
- (string) path
- .query
- (table) wie aus
mw.uri.parseQueryString
- .fragment
- (string) fragment.
Außerdem sind die nachstehenden Eigenschaften vorhanden:
- .userInfo
- (string) user and password
- .hostPort
- (string) host and port
- .authority
- (string) user, password, host, and port
- .queryString
- (string) version of the query table
- .relativePath
- (string) path, query string, and fragment
tostring()
ergibt den (kanonischen) Text der URI.
An Methoden sind vorhanden:
- :parse( s )
- Werte aus der Zeichenkette s in das Objekt einfügen.
- Bestehende Werte, die nicht in s vorkommen, bleiben erhalten.
- :clone()
- Kopie des Objekts
- :extend( parameters )
- parameters ist eine table, deren Wertzuweisungen den bestehenden in der Query-Komponente hinzugefügt werden oder sie überschreiben.
Anwendungsbeispiel
[Bearbeiten | Quelltext bearbeiten]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
- ↑ Gerrit:58897
- ↑ a b c d
Namensraum-Nummer
.id
oder einer der Namen; zurzeit aber nicht die table selbst. - ↑ a b c d Maximal 500 Abfragen pro Gesamt-Seite.
Umgebung
[Bearbeiten | Quelltext bearbeiten]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-Zugriffe
Siehe dazu auch Hilfe:Lua/Internationalisierung.
mw.site
[Bearbeiten | Quelltext bearbeiten]Abfrage allgemeiner Informationen über das Wiki-Projekt und einige statistische Angaben.
- mw.site.currentVersion
- Aktuelle Version von MediaWiki:
1.43.0-wmf.20 (ef87455)
– {{CURRENTVERSION}} - mw.site.scriptPath
- Pfad zum Server-Skript:
/w
– {{SCRIPTPATH}} - mw.site.server
- Domain des Servers:
//de.wikipedia.org
– {{SERVER}} - mw.site.siteName
- Art des Servers:
Wikipedia
– {{SITENAME}} - mw.site.stylePath
- Pfad zu den Server-Stilen:
/w/skins
– {{STYLEPATH}} - mw.site.namespaces
- Angaben zu allen Namensräumen.
- table mit einem Eintrag pro Namensraum. Jedes Element hat die unten beschriebenen Eigenschaften.
- Der Zugriff kann über die Nummer oder irgendeinen Alias erfolgen.
mw.site.namespaces.module.name
istModul
mw.site.namespaces[12].name
istHilfe
mw.site.namespaces.wp.id
ist4
- mw.site.contentNamespaces
- table wie mw.site.namespaces, aber nur Inhaltsnamensräume.
- mw.site.subjectNamespaces
- table wie mw.site.namespaces, aber nur „Vorderseiten“.
- mw.site.talkNamespaces
- table wie mw.site.namespaces, aber nur Diskussionsnamensräume.
- mw.site.interwikiMap( select )
- Interwiki-Tabelle.
- select == "!local" nur nicht-lokale Interwikis. Für die deutschsprachige Wikipedia sind „lokale“ Ziele alle anderen Wikipedien, nicht aber Wikisource.
- mw.site.stats
- Statistische Angaben; alle Details vom Typ number.
- table mit Elementen:
- .pages
- .articles
- .files
- .edits
- .views
- .users
- .activeUsers
- .admins
- mw.site.stats.pagesInCategory( category, which )
- Statistik der Kategorie mit dem Titel category.
- Wenn optionales which fehlt,
nil
oder"*"
ist, wird eine table mit den folgenden Elementen zurückgegeben; ansonsten das Schlüsselwort erwartet.all
– Gesamtzahl der Seiten, Dateien und Unterkategorien.pages
files
subcats
- Diese Funktion ist „teuer“.[1]
- mw.site.stats.pagesInNamespace( nsn )
- nsn ist die Nummer.
- mw.site.stats.usersInGroup( group )
- Anzahl der Benutzer in Gruppe group.
Namensraum-Element
[Bearbeiten | Quelltext bearbeiten]- Jedes Namensraum-Element hat folgende Eigenschaften:
- .id
- number – Nummer des Namensraums.
- .name
- string – Lokaler Name des Namensraums; etwa
Benutzer
. - .canonicalName
- string – Kanonischer Name des Namensraums; etwa
Project
stattWikipedia
. - .displayName
- string – Ersatz-Name für den Haupt-Namensraum, der meist leer wäre:
(Artikel)
oder(Seiten)
oder(gallery)
nil
– in jedem Namensraum, dessen Name nicht leer ist.- .hasSubpages
true
– wenn Unterseiten für diesen Namensraum aktiviert sind.- .hasGenderDistinction
true
– wenn dieser Namensraum unterschiedliche Aliasse für die Geschlechter hat (Benutzer
undBenutzerin
).- .isCapitalized
true
– wenn der erste Buchstabe des Seitentitels immer groß geschrieben wird (abweichend im Wiktionary).- .isContent
true
– wenn es ein Inhaltsnamensraum ist (vereinfacht:[2] NR≥0)- .isIncludable
true
– wenn Seiten eingebunden werden können (vereinfacht:[2] NR≥0)- .isMovable
true
– wenn Seiten verschoben werden können (vereinfacht:[2] NR≥0)- .isSubject
true
– wenn es Inhaltsseiten, aber keine Diskussionsseiten sind (vereinfacht:[2] NR≥0 und gerade)- .isTalk
true
– wenn es ein Diskussionsnamensraum ist (vereinfacht:[2] NR>0 und ungerade)- .defaultContentModel
- string oder
nil
– Das content model für den Namensraum.- Meist wäre es ein string wie
wikitext
– im Modul-Namensraum jedochScribunto
und bei einzelnen Seiten etwacss
oderjavascript
.
- Meist wäre es ein string wie
- .aliases
- table mit einer sequence der Aliasse für den Namensraum.
- .subject
- Querverweis zum Element mit den „Vorderseiten“, wenn das Element einen Diskussionsnamensraum beschreibt; sonst das Element selbst, wenn Inhaltsnamensraum;
nil
, wenn keine Zuordnung definiert ist (NR<0[2]). - .talk
- Querverweis zum Element mit dem korrespondierenden Diskussionsnamensraum; sonst das Element selbst (nur Inhaltsnamensräume);
nil
, wenn keine Zuordnung definiert ist (NR<0[2]). - .associated
- Querverweis zum Element mit dem korrespondierenden Diskussionsnamensraum, wenn das Element „Vorderseiten“ beschreibt; zu den „Vorderseiten“, wenn das Element einen Diskussionsnamensraum beschreibt;
nil
, wenn keine Zuordnung definiert ist (NR<0[2]).- Als associated page bezeichnet man ansonsten die Verknüpfung zwischen Benutzername oder IP mit einer Benutzerseite; das ist hier nicht gemeint.
mw.language
[Bearbeiten | Quelltext bearbeiten]Schwerpunkt 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.language.fetchLanguageName( code, inLanguage )
- Name der Sprache, die durch code beschrieben wird.
- In der jeweils eigenen Sprache selbst („English“); bei optionalem Code inLanguage in dieser.
- Ist keine Übersetzung in inLanguage definiert, wird die momentane Projektsprache benutzt, sonst Englisch, sonst die Sprache selbst.
- Ist code unbekannt, dann ist der Rückgabewert code selbst.
- mw.language.fetchLanguageNames( inLanguage, include )
- Auflistung aller bekannten Sprachen
- In der jeweiligen eigenen Sprache; bei optionalem Code inLanguage in dieser.
- include (optional):
mw
(Vorgabe) – nur wenn die Sprache definiert in MediaWiki oderwgExtraLanguageNames
istall
– alle bekannten Sprachenmwfile
– nur wenn die Sprachemw
erfüllt und ein message file hat.
- Ergibt table mit Zuweisungen code→Name (die Codes sind in Kleinbuchstaben notiert).
- Ist für einzelne code keine Übersetzung definiert, wird analog zu fetchLanguageName() verfahren; ist inLanguage unbekannt, wird Englisch benutzt.
- mw.language.getContentLanguage()
- language-Objekt für Inhaltssprache des Projekts:
de
- mw.language.getFallbacksFor( code )
- Ergibt sequence table, zumindest mit
en
als letztem Element. - Beispiel:
"hsb"
→{ "dsb", "de", "en" }
- mw.language.isKnownLanguageTag( code )
true
– wenn code MediaWiki als IETF-Code bekannt ist.- mw.language.isSupportedLanguage( code )
true
– wenn für code in MediaWiki eine Lokalisierung vorhanden ist.- mw.language.isValidBuiltInCode( code )
true
– wenn code formal geeignet wäre, eine interne Sonder-Lokalisierung zu definieren. Dabei muss code zu keiner bekannten Sprache gehören.- mw.language.isValidCode( code )
true
– wenn code formal korrekt ist; unabhängig davon, ob dies existiert. Dabei muss code zu keiner bekannten Sprache gehören.- mw.language.new( code )
- Bilde ein neues language-Objekt für code.
language-Objekt
[Bearbeiten | Quelltext bearbeiten]Ein neues Objekt für eine Sprache code lässt sich bilden mit
local lang = mw.language.new( code )
tostring( lang )
ergibtlang.code
Anschließend sind verfügbar:
- lang.code
de
- lang:getCode()
- lang:isRTL()
- lang:lc( s )
- lang:lcfirst( s )
- lang:uc( s )
- lang:ucfirst( s )
- lang:caseFold( s )
- lang:formatNum( n )
- lang:parseFormattedNumber( s )
- lang:formatDate( format, timestamp, local )
- Kennt alle Formatierungsdetails; formatiert gemäß der bei Konstruktion von lang gültigen Sprache.
- lang:formatDuration( seconds, allowedIntervals )
- lang:getDurationIntervals( seconds, allowedIntervals )
- lang:getFallbackLanguages()
- lang:plural( n, singular, plural )
- lang:convertPlural( n, forms )
- lang:grammar( case, word )
- lang:convertGrammar( word, case )
- lang:gender( what, masculine, feminine, neutral )
- lang:gender( what, options )
- lang:getArrow( direction )
- Pfeil
→
- direction:
"forwards"
ergibt→
bzw.←
(Vorgabe)"backwards"
ergibt←
bzw.→
"left"
ergibt←
"right"
ergibt→
"up"
rgibt↑
"down"
rgibt↓
- lang:getDir()
ltr
- sonst
rtl
- lang:getDirMark( opposite )
- U+8206
- sonst U+8207
- lang:getDirMarkEntity( opposite )
‎
- sonst
‏
bzw. durchlang:getDirMarkEntity( true )
- lang:toBcp47Code()
mw.message
[Bearbeiten | Quelltext bearbeiten]Systemnachrichten aus dem translatewiki: oder dem MediaWiki-Namensraum.
- mw.message.new( key )
- Schaffe ein neues message-Objekt.
- key ist der Bezeichner der Systemnachricht.
- mw.message.newFallbackSequence( key, keyFallback1, keyFallback2, … )
- Wie mw.message.new( key ), aber mit Ersatzlösungen. Die erste existierende Nachricht wird verwendet.
- mw.message.newRawMessage( s, params, … )
- Schaffe ein neues, aber leeres message-Objekt basierend auf der Zeichenkette s statt einer Systemnachricht.
- Die optionalen params werden an msg.params() weitergegeben.
- mw.message.rawParam( value )
- mw.message.numParam( value )
- mw.message.getDefaultLanguage()
- language-Objekt für die Standard-Sprache.
- Im normalen Wiki identisch mit mw.language.getContentLanguage().
Einige Funktionen wurden im Februar 2014 entfernt (gerrit:110983).
message-Objekt
[Bearbeiten | Quelltext bearbeiten]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.
- msg:params( params )
- Weist Parameterwerte zu.
params
kann eine sequence table sein, oder es ist die Liste einzelner string-Argumente.- Gibt das message-Objekt selbst zurück.
- msg:rawParams( params )
- Gibt das message-Objekt selbst zurück.
- msg:numParams( params )
- Gibt das message-Objekt selbst zurück.
- msg:inLanguage( lang )
- Setzt Sprache über einen Sprachcode.
- Gibt das message-Objekt selbst zurück.
- msg:useDatabase( bool )
msg:title( title )
msg:parse()
- Generiere eine Zeichenkette in HTML-Code aus dem Objekt.
- Dies war kaum einmal sinnvoll, da
#invoke
Wikitext zurückgeben soll. - Diese Funktion ist „teuer“.[1]
msg:parseAsBlock()
- Wie .parse(), jedoch eingeschlossen in ein Block-Level-Tag (
<div>
). - Diese Funktion ist „teuer“.[1]
- msg:plain()
- Wertet die Systemnachricht aus; nach Einbettung aller Parameter.
- Gibt string zurück.
msg:text()
msg:escaped()
- msg:exists()
true
oderfalse
je nach Existenz der Systemnachricht.- msg:isBlank()
true
wenn der Bezeichner der Systemnachricht nicht existiert oder ihr Inhalt leer ist; sonstfalse
.- msg:isDisabled()
true
wenn der Bezeichner der Systemnachricht nicht existiert oder ihr Inhalt leer ist oder die Zeichenkette"-"
; sonstfalse
.
- → Scribunto (englisch)
Eine 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.
- os.clock()
- Ungefähre Anzahl der CPU-Sekunden, die das Programm verbrauchte.
- Dargestellte Genauigkeit/Diskretisierung: 10−9 Sekunden.
- os.date( format, time )
- Datum und Uhrzeit.
- Besser über lang:formatDate() zu erreichen und ortsüblich zu formatieren.
- os.difftime( t2, t1 )
- Anzahl der Sekunden von t1 bis t2.
- os.time( table )
- Uhrzeit auf dem Server als number in Sekunden.
- Bei optionaler table diese auswerten.
- ↑ a b c Sie wird dem expensiveCount hinzugezählt. Dieser ist auf 500 pro dargestellte Gesamt-Seite begrenzt.
- ↑ a b c d e f g h Gilt für übliche Inhalts-Wikis.
Zeichenketten
[Bearbeiten | Quelltext bearbeiten]Die nachfolgenden Abschnitte geben
für Lua-Programmierer eine Kurzreferenz zum Umgang mit Zeichenketten in der Lua-Programmierung.
ASCII und Unicode
[Bearbeiten | Quelltext bearbeiten]Die Wiki-Projekte sind in vollem Unicode geschrieben, Lua arbeitet jedoch nur mit 8-bit-Code (ISO 8859-1).
- Wenn das Suchmuster sich auf ASCII beschränkt, kann etwas effizienter mit den ASCII-Funktionen und entsprechenden Pattern gearbeitet werden, weil die Umwandlung von UTF-8 entfällt. Der 8-bit-Anteil jenseits von ASCII ist nicht sinnvoll nutzbar, weil hier die UTF-8-Kodierungen liegen.
- Allgemeine, beliebige Zeichenketten des Wikitextes müssen mit den
ustring
-Funktionen für Unicode verarbeitet werden.
String-Funktionen (Kurzreferenz)
[Bearbeiten | Quelltext bearbeiten]siehe Scribunto (englisch):
Angegeben sind jeweils die Funktionen für ASCII und Unicode; letztere mit mw.ustring.*()
.
Parameter
[Bearbeiten | Quelltext bearbeiten]Die Parameter bedeuten:
- s – Ausgangs-Zeichenkette
- !!! Datentyp string sicherstellen !!!
- pattern – Suchmuster
- Kann Klammer-Paare (captures) enthalten, die den Ergebnisvariablen zugeordnet werden.
- c – Zeichen-Code (ASCII oder codepoint)
- i – Start-Index;
-1
: letztes Zeichen.- Beginnend mit 1.
- Negativ: vom Ende zählen.
- j – End-Index.
- Position des letzten Zeichens; ab 1 gezählt, einschließlich.
- Negativ: vom Ende zählen;
-1
: bis zum Schluss
- n – Anzahl (optional)
- init – Start-Index (optional); kann negativ sein und zählt dann vom Ende
- plain – pattern nicht als pattern-Syntax, sondern buchstäblich (optional)
Die Index-Zahlen gelten immer in Zeichen; das sind bei der ASCII-Version Bytes.
- Wenn ein Unicode-String nicht ordnungsgemäß nach UTF-8 kodiert ist, wird
nil
von denmw.ustring.*
zurückgegeben. Das ist beim Wikitext nicht zu erwarten, wenn man ihn nicht vorher selbst ruiniert hatte. - Ansonsten ist der Rückgabewert die neue Zeichenkette bzw. die erfragte Anzahl in Byte bzw. Unicode-Zeichen.
Kurzreferenz
[Bearbeiten | Quelltext bearbeiten]- string.byte( s, i, j )
- s:byte( i, j )
- mw.ustring.byte( s, i, j )
- mw.ustring.codepoint( s, i, j )
- Jedes Byte/Zeichen in einzelne Variable
r1, r2, r3, r4 = s:byte( i, j )
- mw.ustring.byteoffset( s, l, i )
- Byte-Position eines Unicode-Zeichens
- string.char( c1, c2, c3, … )
- mw.ustring.char( c1, c2, c3, … )
- Zeichenkette aus den angegebenen Codes bilden
- string.find( s, pattern, init, plain )
- s:find( pattern, init, plain )
- mw.ustring.find( s, pattern, init, plain )
- Beginn und optional Ende des gesamten pattern in s; optional ab Position init gesucht.
j, k = s:find( pattern )
- Wird pattern nicht gefunden, sind beide Zahlen
nil
. - Optionales plain bewirkt die buchstäbliche Suche nach pattern, nicht über die besondere Syntax.
- Siehe auch match()
- Besonderheit: Ein leeres Klammernpaar in pattern ist möglich; liefert die Position dieses Treffers. Klammern (captures) haben ansonsten keine Wirkung.
- string.format( format, p1, p2, … )
- mw.ustring.format( format, p1, p2, … )
- Formatiere Argumente in begrenztem C-Stil (
printf
) - Siehe unten
- mw.ustring.gcodepoint( s, i, j )
- Iterator für eine
for
-Schleife über jedes Zeichen - string.gmatch( s, pattern )
- s:gmatch( pattern )
- mw.ustring.gmatch( s, pattern )
- Iterator für eine
for
-Schleife - string.gsub( s, pattern, replace, n )
- s:gsub( pattern, replace, n )
- mw.ustring.gsub( s, pattern, replace, n )
- Ersetze (substituiere) pattern durch replace.
- n optional; Vorgabe: alle
r, k = s:gsub( pattern, replace )
- Der zweite Rückgabewert ist die Anzahl der vorgenommenen Ersetzungen.
- Vorsicht:
return s:gsub( "X", "U" )
hängt unvermutet eine Zahl an die Zeichenkette des Rückgabewerts an.- Wenn replace eine Zeichenkette ist, wird sie für die Ersetzung benutzt.
- Dabei können Klammerausdrücke durch
%1
bis%9
eingefügt werden.%0
steht für die gesamte Fundstelle. - Wenn replace eine Tabelle ist, wird über den ersten Klammerausdruck auf ein geeignetes Element zugegriffen; ansonsten über den gesamten Treffer.
- Wenn replace eine Funktion ist, wird diese Funktion bei jedem Treffer aufgerufen, und alle Klammerausdrücke als Parameter übergeben; ansonsten der gesamte Treffer.
- Wenn das Ergebnis von Tabellenabfrage oder Funktionsaufruf eine Zeichenkette oder Zahl ist, wird mit diesem Wert ersetzt. Ist es
nil
oderfalse
, dann wird nichts verändert.
- mw.ustring.isutf8( s )
true
wenn die UTF-8-Kodierung gültig ist.- string.len( s )
- s:len()
- mw.ustring.len( s )
- Länge der Zeichenkette
s:len()
ist das Gleiche wie#s
- string.lower( s )
- s:lower()
- mw.ustring.lower( s )
- Kleinbuchstaben
- string.match( s, pattern, init )
- s:match( pattern, init )
- mw.ustring.match( s, pattern, init )
r1, r2, r3 = s:match( pattern )
- Inhalte der Klammern des pattern in s; ohne Klammern
r1=s
- Optional ab Position init
- Siehe auch find()
- string.rep( s, n )
- s:rep( n )
- mw.ustring.rep( s, n )
- (Repeat) n Wiederholungen von s
- Bei der Wiederholung einer ganzen gültigen Zeichenkette spielt die Kodierung keine Rolle; aber der Symmetrie und Vollständigkeit halber auch
mw.ustring.rep()
. - „repeat“ ist ein reserviertes Schlüsselwort, das nicht als Name für eine Funktion verwendet werden kann.
- string.reverse( s )
- s:reverse()
- Zeichenkette rückwärts[1]
- string.sub( s, i, j )
- s:sub( i, j )
- mw.ustring.sub( s, i, j )
- Substring: Teilzeichenkette von i bis j.
- Sowohl i als auch j können negativ sein und zählen dann vom Ende.
- j ist optional und hat
-1
als Vorgabe. - mw.ustring.toNFC( s )
- Unicode-Normalisierung der kanonischen Komposition
- mw.ustring.toNFD( s )
- Unicode-Normalisierung der kanonischen Dekomposition
- string.upper( s )
- s:upper()
- mw.ustring.upper( s )
- Großbuchstaben
- mw.ustring.maxPatternLength
10000
(Mai 2013)- mw.ustring.maxStringLength
2048000
(Mai 2013) und damit für alle darstellbaren Wiki-Quelltexte gerade hinreichend
.format()
[Bearbeiten | Quelltext bearbeiten]siehe Scribunto (englisch)
Die beiden Funktionen
- string.format( spec, p1, p2, … )
- mw.ustring.format( spec, p1, p2, … )
formatieren ihre Argumente p1, p2 usw.
Dabei ist
spec
eine Zeichenkette aus den nachstehenden Spezifikatoren.- Neben den Spezifikatoren kann beliebiger Text eingestreut werden, sofern er keine Prozentzeichen enthält.
- Jeder Spezifikation muss ein Wert
p
i 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
- mit den optionalen Angaben
- f – flags
- w – width (Feldweite)
- p – precision
- s – size
- c – conversion (Kennbuchstabe, Pflicht) für den Datentyp; oder
%%
zur Darstellung eines einzelnen Prozentzeichens.
Die Spezifikation beginnt also mit dem Prozentzeichen und endet mit dem Kennbuchstaben; die näheren Angaben dazwischen sind frei.
- Als flags sind vorhanden: '-', '+', ' ', '#', '0'.
- Für ganze Zahlen werden Feldweiten bis 99 unterstützt. '*' ist nicht verfügbar.
- Für ganze Zahlen werden precisions bis 99 unterstützt. '*' ist nicht verfügbar.
- Length modifiers werden nicht unterstützt.
- Kennbuchstaben für conversion siehe unten.
- Positional specifiers (wie
"%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.
Pattern
[Bearbeiten | Quelltext bearbeiten]Die Pattern entsprechen im Prinzip den verbreiteten regulären Ausdrücken mit einigen Besonderheiten:
- Escape über
%
und so ebenfalls die Kennzeichnung der Spezifikatoren. - Innerhalb der eckigen Klammern für Zeichenbereiche sind auch Spezifikatoren möglich.
- Es können nur einzelne Zeichen, Spezifikatoren oder in eckige Klammern gesetzte Zeichendefinitionen mit einer Wiederholungsangabe
* ? + -
versehen werden. Bei in runde Klammern gesetzten Ausdrücken (captures) ist das nicht möglich. - Es gibt keine Disjunktion
|
(Pipe). - Der Punkt
.
schließt Zeilenumbrüche mit ein (!). - Für Anfang und Ende stehen
^
und$
– im Inneren jedoch als ganz normale Zeichen. Andere Begrenzer wie\b
gibt es nicht. - Es gibt eine non-greedy Wiederholungsangabe
-
(Bindestrich-Minus), die versucht, so wenig wie möglich Zeichen zu liefern.- In
"ababab"
liefert"a.-b"
nur"ab"
, während"a.*b"
die ganze"ababab"
ergeben würde.
- In
- Es gibt keine
{
n,
m}
für die Anzahl der Zeichen. - Es gibt keine globale Kennzeichnung für ignorierte Groß- und Kleinschreibung.
- Ein „balancierter Ausdruck“ kann mit
%b
xy 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.- In
"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.
- In
%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.
Pattern für ASCII
[Bearbeiten | Quelltext bearbeiten]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. |
Pattern für Unicode
[Bearbeiten | Quelltext bearbeiten]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.
mw.text
[Bearbeiten | Quelltext bearbeiten]siehe Scribunto (englisch)
Eine weitere Hilfsbibliothek durch Scribunto, um kleine Manipulationen an Zeichenketten vornehmen zu können.
Unter „Zeichen“ wird hier Unicode verstanden.
- mw.text.decode( s, decodeNamedEntities )
- HTML-Entites durch Zeichencodes ersetzen
- Standard: Nur lt, gt, amp, quot, nbsp sowie alle numerischen.
- Optionales decodeNamedEntities bedeutet: Definition gemäß HTML5 verwenden. Über die in HTML4/XHTML hinaus bekannten sind das etliche mehr.
- mw.text.encode( s, charset )
- Escape für HTML: Zeichencodes durch HTML-Entites ersetzen.
- Standard: '<', '>', '&', '"' und das geschützte Leerzeichen werden ersetzt durch die benannten lt, gt, amp, quot, nbsp. Mögliche weitere Entities sind numerisch.
- Optionales charset ist ein Satz, der geeignet wäre, bei einem pattern in eckigen Klammern zu stehen.
Vorgabe ist"<>&\"' "
mit geschütztem Leerzeichen am Ende.
- Siehe auch mw.text.nowiki()
- mw.text.jsonDecode( s, flags )
- Aus einer Zeichenkette gemäß JSON eine table oder sonstigen Wert generieren.
- s ist die Zeichenkette.
- flags ist eine optionale number; wenn ungleich 0, dann durch Addition von Konstanten kombiniert:
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.
- Beschränkungen durch Lua-Sprachkonzept:
- Wenn ein JSON Array einen Wert
null
enthält, kann es in Lua keine sequence table werden. - Werte
null
in einem JSON object erscheinen nicht. - Es ist nicht möglich, aus Lua zu entscheiden, ob in JSON ein Array oder object vorgelegen hatte, falls die Elemente durchgängig mit Integer-Schlüsseln bezeichnet wurden.
- Wenn ein JSON Array einen Wert
- mw.text.jsonEncode( value, flags )
- Zeichenkette gemäß JSON generieren.
- value ist ein Wert beliebigen Typs.
- flags ist eine optionale number; wenn ungleich 0, dann durch Addition von Konstanten kombiniert:
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).
- Beschränkungen durch Lua-Sprachkonzept:
- Eine leere table wird als leeres Array
[]
und nicht als leeres object{}
generiert. - Um eine sequence table als JSON object abzubilden, muss ein Dummy-Element hinzugefügt werden.
- Eine sequence table mit Schlüsseln ab 0 wird genauso wie eine ab 1 als JSON Array generiert; es sei denn, dass mw.text.JSON_PRESERVE_KEYS angegeben wurde.
- Wenn sowohl numerische Indizes wie auch gleiche Werte als string-Darstellung auftreten, ist das Verhalten nicht vorhersagbar.
- Um ein Array oder object mit einem Wert von
nil
zu erreichen, ist die metamethod__pairs
erforderlich.
- Eine leere table wird als leeres Array
- mw.text.listToText( list, separator, conjunction )
- Alle Elemente einer table aneinanderfügen, ähnlich
table.concat()
. - list ist eine table.
- Vorgaben für die optonalen weiteren Parameter sind:
- separator über MediaWiki:comma-separator als Komma und Leerzeichen: »⧼MediaWiki:comma-separator⧽«
- conjuction über MediaWiki:and verbunden mit MediaWiki:word-separator als: »⧼MediaWiki:comma-separator⧽⧼MediaWiki:word-separator⧽«
- mw.text.nowiki( s )
- Escape für Wikitext: Zeichencodes durch HTML-Entites ersetzen.
- Alle Vorkommen: '"', '&', "'", '<', '=', '>', '[', ']', '{', '|', '}'
- Beginn von s oder unmittelbar nach einem Zeilenumbruch: '#', '*', ':', ';'
- Die „Magischen Wörter“
- Siehe auch mw.text.encode()
- mw.text.split( s, pattern, plain )
- Generiere Tabelle (sequence) aus Zeichenkette s durch Segmentierung (Tokenizer).
- pattern ist der Ausdruck, der die Elemente voneinander trennt.
- Bei leerer Zeichenkette für pattern wird jedes Zeichen einzeln in die Tabelle geschrieben.
- Optionales plain bewirkt die buchstäbliche Suche nach pattern, nicht über die besondere Syntax.
- mw.text.gsplit( s, pattern, plain )
- Iterator-Funktion für
for
analog zumw.text.split()
- mw.text.tag( name, attrs, content )
- Generiere ein HTML-Tag mit dem Bezeichner name.
- Das optionale, aber oft sinnvolle attrs ist eine table mit den Zuweisungen k=v.
- Wenn das optionale content als Zeichenkette (oder number) angegeben wird, wird das Element auch mit einem end-tag nach content versehen; sonst ist es nur ein start-tag.
- Encoding erfolgt nicht automatisch; sofern wünschenswert und erforderlich, muss es mittels mw.text.encode() geeignet veranlasst werden.
- Bei content
=false
wird ein unary tag generiert.
- Diese Funktion gilt nur für HTML-Tags als bloße Zeichenketten. Ein Tag einer Wiki-Erweiterung wie
<ref>
muss mit frame:extensionTag() generiert werden; andernfalls würde es nicht wirksam. - Zu einer später entstandenen, umfassenderen Funktionalität siehe
mw.html
– diese Bibliothek ist im Zweifelsfall votzuziehen und einheitlich darauf umzustellen. - mw.text.trim( s, charset )
- Leerzeichen und Zeilenumbruch an Beginn und Ende von s entfernen.
- Das optionale charset ist eine Zeichenkette, die zwischen den eckigen Klammern eines pattern als
[
set]
stehen kann.- Die Vorgabe ist:
"\t\r\n\f "
- Die Vorgabe ist:
- mw.text.truncate( text, length, ellipsis, adjustLength )
- Abschneiden der Zeichenkette s auf die Länge length.
- Dabei wird an eine abgeschnittene Zeichenkette die Auslassungsmarkierung ellipsis angehängt.
- Wenn length negativ ist, wird der Betrag genommen und der Beginn von s abgeschnitten; sonst das Ende.
- Wenn die optionale ellipsis nicht angegeben ist, wird MediaWiki:ellipsis (also »…«) benutzt. Um nichts anzuhängen, muss explizit eine leere Zeichenkette angegeben werden.
- Wenn das optionale adjustLength mit
true
verwendet wird, ist der Betrag von length die Gesamtlänge einschließlich ellipsis. - mw.text.unstrip( s )
- Entfernt die MediaWiki-internen strip markers.
- Diese Funktion sollte in der normalen Lua-Programmierung nicht benutzt werden, da mit Bruch zu rechnen ist.
- mw.text.unstripNoWiki( s )
- mw.text.killMarkers( s )
mw.dumpObject()
[Bearbeiten | Quelltext bearbeiten]- mw.dumpObject( table )
- Das Objekt table wird in einer menschenfreundlichen Form in eine mehrzeilige Zeichenkette überführt und diese zurückgegeben.
mw.logObject()
verwendet dieses Format.
Anmerkungen
[Bearbeiten | Quelltext bearbeiten]- ↑ Ein mw.ustring.reverse() ist nicht definiert
Daten und Programmierung trennen
[Bearbeiten | Quelltext bearbeiten]Die nachfolgenden Abschnitte stellen Möglichkeiten dar, bei der Programmierung von Lua-Modulen das Basis-Konzept einer Trennung von Programm und Daten umzusetzen.
Allgemeines
[Bearbeiten | Quelltext bearbeiten]Die Trennung von Programm und Daten gehört zum Stoff des ersten Semesters eines Informatikstudiums.
Vorteile:
- Wartbarkeit verbessert,
- Übersichtlichkeit erhöht,
- Robustheit gesteigert,
- Portabilität ermöglicht,
- Flexibilität unterstützt.
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.
- Dadurch können die Konfigurationsdaten an einer zentralen und übersichtlich zugänglichen Stelle gesammelt und auch dokumentiert werden. Wären sie hard-coded überall in den Instruktionen verteilt, wären viel schwieriger alle Vorkommen aufzufinden und bei entstehendem Bedarf anzupassen. Nach einigen Jahren und durch die Nachfolgenden würde das zur Herausforderung.
- Zahlen oder Kennbuchstaben erhalten sprechende Bezeichner. Dadurch wird die Bedeutung der Anweisungen verständlicher. Irrtümer werden vermieden, Fehler treten offenkundig hervor.
- Standardwerte können als Vorgaben definiert werden; bei abweichendem besonderen Bedarf kann die Wirkung der Software von außen durch individuell zugewiesene Parameter beeinflusst werden, ohne dass die Programmierung verändert werden müsste.
- Weil der funktionale Teil ggf. auch auf eigenen Seiten gekapselt ist, während Konfigurationsdaten auf anderen Seiten im Wiki liegen, kann eine aktualisierte Programmierung global verteilt werden, ohne dass sie in jedem einzelnen Projekt mit jeder neuen Version angepasst werden müsste. Siehe dazu Internationalisierung.
Techniken in Lua und Wikis
[Bearbeiten | Quelltext bearbeiten]Systembibliotheken
[Bearbeiten | Quelltext bearbeiten]Die Funktionen der Systembibliotheken liefern diverse global gepflegte Konfigurationsdaten über das aktuelle Wiki.
Lokale Variablen
[Bearbeiten | Quelltext bearbeiten]Im aktuellen Modul können Werte statisch zugewiesen werden, oder auch abhängig von der aktuellen Seite dynamisch ermittelt werden.
- Diese
local
-Zuweisungen sollten geschlossen zu Beginn des Quelltextes erfolgen, damit sie leicht und vollständig wiedergefunden und gepflegt werden können. - Falls nicht selbsterklärend, kann jede Zuweisung auch kommentiert und damit dokumentiert werden.
- Es bietet sich an, die lokalen Zuweisungen als table zu gruppieren. Damit wird bei der späteren Verwendung innerhalb einer Funktion deutlich dass es sich um bestimmte Blöcke der modulweiten Konfiguration handelt, etwa Projektstruktur oder sprachliche Textbausteine.
- Die Werte können ggf. auch durch Aufrufparameter des
#invoke
oder externe Seiten überschrieben werden.
Beispiel: Modul:TemplateData
mw.loadData()
[Bearbeiten | Quelltext bearbeiten]Dies ist Mittel der Wahl für eine Programmierung, die in mehreren Wikis wiederverwendet werden soll.
- Es wird ein Modul im Modul-Namensraum hinterlegt.
- Die Funktion
mw.loadData()
ermöglicht dann die Einbindung in andere Module. - Das Ergebnis wird immer eine table sein und kann eine Struktur aus beliebig vielen atomaren Werten sowie anderer table enthalten.
Vorteile
- Das Resultat wird nur einmal pro dargestellter Seite kompiliert und das Ergebnis dann dieser aktuellen dargestellten Seite zugeordnet. Damit kann es von mehreren
#invoke
-Einbindungen wiederverwendet werden. - Die Ermittlung des Resultats kann dynamisch, also durch Auswertung von Funktionen betreffend der aktuell dargestellten Seite, externer Seiten oder anderer veränderlicher Bedingungen erfolgen.
- Für späteres Wartungs- und Pflegepersonal wird ein übersichtliches und eher kleines Modul dargestellt, das sich leichter überblicken lässt und auch ohne Lua-Erfahrung die Schwelle zur Anpassung einer Zeichenkette oder Zahl senkt.
Nachteile
- Ähnlich JSON darf das Resultat keine Programmierungen vom Typ
function
enthalten, sondern nur reine Daten:nil
,boolean
,number
,string
,table
Beispiel: Modul:URIutil/urn
Unter-Modul
[Bearbeiten | Quelltext bearbeiten]Mittels require()
kann ein anderes Modul eingebunden werden.
Vorteile
- Gegenüber einem mw.loadData() kann das Resultat auch Funktionen enthalten.
Nachteile
- Zurzeit gibt es keine Hinterlegung kompilierter Versionen pro Seite.
Beispiel: Modul:Vorlage:Runeberg/NF
JSON
[Bearbeiten | Quelltext bearbeiten]Seit Oktober 2022 ist die Bibliotheksfunktion mw.loadJsonData()
nutzbar.
- Konzeptionell entspricht dies einer per mw.loadData() einbindbaren Lua-Seite.
- Die Seite kann auch im Modul-Namensraum angelegt werden. Es bietet sich eine Unterseite des versorgten Moduls an.
- Die Syntax ist JSON statt Lua.
- Auch aus jedem anderen Namensraum kann eine
.json
-Seite genutzt werden, etwa geteilt mit Gadgets.
Benutzung: tbl = mw.loadJsonData( seitenname )
- Das Ergebnis ist eine table.
Vorteile
- Die JSON-Notation ist externem Wartungspersonal möglicherweise geläufiger als Lua.
- Skripte in JavaScript können die Seite ebenfalls mit einer Standardfunktion auslesen und die Daten nutzen.
Nachteile
- Anders als ein mw.loadData() kann die Seite nur echte Konstanten enthalten, also keine Funktionen auswerten.
- Kommentare sind unzulässig; müssten ggf. als Elemente von Objekten wirksam eingebracht werden.
Beispiel: Modul:JSTOR/config.json
Vorlagen
[Bearbeiten | Quelltext bearbeiten]Eine beliebige Seite in Wikitext kann ausgelesen, insbesondere aber transkludiert werden.
Vorteile
- Es gibt mehr mit der Vorlagensyntax Vertraute als Lua-Personal.
- Es kann sowohl zur Vereinbarung von Parameterwerten innerhalb der Lua-Programmierung genutzt werden, oder die externe Vorlage wird zur Nachbereitung des Lua-Resultats als Ergebnis der Lua-Funktion verwendet.
Nachteile
- Nur der Datentyp „Zeichenkette“ ist primäres Resultat.
- Weniger effizient in Auswertung und erforderlicher Programmierung zwecks Parsen der Zeichenketten.
Beispiel: Vorlage:Seitenbewertung/Darstellung eingebunden durch Modul:Vorlage:Seitenbewertung
Systemnachrichten
[Bearbeiten | Quelltext bearbeiten]Vorteile
- Einige WP:Systemnachrichten sind womöglich bereits global und lokal definiert und können dann genutzt werden, etwa Textfragmente.
Nachteile
- Nur Admins können Systemnachrichten anlegen und pflegen.
- Der Namensraum ist nicht dafür ausgelegt, eine Vielzahl von Textfragmenten und womöglich Einzeldaten für beliebige Vorlagen zu organisieren.
- In ein anderes Wiki ist dies nicht zu übertragen, und dort wären für die Einrichtung und Pflege wieder Adminrechte erforderlich.
Commons:Data:
[Bearbeiten | Quelltext bearbeiten]Im Namensraum Data:*.tab auf Wikimedia Commons können Seiten im JSON-Format hinterlegt werden, die alle Wikis lokal einbinden und auslesen können.
- Mittels
mw.ext.data.get()
kann die Tabelle bezogen auf die Sprache des aktuellen Wikis oder für alle Sprachen abgerufen werden.
Vorteile
- Die Daten können global zentral gepflegt und genutzt werden.
- Einzelne Wikis brauchen sich nicht um eine Aktualisierung und Verteilung zu bemühen.
- Größere Datenmengen unterliegen keinen Beschränkungen wie etwa Wikidata.
- Skripte in JavaScript können die Seite ebenfalls mit einer Standardfunktion auslesen und nutzen.
Nachteile
- Das Format
.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. - Die globale Definition ist schwieriger zu beobachten und zu überwachen. Ggf. können Seiten jedoch unter den Schutz von template editors gestellt werden, wenn wenig Änderungsbedarf zu erwarten ist.
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
Wikidata
[Bearbeiten | Quelltext bearbeiten]Aus Wikidata können beliebige Eigenschaften eines Items (oder auch anderer Objekte) ausgelesen werden; siehe mw:Extension:Wikibase Client/Lua.
Vorteile
- Mitbenutzung anderweitig gepflegter und aktualisierter Daten.
- Globale Aktualisierung und Nutzung.
- Beliebige Arten der Information; als Zeichenkette.
Nachteile
- Die Anzahl sämtlicher unterschiedlicher Objekte in der aktuell dargestellten Seite ist beschränkt (400); für sämtliche Anwendungen. Das kann leicht zum Problem werden, wenn eine Liste von Gegenständen befüllt werden soll. Generell gibt es Performance-Probleme, wenn viele Objekte abgerufen werden müssen; die Anzahl ist deshalb kaum zu steigern.
- Die Beobachtung und Verfolgung der Änderungsgeschichte bei einer großen Zahl von Datenelementen ist extrem schwierig, weil jede Zahl oder Textelement innerhalb eines anderen Objekts steht, zwischen vielen anderen Eigenschaften dieses Objekts. Auf die Korrektheit der Daten und ihrer Veränderungen ist deshalb kein Verlass.
Internationalisierung
[Bearbeiten | Quelltext bearbeiten]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.
Grundsätzlich: Parametrisierung
[Bearbeiten | Quelltext bearbeiten]Textteile (in menschlicher Sprache) und potentiell veränderliche Konfigurationen (etwa die Namen von Seiten) sollen nie im Inneren des Codes versteckt werden.
- Sie sind dort schwer zu finden, und ein späterer Eingriff durch Unbeteiligte führt oft zu Kollateralschäden.
- Ein Überblick über alle anzupassenden Elemente ist nicht zu erhalten; der aktuelle Konfigurationsstatus ist nicht zu überschauen.
- Wenn sich auch Funktionalitäten verändern, etwa erweitert werden, wird der Transfer und die erneute Anpassung zum Drama; muss wieder von vorn begonnen werden.
Systemvariablen nutzen
[Bearbeiten | Quelltext bearbeiten]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()).
Minimallösung
[Bearbeiten | Quelltext bearbeiten]Alle möglicherweise anzupassenden Texte oder Zahlen werden in Variablen geschrieben. Die Wertzuweisung erfolgt in einem geschlossenen Block am Beginn des Moduls.
- Die anschließenden Funktionen greifen nur noch auf die Variablen zu und können en bloc durch eine neuere Version ausgetauscht werden.
- Zur Anpassung an eine neue Umgebung müssen nur alle Werte im Block geeignet ersetzt werden.
Vorteile
- Einfache Programmierung bei der ersten Erstellung
Nachteile
- Aktualisierung veränderter Funktionalität bedarf einer Neukomposition des Quellcodes in jedem Projekt.
- Bei allen einbindenden Seiten wird eine Aktualisierung ausgelöst.
Automatische Anpassung
[Bearbeiten | Quelltext bearbeiten]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
- Alle befreundeten Projekte können den funktional aktualisierten Code ohne Nacharbeit einspielen.
Nachteile
- Alle Übersetzungen und Anpassungen für jedes Projekt müssen bekannt sein und sind zentral einzupflegen.
- Bei allen einbindenden Seiten wird eine Aktualisierung ausgelöst; auch auf dem pflegenden Projekt.
Globale Tabellen
[Bearbeiten | Quelltext bearbeiten]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.
Systemnachrichten
[Bearbeiten | Quelltext bearbeiten]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
- Alle befreundeten Projekte können den funktional aktualisierten Code ohne Nacharbeit einspielen.
- Für einbindende Seiten wird bei Textänderungen keine Aktualisierung ausgelöst.
- Die Seiten im MediaWiki-Namensraum sind nur durch Administratoren veränderbar und deshalb vor Vandalismus sicher.
Nachteile
- Einbindende Seiten werden bei Textänderungen nicht aktualisiert.
- Wenn es sich nur um besser formulierte Fehlermeldungen handelt, beträfe das nur die Seiten, in denen der Text sichtbar ist; übergangsweise wäre noch die vorherige Formulierung zu sehen.
- Durch ein purge auf einbindende Vorlagen lässt sich eine wichtige Textänderung durchsetzen.
- Die Seiten im MediaWiki-Namensraum sind nur durch Administratoren veränderbar und brauchen zusätzliche Anfragen.
Umhüllende Vorlage
[Bearbeiten | Quelltext bearbeiten]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.
- Beispiel: {{LuaModuleDoc}}
Vorteile
- Alle befreundeten Projekte können den funktional aktualisierten Lua-Code ohne Nacharbeit einspielen.
Nachteile
- Bei allen einbindenden Seiten wird eine Aktualisierung ausgelöst.
- Begrenzt auf die Nutzung durch eine einzige Vorlage.
Unter-Vorlage
[Bearbeiten | Quelltext bearbeiten]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.
- Beispiel: Wikipedia:Lua/Modul-Navigationsfehler
Vorteile
- Alle befreundeten Projekte können den funktional aktualisierten Lua-Code ohne Nacharbeit einspielen.
- Alle Anwendungen können auf die Textsammlung zugreifen.
- Die Untervorlage ist leicht zu pflegen.
Nachteile
- Bei allen einbindenden Seiten wird eine Aktualisierung ausgelöst.
- Der Seitenname der Unter-Vorlage könnte eine zusätzliche Konfiguration erfordern; das lässt sich aber vermeiden, indem er aus dem Modulnamen gebildet und im Vorlagen-Namensraum untergebracht wird.
Unter-Modul
[Bearbeiten | Quelltext bearbeiten]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 enthält.
Vorteile
- Alle befreundeten Projekte können den funktional aktualisierten Lua-Code ohne Nacharbeit einspielen.
- Das Unter-Modul ist von Lua-Programmierern leicht zu pflegen; die einfache Umformulierung einer Zeichenkette auch nicht besonders schwer.
Nachteile
- Bei allen einbindenden Seiten wird eine Aktualisierung ausgelöst.
- Jedes empfangende Projekt muss eigene Lua-Programmierer haben, die auch Änderungen in der Nachrichtenstruktur und den Identifizierern umsetzen können. Das ist nicht schwierig; aber die Veränderung eines Moduls bringt erstmal eine Hemmschwelle und kann zu selbst nicht behebbaren Syntaxfehlern führen, wenn keine Lua-Programmierer für die lokale Modul-Variante verfügbar sind.
Rückfallposition
[Bearbeiten | Quelltext bearbeiten]Es muss immer damit gerechnet werden, dass externe Vereinbarungen oder die lokale Sprache nicht verfügbar sind.
- Es muss immer eine Zeichenkette zurückgegeben werden.
- Im Idealfall wird auf die englischsprachigen Texte zurückgegriffen.
- Mindestens muss der Bezeichner des Textbausteins, eingefasst in mehrere Klammern, zur Identifizierung des Problems dargestellt werden.
- Eine fehlende Seite darf keinen unspezifizierten Skriptfehler auslösen.
Quellcode und Vorschau
[Bearbeiten | Quelltext bearbeiten]In den nachfolgenden Abschnitten
wird beschrieben, wie sich in der Wiki-Umgebung Lua-Quellcode eingeben und testen lässt.
Code-Editor
[Bearbeiten | Quelltext bearbeiten]Bei den dafür vorgesehenen Seiten des Modul-Namensraums schaltet sich bei der Bearbeitung der Seite immer automatisch der CodeEditor zu.
- wikEd usw. müssen abgeschaltet sein.
- Der VisualEditor sollte sich seit Mitte 2013 selbst abschalten.
Seitenvorschau und Testseite
[Bearbeiten | Quelltext bearbeiten]Ä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:
- Zu jedem produktiven Modul sollte eine Testseite in Wikisyntax vorhanden sein. Sie erlaubt einen routinemäßigen Schnelltest, ob das Modul noch prinzipiell in ordnungsgemäßem Zustand ist.
- Es sind nach Funktionen gegliedert die typischen Vorlageneinbindungen und dafür das erwartete Ergebnis und das momentane Resultat aus dem Lua-Modul gegenüberzustellen, so dass sie unmittelbar und übersichtlich verglichen werden können.
- Gleichzeitig kann die Testseite als Bestandteil der Dokumentation alle diese Beispielfälle zur Veranschaulichung nutzen.
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.
Konsole
[Bearbeiten | Quelltext bearbeiten]Wenn man ein Modul mit existierendem Quellcode im Bearbeitungsfeld zum Bearbeiten geöffnet hat, erhält man im Fußbereich der Seite eine Fehlerbereinigungskonsole.
- Dies gilt also nicht bei einer neu erstellten Seite beim ersten Öffnen mit
action=edit
; auch hier jedoch nach der ersten Seitenvorschau alsaction=submit
.
- Suche nach Syntaxfehlern
- Mit der Maus in das grau unterlegten Eingabefeld der „Fehlerbereinigungskonsole“ gehen, ein Gleichheitszeichen
=
eingeben und die Taste Enter drücken.- Wirkung: Der Quellcode im Bearbeitungsfeld wird per API zum Server geschickt, ausgewertet und einige Momente später dargestellt.
- Es wurde jedoch keine Funktion aufgerufen; also wird es kaum ein Resultat des Quellcodes geben.
- Dafür erhält man eine englischsprachige Fehlermeldung mit Angabe der Zeilennummer. Bei aktiviertem Code-Editor wird die Zeilennummer auch im Bearbeitungsfeld dargestellt.
- Statische Ausdrücke
- Statische Ausdrücke ohne Bezug zum Bearbeitungsfeld können berechnet werden, indem ein Gleichheitszeichen vorangestellt und Enter gedrückt wird.
- Modulwert
p
- Die Variable p steht im Konsolenfenster für den Rückgabewert des Moduls – völlig egal, welchen Namen diese lokale Variable im Modul trägt.
- In das Konsolfeld wird eine Komponente des Modul-Rückgabewerts
p
(Variable oder Funktionsaufruf) eingetragen, ein Gleichheitszeichen vorangestellt und Enter gedrückt. - mw.log()
- Anweisungen der Art
mw.log(
text)
bleiben scheinbar wirkungslos; ausgenommen:- in der Konsole,
- bei der Seitenvorschau im Parser Profiling Report.
- Dieser ist für Normalbenutzer unsichtbar; Lua-Programmierer werden ihn sichtbar gemacht haben und auswerten.
- Dort unter der Überschrift „Lua-Logbücher“ und kann dann ausgeklappt werden.
- Es sind beliebig viele Argumente beliebigen Datentyps möglich, die fomatiert mit etwas Abstand hintereinander gezeigt werden.
- Damit können während einer Testphase noch Meldungen in die Programmierung des Moduls eingestreut werden, ohne das Gesamtergebnis der Auswertung zu stören.
- In einer produktiven Version sollte es jedoch nicht mehr auftreten.
- mw.logObject( object, prefix )
- Genauso wie mw.log(), jedoch mit einer table als erstes Argument object. Die Komponenten werden optisch gegliedert dargestellt.
- Ein optionales zweites Argument prefix kann eine Zeichenkette sein, die den angezeigten Namen des object benennt.
- print()
- Diese Funktion ist ein Alias für
mw.log()
und für ein Wiki nur innerhalb der Konsole möglich. Es ist gleichzeitig ein Alias für das Gleichheitszeichen. - Wie dort sind in der Konsole lokale Informationen des Moduls nicht verfügbar.
Bedienung:
- Die bislang erzielten Ergebnisse der Konsole bleiben sichtbar, bis Leeren gedrückt oder die Seite neu aufgebaut wird.
- ↑ gibt Zugriff auf vorige Eingaben.
Für die Gesamtwirkung der Modul-Ergebnisse ist die Vorschau-Funktion wichtiger, insbesondere mit der im vorigen Abschnitt dargestellten Testseite.
Debugging-Meldungen
[Bearbeiten | Quelltext bearbeiten]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.
Benutzer-Spielwiese
[Bearbeiten | Quelltext bearbeiten]In der Vorlagenspielwiese können Module analog zum Modul-Namensraum entwickelt werden.