+(define-public (grob-transformer property func)
+ "Create an override value good for applying @var{func} to either
+pure or unpure values. @var{func} is called with the respective grob
+as first argument and the default value (after resolving all callbacks)
+as the second."
+ (define (worker self container-part grob . rest)
+ (let* ((immutable (ly:grob-basic-properties grob))
+ ;; We need to search the basic-properties alist for our
+ ;; property to obtain values to offset. Our search is
+ ;; complicated by the fact that calling the music function
+ ;; `offset' as an override conses a pair to the head of the
+ ;; alist. This pair must be discounted. The closure it
+ ;; contains is named `self' so it can be easily recognized.
+ ;; If `offset' is called as a tweak, the basic-property
+ ;; alist is unaffected.
+ (target (find-value-to-offset property self immutable))
+ ;; if target is a procedure, we need to apply it to our
+ ;; grob to calculate values to offset.
+ (vals (cond ((procedure? target) (target grob))
+ ;; Argument lists for a pure procedure pulled
+ ;; from an unpure-pure-container may be
+ ;; different from a normal procedure, so we
+ ;; need a different code path and calling
+ ;; convention for procedures pulled from an
+ ;; container as opposed to from the property
+ ((ly:unpure-pure-container? target)
+ (let ((part (container-part target)))
+ (if (procedure? part)
+ (apply part grob rest)
+ part)))
+ (else target))))
+ (func grob vals)))
+ ;; return the container named `self'. The container self-reference
+ ;; seems like chasing its own tail but gets dissolved by
+ ;; define/lambda separating binding and referencing of "self".
+ (define self (ly:make-unpure-pure-container
+ (lambda (grob)
+ (worker self ly:unpure-pure-container-unpure-part grob))
+ (lambda (grob . rest)
+ (apply worker self ly:unpure-pure-container-pure-part
+ grob rest))))
+ self)
+