Modul:Lilypond
Zur Navigation springen
Zur Suche springen
score
Dieses Programm soll über die Vorlage {{Score}} aufgerufen werden, ersetzt das Tag <score> und macht die Erweiterung Score transcludierbar.
hili
Dieses Programm soll über die Vorlage {{Hili}} aufgerufen werden, ersetzt das Tag <syntaxhighlight> und macht diees Erweiterung transcludierbar.
midi
Dieses Programm soll über die Vorlage {{Midi}} aufgerufen werden und macht die Erweiterung Score transcludierbar. Es werden Midi-Dateien erzeugt.
Die Funktion pdf wendet die Vorlage {{pdf}} an und bildet eine Liste von Links für jede Tonleiter in der Reihenfolge des Quintenzirkels, wobei zwischen Dur und Moll unterschieden wird.
Prozedur proc aufrufen: {{#invoke:Lilypond|proc}} · Modul einbinden: local t = require('Module:Lilypond')
Unterseiten
Programmcode
local p = {} -- p stands for package
local music = '\\paper { tagline = ##f }\
\\language \"deutsch\"\
\\relative c\'\' { c-\\markup \"Standardmusic\" d e b }'
--(rgb-color 0.88 0.72 0.53) (\225 255) (\ 184 255) (\ 135 255) x11 burlywood
local gclef = '\\musicglyph #"clefs.G"'
local elise = '\\score { \\new Staff { c4 } }'
local eiffel = '\\null'
local qidur = { "C", "G", "D", "A", "E", "H", "Fis", "Ges", "Des", "As", "Es", "B", "F" } -- Quintenzirkel Dur
local qiall = { "C", "G", "D", "A", "E", "H", "Fis", "Cis", "Gis", "Dis", "Ges", "Des", "As", "Es", "B", "F" } -- Quintenzirkel Dur
local qimol = { "A", "E", "H", "Fis", "Cis", "Gis", "Dis", "Es", "B", "F", "C", "G", "D" } -- Quintenzirkel Moll
function p.multipaths(frame)
local a = frame.args -- direkt per #invoke: übergeben
local b = frame:getParent().args -- an die Vorlage übergebene Parameter
local pfad = trim(b["pfad"] or a["pfad"] or b[1] or a[1] or '')
if pfad == '' then return "<div class=\"blue-gradient fett noclick lily\" style=\"font-size: 1.4em; padding: 10px\">Pfad fehlt</div>" end
local retour = trim(b["test"] or a["test"] or '')
local was = trim(b["was"] or a["was"] or '')
local mypat= "<path[%s%c]+d=\"([^\"]*)"
local zpath, ___ = '', ''
local vbox, _, __
local path, lily, fehler, minx, maxx, miny, maxy, mysvg
local pfade, lilys, svgs, minmax, viewb = {}, {}, {}, {}, {}
local output = ''
local lilyout, lily, lilys = '', '', ''
local svgout, svg = '', ''
local viewbox, vboxen = '', ''
local svgheader = '\n<svg version=\"1.1\" viewBox=\"$\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"'
local width, height, svgstring = '', '', ''
for n in pfad:gmatch(mypat) do
table.insert(pfade, n)
end
if retour ~= '' and was == 'pfade' then
return "Zahl der Pfade: " .. #pfade .. "\n" .. table.concat(pfade,'\n----\n')
end
for i = 1, #pfade do
path = pfade[i]
lily, fehler, minx, maxx, miny, maxy, mysvg = lpath(path)
if type(fehler) == "string" then
return "Pfad enthält Fehler\n" .. "\n" .. fehler .. "\n" .. path .. "\n" .. lily
end
_ = "\n#(define mypath$ \'(\n" .. lily .. "\n))" -- pfaddef:gsub("[§]",lily)
__ = _:gsub("[$]", tostring(i))
___ = "\n_: " .. _ .. '\ngsub("[$]", tostring(i)) ' .. __
output = output .. __
lilys = lilys .. lily
width = tonumber(maxx) - tonumber(minx)
height = tonumber(maxy) - tonumber(miny)
viewbox = minx .. " " .. miny .. " " .. tostring(width) .. " " .. tostring(height)
vboxen = vboxen .. "\nPfad Nr. " .. i .. ' viewbox: ' .. viewbox .. " min/max: " .. table.concat({ minx, miny, maxx, maxy }, ', ')
vbox = svgheader:gsub("[$]", viewbox)
svgout = svgout .. vbox .. mysvg .. "\" />\n</svg>"
end
if retour ~= '' and was == "boxen" then return vboxen end
if retour ~= '' and was == "lily" then return lilys end
if retour ~= '' and was == "out" then return ___ end
lilyout = '{{#tag:tabber|Pfad(e) oneclick=<syntaxhighlight lang=\"latex\" style=\"display: inline-block\" class=\"oneclick\">' ..
output .. '</syntaxhighlight>\n{{!}}-{{!}}\nPfad(e)=\n<syntaxhighlight lang=\"latex\" style=\"display: inline-block\">' ..
output .. "</syntaxhighlight>}}"
svg = '{{#tag:tabber|SVG Pfad oneclick=<syntaxhighlight lang=\"xml\" style=\"display: inline-block\" class=\"oneclick\">' ..
svgout .. '</syntaxhighlight>\n{{!}}-{{!}}\nSVG Pfad=\n<syntaxhighlight lang=\"xml\" style=\"display: inline-block\">' ..
svgout .. "</syntaxhighlight>}}"
return frame:preprocess('\n==Lilypond Path==\n' .. lilyout .. "\n==SVG Code==\n" .. svg)
end
function lpath(s)
local mpath = trim(s)
local number, letter, coords
-- Define the regular expression pattern
local pattern = "[cCmMsSlLhHvVzZ][^cCmMsSlLhHvVzZ]*" -- wir zerteilen den String anhand der Pfadelemente und analysieren in einer
-- separaten Schleife die Zahlen
local numpattern = "[-]?%d*%.?%d+"
local mypath, mycube = {}, {}
local i, j, elts = 1, 1
local exppat = "[-+]?%d+%.?%d*[eE][-+]?%d+"
local error = ""
if type(mpath) ~= "string" or mpath == '' then return "kein Pfad angegeben", "error" .. tostring(mpath) end
pfad = mpath:gsub(exppat, function(w) return " " .. w*1 end) -- wir ersetzen Exponentialzahlen durch Kommazahlen
-- if 1 then return pfad end
-- Iterate over the matches
for match in pfad:gmatch(pattern) do -- ein ganzes Pfadelement
letter = match:match("[cCmMsSlLhHvVzZ]") -- zulässige Pfadkommandos
-- a, q fehlen weil keine Umrechnung auf c vorhnaden
table.insert(mypath, letter)
local nn = {}
for number in match:gmatch(numpattern) do
table.insert(nn, number)
end
table.insert(mycube, nn)
end
local x0, x1, x2, x3, x4, x5, x6 -- Koordinaten der Kontrollpunkte
local y0, y1, y2, y3, y4, y5, y6 -- Koordinaten; stimmen aus historischen Gründen nicht mit x und y überein
letter = mypath[1]
if #mycube[1] ~= 2 or (letter ~= "m" and letter ~= "M") then
return "", "kein gültiger Pfad, falscher Beginn mit " .. letter .. table.concat(mycube[1],', ')
end
local actx, acty = unpack(mycube[1]) -- wir legen den Startpunkt fest
local minx, maxx, miny, maxy = tonumber(actx), tonumber(actx), tonumber(acty), tonumber(acty)
-- if 1 then return table.concat({actx, acty, minx, maxx, miny, maxy}, ', ') end
local lily = "(moveto " .. table.concat(mycube[1],' ') .. ")"
local svg = letter .. table.concat(mycube[1],' ')
for i = 2, #mypath do
letter = mypath[i]
mydim = #mycube[i]
-------------------------------------------------------------------------------------------------
if letter == "m" then -- m
if mydim ~= 2 then
-- return "ungültiger Pfad " .. letter .. table.concat( mycube[i], ", " ) .. "\n" .. output
ung = ung + 1
end
svg = svg .. "\n" .. letter .. " " .. table.concat(mycube[i],', ')
--return table.concat(mycube[i],', ') .. letter
x1, x2 = unpack(mycube[i])
actx = actx + x1 -- nwuw Koordinaten berechnen
acty = acty + x2
if letter == "m" then -- wir bewegen uns ohne zu Zeichnen
lily = lily .. "\n" .. "(rmoveto " .. x1 .. " " .. x2 .. ")"
end
end
-------------------------------------------------------------------------------------------------
if letter == "l" then -- lineto
if mydim % 2 ~= 0 then
return lily, "ungültiger Pfad " .. letter .. table.concat( mycube[i], ", " )
end
elts = mydim / 2
for j = 1, elts do
x1, x2 = unpack(mycube[i], j * 2 - 1, j * 2)
actx = actx + x1 -- nwuw Koordinaten berechnen
acty = acty + x2
lily = lily .. "\n" .. "(rlineto " .. x1 .. " " .. x2 .. ")"
svg = svg .. "\nl " .. x1 .. " " .. x2
if tonumber(actx) < minx then minx = tonumber(actx) end -- Ausmaße des Pfades mitberechnen
if tonumber(actx) > maxx then maxx = tonumber(actx) end
if tonumber(acty) < miny then miny = tonumber(acty) end
if tonumber(acty) > maxy then maxy = tonumber(acty) end
end
end
-------------------------------------------------------------------------------------------------
if letter == "v" or letter == "h" then -- vertikal oder horizonal
if mydim ~= 1 then -- mehrere h's oder v's hintereinander ergeben keinen Sinn
return lily, "ungültiger Pfad " .. letter .. table.concat( mycube[i], ", " )
end
x1 = mycube[i][1]
if letter == "h" then -- horizontale Linie
actx = actx + x1 -- nur x-Koordinate des Endpunktes ändert sich
lily = lily .. "\n" .. "(rlineto " .. x1 .. " 0)"
svg = svg .. "\nl " .. x1 .. " 0"
end
if letter == "v" then -- vertikale Linie
acty = acty + x1
lily = lily .. "\n" .. "(rlineto 0 " .. x1 .. ")"
svg = svg .. "\nl 0 " .. x1
end
end
-------------------------------------------------------------------------------------------------
if letter == "s" then -- spline
if mydim ~= 4 then
return lily, "ungültiger Pfad " .. letter .. " hat nicht 4 Angaben " .. table.concat( mycube[i], ", " )
end
if mypath[i-1] ~= "c" and mypath[i-1] ~= "s" and mypath[i-1] ~= "m" and mypath[i-1] ~= "l"
and mypath[i-1] ~= "h" and mypath[i-1] ~= "v" then
return lily, "Pfadangabe s nur nach c, m, l, v, h oder s zulässig " .. table.concat( mycube[i], ", " )
end
x1, x2, x3, x4 = unpack(mycube[i])
actx = actx + x3
acty = acty + x4 -- neuen aktuellen Endpunkt berechnen, unabhängig von der Umwandlung nach c
-- wir ergänzen s zu einem c
-- die Koordinaten des ersten Punktes errechnen sich (relativ) aus
-- x2 = x0 - x1
-- y3 = y0 - y1
-- x0, y0 sind die Koordinaten des Zielpunktes der vorigen Kurve
-- x1, y1 sind die Koordinaten des 2. Stützpunktes
if mypath[i-1] == "c" then -- voriger Abschnitt war c
y1, y2, y3, y4, y5, y6 = unpack(mycube[i-1])
end
if mypath[i-1] == "c" then -- voriger Abschnitt war c
elts = #mycube[i-1] / 6 -- der letzte Teil des Pfades ist entscheidend
y3, y4, y5, y6 = mycube[i-1][elts * 6 - 3], mycube[i-1][elts * 6 - 2], mycube[i-1][elts * 6 - 1], mycube[i-1][elts * 6]
end
if mypath[i-1] == "m" or mypath[i-1] == "l" or mypath[i-1] == "h" or mypath[i-1] == "v"
then -- voriger Abschnitt war m, l, h oder v
-- c wird folgendermaßen berechnet:
-- 1. Kontrollpunkt wird 0 0
-- die vier Kontrollpunkte werden die letzten vier Kontrollpunkte der c-Kurve
local koordinaten
koordinaten = table.concat({0, 0, x1, x2, x3, x4},' ')
lily = lily .. "\n(rcurveto " .. koordinaten .. ")"
svg = svg .. "\nc " .. koordinaten
end
if mypath[i-1] == "c" or mypath[i-1] == "s" then
z1 = y5 - y3
z2 = y6 - y4
lily = lily .. "\n(rcurveto " .. z1 .. " " .. z2 .. " " .. table.concat(mycube[i],' ') .. ")"
svg = svg .. "\nc " .. z1 .. " " .. z2 .. " " .. table.concat(mycube[i],' ')
end
end
-------------------------------------------------------------------------------------------------
if letter == "c" then -- bezier kurve
if mydim % 6 ~= 0 then
return lily, "ungültiger Pfad " .. letter .. table.concat( mycube[i], ", " ) .. "\n" .. output
end
-- wenn mehrere c hintereinander, aufdröseln!
elts = mydim / 6
for j = 1, elts do
x1, x2, x3, x4, x5, x6 = unpack(mycube[i], j * 6 - 5, j * 6)
coords = { unpack(mycube[i], j * 6 - 5, j * 6) }
actx = actx + x5 -- Koordinaten des aktuellen Punktes aktualisieren
acty = acty + x6
lily = lily .. "\n(rcurveto " .. table.concat(coords,' ') .. ")"
svg = svg .. "\nc ".. table.concat(coords,' ')
if tonumber(actx) < minx then minx = tonumber(actx) end -- Ausmaße des Pfades mitberechnen
if tonumber(actx) > maxx then maxx = tonumber(actx) end
if tonumber(acty) < miny then miny = tonumber(acty) end
if tonumber(acty) > maxy then maxy = tonumber(acty) end
end
--svg = svg .. "\nc ".. table.concat(mycube[i],' ')
end
-------------------------------------------------------------------------------------------------
if tonumber(actx) < minx then minx = tonumber(actx) end -- Ausmaße des Pfades mitberechnen
if tonumber(actx) > maxx then maxx = tonumber(actx) end
if tonumber(acty) < miny then miny = tonumber(acty) end
if tonumber(acty) > maxy then maxy = tonumber(acty) end
-------------------------------------------------------------------------------------------------
if letter == "z" then -- Pfad wird geschlossen
svg = svg .. "\nz"
lily = lily .. "\n(closepath)"
end
end
return lily, false, tostring(minx), tostring(maxx), tostring(miny), tostring(maxy), svg
end
function p.svg2lily(frame)
local a = frame.args -- direkt per #invoke: übergeben
local b = frame:getParent().args -- an die Vorlage übergebene Parameter
local pfad = trim(b["pfad"] or a["pfad"] or b[1] or a[1] or '')
if pfad == '' then return "<div class=\"blue-gradient fett noclick lily\" style=\"font-size: 1.4em; padding: 10px\">Pfad fehlt</div>" end
local retour = trim(b["test"] or a["test"] or '')
local was = trim(b["was"] or a["was"] or '')
local zpath, ___ = '', ''
local vbox, _, __
local path, fehler, minx, maxx, miny, maxy, mysvg
local minmax, viewb = {}, {}
local output = ''
local lilyout, lily = '', ''
local svgout, svg = '', ''
local viewbox, vboxen = '', ''
local svgheader = '\n<svg version=\"1.1\" viewBox=\"$\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"'
local width, height, svgstring = '', '', ''
if pfad == '' then return "Modul Lilypond: kein SVG-Pfad angegeben" end
lily, fehler, minx, maxx, miny, maxy, mysvg = lpath(path)
if type(fehler) == "string" then
return "Pfad enthält Fehler\n" .. "\n" .. fehler .. "\n" .. path .. "\n" .. lily
end
_ = "\n#(define mypath$ \'(\n" .. lily .. "\n))" -- pfaddef:gsub("[§]",lily)
__ = _:gsub("[$]", tostring(i))
___ = "\n_: " .. _ .. '\ngsub("[$]", tostring(i)) ' .. __
output = output .. __
width = tonumber(maxx) - tonumber(minx)
height = tonumber(maxy) - tonumber(miny)
viewbox = minx .. " " .. miny .. " " .. tostring(width) .. " " .. tostring(height)
vboxen = vboxen .. "\nPfad Nr. " .. i .. ' viewbox: ' .. viewbox .. " min/max: " .. table.concat({ minx, miny, maxx, maxy }, ', ')
vbox = svgheader:gsub("[$]", viewbox)
svgout = svgout .. vbox .. mysvg .. "\" />\n</svg>"
if retour ~= '' and was == "boxen" then return vboxen end
if retour ~= '' and was == "lily" then return lilys end
if retour ~= '' and was == "out" then return ___ end
lilyout = '{{#tag:tabber|Pfad(e) oneclick=<syntaxhighlight lang=\"latex\" style=\"display: inline-block\" class=\"oneclick\">' ..
output .. '</syntaxhighlight>\n{{!}}-{{!}}\nPfad(e)=\n<syntaxhighlight lang=\"latex\" style=\"display: inline-block\">' ..
output .. "</syntaxhighlight>}}"
svg = '{{#tag:tabber|SVG Pfad oneclick=<syntaxhighlight lang=\"xml\" style=\"display: inline-block\" class=\"oneclick\">' ..
svgout .. '</syntaxhighlight>\n{{!}}-{{!}}\nSVG Pfad=\n<syntaxhighlight lang=\"xml\" style=\"display: inline-block\">' ..
svgout .. "</syntaxhighlight>}}"
return frame:preprocess('\n==Lilypond Path==\n' .. lilyout .. "\n==SVG Code==\n" .. svg)
end
function p.score(frame)
local a = mw.getCurrentFrame():getParent().args -- sollte alle Aufrufe abdecken
if empty(a) then a = mw.getCurrentFrame().args end
local mus = music
for k, v in pairs(a) do
mus = v
break
end
local b = frame:extensionTag { name = 'score', content = mus, args = { raw = '1' } }
return b
end
function p.midi(frame)
-- dieser Modul macht die Erweiterung Score transkludierbar
-- die Anzeige der Noten wird unterdrückt, statt dessen wird ein wählbares Markup angezeigt
-- dies kann z.B. eine Überschrift etc. sein
local a = mw.getCurrentFrame():getParent().args -- sollte alle Aufrufe abdecken
if empty(a) then a = mw.getCurrentFrame().args end
local _mus = ''
local mus = music
local _midi = a.midi or ''
local _markup = a.markup or gclef
_markup = '\\markup ' .. _markup
for k, v in pairs(a) do
if string.lower(k) ~= "midi" and string.lower(k) ~= "markup" then
mus = v
break
end
end
_mus = '\\language "deutsch"\
\\paper { tagline=##f }\
' .. _markup .. '\
\\score { \
' .. mus .. '\
\\midi { ' .. _midi .. ' }\
}\
'
local b = frame:extensionTag { name = 'score', content = _mus, args = { raw = '1', vorbis = '1' } }
return b
end
function p.mixi(frame)
-- dieser Modul macht die Erweiterung Score transkludierbar
-- die Anzeige der Noten wird unterdrückt, statt dessen wird ein wählbares Markup angezeigt
-- dies kann z.B. eine Überschrift etc. sein
local a = mw.getCurrentFrame():getParent().args -- sollte alle Aufrufe abdecken
if empty(a) then a = mw.getCurrentFrame().args end
local _mus = ''
local mus = music
local _midi = a.midi or ''
local _markup = a.markup or elise
_markup = '\\markup ' .. _markup
for k, v in pairs(a) do
if string.lower(k) ~= "midi" and string.lower(k) ~= "markup" then
mus = v
break
end
end
_mus = '\\language "deutsch"\
\\paper { tagline=##f }\
' .. _markup .. '\
' .. mus .. '\
'
local b = frame:extensionTag { name = 'score', content = _mus, args = { raw = '1', vorbis = '1' } }
return b
end
function p.midix(frame)
-- dieser Modul macht die Erweiterung Score transkludierbar
-- die Anzeige der Noten wird unterdrückt, statt dessen wird ein wählbares Markup angezeigt
-- dies kann z.B. eine Überschrift etc. sein
-- zusätzlich können Variablen definiert werden
local a = mw.getCurrentFrame():getParent().args -- sollte alle Aufrufe abdecken
if empty(a) then a = mw.getCurrentFrame().args end
local _mus = ''
local mus = a.mus or a[1] or music
local var = a.var or a[2] or '' -- Lilypond Variablendefinition, muss außerhalb von score stehen
local _midi = a.midi or ''
local _markup = a.markup or gclef
_markup = '\\markup ' .. _markup
_mus = '\\language "deutsch"\
\\paper { tagline=##f }\
' .. _markup .. '\
' .. var .. '\
\\score { \
' .. mus .. '\
\\midi { ' .. _midi .. ' }\
}\
'
local b = frame:extensionTag { name = 'score', content = _mus, args = { raw = '1', vorbis = '1' } }
return b
end
function p.hili(frame)
-- Syntaxhighlighting von Lilypond-Code
-- standardmäßig als Latex formatiert, weil es keine spezielle Lilypond-Syntax gibt
local a = frame.args -- Direktaufruf via invoke
local b = frame:getParent().args -- Aufruf via Vorlage
local mus = music
for k, v in pairs(a) do
if string.lower(k) ~= "lang" then -- damit kann der Parameter beliebig benannt werden, nur lang wird ausgenommen
mus = v
break
end
end
for k, v in pairs(b) do
if string.lower(k) ~= "lang" then -- damit kann der Parameter beliebig benannt werden, nur lang wird ausgenommen
mus = v
break
end
end
local _lang = a.lang or b.lang or 'latex'
local _ = frame:extensionTag { name = 'syntaxhighlight', content = mus, args = { lang = _lang } }
return _
end
function p.hilio(frame)
-- Syntaxhighlighting von Lilypond-Code
-- wird nur bei Adminaccount angezeigt
-- standardmäßig als Latex formatiert, weil es keine spezielle Lilypond-Syntax gibt
local a = frame.args -- Direktaufruf via invoke
local b = frame:getParent().args -- Aufruf via Vorlage
local mus = music
for k, v in pairs(a) do
if string.lower(k) ~= "lang" then -- damit kann der Parameter beliebig benannt werden, nur lang wird ausgenommen
mus = v
break
end
end
for k, v in pairs(b) do
if string.lower(k) ~= "lang" then -- damit kann der Parameter beliebig benannt werden, nur lang wird ausgenommen
mus = v
break
end
end
local _lang = a.lang or b.lang or 'latex'
local _ = frame:extensionTag { name = 'syntaxhighlight', content = mus, args = { lang = _lang } }
return frame:preprocess('{{Only|1=' .. _ .. '}}')
end
function p.pdf(frame)
local a = mw.getCurrentFrame():getParent().args
if empty(a) then a = mw.getCurrentFrame().args end
local name = a[1] or '{{PAGENAME}}' -- Name der PDF-Datei
local titel = a[5] or name -- Linkbeschreibung
-- Achtung, bei benannten Parametern werden Leerzeichen am Anfang und am Ende entfernt
local tonart = a.art or a[2] or 'dur' -- Tonart: Dur, Moll etc
local pre = a.pre or a[3] or '' -- was vor der Tonartbezeichnung kommen soll, z.B. " Gipsy-Scale" überflüssig???
local suf = a.suf or a[4] or 'Dur' -- was nach der Tonartbezeichnung kommen soll, z-B, " Dur"
-- der Name der PDF-Datei setzt sich dann folgendermaßen zusammen: name .. pre .. tonart .. suf
if string.lower(tonart) == 'dur' then
leiter = qidur
else
leiter = qimol
end
local vorname = trim(name) .. ' ' .. trim(pre) .. ' '
local suffx = trim(suf)
pdf = frame:expandTemplate { title = 'pdf', args = { vorname .. leiter[1] .. ' ' .. suffx } }
qilen = #leiter -- Zahl der Elemente im Quintenzirkel
for i=2,qilen do -- alle Tonleitern im Quintenzirkel abarbeiten
pdf = pdf .. ' · ' .. frame:expandTemplate { title = 'pdf', args = { vorname .. leiter[i] .. ' ' .. suffx } }
end
return pdf
end
function p.scale(frame)
local a = mw.getCurrentFrame():getParent().args -- bei Aufruf über Vorlage ist :getParent(). erforderlich
if empty(a) then a = mw.getCurrentFrame().args end -- entweder Direktaufruf oder über Vorlage, so bin ich für alles gerüstet
local pre = a.pre or a[1] or '{{PAGENAME}}'
local suf = a.suf or a[2] or 'Dur'
local art = a.art or a.geschlecht or a[3] or 'dur'
local link = a.link or a[4] or '' -- Linkbeschriftung
local templ = a.template or a.templ or a.vorlage or a[5] or '' -- soll eine Vorlage angewendet oder nur ein Link erzeugt werden
local trenn = a.trenn or a.trennzeichen or a[6] or '·' -- das Trennzeichen kann umdefiniert werden
local leiter = qidur
if art == 'moll' then leiter = qimol end
if art == 'all' then leiter = qiall end
pre = trim(pre) .. ' '
suf = ' ' .. trim(suf)
trenn = ' ' .. trenn .. ' '
local page_name = pre .. leiter[1] .. suf
if link == '' then
linkp = page_name
else
link = link .. ' '
linkp = link .. leiter[1] .. suf
end
qilen = #leiter -- Zahl der Elemente im Quintenzirkel
local _ = ''
if templ ~= '' then
_ = frame:expandTemplate { title = templ, args = { page_name } }
for i=2,qilen do
page_name = pre .. leiter[i] .. suf
_ = _ .. trenn .. frame:expandTemplate { title = templ, args = { page_name } }
end
return _
end
-- es wurde keine Vorlage angegeben, nur Links erzeugen
_ = frame:preprocess( '[[' .. page_name .. '|' .. linkp .. ']]' )
for i=2,qilen do -- alle Tonleitern im Quintenzirkel abarbeiten
page_name = pre .. leiter[i] .. suf
if link == '' then
linkp = page_name
else
linkp = link .. leiter[i] .. suf
end
_ = _ .. trenn .. frame:preprocess( '[[' .. page_name .. '|' .. linkp .. ']]' )
end
return _
end
function p.rep(frame)
local repetitions = tonumber(frame.args[2])
if not repetitions then
return frame.args[1] or ''
end
return string.rep( frame.args[1] or '', repetitions )
end
function trim(s)
-- entfernt Weißraum an den beiden Enden des Strings
if type(s) ~= "string" then return s end -- es muss ein String sein
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function empty (self)
-- es gibt keine eingebaute Funktion, um zu überprüfen, ob eine Tabelle leer ist
-- diese Funktion liefert true, wenn die Tabelle leer ist
-- hilfreich bei frame.args oder frame:parent().args etc.
for _, _ in pairs(self) do
return false
end
return true
end
function round(num, numDecimalPlaces)
if type(num) ~= "number" or type(numDecimalPlaces) ~= "number" then return false end
return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
end
return p