Problem mit Übernahme von Angaben aus header in tocItem mit with-header-scopes

Begonnen von martinmagtenor, Mittwoch, 11. Dezember 2024, 20:54

« vorheriges - nächstes »

martinmagtenor

Harm hatte im Beitrag Übernahme von Angaben in header in tocItem eine tolle Lösung für das Kernproblem beigetragen.

Mein Projekt schreitet voran und da sind neue Schwierigkeiten sichtbar geworden, für die ich keine Lösung gefunden habe: Das entstehende Inhaltsverzeichnis ist nicht korrekt, da der jeweils letzte Titel (piece aus \header { }) eines Bookpart für alle Einträge wiederholt wird!

Das ganze Projekt besteht aus vielen, eher kleinen Orgelkompositionen, einige sind sind nur eine Zeile lang, andere gehen auch über 5 bis 6 Seiten. Etliche Stücke gehören zusammen, werden deshalb in einem bookpart zusammengefasst, sollen aber jeweils einen eigenen Eintrag im Inhaltsverzeichnis erhalten.

D.h. in einem bookpart stehen hintereinander mehrere Partituren (score). Wegen der unterschiedlichen Angaben folgen im Quellcode hintereinander \header { ... }, \score { ... }, \header { ... }, usw. natürlich immer paarweise.

Und im Inhaltsverzeichnis wiederholt sich dann der Titel (piece) aus dem jeweils letzten header! Interessanterweise sind die angegebenen Seitennummern korrekt. (Auf das spezielle Seitennummern-Offset-Problem gehe ich hier nicht ein, das Inhaltsverzeichnis bekommt hier die Seite 1 und dann folgen 2 usw.)

Und hier der Beispielcode:

\version "2.24.1"

#(define (scopes)
"Returns a list of header-modules from bookpart, book and @code{$defaultheader}.
"
  (let* ((current-bookpart (ly:parser-lookup '$current-bookpart))
         (current-book (ly:parser-lookup '$current-book))
         (book-header
           (if current-book
               (ly:book-header current-book)
               #f))
         (bookpart-header
           (if current-bookpart
               (ly:book-header current-bookpart)
               #f)))
     (filter module? (list bookpart-header book-header $defaultheader))))

#(define-markup-command (with-header-scopes layout props scopes markup)
  (list? markup?)
  "Interpret the given @var{markup} with the header fields from @var{scopes}
added to the props.
This way, one can re-use the same functions (using
@code{\\fromproperty #'header:field}) in the header block and as top-level
markup."
  (let* ((alists (map ly:module->alist scopes))
         (prefixed-alist
          (map
            (lambda (alist)
              (map
                (lambda (entry)
                  (cons
                    (string->symbol (format #f "header:~s" (car entry)))
                    (cdr entry)))
                alist))
           alists))
         (props
           (append
             prefixed-alist
             props
             (layout-extract-page-properties layout))))
    (interpret-markup layout props markup)))


\header { title = "All books" }

\book {
  \paper {
    ragged-bottom = ##t
    tocItemMarkup = \tocItemWithDotsMarkup
  }
  \header { piece = "This book" }
  \markuplist \table-of-contents

  \bookpart {
    \header { piece = "First Piece of Part One" }
    \tocItem \markup \with-header-scopes #(scopes) \fromproperty #'header:piece

    \score { \relative c'' { a a a a } }

    \header { piece = "Second Piece of Part One" }
    \tocItem \markup \with-header-scopes #(scopes) \fromproperty #'header:piece
    \score { \relative c' { d d d d } }

    \pageBreak
    \header { piece = "Third Piece of Part One" }
    \tocItem \markup \with-header-scopes #(scopes) \fromproperty #'header:piece
    \score { \relative c' { e e e e } }
  }

  \bookpart {
    \header { piece = "Bookpart Two" }

    \tocItem \markup \with-header-scopes #(scopes) \fromproperty #'header:piece

    \score { \relative c' { c c c c } }
  }

  \bookpart {
    \header { piece = "First Piece of Part Three" }
    \tocItem \markup \with-header-scopes #(scopes) \fromproperty #'header:piece

    \score { \relative c' { a a a a } }
  }

  \bookpart {
    \header { piece = "Second Piece of Part Three" }
    \tocItem \markup \with-header-scopes #(scopes) \fromproperty #'header:piece

    \score { \relative c' { d d d d } } }
}


Irgend eine Idee, wie man erreichen kann, dass die Titel im Inhaltsverzeichnis korrekt eingetragen werden?

Dass man Header-Anteile innerhalb von \score angeben kann, hilft hier nicht. Jedenfalls habe ich es nicht hinbekommen. Und den Seitenumbruch zwischen mehreren \bookpart { } scheint man nicht unterdrücken zu können.

Das von meinem Lilypond (2.24.1) erzeugte PDF-Dokument füge ich noch an: Du darfst diesen Dateianhang nicht ansehen.

Schon mal Danke für alle Ideen.

Martin

harm6

Wenn Du in einem bookpart
\header { ... }, \score { ... }, \header { ... }, \score { ... }
schreibst, so hast Du (syntaktisch gesprochen) mehrere book(part)-header geschrieben. Wobei jeder vorangegangene header durch den neuen ein update erfährt. D.h. dann aber auch, daß die piece-Setzung im letzten header alle vorangegangenen überschreibt. Das siehst Du nicht nur im Inhaltsverzeichnis sondern auch bei den score-Überschriften.
Es führt also kein Weg daran vorbei score-header zu verwenden, geht nicht anders (zumindest solange Du score-Überschriften haben willst).

Nun zum Inhaltsverzeichnis:
Am einfachsten scheint mir zu sein im bookpart-header custom-slots zu setzen und diese dann aufzurufen. Ob das dann immer noch weniger Schreibarbeit ist musst Du selbst entscheiden.

\version "2.24.1"

#(define (scopes)
"Returns a list of header-modules from bookpart, book and @code{$defaultheader}.
"
  (let* ((current-bookpart (ly:parser-lookup '$current-bookpart))
         (current-book (ly:parser-lookup '$current-book))
         (book-header
           (if current-book
               (ly:book-header current-book)
               #f))
         (bookpart-header
           (if current-bookpart
               (ly:book-header current-bookpart)
               #f)))
     (filter module? (list bookpart-header book-header $defaultheader))))

#(define-markup-command (with-header-scopes layout props scopes markup)
  (list? markup?)
  "Interpret the given @var{markup} with the header fields from @var{scopes}
added to the props.
This way, one can re-use the same functions (using
@code{\\fromproperty #'header:field}) in the header block and as top-level
markup."
  (let* ((prefixed-alists (headers-property-alist-chain scopes))
         (props
           (append
             prefixed-alists
             props
             (layout-extract-page-properties layout))))
    (interpret-markup layout props markup)))

\header { title = "All books" }

\book {
  \paper {
    ragged-bottom = ##t
    tocItemMarkup = \tocItemWithDotsMarkup
  }
  \header { piece = "This book" }
 
  \markuplist \table-of-contents

  \bookpart {
  \header {
    score-I = "First Piece of Part One"
    score-II = "Second Piece of Part One"
    score-III = "Third Piece of Part One"
  }

  \tocItem
    \markup \with-header-scopes #(scopes) \fromproperty #'header:score-I
   
    \score {
      \relative c'' { a a a a }
      \header { piece = "First Piece of Part One" }
    }

  \tocItem
    \markup \with-header-scopes #(scopes) \fromproperty #'header:score-II
   
    \score {
      \relative c' { d d d d }
      \header { piece = "Second Piece of Part One" }
    }
   
    \pageBreak
   
  \tocItem
    \markup \with-header-scopes #(scopes) \fromproperty #'header:score-III
   
    \score {
      \relative c' { e e e e }
      \header { piece = "Third Piece of Part One" }
    }
  }

  \bookpart {
    \header { piece = "Bookpart Two" }

  \tocItem
    \markup \with-header-scopes #(scopes) \fromproperty #'header:piece
   
    \score { \relative c' { c c c c } }
  }

  \bookpart {
    \header { piece = "First Piece of Part Three" }
   
  \tocItem
    \markup \with-header-scopes #(scopes) \fromproperty #'header:piece
   
    \score { \relative c' { a a a a } }
  }

  \bookpart {
    \header { piece = "Second Piece of Part Three" }
   
  \tocItem
    \markup \with-header-scopes #(scopes) \fromproperty #'header:piece
   
    \score { \relative c' { c c c c } }
  }
}

Gruß,
  Harm

P.S. `with-header-scopes` habe ich nochmal überarbeitet und kürzen können.

martinmagtenor

Hallo Harm,

herzlichen Dank. Das mit den Score-Überschriften war mir inzwischen auch aufgefallen. Danke für die (indirekte) Bestätigung, dass das kein anderer Bug ist.

Und Danke für die Optimierung.

Das mit den custom-slots ist ein interessanter Ansatz. Ich denke, dass ich damit leben kann. Auch wenn das ein klein wenig mehr Tipparbeit ist, bleiben inhaltliche Korrekturen oder Modifikationen auf eine Stelle beschränkt. Erst Änderungen an der Struktur der Bookparts hat Auswirkungen auf die custom-slots und das ist für mich in Ordnung.

Grüße,
  Martin