Guten Abend!
Als 2. Scheme-Etüde (nicht besonders musikspezifisch) habe ich nun mal den Rahmen für ein Miniprogramm zusammengeschraubt, das Infos aus einer Lilypond-Datei (die im Normalfall natürlich aus den musikalischen Kontexten einzusammeln wären) in eine JSON-Datei schreiben könnte - zwecks leichteren Datenaustausches, zur Weiterverarbeitung in anderen Programmen (z.B. auch im Browser).
Auch, wenn es offenbar auf diese Weise funktioniert, bin ich für jegliche Hinweise, die vielleicht zu einem besseren und eleganteren Code führen, dankbar.
Insbesondere haben sich die folgenden Fragen ergeben:
1. Kann man den absoluten Pfad zur aktuellen Datei tatsächlich nur über den Zugriff auf die command line auslesen, oder geht das auch direkter?
2. Wie kann man in Scheme/Guile einen garantiert universell funktionierenden path separator ansprechen? – Aus der guile-Referenz bin ich da nicht ganz schlau geworden.
3. Gibt es evtl. schon so etwas à la „ly2json“? - Dann bräuchte man das Rad ja nicht neu zu erfinden.
\version "2.19.37"
% Zur Übung sollen hier die Elemente aus der folgenden Liste in eine JSON-Datei kopiert werden,
% die im gleichen Verzeichnis liegen soll wie die vorliegende Lilypond-Datei:
#(define elemente_als_liste '("Element 1"
"Element 2"
"Element 3"
"Element 4"
"Element 5"
"Element 6"
"Element 7"
"Element 8"))
% Die Funktion "command-line" gibt offenbar eine in Klammern eingefasste String-Liste zurück,
% deren letztes Element der absolute Dateipfad der vorliegenden Lilypond-Datei ist:
#(define (generiere_neuen_absoluten_pfad_zu_einer_js_datei_im_gleichen_verzeichnis)
(let ((kommandozeile (object->string (command-line))))
(string-append
(substring kommandozeile
(+ (string-rindex kommandozeile #\sp) 2)
(+ (string-rindex kommandozeile #\/) 1))
"Und hier ist das neue JSON-Objekt.js")))
#(define (erstelle_ein_json_objekt_und_schreibe_es_in_die_datei)
(let ((elemente_als_string "")
(ausgabe ""))
; In rekursiven Aufrufen entnimmt die folgende Funktion ein Element nach dem anderen von vorne aus der Liste
; und fügt die Elemente zu einem String zusammen (dazwischen jeweils: ", "):
(define (verarzte_das_naechste_element_aus_der_liste aktuelle_liste)
(cond ((null? aktuelle_liste) aktuelle_liste)
(else
(set! elemente_als_string
(string-append elemente_als_string (car aktuelle_liste) "\", \""))
(verarzte_das_naechste_element_aus_der_liste (cdr aktuelle_liste)))))
; Um daraus ein rechtschaffenes JSON-Objekt zu machen, sind noch ein paar umschließende Elemente erforderlich,
; wobei zuvor am Ende drei überflüssige Zeichen (, ") zu löschen sind:
(define (stoepsele_das_json_objekt_zusammen)
(set! ausgabe
(string-append
"{\n \"Inhalt der Lilypond-Liste\": [\""
(substring elemente_als_string 0 (- (string-length elemente_als_string) 3))
"]\n}")))
; Der Parameter "w" beim Öffnen des Ausgabeports sorgt dafür, dass bereits vorhandene Dateiinhalte überschrieben werden
; (der Parameter "a" würde den neuen String an den vorhandenen Inhalt anhängen):
(define (übertrage_das_neugeschaffene_kunstwerk_in_die_datei)
(let (
(ausgabeport
(open-file
(generiere_neuen_absoluten_pfad_zu_einer_js_datei_im_gleichen_verzeichnis) "w")))
(format ausgabeport ausgabe)
(close ausgabeport)
(display "\nDie JSON-Datei wurde im gleichen Pfad wie die Lilypond-Datei erstellt (bzw. dort ueberschrieben).")))
(verarzte_das_naechste_element_aus_der_liste elemente_als_liste)
(stoepsele_das_json_objekt_zusammen)
(übertrage_das_neugeschaffene_kunstwerk_in_die_datei)))
#(erstelle_ein_json_objekt_und_schreibe_es_in_die_datei)
Danke und herzliche Grüße
Jost