Reflection in LilyPond/Scheme? [GELÖST]

Begonnen von ingmar, Samstag, 20. Januar 2018, 21:44

« vorheriges - nächstes »

ingmar

Hallo,

ist es eigentlich möglich, in LilyPond definierte Variablen von außen abzufragen? Ich stelle mir das so vor: LilyPond kompiliert ein File und liefert dem Aufrufer als Resultat eine Liste der darin definierten Variablen - die Namen würden mir schon reichen, die Werte brauche ich (erstmal) nicht. Aufrufen möchte ich das zum Beispiel aus Python.

Beispiel:

\version "2.19.64"

A = 1
BB = "zwei"
CCC = { c d e f g }
% DDDD = "auskommentiert"


Das File würde ich mit LilyPond aufrufen und als Antwort einen String bekommen: "A, BB, CCC". Oder, nicht ganz so elegant, aber brauchbar: LilyPond würde ein File schreiben, das diese Liste von Variablennamen enthält.

Geht sowas ohne große Klimmzüge? : - )

Danke, Gruß,
--ingmar

harm6

#1
Hallo Ingmar,

ich glaube nicht, daß das so einfach ist...

Zunächst stellt sich die Frage was genau denn eine im file definierte Variable ist.
Es gibt ja
1) In lilypond-syntax definierte: BB = "zwei"
2) In scheme-syntax definierte: #(define ... ...)
3) Definitionen, die a) sowieso präsent sind (in current-module) b) unter der Hand definiert werden.

Um 3a) zu betrachten (alphabetisch sortierte Namen, ohne die entsprechenden Setzungen):

#(pretty-print
(sort
   (map
     car
     (ly:module->alist (current-module)))
   (lambda (p q) (symbol<? p q))))

Eine lange Liste...

Zu 3b)
Schon { r4 } fügt eine neue Definition hinzu, nämlich einen toplevel-score...

Somit ist eine Definition eigentlich das, was der parser als Definition betrachtet. Und da fängt es dann an haarig zu werden.

Vielleicht geht folgendes in die von Dir gewünschte Richtung:


\version "2.19.65"

#(define current-module-bindings (ly:module->alist (current-module)))

A = 1
BB = "zwei"
CCC = { c d e f g }
% DDDD = "auskommentiert"

% { r4 }

#(let ((bindings
         (assoc-remove!
           (lset-difference
             equal?
             (ly:module->alist (current-module))
             current-module-bindings)
           'current-module-bindings)))
  (pretty-print
    (map car bindings))
    )


Gruß,
  Harm

ingmar

ZitatSchon { r4 } fügt eine neue Definition hinzu, nämlich einen toplevel-score...

Somit ist eine Definition eigentlich das, was der parser als Definition betrachtet. Und da fängt es dann an haarig zu werden.

Nunja, Definition mag sein - aber es muss ja auch mit einem Symbol assoziiert werden, damit man es als "Variable" bezeichnen kann...

Das von dir gelieferte Beispiel macht jedenfalls genau, was ich gesucht habe! Kompliment! Ist ja erstaunlich, was man unterwegs so alles an Variablen definiert! : - )

(Wie dein Code eigentlich funktioniert, wage ich kaum zu ahnen ...)


Danke und Gruß,
--ingmar

harm6

#3
Zitat von: ingmar am Montag, 22. Januar 2018, 19:59
ZitatSchon { r4 } fügt eine neue Definition hinzu, nämlich einen toplevel-score...

Somit ist eine Definition eigentlich das, was der parser als Definition betrachtet. Und da fängt es dann an haarig zu werden.

Nunja, Definition mag sein - aber es muss ja auch mit einem Symbol assoziiert werden, damit man es als "Variable" bezeichnen kann...

Wird es, nämlich mit 'toplevel-scores.
Versuch mal
toplevel-scores = #'()
ans Ende eines files zu setzen: wenn Du nicht gerade ein anderes book, o.ä. definiert hast wird kein pdf erstellt.

Zitat von: ingmar(Wie dein Code eigentlich funktioniert, wage ich kaum zu ahnen ...)
- Alle default-definitions sind in (current-module). Die lese ich aus und pack sie als alist in 'current-module-bindings
- Nach dem sonstigen file-Inhalt, lese ich aus was sich jetzt in (current-module) befindet und "subtrahiere" diese zwei Listen, um zu erhalten was neu ist. Zum Schluß muss ich dann noch meine eigene 'current-module-bindings-definition löschen.
- Ausgabe ist eine Liste mit Namen von definitions.

Voilà

Gruß,
  Harm


ingmar

#4
Hm! Es klappt doch noch nicht ganz so, wie ichs mir erhofft hatte.

Wenn ich ein beliebiges Lilypond-Skript, das aber nur Variablendefinitionen enthält, mit Harms Code erweitere und dann in Frescobaldi aufrufe, passiert folgendes:

* Es werden keine sichtbaren Noten erzeugt (klar, denn ich definiere ja nur Variablen)
* Frescobaldis Protokoll-Tab listet mir die Variablennamen auf.
Wunderbar!

...aber nun rufe ich das gleiche Skript aus dem Terminal auf: <Pfad>/LilyPond <Pfad>typicalFile.ly

* Ich erwarte, diese Liste der Variablennamen nun im Terminalfenster zu lesen.
* Stattdessen öffnet sich ein LilyPond-Fenster, das mir mein File anzeigt. Im Menu könnte ich das Kompilieren starten. Das hilft nun leider nicht weiter.
* In .../Documentation/usage/command_002dline-usage hab ich nach Hinweisen gesucht: "Keine GUI öffnen, sofort kompilieren.hätte ich erwartet, einen Hinweis zu finden. Aber offenbar übersehe ich ihn.
* Hab mal versucht, als weiteren Parameter einen existierenden Folder zu übergeben.. könnte ja sein, wenn ich LilyPond sage, wo das (hier nicht erwartete) Ergebnis hingehen soll, dass es dann gleich kompiliert. Aber Pustekuchen.

Ich muss hinzufügen, dass ich auf einem Mac arbeite. Aber grundsätzlich ist auch das in Unix-System, so dass ein Verfahren, das unter Linux zum Ziel führt, hier auch nicht ganz falsch sein sollte...

Tja - wir sind sicher knapp vor dem Ziel... weiß jemand weiter? Danke!
--ingmar

Edit: Fehlerhaft stehengebliebene Copy&Paste-Rest weggestrichen.

harm6

Hallo ingmar,

mir ist Deine Frage nicht in allen Einzelheiten klar.
Soweit es Frescobaldi betrifft kann ich Dir sowieso nicht weiterhelfen, ich hab's nicht auf dem Rechner.

Aber wenn ich folgenden Code:

\version "2.19.65"

#(define current-module-bindings (ly:module->alist (current-module)))

A = 1
BB = "zwei"
CCC = { c d e f g }
% DDDD = "auskommentiert"

%C{ c'4 }

#(let ((bindings
         (assoc-remove!
           (lset-difference
             equal?
             (ly:module->alist (current-module))
             current-module-bindings)
           'current-module-bindings)))
  (pretty-print
    (map car bindings))
    )
   
% toplevel-scores = #'()

in ein file packe und es lily-vars.ly nenne und im terminal
lilypond lily-vars.ly
eingebe, erscheint:
Zitat von: terminal
GNU LilyPond 2.19.65
Processing `lilypondH/Test/forum/test/vars/lily-vars.ly'
Parsing...(BB A CCC)

Success: compilation successfully completed

Ist das nicht was Du wolltest?

Gruß,
  Harm

ingmar

Danke für die Antwort. Ich habe die Lösung gefunden. Ist einfach eine Apple-Verwirrung.

Zur Erklärung:
* Wenn ich in das Terminals eingebe LilyPond (oder auch lilypond), bekomme ich eine Fehlermeldung: -bash: LilyPond: command not found
* Also gebe ich den gesamten Pfad ein, mit dem Ergebnis: -bash: <MEIN DIRECTORY>/LilyPond 3.app: is a directory
* Ja, das ist ein Folder! Im Dateibrowser wird nämlich auf Macs der Programmfolder als verschlossene "Kiste" dargestellt - offenbar, damit der Enduser daran nicht herumspielt. Natürlich muss man aber die ausführbare Datei angeben. Ich kann diese "Kiste", den Folder, auch durchaus öffnen und Vermutungen darüber anstellen, welches File nun aufzurufen ist. Ich hatte mich entschieden für: <MEIN DIRECTORY>/LilyPond\ 3.app/Contents/MacOS/LilyPond.
* Klingt erstmal gut, ist aber halt DIE FALSCHE DATEI! - Das Ergebnis hatte ich ja in meinem letzten Posting beschrieben: Die Anwendung öffnet sich und lädt das File in einem Textfenster.
* Um einfach zu kompilieren, muss eine andere Binary aufgerufen werden: <MEIN DIRECTORY>/LilyPond\ 3.app/Contents/Resources/bin/lilypond
* Das wird auch an einer etwas versteckten Stelle, hier, beschrieben. Und damit klappt es auch.

Ist also eine reine Mac-Spezialität, und hat gar nichts mit deiner Lösung, Harms, zu tun.

Danke nochmal, Gruß,
--ingmar