lilypond-user
[Top][All Lists]
Advanced

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

Best current method to include only once


From: Michael J. O'Donnell
Subject: Best current method to include only once
Date: Sun, 14 Feb 2010 12:05:11 -0600
User-agent: Thunderbird 2.0.0.23 (X11/20090817)

For those who would like to use it too, I append a complete utility file
that I use to copy in a file full of definitions with \includeIfAbsent,
skipping the copy if the file has already been copied in with
\includeIfAbsent. This utility file should be copied in with \include
(not \includeIfAbsent) wherever \includeIfAbsent might be used.

If you have already copied in a target file with \include,
\includeIfAbsent will copy it in again. To avoid that behavior, you can
add include guards, similar to the one on the definition of
includeIfAbsent, to the target file. But I'd rather just replace each
\include with \includeIfAbsent as I notice that behavior.

It is probably harmless to define includeIfAbsent repeatedly, but I
avoided it for cleanliness. It is probably a fine idea to guard each
definition of a utility function or variable in a similar way, but I
doubt that many of us will bother.

Unfortunately, includeIfAbsent does not behave precisely like include in
the case when it actually copies in the target file. All definitions in
the target file are evaluated in an inner scope. So, definitions in the
target file should be given with the Scheme function
define-public-toplevel, rather than LilyPond definition syntax, as
explained in the comment within the utility file. Use of
define-public-toplevel is probably a good idea anyway, for robustness.

I don't see how to provide something like \includeIfAbsent operating in
the same toplevel scope as \include, except by hacking the lexical
analyzer (requiring a recompilation of LilyPond), or duplicating what
the lexical analyzer performs (which risks getting out of whack with the
state of the lexical analyzer and/or parser). The internal comment
describes an alternative that appears to perform all of the desired
actions, including output of *.ps and *.ps score files, but LilyPond
crashes with a segmentation fault at the very end. If you want to cross
your fingers and use that version for perfect (?) backwards
compatibility with your include files, replace "(ly:parser-clone
parser)" with "parser".

\version "2.12.2"

\sourcefilename "ODBOL_input-utility.ly"

% Include a file unless it has already been included.  This executes
% in a cloned parser, so all definitions in the included file need to
% be made global with define-public-toplevel.  Include seems to be
% implemented in the lexical analyzer, and I don't see how to do it
% properly at a higher level.  Executing in the main parser appears to
% have the right effect, and produce all desired output, but LilyPond
% ends with a segmentation fault.

%
% In the included file, do lilypond variable defintion
%
%      var = <stuff>
% as
%      #(define-public-toplevel var #{ <stuff> #} )
%
% music function definition
%
%      fname = #(define-music-function <stuff>)
% as
%      #(define-public-toplevel fname (define-music-function <stuff>))
%
% markup definition
%
%      var = \markup { <stuff> }
% as
%      #(define-public-toplevel var (markup <translated-stuff>))
%
% Using the translation described in the LilyPond Notation Manual
% section Markup-construction-in-Scheme
%


#(if (not (defined? 'includeIfAbsent))

  (define-public-toplevel includeIfAbsent  (define-music-function
(parser location fileName) (string?)

    (let ((guardName (string-append "Already Got " fileName)))

      (if (not (defined? (string->symbol guardName)))
        (begin

          (primitive-eval (list 'define (string->symbol guardName) #t))

          (ly:parser-parse-string (ly:parser-clone parser)
(string-concatenate (list "\\include \"" fileName "\"")))

          (make-music 'SequentialMusic 'void #t)

        )

        (make-music 'SequentialMusic 'void #t)

) ) ) ) )





reply via email to

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