Hello David,

> But there’s got to be a way to access these properties, right?  Or is the 
\book
> (\bookpart, \score) context just not available?

I think the book header is not available at time of markup evaluation. What is 
available is the paper-block via layout. So what we could do is

%%%
#(define-markup-command (from-layout layout props symbol) (symbol?)
   (interpret-markup layout props
                     (ly:output-def-lookup layout symbol empty-markup)))

\book {
  \header {
    testfield = "test"
  }
  #(for-each
    (lambda (pair)
      (ly:output-def-set-variable! (ly:book-paper $current-book) (car pair) 
(cdr pair)))
    (car (headers-property-alist-chain (list (ly:book-header $current-
book)))))
  \markup \from-layout #'header:testfield
}
%%%

This injects header variables into the current book-block and thus makes them 
accessible via layout. `from-layout` mimicks `from-property` but takes the 
value from the layout instead.

We can even turn this into a nice markup command and make this compatible with 
bookpart and top-level:

%%%
#(define-markup-command (from-layout layout props symbol) (symbol?)
   (interpret-markup layout props
                     (ly:output-def-lookup layout symbol empty-markup)))

inject-header =
#(define-scheme-function () ()
   (let ((header $defaultheader)
         (paper #{ \paper { } #}))
     (if $current-book
         (set! header (ly:book-header (or $current-bookpart $current-book))))
     (for-each
      (lambda (pair)
        (ly:output-def-set-variable! paper (car pair) (cdr pair)))
      (car (headers-property-alist-chain (list header))))
     paper))

\header {
  testfield = "outer"
}
\inject-header
\book {
  \header {
    testfield = "middle"
  }
  \inject-header
  \bookpart {
    \header {
      testfield = "inner"
    }
    \inject-header
    \markup { A: \from-layout #'header:testfield }
  }
  \markup { B: \from-layout #'header:testfield }
}
\markup { C: \from-layout #'header:testfield }
%%%

Handling score headers can also be done, though it would need to be done 
differently. One could do it like

%%%
score-inject-header =
#(define-scheme-function (score) (ly:score?)
   (let ((header (ly:score-header score))
         (layout #{ \layout { } #}))
     (for-each
      (lambda (pair)
        (ly:output-def-set-variable! layout (car pair) (cdr pair)))
      (car (headers-property-alist-chain (list header))))
     (ly:score-add-output-def! score layout)
     score))

\score-inject-header\score {
  \header {
    testfield = "score"
  }
  s4-\markup { 0: \from-layout #'header:testfield }
}
%%%

Cheers,
Tina

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to