]> git.donarmstrong.com Git - lilypond.git/commitdiff
Allow markup lists to be composed at run-time
authorDavid Kastrup <dak@gnu.org>
Fri, 22 Mar 2013 08:25:05 +0000 (09:25 +0100)
committerDavid Kastrup <dak@gnu.org>
Sat, 6 Apr 2013 06:52:41 +0000 (08:52 +0200)
Using a markup command on a markup list generated by a markup list
command was not previously possible.  Now things like

  \with-color #red { \column-lines { x y z } }

work as well.

scm/define-markup-commands.scm
scm/ly-syntax-constructors.scm

index 98047b57418ecd5d881ba955869cbdcaad2a7742..ff977b2bfbb3262c28ab427d972929e200fc9ff7 100755 (executable)
@@ -4277,3 +4277,40 @@ where @var{X} is the number of staff spaces."
   (pair? markup-list?)
   "Like @code{\\override}, for markup lists."
   (interpret-markup-list layout (cons (list new-prop) props) args))
+
+(define-markup-list-command (map-markup-commands layout props compose args)
+  (procedure? markup-list?)
+  "This applies the function @var{compose} to every markup in
+@var{args} (including elements of markup list command calls) in order
+to produce a new markup list.  Since the return value from a markup
+list command call is not a markup list but rather a list of stencils,
+this requires passing those stencils off as the results of individual
+markup calls.  That way, the results should work out as long as no
+markups rely on side effects."
+  (let ((key (make-symbol "key")))
+    (catch
+     key
+     (lambda ()
+       ;; if `compose' does not actually interpret its markup
+       ;; argument, we still need to return a list of stencils,
+       ;; created from the single returned stencil
+       (list
+        (interpret-markup layout props
+                          (compose
+                           (make-on-the-fly-markup
+                            (lambda (layout props m)
+                              ;; here all effects of `compose' on the
+                              ;; properties should be visible, so we
+                              ;; call interpret-markup-list at this
+                              ;; point of time and harvest its
+                              ;; stencils
+                              (throw key
+                                     (interpret-markup-list
+                                      layout props args)))
+                            (make-null-markup))))))
+     (lambda (key stencils)
+       (map
+        (lambda (sten)
+          (interpret-markup layout props
+                            (compose (make-stencil-markup sten))))
+        stencils)))))
index 3fdf6987273e4fa1e82d202e81d8e787ee5c8fc3..7817ec25c5ddee138681eed94ca77b5ec8f3490c 100644 (file)
@@ -18,7 +18,7 @@
 ;; TODO: use separate module for syntax
 ;; constructors. Also create wrapper around the constructor?
 (defmacro define-ly-syntax (args . body)
-  `(define-public ,args ,(cons 'begin body)))
+  `(define-public ,args ,@body))
 
 ;; A ly-syntax constructor takes two extra parameters, parser and
 ;; location. These are mainly used for reporting errors and
@@ -172,20 +172,24 @@ into a @code{MultiMeasureTextEvent}."
 ;;   (bold (raise 4 (italic markup2)))
 ;;   (bold (raise 4 (italic markup3))))
 
-  (map (lambda (arg)
-         (fold
-          (lambda (cmd prev) (append cmd (list prev)))
-          arg
-          commands))
-       (if (every markup? markups)
-           markups
-           (begin
-             (ly:parser-error parser
-                              (format #f
-                                      (_ "uncomposable markup list elements ~a")
-                                      (remove markup? markups))
-                              location)
-             (filter markup? markups)))))
+  (define (compose arg)
+    (fold
+     (lambda (cmd prev) (append cmd (list prev)))
+     arg
+     commands))
+  (let loop ((markups markups) (completed '()))
+    (cond ((null? markups) (reverse! completed))
+          ((markup? (car markups))
+           (loop (cdr markups)
+                 (cons (compose (car markups)) completed)))
+          (else
+           (call-with-values
+               (lambda () (break! markup? markups))
+             (lambda (complex rest)
+               (loop rest
+                     (reverse!
+                      (make-map-markup-commands-markup-list
+                       compose complex) completed))))))))
 
 (define-ly-syntax (property-operation parser location ctx music-type symbol . args)
   (let* ((props (case music-type