Use chapters for digital toc

* introduce \songsChapter and \markuppage
* have nested chapters in PDF toc
This commit is contained in:
tux
2026-07-05 14:09:44 +02:00
parent 50e08220c4
commit 7076b16b63
3 changed files with 145 additions and 56 deletions
+115 -50
View File
@@ -119,7 +119,7 @@ width may require additional tweaking.)"
includeSong =
#(define-void-function (parser location filename) (string?)
#(define-void-function (filename) (string?)
#{
\bookOutputName #filename
#}
@@ -130,32 +130,47 @@ includeSong =
(acons label additional-page-numbers additional-page-switch-label-list))
(set! song-list
(acons (string->symbol filename)
(acons 'label label
(acons 'header HEADER
(acons 'music MUSIC
(acons 'layout LAYOUT
(acons 'text-pages
(map (lambda (text)
`(
(label . ,label)
(header . ,HEADER)
(music . ,MUSIC)
(layout . ,LAYOUT)
(text-pages . ,(map (lambda (text)
#{ \markuplist \setsongfilename $filename $text #})
TEXT_PAGES)
'())))))
TEXT_PAGES))
)
song-list))
))
blankpage =
#(define-void-function (parser location) ()
#(define-void-function () ()
(set! song-list
(acons 'emptyPage
'()
song-list)))
imagepage =
#(define-void-function (parser location xsize filename) (number? string?)
#(define-void-function (xsize filename) (number? string?)
(set! song-list
(acons 'imagePage
(acons 'xsize xsize (acons 'filename filename '()))
`((xsize . ,xsize)
(filename . ,filename))
song-list)))
markuppage =
#(define-void-function (mkup) (markup?)
(set! song-list
(acons 'markupPage
`((markup . ,mkup))
song-list)))
#(define chapters '())
songsChapter =
#(define-void-function (title) (string?)
(set! chapters
(cons (cons title (length song-list)) chapters)))
#(define-markup-command (pagecenter layout props stuff)(markup?)
(interpret-markup layout props
(let ((halfpaperheight (/ (ly:output-def-lookup layout 'paper-height) 2))
@@ -164,42 +179,92 @@ imagepage =
)))
songs =
#(define-void-function (parser location) ()
#(define-void-function () ()
(let* ((ordered (reverse song-list))
(total (length ordered))
;; Ein Lied erzeugt nur dann einen PDF-Outline-Eintrag (/OUT), wenn
;; title oder starttext gesetzt sind (siehe build-full-title). Nur solche
;; Lieder duerfen als Kapitel-Kinder gezaehlt werden -- sonst wird die
;; /Count zu hoch und der erste Folgeeintrag (z.B. ein spaeteres Kapitel)
;; rutscht faelschlich als Kind mit hinein.
(emits-bookmark?
(lambda (e)
(and (not (eq? (car e) 'emptyPage))
(not (eq? (car e) 'imagePage))
(not (eq? (car e) 'markupPage))
(let ((vars (extract-and-check-vars-from-header
(assq-ref (cdr e) 'header) '(title starttext))))
(if (or (assq-ref vars 'title) (assq-ref vars 'starttext)) #t #f)))))
(count-bookmark-songs
(lambda (start end)
(let loop ((i 0) (l ordered) (c 0))
(cond ((or (null? l) (>= i end)) c)
((< i start) (loop (+ i 1) (cdr l) c))
(else (loop (+ i 1) (cdr l) (if (emits-bookmark? (car l)) (+ c 1) c)))))))
;; chapters: (title . start-index). start-index = Anzahl der song-list-
;; Eintraege beim Aufruf von songsChapter = Index in `ordered`, ab dem
;; das Kapitel beginnt.
(chapters-asc (sort chapters (lambda (a b) (< (cdr a) (cdr b)))))
;; pending: aufsteigende Liste von (start title count); count = Anzahl
;; der Lesezeichen-Lieder von diesem Kapitel bis zum Beginn des naechsten.
(pending
(let loop ((chs chapters-asc) (acc '()))
(if (null? chs)
(reverse acc)
(let* ((title (caar chs))
(start (cdar chs))
(end (if (null? (cdr chs)) total (cdadr chs)))
(cnt (count-bookmark-songs start end)))
(loop (cdr chs) (cons (list start title cnt) acc))))))
(index 0))
(for-each (lambda (songitems)
(ly:book-add-bookpart! (ly:parser-lookup '$current-book)
(let ((filename (car songitems))
(songvars (cdr songitems)))
(if (eq? filename 'emptyPage)
#{ \bookpart { \markup { \null } } #}
(if (eq? filename 'imagePage)
(let ((xsize (assq-ref songvars 'xsize))
(filename (ly:format "~a/~a" imagePagePath (assq-ref songvars 'filename))))
#{ \bookpart {
\paper {
%{
inner-margin = 0
outer-margin = 0
binding-offset = 0
top-margin = 0
bottom-margin = 0
%}
print-page-number = ##f
last-bottom-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . 0))
page-count = 1
}
\markup { \pagecenter { \epsfile #X #xsize #filename } }
} #}
)
(let* ((newnumber (+ 1 song-number))
(header #{ \bookpart { $(assq-ref songvars 'header) \header {
songfilename = $(symbol->string filename)
myindexlabel = #(assq-ref songvars 'label)
songnumber = #(number->string newnumber)
} } #})
(music (assq-ref songvars 'music))
(layout (assq-ref songvars 'layout))
(text-pages (assq-ref songvars 'text-pages))
(label (assq-ref songvars 'label)))
(let ((this-index index))
(set! index (+ index 1))
(ly:book-add-bookpart! (ly:parser-lookup '$current-book)
(let ((filename (car songitems))
(songvars (cdr songitems)))
(if (eq? filename 'emptyPage)
#{ \bookpart { \markup { \null } } #}
(if (eq? filename 'markupPage)
#{ \bookpart { \markup { $(assq-ref songvars 'markup) } } #}
(if (eq? filename 'imagePage)
(let ((xsize (assq-ref songvars 'xsize))
(filename (ly:format "~a/~a" imagePagePath (assq-ref songvars 'filename))))
#{ \bookpart {
\paper {
%{
inner-margin = 0
outer-margin = 0
binding-offset = 0
top-margin = 0
bottom-margin = 0
%}
print-page-number = ##f
last-bottom-spacing = #'((basic-distance . 0) (minimum-distance . 0) (padding . 0))
page-count = 1
}
\markup { \pagecenter { \epsfile #X #xsize #filename } }
} #}
)
;; Ist ein Kapitel faellig (Start <= aktuelle Position) und dies ein
;; echtes Lied, wird die Kapitelinfo an dieses Lied gehaengt und aus
;; `pending` entfernt.
(let* ((newnumber (+ 1 song-number))
(chaptertitle (if (and (pair? pending) (<= (car (car pending)) this-index))
(cadr (car pending)) #f))
(chaptercount (if chaptertitle (caddr (car pending)) 0))
(header #{ \bookpart { $(assq-ref songvars 'header) \header {
songfilename = $(symbol->string filename)
myindexlabel = #(assq-ref songvars 'label)
songnumber = #(number->string newnumber)
chaptertitle = #chaptertitle
chaptercount = #chaptercount
} } #})
(music (assq-ref songvars 'music))
(layout (assq-ref songvars 'layout))
(text-pages (assq-ref songvars 'text-pages))
(label (assq-ref songvars 'label)))
(if chaptertitle (set! pending (cdr pending)))
(set! song-number newnumber)
#{
\bookpart {
@@ -208,9 +273,9 @@ songs =
\score { $music \layout { $layout songfilename = $(symbol->string filename) } }
$(add-text-pages text-pages)
}
#}))))))
(reverse song-list)
))
#}))))))))
ordered
)))
#(define (boernel-stats)
(let (