lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Macro pre-processing?


From: Nicolas Sceaux
Subject: Re: Macro pre-processing?
Date: Mon, 01 May 2006 23:43:12 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin)

"Rick Hansen (aka RickH)" <address@hidden> writes:

> Nice, will it will basically generate source code AFTER the \include files
> are merged but BEFORE compilation by LP occurs?  The ability to modularize
> source code generation into macros would be valuable, kind of like "smart"
> \include files, where one can generate conditional LP music source code.

May you quote the original message to which your answering? it's not
easy to guess what you're talking about? I suppose you're answering to
Geoff's post about pre processor.

>> In two weeks, when I'm done with finals, I'll revisit my roughed-out
>> preprocessor and see if it can be made usable and easy.

Anyway, "smart" includes are already possible with LilyPond.
For instance, it's usual to see the following in a LilyPond file:

  -- pieceA/lead-score.ly --
 | global = {
 |   \key g \major
 |   \time 3/4
 |   s2.*27 \bar "|."
 | }
 |
 | \score {
 |   ...
 |     \new Staff << \global { ..music1.. } >>
 |     \new Staff << \global { ..music2.. } >>
 |   ...
  -------------------

When you build several version of a score (eg. lead score, separate
parts, etc), you put the content of the global variable in its own file:

  -- pieceA/global.ily --
 | \key g \major
 | \time 3/4
 | s2.*27 \bar "|."
  ----------------

and then, in each score file:

  -- pieceA/lead-score.ly --
 | global = { \include "pieceA/global.ily" }
 | \score {
 |   ...
 |     \new Staff << \global { ..music1.. } >>
 |     \new Staff << \global { ..music2.. } >>
 |   ...
 | }
  -------------------

But then there is a pattern, the global variable affectation repeated in
each main score file.
So you define a music function, that will automatically include the
global.ily the first time it is invoked, and the following ones just
return what has already been loaded:

Supposing that (*cuurent-piece*) holds the identifier of the piece (I
use such identifiers to distinguate the different pieces in a book, and
to designate the drectory in which the piece files are placed, "pieceA"
above):

  global = 
  #(define-music-function (parser location) ()
    (let* ((global-symbol (string->symbol (format "global~a" 
(*current-piece*))))
           (global-music (ly:parser-lookup parser global-symbol)))
     (if (not (ly:music? global-music))
         (let* ((global-file (string-append (*current-piece*) "/global.ily")))
           (set! global-music #{ \include $global-file #})
           (ly:parser-define! parser global-symbol global-music)))
     (ly:music-deep-copy global-music)))

[By the way, here you see an example of a music function using the
parser argument].

Then, all you have to write in your score files is:

  -- pieceA/lead-score.ly --
 | \score {
 |   ...
 |     \new Staff << \global { ..music1.. } >>
 |     \new Staff << \global { ..music2.. } >>
 |   ...
 | }
  -------------------

the pieceA/global.ily file is then auto-included.


But then you have to tell lilypond the identifier of each score, so the
benefit is not evident. Let's create another function to include a piece
in the main file, which will set the identifier of the piece.

  ---- common.ily ----
 | #(use-modules (srfi srfi-39))
 | #(define *current-piece* (make-parameter ""))
 |
 | includeScore =
 | #(define-music-function (parser location name) (string?)
 |    (parameterize ((*current-piece* name))
 |      (ly:parser-parse-string (ly:clone-parser parser)
 |                              (string-append "\\include \"" name 
"/score.ily\""))
 |      (make-music 'SequentialMusic 'void #t)))
 |
 | global = 
 | #(define-music-function (parser location) ()
 |   (let* ((global-symbol (string->symbol (format "global~a" 
(*current-piece*))))
 |          (global-music (ly:parser-lookup parser global-symbol)))
 |    (if (not (ly:music? global-music))
 |        (let* ((global-file (string-append (*current-piece*) "/global.ily")))
 |          (set! global-music #{ \include $global-file #})
 |          (ly:parser-define! parser global-symbol global-music)))
 |    (ly:music-deep-copy global-music)))
  ---- common.ily ----

  ---- main.ly ----
 | \include "common.ily"
 |
 | %% includes pieceA/score.ily and sets (*current-piece*) to pieceA
 | \includeScore "pieceA"  
 | \includeScore "pieceB"
 | ...
  ---- main.ly ----

  ---- pieceA/score.ily ----
 | \score {
 |   << 
 |    \new Staff << \global { ..music1.. } >>
 |    \new Staff << \global { ..music2.. } >>
 |   >>
 | }
  ---- pieceA/score.ily ----

  ---- pieceA/global.ily ----
 | \key g \major
 | \time 3/4
 | s2.*27 \bar "|."
  ---- pieceA/global.ily ----

etc.

nicolas




reply via email to

[Prev in Thread] Current Thread [Next in Thread]