%% DO NOT EDIT this file manually; it is automatically
%% generated from LSR http://lsr.di.unimi.it
%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
%% and then run scripts/auxiliar/makelsr.py
%%
%% This file is in the public domain.
\version "2.19.22"

\header {
  lsrtags = "automatic-notation, really-cool, scheme-language"

  texidoc = "
A lilypond score internally is just a Scheme expression, generated by
the lilypond parser. Using scheme, one can also automatically generate
a score without an input file. If you have the music expression in
scheme, a score can be generated by simply calling (scorify-music music) on your music. This will generate a score object, for which you
can then set a custom layout block with (let* ((layout
(ly:output-def-clone $defaultlayout)))
   ; modify the layout here, then assign it:
   (ly:score-add-output-def! score layout)
  )


Finally, all you have to do it to pass this score to lilypond for
typesetting. This snippet defines functions @code{(add-score
score)}, @code{(add-text text)} and @code{(add-music
music)} to pass a complete score, some markup or some music to lilypond
for typesetting.

This snippet also works for typesetting scores inside a @code{\\book
@{...@}} block, as well as top-level scores. To achieve this, each
score schedulled for typesetting is appended to the list of toplevel
scores and the toplevel-book-handler (which is a scheme function called
to process a book once a @code{\\book@{..@}} block is closed) is
modified to inser all collected scores so far to the book.

"
  doctitle = "Generating whole scores (also book parts) in scheme without using the parser"
} % begin verbatim
%%

#(define-public (add-score score)
   (ly:parser-define! 'toplevel-scores
                      (cons score (ly:parser-lookup 'toplevel-scores))))

#(define-public (add-text text)
  (add-score (list text)))

#(define-public (add-music music)
  (collect-music-aux (lambda (score)
		       (add-score score))
		     music))

#(define-public (toplevel-book-handler book)
   (map (lambda (score)
          (ly:book-add-score! book score))
        (reverse! (ly:parser-lookup 'toplevel-scores)))
   (ly:parser-define! 'toplevel-scores (list))
   (print-book-with-defaults book))

#(define-public (book-score-handler book score)
   (add-score score))

#(define-public (book-text-handler book text)
   (add-text text))

#(define-public (book-music-handler book music)
   (add-music music))

%%%


%% Just some example score to show how to use these functions:
#(define add-one-note-score #f)
#(let ((pitch 0))
  (set! add-one-note-score
        (lambda (parser)
          (let* ((music (make-music 'EventChord
                          'elements (list (make-music 'NoteEvent
                                            'duration (ly:make-duration 2 0 1/1)
                                            'pitch (ly:make-pitch 0 pitch 0)))))
                 (score (scorify-music music))
                 (layout (ly:output-def-clone $defaultlayout))
                 (note-name (case pitch
                              ((0) "do")
                              ((1) "ré")
                              ((2) "mi")
                              ((3) "fa")
                              ((4) "sol")
                              ((5) "la")
                              ((6) "si")
                              (else "huh")))
                 (title (markup #:large #:line ("Score with a" note-name))))
            (ly:score-add-output-def! score layout)
            (add-text title)
            (add-score score))
            (set! pitch (modulo (1+ pitch) 7)))))

oneNoteScore =
#(define-music-function () ()
   (add-one-note-score (*parser*))
   (make-music 'Music 'void #t))

%%%

\book {
  \oneNoteScore
}


\book {
  \oneNoteScore
  \oneNoteScore
}

% Top-level scores are also handled correctly
\oneNoteScore
\oneNoteScore
