Hello, > Le 29/06/2021 10:42, Matt Hood <mattho...@gmail.com> a écrit : > > > Hi everyone, > > I'm working with lilypond output in the browser, using its SVG export > function. Lilypond permits attaching attributes to particular kinds of > grobs, e.g.: > > { > \override NoteHead.output-attributes = > #'((class . "NoteHead")) > c > } > > The above will cause all NoteHead objects to have the following SVG: > > <g class="NoteHead"> > ...NoteHead grob SVG elements... > </g> > > My question is: how can I make it so that all graphical objects have > their name in the class attribute? > > I've tried using the following scheme function: > > #(define (add-class grob grob-origin context) > (let (name (cdr (assoc 'name
This lacks a pair of parentheses around the bindings. You might have posted the wrong version of your code. > (ly:grob-property grob 'meta)))) > (set! (ly:grob-property grob 'output-attributes) '((class > . name))))) '((class . name)) is literally a list containing a list of the symbols 'class and 'name, which is not very useful ;-) You rather want quasiquoting: `((class . ,name)). > > This successfully (I believe) extracts the correct name, and assigns > it to the output-attributes field. As per the instructions in the > lilypond documentation, I then attempted to use \applyOutput Score > #add-class to apply this function to all graphical objects, but it > didn't supply all of the required objects. My attempted code is below: > > \applyOutput Score #add-class > \score { > \new RhythmicStaff { > c'2 c'16 c' c' c' \tuplet 5/4 { c'16 c' c' c' c' } > } > } > > If I add a print call to the add-class function, I can see that it was > called for the objects with the following names from which crucial > objects such as NoteHead are missing: > > NonMusicalPaperColumn > PaperColumn > Clef > TimeSignature > LedgerLineSpanner > StaffSymbol > VerticalAxisGroup > SystemStartBar > SpacingSpanner > VerticalAlignment > StaffSpacing > BreakAlignment > LeftEdge > BreakAlignGroup > BreakAlignGroup > BreakAlignGroup I'm not sure how you got this output. The way the code is written, the \applyOutput is separate from the main \score, so it is a score of its own containing no actual music. If you move it to the beginning of the music, you should get at least one NoteHead, as illustrated here: \version "2.22.0" { \applyOutput Score #(lambda (grob origin context) (ly:message "~s" grob) (set! (ly:grob-property grob 'color) red)) << { c d e f } \\ { g a b c' } >> } This also shows the reason why \applyOutput isn't working as you are expecting. \applyOutput applies to one single time step. Think of it as a \once \override. I don't think there currently exists an equivalent of \applyOutput for the whole score (perhaps because there were not many use cases before output-attributes). However, this problem can be solved by writing an engraver (those are the powerful tools that \applyOutput uses under the hood). \version "2.22.0" \layout { \context { \Score \consists #(lambda (context) (make-engraver (acknowledgers ((grob-interface engraver grob source-engraver) (set! (ly:grob-property grob 'output-attributes) `((class . ,(grob::name grob)))))))) } } << { c d e f } \\ { g a b c' } >> Out of curiosity: what tool is this for? Best, Jean