Variables are perhaps most useful for combining lengthy sections
of music and/or annotation in various ways, while tags are more
useful for selecting one from several alternative shorter sections
-of music. Whichever method is used, separating the notation from
+of music. You can also employ tags for splicing pieced of music
+together at several places.
+
+Whichever method is used, separating the notation from
the structure of the score will make it easier to change the
structure while leaving the notation untouched.
@funindex \tag
@funindex \keepWithTag
@funindex \removeWithTag
+@funindex \pushToTag
+@funindex \appendToTag
@cindex tag
@cindex keep tagged music
@cindex remove tagged music
+@cindex splice into tagged music
The @code{\tag #'@var{partA}} command marks a music expression
with the name @var{partA}.
the first filter will remove all tagged sections except the one
named, and the second filter will remove even that tagged section.
+Sometimes you want to splice some music at a particular place in an
+existing music expression. You can use @code{\pushToTag} and
+@code{\appendToTag} for adding material at the front or end of the
+@code{elements} of an existing music construct. Not every music
+construct has @code{elements}, but sequential and simultaneous music are
+safe bets:
+
+@lilypond[verbatim,quote]
+test = { \tag #'here { \tag #'here <<c''>> } }
+
+{
+ \pushToTag #'here \pushToTag #'here
+ \pushToTag #'here \test g' e' c'
+ \appendToTag #'here \appendToTag #'here
+ \appendToTag #'here \test g' e' c'
+}
+@end lilypond
+
+Both commands get a tag, the tagged expression, and finally the material
+you want to splice in at every given tag. The commands make sure to
+copy everything that they change so that the original @code{\test}
+retains its meaning.
@seealso
Learning Manual:
--- /dev/null
+\version "2.15.13"
+
+\header{
+ texidoc="
+Adding material to a tag in sequential and simultaneous expressions
+using @code{\\pushToTag} and @code{\\appendToTag}. One should get the
+equivalent of
+@example
+@{ c' e' g' <<c' e' g' c''>> <<c'' g' e' c'>> g' e' c' @}
+@end example
+"
+}
+
+\layout { ragged-right = ##t }
+
+test = { \tag #'here { \tag #'here <<c''>> }}
+
+{
+ \pushToTag #'here \pushToTag #'here \pushToTag #'here \test g' e' c'
+ \appendToTag #'here \appendToTag #'here \appendToTag #'here \test g' e' c'
+}
'elements (list (make-music 'PageTurnEvent
'break-permission 'allow))))
+appendToTag =
+#(define-music-function (parser location tag music more)
+ (symbol? ly:music? ly:music?)
+ (_i "Append @var{more} to the @code{elements} of all music
+expressions in @var{music} that are tagged with @var{tag}.")
+ (music-map-copy (lambda (m)
+ (if (memq tag (ly:music-property m 'tags))
+ (begin
+ (set! m (music-clone m))
+ (set! (ly:music-property m 'elements)
+ (append (ly:music-property m 'elements)
+ (list more)))))
+ m)
+ music))
+
applyContext =
#(define-music-function (parser location proc) (procedure?)
(_i "Modify context properties with Scheme procedure @var{proc}.")
trill-events)))))
main-note))
+pushToTag =
+#(define-music-function (parser location tag music more)
+ (symbol? ly:music? ly:music?)
+ (_i "Add @var{more} to the front of @code{elements} of all music
+expressions in @var{music} that are tagged with @var{tag}.")
+ (music-map-copy (lambda (m)
+ (if (memq tag (ly:music-property m 'tags))
+ (begin
+ (set! m (music-clone m))
+ (set! (ly:music-property m 'elements)
+ (cons more (ly:music-property m 'elements)))))
+ m)
+ music))
+
quoteDuring =
#(define-music-function (parser location what main-music) (string? ly:music?)
(_i "Indicate a section of music to be quoted. @var{what} indicates the name
(music-map function e)))
(function music)))
+(define-public (music-map-copy function music)
+ "Apply @var{function} to @var{music} and all of the music it contains.
+
+First it recurses over the children, then the function is applied to
+@var{music}. This can be used for non-destructive changes when the
+original @var{music} should retain its meaning. When you change an
+element, return a changed copy. Then all ancestors will recursively
+become changed copies as well. The check for change is done via
+@code{eq?}."
+ (let* ((es (ly:music-property music 'elements))
+ (e (ly:music-property music 'element))
+ (esnew (pair-fold-right
+ (lambda (y tail)
+ (let ((res (music-map-copy function (car y))))
+ (if (and (eq? (cdr y) tail)
+ (eq? (car y) res))
+ y
+ (cons res tail))))
+ '() es))
+ (enew (if (ly:music? e)
+ (music-map-copy function e)
+ e)))
+ (if (not (and (eq? es esnew)
+ (eq? e enew)))
+ (begin
+ (set! music (music-clone music))
+ (set! (ly:music-property music 'elements) esnew)
+ (set! (ly:music-property music 'element) enew)))
+ (function music)))
+
(define-public (music-filter pred? music)
"Filter out music expressions that do not satisfy @var{pred?}."