[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Argument transfer?
From: |
Nicolas Sceaux |
Subject: |
Re: Argument transfer? |
Date: |
Tue, 07 Jun 2005 23:22:42 +0200 |
User-agent: |
Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux) |
Nicolas Sceaux <address@hidden> writes:
> I would like to see a real example where a pre processor is a win over
> using LilyPond's built-in extensibility capabilities, which many seem
> to underestimate.
To be more precise about how extensible LilyPond is, I'll show an
example of a file I'm working on, which is a unit test file for a
`display-lily-music' function: this function takes a music expression
(the scheme internal representation) and outputs a string,
representing the music expression using LilyPond notation. For
instance:
guile> (display-lily-music #{ \bar "||" #})
{ \bar "||"
}
The test file looks like:
{
##[ << { a b } \\ { c d } >> #]
##[ < c\1 e\3 >4.*3/4-. #]
##[ { c1 \afterGrace { b,16 c } d2 } #]
##[ { \makeClusters { c4 g } } #]
##[ \tempo 4 = 120 #]
##[ \clef "alto_3" #]
##[ \time 2/4 #]
##[ \bar "|." #]
##[ \once \set Score . skipBars = ##t #]
}
What this snippet does, is parsing the expression between #[ and #],
which gives a internal music expression, then calling the
`display-lily-music' function, to get back a string. The input and
this output string are compared, and if they are different, a report
is printed in the output score. For instance, if the file contains:
{
##[ \figures { < 6 > } #]
}
Then the resulting score contains the following markups:
\figures { < 6 > }
\new FiguredBass \figuremode { < 6 > }
showing that a difference has been found. No preprocessor needed.
For the curious, the definition of the #[ #] syntax, defined in the
top of the test file (no hacking LilyPond's core needed):
%%%
%%% Utilities
%%%
#(begin
(init-print-lily parser)
(define gen-lily-sym
;; Generate a lilyvartmpXX symbol, that may be (hopefully) unique.
(let ((var-idx -1))
(lambda ()
(set! var-idx (1+ var-idx))
(string->symbol (format #f "lilyvartmp~a"
(list->string (map (lambda (chr)
(integer->char (+
(char->integer #\a) (- (char->integer chr)
(char->integer #\0)))))
(string->list
(number->string var-idx)))))))))
(define (my-parse-string-result str parser module)
"Parse `str', which is supposed to contain a music expression."
(let ((music-sym (gen-lily-sym)))
(ly:parser-parse-string
parser
(format #f "
~a = \\notemode { ~a }
#(ly:export '~a)
#(module-define! (resolve-module '~a) '~a ~a)
"
music-sym str music-sym (module-name module) music-sym
music-sym))
(eval `,music-sym module)))
(define (my-read-lily-expression chr port)
(let ((lily-string (call-with-output-string
(lambda (out)
(do ((c (read-char port) (read-char port)))
((and (char=? c #\#)
(char=? (peek-char port) #\]))
(read-char port))
(display c out))))))
`(let* ((parser-clone (ly:clone-parser parser))
(input-str (string-trim-both ,lily-string))
(music (car (ly:music-property
(my-parse-string-result input-str parser-clone
(current-module))
'elements)))
(result-str (string-trim-both (print-lily-music music))))
(if (string=? input-str result-str)
(ly:export (make-music 'SequentialMusic))
(ly:export
(make-music
'SimultaneousMusic
'elements
(list (make-music
'ContextSpeccedMusic
'context-id
"$uniqueContextId"
'property-operations
'()
'context-type
'Lyrics
'element
(make-music
'SequentialMusic
'elements
(list (make-music
'EventChord
'elements
(list (make-music
'LyricEvent
'duration
(ly:make-duration 2 0 1 1)
'text
(markup #:simple input-str)))))))
(make-music
'ContextSpeccedMusic
'context-id
"$uniqueContextId"
'property-operations
'()
'context-type
'Lyrics
'element
(make-music
'SequentialMusic
'elements
(list (make-music
'EventChord
'elements
(list (make-music
'LyricEvent
'duration
(ly:make-duration 2 0 1 1)
'text
(markup #:simple result-str))))
(make-music
'EventChord
'elements
(list (make-music
'BreakEvent
'page-penalty
0
'penalty
-10001)))))))))))))
(read-hash-extend #\[ my-read-lily-expression))
nicolas