]> git.donarmstrong.com Git - lilypond.git/commitdiff
Automatic table of contents:
authorNicolas Sceaux <nicolas.sceaux@free.fr>
Sun, 17 Jun 2007 11:19:27 +0000 (13:19 +0200)
committerNicolas Sceaux <nicolas.sceaux@free.fr>
Sun, 17 Jun 2007 11:19:27 +0000 (13:19 +0200)
 - markups used for building the table of contents (its title, the
 text/page-number lines) are defined as \paper variables, like the
 titling markups;

 - A music function is defined to place a label and push a (label
 paper-markup-variable text-markup) element to a list of toc items;

 - a \table-of-contents markup list command reads this toc items list to
 generate the table of contents.

Documentation/user/non-music.itely
input/regression/page-label.ly
input/regression/toc.ly [new file with mode: 0644]
ly/declarations-init.ly
ly/toc-init.ly [new file with mode: 0644]
scm/define-markup-commands.scm

index 2ee1f37f3b9469a6a3af4fd46de944bc83945a48..536780c36f263afd303e245e63c69a2cd5e4c81a 100644 (file)
@@ -482,6 +482,7 @@ some pieces include a lot more information.
 * Creating titles::             
 * Custom titles::               
 * Reference to page numbers::   
+* Table of contents::           
 @end menu
 
 
@@ -742,26 +743,30 @@ command, either at top-level or inside music.  This label can then be
 refered to in a markup, to get the number of the page where the marked
 point is placed, using the @code{\page-ref} markup command.
 
-@verbatim
-\label #'firstScore
-\score {
-  {
-    c'1
-    \mark A \label #'markA
-    c'
+@lilypond[verbatim,line-width=11.0\cm]
+\header { tagline = ##f }
+\book {
+  \label #'firstScore
+  \score {
+    {
+      c'1
+      \pageBreak \mark A \label #'markA
+      c'
+    }
   }
-}
 
-\markup { The first score is on page \page-ref #'firstScore "0" "?" }
-\markup { Mark A is on page \page-ref #'markA "0" "?" }
-@end verbatim
+  \markup { The first score begins on page \page-ref #'firstScore "0" "?" }
+  \markup { Mark A is on page \page-ref #'markA "0" "?" }
+}
+@end lilypond
 
 The @code{\page-ref} markup command takes three arguments:
 @enumerate
-@item the label, a scheme symbol, eg. #'firstScore
+@item the label, a scheme symbol, eg. @code{#'firstScore};
 @item a markup that will be used as a gauge to estimate the dimensions
-of the markup
-@item a markup that will be used if the label is not known
+of the markup;
+@item a markup that will be used in place of the page number if the label 
+is not known;
 @end enumerate
 
 The reason why a gauge is needed is that, at the time markups are
@@ -772,53 +777,125 @@ the markup have to be known before, so a gauge is used to decide these
 dimensions.  If the book has between 10 and 99 pages, it may be "00",
 ie. a two digit number.
 
-@code{\label} and @code{\page-ref} can be used to build a table of contents:
-
-@verbatim
-#(set-default-paper-size "a6")
+@refcommands
 
-#(define-markup-command (toc-line layout props label text) (symbol? markup?)
-  (interpret-markup layout props
-   (markup #:fill-line (text #:page-ref label "8" "?"))))
+@funindex \label
+@code{\label}
+@funindex \page-ref
+@code{\page-ref}
 
-\markup \column {
-  \large \fill-line { \null "Table of contents" \null }
-  \hspace #1
-  \toc-line #'toc "Table of contents"
-  \toc-line #'scoreI "First Score"
-  \toc-line #'markA \line { \hspace #3 Mark A }
-  \toc-line #'scoreII "Second Score"
-} \label #'toc
+@node Table of contents
+@subsection Table of contents
+A table of contents is included using the @code{\markuplines \table-of-contents}
+command.  The elements which should appear in the table of contents are
+entered with the @code{\tocItem} command, which may be used either at
+top-level, or inside a music expression.
 
+@verbatim
+\markuplines \table-of-contents
 \pageBreak
 
+\tocItem \markup "First score"
+\score { 
+  {
+    c'  % ...
+    \tocItem \markup "Some particular point in the first score"
+    d'  % ... 
+  }
+}
+
+\tocItem \markup "Second score"
 \score {
-  { 
-    c'1 \break
-    \mark A \label #'markA
-    c'1
+  {
+    e' % ...
   }
-  \header { piece = "First score" }
-} \label #'scoreI
+}
+@end verbatim
 
-\pageBreak
+The markups which are used to format the table of contents are defined
+in the @code{\paper} block. The default ones are @code{tocTitleMarkup},
+for formatting the title of the table, and @code{tocItemMarkup}, for
+formatting the toc elements, composed of the element title and page
+number. These variables may be changed by the user:
 
-\score {
-  { d' }
-  \header { piece = "Second score" }
-} \label #'scoreII
+@verbatim
+\paper {
+  %% Translate the toc title into French:
+  tocTitleMarkup = \markup \huge \column {
+    \fill-line { \null "Table des matières" \null }
+    \hspace #1
+  }
+  %% use larfer font size
+  tocItemMarkup = \markup \large \fill-line {
+    \fromproperty #'toc:text \fromproperty #'toc:page
+  }
+}
 @end verbatim
 
-In this example, a @code{\toc-line} markup command is defined to build
-the table of content items. As this example has less than 10 pages, the
-gauge used by @code{\page-ref} has a single digit.
+Note how the toc element text and page number are refered to in
+the @code{tocItemMarkup} definition.
+
+New commands and markups may also be defined to build more elaborated
+table of contents:
+@itemize @bullet
+@item first, define a new markup variable in the @code{\paper} block
+@item then, define a music function which aims at adding a toc element
+using this markup paper variable.
+@end itemize
+
+In the following example, a new style is defined for entering act names
+in the table of contents of an opera:
+
+@verbatim
+\paper {
+  tocActMarkup = \markup \large \column {
+    \hspace #1
+    \fill-line { \null \italic \fromproperty #'toc:text \null }
+    \hspace #1
+  }
+}
+
+tocAct = 
+#(define-music-function (parser location text) (markup?)
+   (add-toc-item! 'tocActMarkup text))
+@end verbatim
+
+@lilypond[line-width=11.0\cm]
+\header { tagline = ##f }
+\paper {
+  tocActMarkup = \markup \large \column {
+    \hspace #1
+    \fill-line { \null \italic \fromproperty #'toc:text \null }
+    \hspace #1
+  }
+}
+
+tocAct = 
+#(define-music-function (parser location text) (markup?)
+   (add-toc-item! 'tocActMarkup text))
+
+\book {
+  \markuplines \table-of-contents
+  \tocAct \markup { Atto Primo }
+  \tocItem \markup { Coro. Viva il nostro Alcide }
+  \tocItem \markup { Cesare. Presti omai l'Egizzia terra }
+  \tocAct \markup { Atto Secondo }
+  \tocItem \markup { Sinfonia }
+  \tocItem \markup { Cleopatra. V'adoro, pupille, saette d'Amore }
+  \markup \null
+}
+@end lilypond
+
+@seealso
+
+Init files: @file{ly/@/toc@/-init@/.ly}.
 
 @refcommands
 
-@funindex \label
-@code{\label}
-@funindex \page-ref
-@code{\page-ref}
+@funindex \table-of-contents
+@code{\table-of-contents}
+@funindex \tocItem
+@code{\tocItem}
 
 @node MIDI output
 @section MIDI output
index 6f1e5c8e881c3b779cbe291285d32fd4bf167dc1..cb023872dc64d1adcb0d8b0da51baf851eb25b0b 100644 (file)
@@ -11,34 +11,36 @@ and refered to in markups."
   (interpret-markup layout props
    (markup #:fill-line (text #:page-ref label "8" "?"))))
 
-\markup \huge \fill-line { \null "Title Page" \null }
-
-\pageBreak
-
-\label #'toc
-\markup \column {
-  \large \fill-line { \null "Table of contents" \null }
-  \toc-line #'toc "Table of contents"
-  \toc-line #'firstScore "First Score"
-  \toc-line #'markA "Mark A"
-  \toc-line #'markB "Mark B"
-  \toc-line #'markC "Mark C"
-  \toc-line #'unknown "Unknown label"
-}
+\book {
+  \markup \huge \fill-line { \null "Title Page" \null }
+
+  \pageBreak
+
+  \label #'toc
+  \markup \column {
+    \large \fill-line { \null "Table of contents" \null }
+    \toc-line #'toc "Table of contents"
+    \toc-line #'firstScore "First Score"
+    \toc-line #'markA "Mark A"
+    \toc-line #'markB "Mark B"
+    \toc-line #'markC "Mark C"
+    \toc-line #'unknown "Unknown label"
+  }
 
-\pageBreak
-
-\label #'firstScore
-\score {
-  { c'2 c'
-    \mark \markup { A (page \concat { \page-ref #'markA "0" "?" ) }} \label #'markA 
-    c' c'
-    \pageBreak
-    \mark "B" \label #'markB
-    d' d'
-    d' d'
-    \once \override Score . RehearsalMark #'break-visibility = #begin-of-line-invisible
-    \mark "C" \label #'markC
+  \pageBreak
+
+  \label #'firstScore
+  \score {
+    { c'2 c'
+      \mark \markup { A (page \concat { \page-ref #'markA "0" "?" ) }} \label #'markA 
+      c' c'
+      \pageBreak
+      \mark "B" \label #'markB
+      d' d'
+      d' d'
+      \once \override Score . RehearsalMark #'break-visibility = #begin-of-line-invisible
+      \mark "C" \label #'markC
+    }
+    \header { piece = "First score" }
   }
-  \header { piece = "First score" }
 }
\ No newline at end of file
diff --git a/input/regression/toc.ly b/input/regression/toc.ly
new file mode 100644 (file)
index 0000000..e6164ea
--- /dev/null
@@ -0,0 +1,29 @@
+\version "2.11.26"
+
+\header {
+  texidoc = "A table of contents is included using
+@code{\\markuplines \\table-of-contents}. The toc items are added with
+the @code{\\tocItem} command."
+}
+
+#(set-default-paper-size "a6")
+
+\book {
+  \markuplines \table-of-contents
+  \pageBreak
+
+  \tocItem \markup "The first score"
+  \score {
+    { 
+      c'1 \pageBreak
+      \mark "A" \tocItem \markup "Mark A"
+      d'
+    }
+  }
+  \pageBreak
+  \tocItem \markup "The second score"
+  \score {
+    { e' }
+    \header { piece = "Second score" }
+  }
+}
\ No newline at end of file
index 364068c043c0f8cd60bb9abc48139c53860c37ed..b8c36e4f338dff45d3c9e204d9b72003188d3e60 100644 (file)
@@ -10,6 +10,7 @@ maxima = #(ly:make-duration -3 0)
 
 \include "markup-init.ly"
 \include "music-functions-init.ly"
+\include "toc-init.ly"
 
 %% default note names are dutch
 \include "nederlands.ly"
diff --git a/ly/toc-init.ly b/ly/toc-init.ly
new file mode 100644 (file)
index 0000000..334c983
--- /dev/null
@@ -0,0 +1,59 @@
+\version "2.11.26"
+
+%% defined later, in a closure
+#(define-public (add-toc-item! markup-symbol text)
+  #f)
+#(define-public (toc-items)
+  #f)
+
+#(let ((toc-item-list (list)))
+   (set! add-toc-item!
+        (lambda (markup-symbol text)
+          (let ((label (gensym "toc")))
+            (set! toc-item-list
+                  (cons (list label markup-symbol text)
+                        toc-item-list))
+            (make-music 'EventChord
+              'page-marker #t
+              'page-label label
+              'elements (list (make-music 'LabelEvent
+                                'page-label label))))))
+   (set! toc-items (lambda ()
+                    (reverse toc-item-list))))
+
+\paper {
+  tocTitleMarkup = \markup \huge \column {
+    \fill-line { \null "Table of Contents" \null }
+    \hspace #1
+  }
+  tocItemMarkup = \markup \fill-line {
+    \fromproperty #'toc:text \fromproperty #'toc:page
+  }
+}
+
+#(define-markup-list-command (table-of-contents layout props) ()
+  "Outputs the table of contents, using the paper variable
+@code{tocTitleMarkup} for its title, then the list of lines
+built using the @code{tocItem} music function
+Usage: @code{\\markuplines \\table-of-contents}"
+  (cons (interpret-markup layout props
+                         (ly:output-def-lookup layout 'tocTitleMarkup))
+       (space-lines (chain-assoc-get 'baseline-skip props)
+                   (map (lambda (toc-item)
+                          (let ((label (car toc-item))
+                                (toc-markup (cadr toc-item))
+                                (text (caddr toc-item)))
+                            (interpret-markup
+                              layout
+                              (cons (list (cons 'toc:page 
+                                           (markup #:page-ref label "XXX" "?"))
+                                          (cons 'toc:text text))
+                                    props)
+                              (ly:output-def-lookup layout toc-markup))))
+                        (toc-items)))))
+
+tocItem = 
+#(define-music-function (parser location text) (markup?)
+   "Add a line to the table of content, using the @code{tocItemMarkup} paper
+variable markup"
+   (add-toc-item! 'tocItemMarkup text))
index 956bd817bfa2a15e39ab68c965e54fb24957c8bb..5405aff31253b4879470adeb0b4011f361fb46f4 100644 (file)
@@ -1493,7 +1493,7 @@ when @var{label} is not found."
 ;; Markup list commands
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(define (space-lines baseline-skip lines)
+(define-public (space-lines baseline-skip lines)
   (map (lambda (line)
         (stack-lines DOWN 0.0 (/ baseline-skip 2.0)
                      (list (ly:make-stencil "" (cons 0 0) (cons 0 0))