3

I have the following Lilypond source file consisting of a few blocks of the following form:

global = \relative { ... }
Soprano = \relative { ... }
Alto = \relative { ... } % ditto Tenor, Bass

\score { \new StaffGroup <<
  \new Staff << \clef "G" \global \Soprano >>
  \new Staff << \clef "G" \global \Alto >>
  \new Staff << \clef "G_8" \global \Tenor >>
  \new Staff << \clef "F" \global \Bass >>
>> \layout { } }

Obviously the global, Soprano, Alto, Tenor, Bass definitions change each time, but the \score block remains the same.

I want to factor that block in a Scheme macro. However, the simplest definition I tried,

#(define (Choral) (ly:make-score #{ \new StaffGroup <<
  \new Staff << \clef "G" \global \Soprano >>
  \new Staff << \clef "G" \global \Alto >>
  \new Staff << \clef "G_8" \global \Tenor >>
  \new Staff << \clef "F" \global \Bass >>
>> #} ))

has the following inconvenients: (1) it must be invoked by #(Choral) instead of the more natural \Choral, and worse, (2) it produces no output whatsoever. If I try to put a \layout { } block in the (Choral) definition lilypond produces the following error: error: syntax error, unexpected \layout.

Is there a simple way to write a macro that produces a \score block with attached \layout ?

Circonflexe
  • 351
  • 1
  • 9
  • Self-answer: just use the `collect-music-for-book` function, defined in `scm/lily-library.scm`; full example: `Choral = #(define-music-function (parser location) () (collect-music-for-book parser #{ ... #}) #{ #})` (the second `#{ #}` is a void-music expression, the first one contains the four-voice SATB as above). – Circonflexe Jan 17 '17 at 22:07

1 Answers1

1

Why a Scheme macro? You can just use \include (it's like pasting the content of a file in the line you put it). So you might use the same score block file:

% myScoreBlock.ly file
\score {
  \new StaffGroup <<
    \new Staff << \clef "G" \global \Soprano >>
    \new Staff << \clef "G" \global \Alto >>
    \new Staff << \clef "G_8" \global \Tenor >>
    \new Staff << \clef "F" \global \Bass >>
  >> \layout { }
}

to be included in any other file which have the same variables:

% example of a piece
\version "2.19.54"

global = { \time 2/4 }
Soprano = \relative { d2 }
Alto = \relative { f2 }
Tenor = \relative { e2 }
Bass = \relative { g2 }

\include "myScoreBlock.ly"

Another option to reduce the size of the input is using built-in templates. There's also a built-in template for SATB scores.

fedelibre
  • 398
  • 1
  • 8
  • 2
    Pure Scheme (I just posted a solution) is both much cleaner and faster (maybe significantly so, depending on the filesystem). – Circonflexe Jan 17 '17 at 22:17