In my LilyPond file (which is a minimal excerpt in a recent project I am
working on), I created a Scheme-based music function to set grob
properties by passing an `alist`. The method works by merging the given
property `alist` to the `details` grob property. In order not to get
confused with the builtin props I added a prefix.
The key code is in the `useScore` variable definition. WHen I am adding
properties for different grobs separately, It works with no problem.
However, when I put all properties in a hash table and and use a
`hash-for-each` to traverse all the property entries and assign them to
the corresponding grobs, I got an error. I don't know why this error
occurs. So what is wrong with my program?
\version "2.24.4"
#(define (alist-prop-updater prop new-data)
(grob-transformer prop
(lambda (grob original)
(if (or (null? original) (eq? original #f))
(alist-copy new-data)
(begin
(for-each
(lambda (entry)
(let*
(
(k (car entry)) (v (cdr entry))
(original-entry (sloppy-assoc k original))
)
(if original-entry
(set-cdr! original-entry v)
(append! original `(,entry))
)
)
)
new-data
)
original
)
)
)
)
)
#(define score-config-prefixer (symbol-prefix-proc 'SCORE:))
alistPropUpdate = #(define-music-function
(grobsym prop new-data) (symbol? symbol? list?)
#{
\propertyTweak $prop #(alist-prop-updater prop new-data) $grobsym
#}
)
configScore = #(define-music-function
(grobsym config-table) (symbol? list?)
#{
\alistPropUpdate $grobsym details
#(map
(lambda (entry)
(let*
(
(k (car entry)) (v (cdr entry))
(prefixed-k (score-config-prefixer k))
)
(cons prefixed-k v)
)
)
config-table
)
#}
)
% a hash table containing all configurations
"SCORE:global-config" = #(alist->hash-table '(
(Clef . (
(line-thickness . .075)
(change-clef-size . .84)
))
(Notehead . (
(line-thickness . .1)
))
(Rest . (
(slope . .32)
(line-thickness . .09)
(max-h-span . 1)
(tip-edges . 12)
(tip-offset . (0.23 . 0.51))
(tip-radius . 0.24)
))
(Accidental . (
(use-double-sharp . #t)
(line-thickness . 0.08)
(symbol-pad . 0.1)
(paren-pad . 0.2)
))
))
useScore = {
% This works ...
%{
\configScore Clef #'(
(line-thickness . .075)
(change-clef-size . .84)
)
\configScore NoteHead #'(
(line-thickness . .1)
)
\configScore Rest #'(
(slope . .32)
(line-thickness . .09)
(max-h-span . 1)
(tip-edges . 12)
(tip-offset . (0.23 . 0.51))
(tip-radius . 0.24)
)
\configScore Accidental #'(
(use-double-sharp . #t)
(line-thickness . 0.08)
(symbol-pad . 0.1)
(paren-pad . 0.2)
)
%}
% but this will cause an error
% error message:
%{
test-scheme.ly:36:70: error: bad grob property path (Notehead details)
\propertyTweak #prop #(alist-prop-updater prop new-data) $grobsy
test-scheme.ly:112:4: error: error in #{ ... #}
#
(hash-for-each
...
%}
#(hash-for-each
(lambda (grobsym config-table)
#{
\configScore $grobsym #(alist-copy config-table)
#}
)
SCORE:global-config
)
}
\layout {
\context { \Score \useScore }
}
\score {
\new Staff {
\relative c' {
c d e f g f e d c
}
}
}