]> git.donarmstrong.com Git - lilypond.git/blob - ly/music-functions-init.ly
Issue 4533: Stop the generic \tweak command from working as override
[lilypond.git] / ly / music-functions-init.ly
1 %%%% -*- Mode: Scheme -*-
2
3 %%%% This file is part of LilyPond, the GNU music typesetter.
4 %%%%
5 %%%% Copyright (C) 2003--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 %%%%                          Jan Nieuwenhuizen <janneke@gnu.org>
7 %%%%
8 %%%% LilyPond is free software: you can redistribute it and/or modify
9 %%%% it under the terms of the GNU General Public License as published by
10 %%%% the Free Software Foundation, either version 3 of the License, or
11 %%%% (at your option) any later version.
12 %%%%
13 %%%% LilyPond is distributed in the hope that it will be useful,
14 %%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
15 %%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 %%%% GNU General Public License for more details.
17 %%%%
18 %%%% You should have received a copy of the GNU General Public License
19 %%%% along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
20
21 \version "2.19.25"
22
23
24 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 %% this file is alphabetically sorted.
26 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27
28 %% need SRFI-1 for filter; optargs for lambda*
29 #(use-modules (srfi srfi-1)
30               (ice-9 optargs))
31
32 %% TODO: using define-music-function in a .scm causes crash.
33
34 absolute =
35 #(define-music-function (music)
36    (ly:music?)
37    (_i "Make @var{music} absolute.  This does not actually change the
38 music itself but rather hides it from surrounding @code{\\relative}
39 and @code{\\fixed} commands.")
40    (make-music 'RelativeOctaveMusic 'element music))
41
42 acciaccatura =
43 #(def-grace-function startAcciaccaturaMusic stopAcciaccaturaMusic
44    (_i "Create an acciaccatura from the following music expression"))
45
46 %% keep these two together
47 instrument-definitions = #'()
48 addInstrumentDefinition =
49 #(define-void-function
50    (name lst) (string? list?)
51    (_i "Create instrument @var{name} with properties @var{list}.")
52    (set! instrument-definitions (acons name lst instrument-definitions)))
53
54 addQuote =
55 #(define-void-function (name music) (string? ly:music?)
56    (_i "Define @var{music} as a quotable music expression named
57 @var{name}")
58    (add-quotable name music))
59
60 %% keep these two together
61 afterGraceFraction = #(cons 6 8)
62 afterGrace =
63 #(define-music-function (main grace) (ly:music? ly:music?)
64    (_i "Create @var{grace} note(s) after a @var{main} music expression.")
65    (let ((main-length (ly:music-length main))
66          (fraction  (ly:parser-lookup 'afterGraceFraction)))
67      (make-simultaneous-music
68       (list
69        main
70        (make-sequential-music
71         (list
72
73          (make-music 'SkipMusic
74                      'duration (ly:make-duration
75                                 0 0
76                                 (* (ly:moment-main-numerator main-length)
77                                    (car fraction))
78                                 (* (ly:moment-main-denominator main-length)
79                                    (cdr fraction))))
80          (make-music 'GraceMusic
81                      'element grace)))))))
82
83
84 %% music identifiers not allowed at top-level,
85 %% so this is a music-function instead.
86 allowPageTurn =
87 #(define-music-function () ()
88    (_i "Allow a page turn. May be used at toplevel (ie between scores or
89 markups), or inside a score.")
90    (make-music 'EventChord
91                'page-marker #t
92                'page-turn-permission 'allow
93                'elements (list (make-music 'PageTurnEvent
94                                            'break-permission 'allow))))
95
96 alterBroken =
97 #(define-music-function (property arg item)
98   (symbol-list-or-symbol? list? symbol-list-or-music?)
99   (_i "Override @var{property} for pieces of broken spanner @var{item}
100 with values @var{arg}.  @var{item} may either be music in the form of
101 a starting spanner event, or a symbol list in the form
102 @samp{Context.Grob} or just @samp{Grob}.  Iff @var{item} is in the
103 form of a spanner event, @var{property} may also have the form
104 @samp{Grob.property} for specifying a directed tweak.")
105   (if (ly:music? item)
106       (if (eq? (ly:music-property item 'span-direction) START)
107           (tweak property (value-for-spanner-piece arg) item)
108           (begin
109             (ly:music-warning item (_ "not a spanner"))
110             item))
111       (let* ((p (check-grob-path item (*location*)
112                                  #:default 'Bottom
113                                  #:min 2
114                                  #:max 2))
115              (name (and p (second p)))
116              (description
117               (and name (assoc-get name all-grob-descriptions))))
118         (if (and description
119                  (member 'spanner-interface
120                          (assoc-get 'interfaces
121                                     (assoc-get 'meta description))))
122             (propertyOverride (append item (if (symbol? property)
123                                        (list property)
124                                        property))
125                       (value-for-spanner-piece arg))
126             (begin
127               (ly:input-warning (*location*) (_ "not a spanner name, `~a'") name)
128               (make-music 'Music))))))
129
130 appendToTag =
131 #(define-music-function (tag more music)
132    (symbol? ly:music? ly:music?)
133    (_i "Append @var{more} to the @code{elements} of all music
134 expressions in @var{music} that are tagged with @var{tag}.")
135    (music-map (lambda (m)
136                 (if (memq tag (ly:music-property m 'tags))
137                     (set! (ly:music-property m 'elements)
138                           (append (ly:music-property m 'elements)
139                                   (list more))))
140                 m)
141               music))
142
143 applyContext =
144 #(define-music-function (proc) (procedure?)
145    (_i "Modify context properties with Scheme procedure @var{proc}.")
146    (make-music 'ApplyContext
147                'procedure proc))
148
149 applyMusic =
150 #(define-music-function (func music) (procedure? ly:music?)
151    (_i"Apply procedure @var{func} to @var{music}.")
152    (func music))
153
154 applyOutput =
155 #(define-music-function (target proc) (symbol-list-or-symbol? procedure?)
156    (_i "Apply function @code{proc} to every layout object matched by
157 @var{target} which takes the form @code{Context} or @code{Context.Grob}.")
158    (let ((p (check-grob-path target (*location*) #:max 2)))
159      (if p
160          (make-music 'ApplyOutputEvent
161                      'procedure proc
162                      'context-type (car p)
163                      (if (pair? (cdr p))
164                          (list (cons 'symbol (cadr p)))
165                          '()))
166          (make-music 'Music))))
167
168 appoggiatura =
169 #(def-grace-function startAppoggiaturaMusic stopAppoggiaturaMusic
170    (_i "Create an appoggiatura from @var{music}"))
171
172 % for regression testing purposes.
173 assertBeamQuant =
174 #(define-music-function (l r) (pair? pair?)
175    (_i "Testing function: check whether the beam quants @var{l} and @var{r} are correct")
176    (make-grob-property-override 'Beam 'positions (check-quant-callbacks l r)))
177
178 % for regression testing purposes.
179 assertBeamSlope =
180 #(define-music-function (comp) (procedure?)
181    (_i "Testing function: check whether the slope of the beam is the same as @code{comp}")
182    (make-grob-property-override 'Beam 'positions (check-slope-callbacks comp)))
183
184 autochange =
185 #(define-music-function (pitch clef-1 clef-2 music)
186   ((ly:pitch? (ly:make-pitch 0 0)) (ly:context-mod?)(ly:context-mod?) ly:music?)
187   (_i "Make voices that switch between staves automatically.  As an option the
188 pitch where to switch staves may be specified.  The clefs for the staves are
189 optional as well.  Setting clefs  works only for implicitly instantiated
190 staves.")
191   (let ;; keep the contexts alive for the full duration
192        ((skip (make-skip-music (make-duration-of-length
193                                      (ly:music-length music)))))
194     #{
195       <<
196         \context Staff = "up" $(or clef-1 #{ \with { \clef "treble" } #})
197           <<
198           #(make-autochange-music pitch music)
199           \new Voice { #skip }
200           >>
201         \context Staff = "down" $(or clef-2 #{ \with { \clef "bass" } #})
202           \new Voice { #skip }
203       >>
204     #}))
205
206 balloonGrobText =
207 #(define-music-function (grob-name offset text)
208    (symbol? number-pair? markup?)
209    (_i "Attach @var{text} to @var{grob-name} at offset @var{offset}
210  (use like @code{\\once})")
211    (make-event-chord
212     (list
213      (make-music 'AnnotateOutputEvent
214                  'symbol grob-name
215                  'X-offset (car offset)
216                  'Y-offset (cdr offset)
217                  'text text))))
218
219 balloonText =
220 #(define-event-function (offset text) (number-pair? markup?)
221    (_i "Attach @var{text} at @var{offset} (use like @code{\\tweak})")
222    (make-music 'AnnotateOutputEvent
223                'X-offset (car offset)
224                'Y-offset (cdr offset)
225                'text text))
226
227 bar =
228 #(define-music-function (type) (string?)
229    (_i "Insert a bar line of type @var{type}")
230    (context-spec-music
231     (make-property-set 'whichBar type)
232     'Timing))
233
234 barNumberCheck =
235 #(define-music-function (n) (integer?)
236    (_i "Print a warning if the current bar number is not @var{n}.")
237    (make-music 'ApplyContext
238                'procedure
239                (lambda (c)
240                  (let ((cbn (ly:context-property c 'currentBarNumber)))
241                    (if (and  (number? cbn) (not (= cbn n)))
242                        (ly:input-warning (*location*)
243                                          "Barcheck failed got ~a expect ~a"
244                                          cbn n))))))
245
246 beamExceptions =
247 #(define-scheme-function (music) (ly:music?)
248    (_i "Extract a value suitable for setting
249 @code{Timing.beamExceptions} from the given pattern with explicit
250 beams in @var{music}.  A bar check @code{|} has to be used between
251 bars of patterns in order to reset the timing.")
252    (extract-beam-exceptions music))
253
254 bendAfter =
255 #(define-event-function (delta) (real?)
256    (_i "Create a fall or doit of pitch interval @var{delta}.")
257    (make-music 'BendAfterEvent
258                'delta-step delta))
259
260 bookOutputName =
261 #(define-void-function (newfilename) (string?)
262    (_i "Direct output for the current book block to @var{newfilename}.")
263    (set! (paper-variable #f 'output-filename) newfilename))
264
265 bookOutputSuffix =
266 #(define-void-function (newsuffix) (string?)
267    (_i "Set the output filename suffix for the current book block to
268 @var{newsuffix}.")
269    (set! (paper-variable #f 'output-suffix) newsuffix))
270
271 %% \breathe is defined as a music function rather than an event identifier to
272 %% ensure it gets useful input location information: as an event identifier,
273 %% it would have to be wrapped in an EventChord to prevent it from being
274 %% treated as a post_event by the parser
275 breathe =
276 #(define-music-function () ()
277    (_i "Insert a breath mark.")
278    (make-music 'BreathingEvent))
279
280 clef =
281 #(define-music-function (type) (string?)
282    (_i "Set the current clef to @var{type}.")
283    (make-clef-set type))
284
285
286 compoundMeter =
287 #(define-music-function (args) (pair?)
288   (_i "Create compound time signatures. The argument is a Scheme list of
289 lists. Each list describes one fraction, with the last entry being the
290 denominator, while the first entries describe the summands in the
291 enumerator. If the time signature consists of just one fraction,
292 the list can be given directly, i.e. not as a list containing a single list.
293 For example, a time signature of (3+1)/8 + 2/4 would be created as
294 @code{\\compoundMeter #'((3 1 8) (2 4))}, and a time signature of (3+2)/8
295 as @code{\\compoundMeter #'((3 2 8))} or shorter
296 @code{\\compoundMeter #'(3 2 8)}.")
297   (let* ((mlen (calculate-compound-measure-length args))
298          (beat (calculate-compound-base-beat args))
299          (beatGrouping (calculate-compound-beat-grouping args))
300          (timesig (cons (ly:moment-main-numerator mlen)
301                         (ly:moment-main-denominator mlen))))
302   #{
303     \once \override Timing.TimeSignature.stencil = #(lambda (grob)
304       (grob-interpret-markup grob (make-compound-meter-markup args)))
305     \set Timing.timeSignatureFraction = #timesig
306     \set Timing.baseMoment = #beat
307     \set Timing.beatStructure = #beatGrouping
308     \set Timing.beamExceptions = #'()
309     \set Timing.measureLength = #mlen
310   #} ))
311
312 compressMMRests =
313 #(define-music-function (music) (ly:music?)
314   (_i "Remove the empty bars created by multi-measure rests,
315 leaving just the first bar containing the MM rest itself.")
316    (music-map
317     (lambda (m)
318       (if (eq? 'MultiMeasureRestMusic (ly:music-property m 'name))
319           #{ \once \set Score.skipBars = ##t #m #}
320           #{ #m #} ))
321     music))
322
323 crossStaff =
324 #(define-music-function (notes) (ly:music?)
325   (_i "Create cross-staff stems")
326   #{
327   \temporary \override Stem.cross-staff = #cross-staff-connect
328   \temporary \override Flag.style = #'no-flag
329   #notes
330   \revert Stem.cross-staff
331   \revert Flag.style
332 #})
333
334 cueClef =
335 #(define-music-function (type) (string?)
336   (_i "Set the current cue clef to @var{type}.")
337   (make-cue-clef-set type))
338
339 cueClefUnset =
340 #(define-music-function () ()
341   (_i "Unset the current cue clef.")
342   (make-cue-clef-unset))
343
344 cueDuring =
345 #(define-music-function
346    (what dir main-music) (string? ly:dir? ly:music?)
347    (_i "Insert contents of quote @var{what} corresponding to @var{main-music},
348 in a CueVoice oriented by @var{dir}.")
349    (make-music 'QuoteMusic
350                'element main-music
351                'quoted-context-type 'CueVoice
352                'quoted-context-id "cue"
353                'quoted-music-name what
354                'quoted-voice-direction dir))
355
356 cueDuringWithClef =
357 #(define-music-function
358    (what dir clef main-music) (string? ly:dir? string? ly:music?)
359    (_i "Insert contents of quote @var{what} corresponding to @var{main-music},
360 in a CueVoice oriented by @var{dir}.")
361    (make-music 'QuoteMusic
362                'element main-music
363                'quoted-context-type 'CueVoice
364                'quoted-context-id "cue"
365                'quoted-music-name what
366                'quoted-music-clef clef
367                'quoted-voice-direction dir))
368
369
370
371 displayLilyMusic =
372 #(define-music-function (port music) ((output-port?) ly:music?)
373    (_i "Display the LilyPond input representation of @var{music}
374 to @var{port}, defaulting to the console.")
375    (let ((port (or port (current-output-port))))
376      (newline port)
377      (display-lily-music music port))
378    music)
379
380 displayMusic =
381 #(define-music-function (port music) ((output-port?) ly:music?)
382    (_i "Display the internal representation of @var{music} to
383 @var{port}, default to the console.")
384    (let ((port (or port (current-output-port))))
385      (newline port)
386      (display-scheme-music music port))
387    music)
388
389 displayScheme =
390 #(define-scheme-function (port expr) ((output-port?) scheme?)
391    (_i "Display the internal representation of @var{expr} to
392 @var{port}, default to the console.")
393    (let ((port (or port (current-output-port))))
394      (newline port)
395      (display-scheme-music expr port))
396    expr)
397
398
399
400 endSpanners =
401 #(define-music-function (music) (ly:music?)
402    (_i "Terminate the next spanner prematurely after exactly one note
403 without the need of a specific end spanner.")
404    (let* ((start-span-evs (filter (lambda (ev)
405                                     (equal? (ly:music-property ev 'span-direction)
406                                             START))
407                                   (extract-typed-music music 'span-event)))
408           (stop-span-evs
409            (map (lambda (m)
410                   (music-clone m 'span-direction STOP))
411                 start-span-evs))
412           (end-ev-chord (make-music 'EventChord
413                                     'elements stop-span-evs))
414           (total (make-music 'SequentialMusic
415                              'elements (list music
416                                              end-ev-chord))))
417      total))
418
419 eventChords =
420 #(define-music-function (music) (ly:music?)
421    (_i "Compatibility function wrapping @code{EventChord} around
422 isolated rhythmic events occuring since version 2.15.28, after
423 expanding repeat chords @samp{q}.")
424    (event-chord-wrap! music))
425
426 featherDurations=
427 #(define-music-function (factor argument) (ly:moment? ly:music?)
428    (_i "Adjust durations of music in @var{argument} by rational @var{factor}.")
429    (let ((orig-duration (ly:music-length argument))
430          (multiplier (ly:make-moment 1 1)))
431
432      (for-each
433       (lambda (mus)
434         (if (< 0 (ly:moment-main-denominator (ly:music-length mus)))
435             (begin
436               (ly:music-compress mus multiplier)
437               (set! multiplier (ly:moment-mul factor multiplier)))))
438       (extract-named-music argument '(EventChord NoteEvent RestEvent SkipEvent)))
439      (ly:music-compress
440       argument
441       (ly:moment-div orig-duration (ly:music-length argument)))
442
443      argument))
444
445 finger =
446 #(define-event-function (finger) (number-or-markup?)
447    (_i "Apply @var{finger} as a fingering indication.")
448
449    (make-music
450             'FingeringEvent
451             (if (number? finger) 'digit 'text)
452             finger))
453
454 fixed =
455 #(define-music-function (pitch music)
456    (ly:pitch? ly:music?)
457    (_i "Use the octave of @var{pitch} as the default octave for @var{music}.")
458    (let ((octave-marks (1+ (ly:pitch-octave pitch))))
459      (cond ((not (= 0 octave-marks))
460             (ly:music-transpose music (ly:make-pitch octave-marks 0 0))
461             ;;In order to leave unchanged the notes in any enclosed
462             ;; \absolute or \fixed or \relative, make a cancelling shift
463             (map (lambda (m)
464                    (ly:music-transpose m (ly:make-pitch (- octave-marks) 0 0)))
465                  (extract-named-music music 'RelativeOctaveMusic)))))
466    (make-music 'RelativeOctaveMusic 'element music))
467
468 footnote =
469 #(define-music-function (mark offset footnote item)
470    ((markup?) number-pair? markup? symbol-list-or-music?)
471    (_i "Make the markup @var{footnote} a footnote on @var{item}.  The
472 footnote is marked with a markup @var{mark} moved by @var{offset} with
473 respect to the marked music.
474
475 If @var{mark} is not given or specified as @var{\\default}, it is
476 replaced by an automatically generated sequence number.  If @var{item}
477 is a symbol list of form @samp{Grob} or @samp{Context.Grob}, then
478 grobs of that type will be marked at the current time step in the
479 given context (default @code{Bottom}).
480
481 If @var{item} is music, the music will get a footnote attached to a
482 grob immediately attached to the event, like @var{\\tweak} does.  For
483 attaching a footnote to an @emph{indirectly} caused grob, write
484 @code{\\single\\footnote}, use @var{item} to specify the grob, and
485 follow it with the music to annotate.
486
487 Like with @code{\\tweak}, if you use a footnote on a following
488 post-event, the @code{\\footnote} command itself needs to be attached
489 to the preceding note or rest as a post-event with @code{-}.")
490    (let ((mus (make-music
491                'FootnoteEvent
492                'X-offset (car offset)
493                'Y-offset (cdr offset)
494                'automatically-numbered (not mark)
495                'text (or mark (make-null-markup))
496                'footnote-text footnote)))
497      (once (propertyTweak 'footnote-music mus item))))
498
499 grace =
500 #(def-grace-function startGraceMusic stopGraceMusic
501    (_i "Insert @var{music} as grace notes."))
502
503 grobdescriptions =
504 #(define-scheme-function (descriptions) (list?)
505    (_i "Create a context modification from @var{descriptions}, a list
506 in the format of @code{all-grob-descriptions}.")
507    (ly:make-context-mod
508     (map (lambda (p)
509            (list 'assign (car p) (ly:make-grob-properties (cdr p))))
510          descriptions)))
511
512 harmonicByFret = #(define-music-function (fret music) (number? ly:music?)
513   (_i "Convert @var{music} into mixed harmonics; the resulting notes resemble
514 harmonics played on a fretted instrument by touching the strings at @var{fret}.")
515   #{
516     \set harmonicDots = ##t
517     \temporary \override TabNoteHead.stencil = #(tab-note-head::print-custom-fret-label (number->string fret))
518     \temporary \override NoteHead.Y-extent = #grob::always-Y-extent-from-stencil
519     \temporary \override NoteHead.stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed)
520                                             (ly:note-head::print grob))
521     #(make-harmonic
522        (calc-harmonic-pitch (fret->pitch (number->string fret)) music))
523     \unset harmonicDots
524     \revert TabNoteHead.stencil
525     \revert NoteHead.Y-extent
526     \revert NoteHead.stencil
527   #})
528
529 harmonicByRatio = #(define-music-function (ratio music) (number? ly:music?)
530     (_i "Convert @var{music} into mixed harmonics; the resulting notes resemble
531 harmonics played on a fretted instrument by touching the strings at the point
532 given through @var{ratio}.")
533   #{
534     \set harmonicDots = ##t
535     \temporary \override TabNoteHead.stencil = #(tab-note-head::print-custom-fret-label (ratio->fret ratio))
536     \temporary \override NoteHead.Y-extent = #(ly:make-unpure-pure-container ly:grob::stencil-height)
537     \temporary \override NoteHead.stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed)
538                                             (ly:note-head::print grob))
539     #(make-harmonic
540       (calc-harmonic-pitch (ratio->pitch ratio) music))
541     \unset harmonicDots
542     \revert TabNoteHead.stencil
543     \revert NoteHead.Y-extent
544     \revert NoteHead.stencil
545   #})
546
547 hide =
548 #(define-music-function (item) (symbol-list-or-music?)
549    (_i "Set @var{item}'s @samp{transparent} property to @code{#t},
550 making it invisible while still retaining its dimensions.
551
552 If @var{item} is a symbol list of form @code{GrobName} or
553 @code{Context.GrobName}, the result is an override for the grob name
554 specified by it.  If @var{item} is a music expression, the result is
555 the same music expression with an appropriate tweak applied to it.")
556    (propertyTweak 'transparent #t item))
557
558 inStaffSegno =
559 #(define-music-function () ()
560    (_i "Put the segno variant 'varsegno' at this position into the staff,
561 compatible with the repeat command.")
562    (make-music 'ApplyContext
563                'procedure
564                (lambda (ctx)
565                  (let ((score-ctx (ly:context-find ctx 'Score)))
566                    (if (ly:context? score-ctx)
567                      (let ((old-rc (ly:context-property score-ctx 'repeatCommands '())))
568                        (if (eq? (memq 'segno-display old-rc) #f)
569                          (ly:context-set-property! score-ctx 'repeatCommands (cons 'segno-display old-rc)))))))))
570
571 instrumentSwitch =
572 #(define-music-function
573    (name) (string?)
574    (_i "Switch instrument to @var{name}, which must be predefined with
575 @code{\\addInstrumentDefinition}.")
576    (let* ((handle (assoc name instrument-definitions))
577           (instrument-def (if handle (cdr handle) '())))
578
579      (if (not handle)
580          (ly:input-warning (*location*) "No such instrument: ~a" name))
581      (context-spec-music
582       (make-music 'SimultaneousMusic
583                   'elements
584                   (map (lambda (kv)
585                          (make-property-set
586                           (car kv)
587                           (cdr kv)))
588                        instrument-def))
589       'Staff)))
590
591
592
593 keepWithTag =
594 #(define-music-function (tags music)
595    (symbol-list-or-symbol? ly:music?)
596    (_i "Include only elements of @var{music} that are tagged with one
597 of the tags in @var{tags}.  @var{tags} may be either a single symbol
598 or a list of symbols.
599
600 Each tag may be declared as a member of at most one tag group (defined
601 with @code{\\tagGroup}).  If none of a @var{music} element's tags
602 share a tag group with one of the specified @var{tags}, the element is
603 retained.")
604    (music-filter
605     (tags-keep-predicate tags)
606     music))
607
608 key =
609 #(define-music-function (tonic pitch-alist)
610    ((ly:pitch? '()) (list? '()))
611    (_i "Set key to @var{tonic} and scale @var{pitch-alist}.
612 If both are null, just generate @code{KeyChangeEvent}.")
613    (cond ((null? tonic) (make-music 'KeyChangeEvent))
614          ((null? pitch-alist)
615           (ly:parser-error (_ "second argument must be pitch list")
616                            (*location*))
617           (make-music 'SequentialMusic 'void #t))
618          (else
619           (ly:music-transpose
620            (make-music 'KeyChangeEvent
621                 'tonic (ly:make-pitch 0 0 0)
622                 'pitch-alist pitch-alist)
623            tonic))))
624
625 killCues =
626 #(define-music-function (music) (ly:music?)
627    (_i "Remove cue notes from @var{music}.")
628    (music-map
629     (lambda (mus)
630       (if (and (string? (ly:music-property mus 'quoted-music-name))
631                (string=? (ly:music-property mus 'quoted-context-id "") "cue"))
632           (ly:music-property mus 'element)
633           mus))
634     music))
635
636
637
638 label =
639 #(define-music-function (label) (symbol?)
640    (_i "Create @var{label} as a bookmarking label.")
641    (make-music 'EventChord
642                'page-marker #t
643                'page-label label
644                'elements (list (make-music 'LabelEvent
645                                            'page-label label))))
646
647
648 language =
649 #(define-void-function (language) (string?)
650    (_i "Set note names for language @var{language}.")
651    (note-names-language language))
652
653 languageSaveAndChange =
654 #(define-void-function (language) (string?)
655   (_i "Store the previous pitchnames alist, and set a new one.")
656   (set! previous-pitchnames pitchnames)
657   (note-names-language language))
658
659 languageRestore =
660 #(define-void-function () ()
661    (_i "Restore a previously-saved pitchnames alist.")
662    (if previous-pitchnames
663        (begin
664         (set! pitchnames previous-pitchnames)
665         (ly:parser-set-note-names pitchnames))
666       (ly:input-warning (*location*) (_ "No other language was defined previously. Ignoring."))))
667
668
669 magnifyMusic =
670 #(define-music-function (mag music) (positive? ly:music?)
671    (_i "Magnify the notation of @var{music} without changing the
672 staff-size, using @var{mag} as a size factor.  Stems, beams,
673 slurs, ties, and horizontal spacing are adjusted automatically.")
674
675    ;; these props are NOT allowed to shrink below default size
676    (define unshrinkable-props
677      '(
678        ;; stems
679        (Stem thickness)
680
681        ;; slurs
682        (Slur line-thickness)
683        (Slur thickness)
684        (PhrasingSlur line-thickness)
685        (PhrasingSlur thickness)
686
687        ;; ties
688        (Tie line-thickness)
689        (Tie thickness)
690        (LaissezVibrerTie line-thickness)
691        (LaissezVibrerTie thickness)
692        (RepeatTie line-thickness)
693        (RepeatTie thickness)
694        ))
695
696    ;; these props ARE allowed to shrink below default size
697    (define shrinkable-props
698      (let ((baseline-skip-props
699              (find-named-props 'baseline-skip all-grob-descriptions))
700            (word-space-props
701              (find-named-props 'word-space all-grob-descriptions)))
702        (append
703          baseline-skip-props
704          word-space-props
705          '(
706            ;; TODO: uncomment spacing-increment here once Issue 3987 is fixed
707            ;; override at the 'Score level
708            ;(SpacingSpanner spacing-increment)
709
710            ;; lengths and heights
711            (Beam length-fraction)
712            (Stem length-fraction)
713            (Stem beamlet-default-length)
714            (Stem double-stem-separation)
715            (Slur height-limit)
716            (Slur minimum-length)
717            (PhrasingSlur height-limit)
718            (PhrasingSlur minimum-length)
719
720            ;; Beam.beam-thickness is dealt with separately below
721            ))))
722    #{
723      \context Bottom {
724        %% TODO: uncomment \newSpacingSection once Issue 3990 is fixed
725        %\newSpacingSection
726        #(scale-fontSize 'magnifyMusic mag)
727        #(scale-props    'magnifyMusic mag #f unshrinkable-props)
728        #(scale-props    'magnifyMusic mag #t shrinkable-props)
729        #(scale-beam-thickness mag)
730
731        #music
732
733        %% TODO: uncomment \newSpacingSection once Issue 3990 is fixed
734        %\newSpacingSection
735        %% reverse engineer the former fontSize value instead of using \unset
736        #(revert-fontSize 'magnifyMusic mag)
737        #(revert-props    'magnifyMusic mag (append unshrinkable-props
738                                                    shrinkable-props
739                                                    '((Beam beam-thickness))))
740      }
741    #})
742
743 magnifyStaff =
744 #(define-music-function (mag) (positive?)
745    (_i "Change the size of the staff, adjusting notation size and
746 horizontal spacing automatically, using @var{mag} as a size factor.")
747
748    ;; these props are NOT allowed to shrink below default size
749    (define unshrinkable-props
750      '((StaffSymbol thickness)))
751
752    ;; these props ARE allowed to shrink below default size
753    (define shrinkable-props
754      (let* ((baseline-skip-props
755               (find-named-props 'baseline-skip all-grob-descriptions))
756             (word-space-props
757               (find-named-props 'word-space all-grob-descriptions))
758             (space-alist-props
759               (find-named-props 'space-alist all-grob-descriptions)))
760        (append
761          baseline-skip-props
762          word-space-props
763          space-alist-props
764          '(
765            ;; override at the 'Score level
766            (SpacingSpanner spacing-increment)
767
768            (StaffSymbol staff-space)
769            (BarLine kern)
770            (BarLine segno-kern)
771            (BarLine hair-thickness)
772            (BarLine thick-thickness)
773            (Stem beamlet-default-length)
774            (Stem double-stem-separation)
775            ))))
776
777    #{
778      \stopStaff
779
780      %% revert settings from last time
781      %% (but only if \magnifyStaff has already been used
782      %% and the staff magnification is changing)
783      #(revert-fontSize 'magnifyStaff mag)
784      #(revert-props    'magnifyStaff mag (append unshrinkable-props
785                                                  shrinkable-props))
786
787      %% scale settings
788      %% (but only if staff magnification is changing
789      %% and does not equal 1)
790      #(scale-fontSize 'magnifyStaff mag)
791      #(scale-props    'magnifyStaff mag #f unshrinkable-props)
792      #(scale-props    'magnifyStaff mag #t shrinkable-props)
793
794      %% this might cause problems until Issue 3990 is fixed
795      \newSpacingSection
796
797      \startStaff
798      \set Staff.magnifyStaffValue = #mag
799    #})
800
801 makeClusters =
802 #(define-music-function (arg) (ly:music?)
803    (_i "Display chords in @var{arg} as clusters.")
804    (music-map note-to-cluster arg))
805
806 modalInversion =
807 #(define-music-function (around to scale music)
808     (ly:pitch? ly:pitch? ly:music? ly:music?)
809     (_i "Invert @var{music} about @var{around} using @var{scale} and
810 transpose from @var{around} to @var{to}.")
811     (let ((inverter (make-modal-inverter around to scale)))
812       (change-pitches music inverter)
813       music))
814
815 modalTranspose =
816 #(define-music-function (from to scale music)
817     (ly:pitch? ly:pitch? ly:music? ly:music?)
818     (_i "Transpose @var{music} from pitch @var{from} to pitch @var{to}
819 using @var{scale}.")
820     (let ((transposer (make-modal-transposer from to scale)))
821       (change-pitches music transposer)
822       music))
823
824 inversion =
825 #(define-music-function
826    (around to music) (ly:pitch? ly:pitch? ly:music?)
827    (_i "Invert @var{music} about @var{around} and
828 transpose from @var{around} to @var{to}.")
829    (music-invert around to music))
830
831 mark =
832 #(define-music-function
833    (label) ((number-or-markup?))
834   "Make the music for the \\mark command."
835   (let* ((set (and (integer? label)
836                    (context-spec-music (make-property-set 'rehearsalMark label)
837                                       'Score)))
838          (ev (make-music 'MarkEvent
839                          'origin (*location*))))
840
841     (if set
842         (make-sequential-music (list set ev))
843         (begin
844           (if label (set! (ly:music-property ev 'label) label))
845           ev))))
846
847 musicMap =
848 #(define-music-function (proc mus) (procedure? ly:music?)
849    (_i "Apply @var{proc} to @var{mus} and all of the music it contains.")
850    (music-map proc mus))
851
852 %% noPageBreak and noPageTurn are music functions (not music indentifiers),
853 %% because music identifiers are not allowed at top-level.
854 noPageBreak =
855 #(define-music-function () ()
856    (_i "Forbid a page break.  May be used at toplevel (i.e., between scores or
857 markups), or inside a score.")
858    (make-music 'EventChord
859                'page-marker #t
860                'page-break-permission 'forbid
861                'elements (list (make-music 'PageBreakEvent
862                                            'break-permission '()))))
863
864 noPageTurn =
865 #(define-music-function () ()
866    (_i "Forbid a page turn.  May be used at toplevel (i.e., between scores or
867 markups), or inside a score.")
868    (make-music 'EventChord
869                'page-marker #t
870                'page-turn-permission 'forbid
871                'elements (list (make-music 'PageTurnEvent
872                                            'break-permission '()))))
873
874
875
876 octaveCheck =
877 #(define-music-function (pitch) (ly:pitch?)
878    (_i "Octave check.")
879    (make-music 'RelativeOctaveCheck
880                'pitch pitch))
881
882 offset =
883 #(define-music-function (property offsets item)
884   (symbol-list-or-symbol? scheme? symbol-list-or-music?)
885    (_i "Offset the default value of @var{property} of @var{item} by
886 @var{offsets}.  If @var{item} is a string, the result is
887 @code{\\override} for the specified grob type.  If @var{item} is
888 a music expression, the result is the same music expression with an
889 appropriate tweak applied.")
890   (if (ly:music? item)
891       ; In case of a tweak, grob property path is Grob.property
892       (let ((prop-path (check-grob-path
893                          (if (symbol? property)
894                              (list property)
895                              property) (*location*)
896                          #:start 1 #:default #t #:min 2 #:max 2)))
897         (if prop-path
898             ; If the head of the grob property path is a symbol--i.e.,
899             ; a grob name, produce a directed tweak.  Otherwise, create
900             ; an ordinary tweak.
901             (if (symbol? (car prop-path))
902                 (tweak prop-path (offsetter (second prop-path) offsets) item)
903                 (tweak (second prop-path)
904                        (offsetter (second prop-path) offsets)
905                        item))
906             item))
907       ; In case of an override, grob property path is Context.Grob.property.
908       (let ((prop-path (check-grob-path
909                          (append item
910                                  (if (symbol? property)
911                                      (list property)
912                                      property)) (*location*)
913                          #:default 'Bottom #:min 3 #:max 3)))
914         (if prop-path
915             (propertyOverride prop-path (offsetter (third prop-path) offsets))
916             (make-music 'Music)))))
917
918 omit =
919 #(define-music-function (item) (symbol-list-or-music?)
920    (_i "Set @var{item}'s @samp{stencil} property to @code{#f},
921 effectively omitting it without taking up space.
922
923 If @var{item} is a symbol list of form @code{GrobName} or
924 @code{Context.GrobName}, the result is an override for the grob name
925 specified by it.  If @var{item} is a music expression, the result is
926 the same music expression with an appropriate tweak applied to it.")
927    (propertyTweak 'stencil #f item))
928
929 once =
930 #(define-music-function (music) (ly:music?)
931    (_i "Set @code{once} to @code{#t} on all layout instruction events
932 in @var{music}.  This will complain about music with an actual
933 duration.  As a special exception, if @var{music} contains
934 @samp{tweaks} it will be silently ignored in order to allow for
935 @code{\\once \\propertyTweak} to work as both one-time override and proper
936 tweak.")
937    (if (not (pair? (ly:music-property music 'tweaks)))
938        (for-some-music
939         (lambda (m)
940           (cond ((music-is-of-type? m 'layout-instruction-event)
941                  (set! (ly:music-property m 'once) #t)
942                  #t)
943                 ((ly:duration? (ly:music-property m 'duration))
944                  (ly:music-warning m (_ "Cannot apply \\once to timed music"))
945                  #t)
946                 (else #f)))
947         music))
948    music)
949
950 ottava =
951 #(define-music-function (octave) (integer?)
952    (_i "Set the octavation.")
953    (make-music 'OttavaMusic
954                'ottava-number octave))
955
956 overrideTimeSignatureSettings =
957 #(define-music-function
958    (time-signature base-moment beat-structure beam-exceptions)
959    (fraction? fraction? list? list?)
960
961    (_i "Override @code{timeSignatureSettings}
962 for time signatures of @var{time-signature} to have settings
963 of @var{base-moment}, @var{beat-structure}, and @var{beam-exceptions}.")
964
965    ;; TODO -- add warning if largest value of grouping is
966    ;;       greater than time-signature.
967   (let ((setting (make-setting base-moment beat-structure beam-exceptions)))
968     (override-time-signature-setting time-signature setting)))
969
970 overrideProperty =
971 #(define-music-function (grob-property-path value)
972    (symbol-list? scheme?)
973
974    (_i "Set the grob property specified by @var{grob-property-path} to
975 @var{value}.  @var{grob-property-path} is a symbol list of the form
976 @code{Context.GrobName.property} or @code{GrobName.property}, possibly
977 with subproperties given as well.
978
979 As opposed to @code{\\override} which overrides the context-dependent
980 defaults with which a grob is created, this command uses
981 @code{Output_property_engraver} at the grob acknowledge stage.  This
982 may be necessary for overriding values set after the initial grob
983 creation.")
984    (let ((p (check-grob-path grob-property-path (*location*)
985                              #:default 'Bottom
986                              #:min 3)))
987      (if p
988          (make-music 'ApplyOutputEvent
989                      'context-type (first p)
990                      'procedure
991                      (lambda (grob orig-context context)
992                        (if (equal?
993                             (cdr (assoc 'name (ly:grob-property grob 'meta)))
994                             (second p))
995                            (ly:grob-set-nested-property!
996                             grob (cddr p) value))))
997          (make-music 'Music))))
998
999
1000
1001
1002
1003
1004 %% pageBreak and pageTurn are music functions (iso music indentifiers),
1005 %% because music identifiers are not allowed at top-level.
1006 pageBreak =
1007 #(define-music-function () ()
1008    (_i "Force a page break.  May be used at toplevel (i.e., between scores or
1009 markups), or inside a score.")
1010    (make-music 'EventChord
1011                'page-marker #t
1012                'line-break-permission 'force
1013                'page-break-permission 'force
1014                'elements (list (make-music 'LineBreakEvent
1015                                            'break-permission 'force)
1016                                (make-music 'PageBreakEvent
1017                                            'break-permission 'force))))
1018
1019 pageTurn =
1020 #(define-music-function () ()
1021    (_i "Force a page turn between two scores or top-level markups.")
1022    (make-music 'EventChord
1023                'page-marker #t
1024                'line-break-permission 'force
1025                'page-break-permission 'force
1026                'page-turn-permission 'force
1027                'elements (list (make-music 'LineBreakEvent
1028                                            'break-permission 'force)
1029                                (make-music 'PageBreakEvent
1030                                            'break-permission 'force)
1031                                (make-music 'PageTurnEvent
1032                                            'break-permission 'force))))
1033
1034 parallelMusic =
1035 #(define-void-function (voice-ids music) (list? ly:music?)
1036    (_i "Define parallel music sequences, separated by '|' (bar check signs),
1037 and assign them to the identifiers provided in @var{voice-ids}.
1038
1039 @var{voice-ids}: a list of music identifiers (symbols containing only letters)
1040
1041 @var{music}: a music sequence, containing BarChecks as limiting expressions.
1042
1043 Example:
1044
1045 @verbatim
1046   \\parallelMusic #'(A B C) {
1047     c c | d d | e e |
1048     d d | e e | f f |
1049   }
1050 <==>
1051   A = { c c | d d | }
1052   B = { d d | e e | }
1053   C = { e e | f f | }
1054 @end verbatim
1055
1056 The last bar checks in a sequence are not copied to the result in
1057 order to facilitate ending the last entry at non-bar boundaries.
1058 ")
1059    (define voice-count (length voice-ids))
1060    (define (bar-check? m)
1061      "Checks whether m is a bar check."
1062      (eq? (ly:music-property m 'name) 'BarCheck))
1063    (define (recurse-and-split-list lst)
1064      "Return either a list of music lists split along barchecks, or @code{#f}."
1065      (if (any bar-check? lst)
1066          (let* ((voices (apply circular-list (make-list voice-count '())))
1067                 (current-voices voices)
1068                 (current-sequence '()))
1069            ;;
1070            ;; utilities
1071            (define (push-music m)
1072              "Push the music expression into the current sequence"
1073              (set! current-sequence (cons m current-sequence)))
1074            (define (change-voice)
1075              "Store the previously built sequence into the current voice and
1076 change to the following voice."
1077              (set-car! current-voices
1078                        (cons current-sequence
1079                              (car current-voices)))
1080              (set! current-sequence '())
1081              (set! current-voices (cdr current-voices)))
1082            (for-each (lambda (m)
1083                        (let ((split? (recurse-and-split m)))
1084                          (if split?
1085                              (for-each
1086                               (lambda (m)
1087                                 (push-music m)
1088                                 (change-voice))
1089                               split?)
1090                              (begin
1091                                (push-music m)
1092                                (if (bar-check? m) (change-voice))))))
1093                      lst)
1094            (if (pair? current-sequence) (change-voice))
1095            ;; Un-circularize voices
1096            (set! voices (list-head voices voice-count))
1097
1098            ;; Remove trailing bar checks to facilitate ending a
1099            ;; sequence on a non-bar, reverse partial sequences and sequences
1100            (set! voices (map!
1101                          (lambda (l)
1102                            (map! reverse!
1103                                  (reverse!
1104                                   (if (and (pair? l) (pair? (car l))
1105                                            (bar-check? (caar l)))
1106                                       (cons (cdar l) (cdr l))
1107                                       l))))
1108                          voices))
1109
1110            ;; check sequence length
1111            (apply for-each (lambda seqs
1112                              (define (seq-len seq)
1113                                (reduce ly:moment-add
1114                                        (ly:make-moment 0)
1115                                        (map ly:music-length seq)))
1116                              (let ((moment-reference (seq-len (car seqs))))
1117                                (for-each (lambda (seq)
1118                                            (if (not (equal? (seq-len seq)
1119                                                             moment-reference))
1120                                                (ly:music-warning
1121                                                 (if (pair? seq)
1122                                                     (last seq)
1123                                                     (caar seqs))
1124                                                 (_ "Bars in parallel music don't have the same length"))))
1125                                          seqs)))
1126                   voices)
1127            (map concatenate! voices))
1128          (let ((deeper (map recurse-and-split lst)))
1129            (and (any pair? deeper)
1130                 (apply zip (map
1131                             (lambda (m split)
1132                               (or split
1133                                   (ly:music-deep-copy (make-list voice-count m))))
1134                             lst deeper))))))
1135    (define (recurse-and-split music)
1136      "This returns either a list of music split along barchecks, or
1137 @code{#f}."
1138      (let* ((elt (ly:music-property music 'element))
1139             (elts (ly:music-property music 'elements))
1140             (split-elt (and (ly:music? elt) (recurse-and-split elt)))
1141             (split-elts (and (pair? elts) (recurse-and-split-list elts))))
1142        (and (or split-elt split-elts)
1143             (map
1144              (lambda (e es)
1145                (let ((m (ly:music-deep-copy music
1146                        ;;; reassigning the origin of the parent only
1147                        ;;; makes sense if the first expression in the
1148                        ;;; result is from a distributed origin
1149                                             (or (and (ly:music? e) e)
1150                                                 (and (pair? es) (car es))))))
1151                  (if (ly:music? e)
1152                      (set! (ly:music-property m 'element) e))
1153                  (if (pair? es)
1154                      (set! (ly:music-property m 'elements) es))
1155                  m))
1156              (or split-elt (circular-list #f))
1157              (or split-elts (circular-list #f))))))
1158    (let ((voices (recurse-and-split music)))
1159      (if voices
1160          ;;
1161          ;; bind voice identifiers to the voices
1162          (for-each (lambda (voice-id voice)
1163                      (ly:parser-define! voice-id voice))
1164                    voice-ids voices)
1165          (ly:music-warning music
1166                            (_ "ignoring parallel music without barchecks")))))
1167
1168 parenthesize =
1169 #(define-music-function (arg) (ly:music?)
1170    (_i "Tag @var{arg} to be parenthesized.")
1171
1172    (if (memq 'event-chord (ly:music-property arg 'types))
1173        ;; arg is an EventChord -> set the parenthesize property
1174        ;; on all child notes and rests
1175        (for-each
1176         (lambda (ev)
1177           (if (or (memq 'note-event (ly:music-property ev 'types))
1178                   (memq 'rest-event (ly:music-property ev 'types)))
1179               (set! (ly:music-property ev 'parenthesize) #t)))
1180         (ly:music-property arg 'elements))
1181        ;; No chord, simply set property for this expression:
1182        (set! (ly:music-property arg 'parenthesize) #t))
1183    arg)
1184
1185 #(define (make-directed-part-combine-music direction chord-range part1 part2
1186           one-context-settings
1187           two-context-settings
1188           shared-context-settings)
1189
1190    (let* ((pc-music (make-music 'PartCombineMusic))
1191           (m1 (context-spec-music (make-non-relative-music part1) 'Voice "one"))
1192           (m2 (context-spec-music (make-non-relative-music part2) 'Voice "two"))
1193           (listener (ly:parser-lookup 'partCombineListener))
1194           (evs2 (recording-group-emulate m2 listener))
1195           (evs1 (recording-group-emulate m1 listener))
1196           (split-list
1197            (if (and (assoc "one" evs1) (assoc "two" evs2))
1198                (determine-split-list (reverse! (assoc-get "one" evs1) '())
1199                                      (reverse! (assoc-get "two" evs2) '())
1200                                      chord-range)
1201                '()))
1202           (L1 (ly:music-length part1))
1203           (L2 (ly:music-length part2))
1204           ;; keep the contexts alive for the full duration
1205           (skip (make-skip-music (make-duration-of-length
1206                                   (if (ly:moment<? L1 L2) L2 L1)))))
1207
1208      (set! (ly:music-property pc-music 'elements)
1209            (list (make-music
1210                   'PartCombinePartMusic
1211                   'element m1
1212                   'context-change-list
1213                   (make-part-combine-context-changes
1214                    default-part-combine-context-change-state-machine-one
1215                    split-list))
1216                  (make-music
1217                   'PartCombinePartMusic
1218                   'element m2
1219                   'context-change-list
1220                   (make-part-combine-context-changes
1221                    default-part-combine-context-change-state-machine-two
1222                    split-list))))
1223
1224      (set! (ly:music-property pc-music 'direction) direction)
1225
1226      #{ \context Staff <<
1227           \context Voice = "one" \with #one-context-settings { #skip }
1228           \context Voice = "two" \with #two-context-settings { #skip }
1229           \context Voice = "shared" \with #shared-context-settings { #skip }
1230           \context Voice = "solo" { #skip }
1231           \context NullVoice = "null" { #skip }
1232           #pc-music
1233           #(make-part-combine-marks
1234             default-part-combine-mark-state-machine split-list)
1235         >> #} ))
1236
1237 partcombine =
1238 #(define-music-function (chord-range part1 part2)
1239    ((number-pair? '(0 . 8)) ly:music? ly:music?)
1240    (_i "Take the music in @var{part1} and @var{part2} and return
1241 a music expression containing simultaneous voices, where @var{part1}
1242 and @var{part2} are combined into one voice where appropriate.
1243 Optional @var{chord-range} sets the distance in steps between notes
1244 that may be combined into a chord or unison.")
1245    (make-directed-part-combine-music #f chord-range part1 part2
1246     #{ \with { \voiceOne \override DynamicLineSpanner.direction = #UP } #}
1247     #{ \with { \voiceTwo \override DynamicLineSpanner.direction = #DOWN } #}
1248     #{ #} ))
1249
1250 partcombineUp =
1251 #(define-music-function (chord-range part1 part2)
1252    ((number-pair? '(0 . 8)) ly:music? ly:music?)
1253    (_i "Take the music in @var{part1} and @var{part2} and typeset so
1254 that they share a staff with stems directed upward.")
1255    (make-directed-part-combine-music UP chord-range part1 part2
1256     #{ \with { \voiceOne \override DynamicLineSpanner.direction = #UP } #}
1257     #{ \with { \voiceThree \override DynamicLineSpanner.direction = #UP } #}
1258     #{ \with { \voiceOne \override DynamicLineSpanner.direction = #UP } #} ))
1259
1260 partcombineDown =
1261 #(define-music-function (chord-range part1 part2)
1262    ((number-pair? '(0 . 8)) ly:music? ly:music?)
1263    (_i "Take the music in @var{part1} and @var{part2} and typeset so
1264 that they share a staff with stems directed downward.")
1265    (make-directed-part-combine-music DOWN chord-range part1 part2
1266     #{ \with { \voiceFour \override DynamicLineSpanner.direction = #DOWN } #}
1267     #{ \with { \voiceTwo \override DynamicLineSpanner.direction = #DOWN } #}
1268     #{ \with { \voiceTwo \override DynamicLineSpanner.direction = #DOWN } #} ))
1269
1270 partcombineForce =
1271 #(define-music-function (type once) (boolean-or-symbol? boolean?)
1272    (_i "Override the part-combiner.")
1273    (make-music 'EventChord
1274                'elements (list (make-music 'PartCombineForceEvent
1275                                            'forced-type type
1276                                            'once once))))
1277 partcombineApart = \partcombineForce #'apart ##f
1278 partcombineApartOnce = \partcombineForce #'apart ##t
1279 partcombineChords = \partcombineForce #'chords ##f
1280 partcombineChordsOnce = \partcombineForce #'chords ##t
1281 partcombineUnisono = \partcombineForce #'unisono ##f
1282 partcombineUnisonoOnce = \partcombineForce #'unisono ##t
1283 partcombineSoloI = \partcombineForce #'solo1 ##f
1284 partcombineSoloIOnce = \partcombineForce #'solo1 ##t
1285 partcombineSoloII = \partcombineForce #'solo2 ##f
1286 partcombineSoloIIOnce = \partcombineForce #'solo2 ##t
1287 partcombineAutomatic = \partcombineForce ##f ##f
1288 partcombineAutomaticOnce = \partcombineForce ##f ##t
1289
1290 partial =
1291 #(define-music-function (dur) (ly:duration?)
1292   (_i "Make a partial measure.")
1293
1294   ;; We use `descend-to-context' here instead of `context-spec-music' to
1295   ;; ensure \partial still works if the Timing_translator is moved
1296     (descend-to-context
1297      (context-spec-music (make-music 'PartialSet
1298                                      'origin (*location*)
1299                                      'duration dur)
1300                          'Timing)
1301      'Score))
1302
1303 pitchedTrill =
1304 #(define-music-function
1305    (main-note secondary-note)
1306    (ly:music? ly:music?)
1307    (_i "Print a trill with @var{main-note} as the main note of the trill and
1308 print @var{secondary-note} as a stemless note head in parentheses.")
1309    (let* ((get-notes (lambda (ev-chord)
1310                        (extract-named-music ev-chord 'NoteEvent)))
1311           (sec-note-events (get-notes secondary-note))
1312           (trill-events (extract-named-music main-note 'TrillSpanEvent)))
1313      (if (pair? sec-note-events)
1314          (begin
1315            (let* ((trill-pitch (ly:music-property (car sec-note-events) 'pitch))
1316                   (forced (ly:music-property (car sec-note-events) 'force-accidental)))
1317
1318              (if (ly:pitch? trill-pitch)
1319                  (for-each (lambda (m)
1320                              (ly:music-set-property! m 'pitch trill-pitch)) trill-events)
1321                  (begin
1322                    (ly:input-warning (*location*) (_ "Second argument of \\pitchedTrill should be single note: "))
1323                    (display sec-note-events)))
1324
1325              (if (eq? forced #t)
1326                  (for-each (lambda (m)
1327                              (ly:music-set-property! m 'force-accidental forced))
1328                            trill-events)))))
1329      main-note))
1330
1331 propertyOverride =
1332 #(define-music-function (grob-property-path value)
1333    (symbol-list? scheme?)
1334    (_i "Set the grob property specified by @var{grob-property-path} to
1335 @var{value}.  @var{grob-property-path} is a symbol list of the form
1336 @code{Context.GrobName.property} or @code{GrobName.property}, possibly
1337 with subproperties given as well.  This music function is mostly intended
1338 for use from Scheme as a substitute for the built-in @code{\\override}
1339 command.")
1340    (let ((p (check-grob-path grob-property-path (*location*)
1341                              #:default 'Bottom
1342                              #:min 3)))
1343      (if p
1344          (context-spec-music
1345           (make-music 'OverrideProperty
1346                       'symbol (cadr p)
1347                       'origin (*location*)
1348                       'grob-value value
1349                       'grob-property-path (cddr p)
1350                       'pop-first #t)
1351           (car p))
1352          (make-music 'Music))))
1353
1354 propertyRevert =
1355 #(define-music-function (grob-property-path)
1356    (symbol-list?)
1357    (_i "Revert the grob property specified by @var{grob-property-path} to
1358 its previous value.  @var{grob-property-path} is a symbol list of the form
1359 @code{Context.GrobName.property} or @code{GrobName.property}, possibly
1360 with subproperties given as well.  This music function is mostly intended
1361 for use from Scheme as a substitute for the built-in @code{\\revert}
1362 command.")
1363    (let ((p (check-grob-path grob-property-path (*location*)
1364                              #:default 'Bottom
1365                              #:min 3)))
1366      (if p
1367          (context-spec-music
1368           (make-music 'RevertProperty
1369                       'symbol (cadr p)
1370                       'origin (*location*)
1371                       'grob-property-path (cddr p))
1372           (car p))
1373          (make-music 'Music))))
1374
1375 propertySet =
1376 #(define-music-function (property-path value)
1377    (symbol-list-or-symbol? scheme?)
1378    (_i "Set the context property specified by @var{property-path} to
1379 @var{value}.  This music function is mostly intended for use from
1380 Scheme as a substitute for the built-in @code{\\set} command.")
1381    (let ((p (check-context-path property-path (*location*))))
1382      (if p
1383          (context-spec-music
1384           (make-music 'PropertySet
1385                       'symbol (cadr p)
1386                       'value value
1387                       'origin (*location*))
1388           (car p))
1389          (make-music 'Music))))
1390
1391 propertyTweak =
1392 #(define-music-function (prop value item)
1393    (symbol-list-or-symbol? scheme? symbol-list-or-music?)
1394    (_i "Add a tweak to the following @var{item}, usually music.
1395 This generally behaves like @code{\\tweak} but will turn into an
1396 @code{\\override} when @var{item} is a symbol list.
1397
1398 In that case, @var{item} specifies the grob path to override.  This is
1399 mainly useful when using @code{\\propertyTweak} as as a component for
1400 building other functions like @code{\\omit}.  It is not the default
1401 behavior for @code{\\tweak} since many input strings in
1402 @code{\\lyricmode} can serve equally as music or as symbols which
1403 causes surprising behavior when tweaking lyrics using the less
1404 specific semantics of @code{\\propertyTweak}.
1405
1406 @var{prop} can contain additional elements in which case a nested
1407 property (inside of an alist) is tweaked.")
1408    ;; Why not instead make the parser treat strings preferably as
1409    ;; music in lyrics mode rather than as symbol?  Because then
1410    ;;
1411    ;; \tweak text "whatever" mylyrics
1412    ;;
1413    ;; will try putting a lyric event with text "whatever" in the text
1414    ;; property of lyrics.  So we want expressions allowing both
1415    ;; strings and lyrics to deliver strings: more complex conversions
1416    ;; should only be attempted when the simple uses don't match the
1417    ;; given predicate.
1418    (if (ly:music? item)
1419        (tweak prop value item)
1420        (propertyOverride (append item (if (symbol? prop) (list prop) prop))
1421                          value)))
1422
1423 propertyUnset =
1424 #(define-music-function (property-path)
1425    (symbol-list-or-symbol?)
1426    (_i "Unset the context property specified by @var{property-path}.
1427 This music function is mostly intended for use from Scheme as a
1428 substitute for the built-in @code{\\unset} command.")
1429    (let ((p (check-context-path property-path (*location*))))
1430      (if p
1431          (context-spec-music
1432           (make-music 'PropertyUnset
1433                       'symbol (cadr p)
1434                       'origin (*location*))
1435           (car p))
1436          (make-music 'Music))))
1437
1438 pushToTag =
1439 #(define-music-function (tag more music)
1440    (symbol? ly:music? ly:music?)
1441    (_i "Add @var{more} to the front of @code{elements} of all music
1442 expressions in @var{music} that are tagged with @var{tag}.")
1443    (music-map (lambda (m)
1444                 (if (memq tag (ly:music-property m 'tags))
1445                     (set! (ly:music-property m 'elements)
1446                           (cons more (ly:music-property m 'elements))))
1447                 m)
1448               music))
1449
1450 quoteDuring =
1451 #(define-music-function (what main-music) (string? ly:music?)
1452    (_i "Indicate a section of music to be quoted.  @var{what} indicates the name
1453 of the quoted voice, as specified in an @code{\\addQuote} command.
1454 @var{main-music} is used to indicate the length of music to be quoted;
1455 usually contains spacers or multi-measure rests.")
1456    (make-music 'QuoteMusic
1457                'element main-music
1458                'quoted-music-name what))
1459
1460
1461 relative =
1462 #(define-music-function (pitch music)
1463    ((ly:pitch?) ly:music?)
1464    (_i "Make @var{music} relative to @var{pitch}.  If @var{pitch} is
1465 omitted, the first note in @var{music} is given in absolute pitch.")
1466    ;; When \relative has no clear decision (can only happen with
1467    ;; scales with an even number of steps), it goes down (see
1468    ;; pitch.cc).  The following formula puts out f for both the normal
1469    ;; 7-step scale as well as for a "shortened" scale missing the
1470    ;; final b.  In either case, a first note of c will end up as c,
1471    ;; namely pitch (-1, 0, 0).
1472    (ly:make-music-relative! music
1473                             (or pitch
1474                                 (ly:make-pitch
1475                                  -1
1476                                  (quotient
1477                                   ;; size of current scale:
1478                                   (ly:pitch-steps (ly:make-pitch 1 0))
1479                                   2))))
1480    (make-music 'RelativeOctaveMusic
1481                'element music))
1482
1483 removeWithTag =
1484 #(define-music-function (tags music)
1485    (symbol-list-or-symbol? ly:music?)
1486    (_i "Remove elements of @var{music} that are tagged with one of the
1487 tags in @var{tags}.  @var{tags} may be either a single symbol or a list
1488 of symbols.")
1489    (music-filter
1490     (tags-remove-predicate tags)
1491     music))
1492
1493 resetRelativeOctave =
1494 #(define-music-function (pitch) (ly:pitch?)
1495    (_i "Set the octave inside a \\relative section.")
1496
1497    (make-music 'SequentialMusic
1498                'to-relative-callback
1499                (lambda (music last-pitch) pitch)))
1500
1501 retrograde =
1502 #(define-music-function (music)
1503     (ly:music?)
1504     (_i "Return @var{music} in reverse order.")
1505     (retrograde-music music))
1506
1507 revertTimeSignatureSettings =
1508 #(define-music-function
1509    (time-signature)
1510    (pair?)
1511
1512    (_i "Revert @code{timeSignatureSettings}
1513 for time signatures of @var{time-signature}.")
1514    (revert-time-signature-setting time-signature))
1515
1516 rightHandFinger =
1517 #(define-event-function (finger) (number-or-markup?)
1518    (_i "Apply @var{finger} as a fingering indication.")
1519
1520    (make-music
1521             'StrokeFingerEvent
1522             (if (number? finger) 'digit 'text)
1523             finger))
1524
1525 scaleDurations =
1526 #(define-music-function (fraction music)
1527    (fraction? ly:music?)
1528    (_i "Multiply the duration of events in @var{music} by @var{fraction}.")
1529    (ly:music-compress music
1530                       (ly:make-moment (car fraction) (cdr fraction))))
1531
1532 settingsFrom =
1533 #(define-scheme-function (ctx music)
1534    ((symbol?) ly:music?)
1535    (_i "Take the layout instruction events from @var{music}, optionally
1536 restricted to those applying to context type @var{ctx}, and return
1537 a context modification duplicating their effect.")
1538    (let ((mods (ly:make-context-mod)))
1539      (define (musicop m)
1540        (if (music-is-of-type? m 'layout-instruction-event)
1541            (ly:add-context-mod
1542             mods
1543             (case (ly:music-property m 'name)
1544               ((PropertySet)
1545                (list 'assign
1546                      (ly:music-property m 'symbol)
1547                      (ly:music-property m 'value)))
1548               ((PropertyUnset)
1549                (list 'unset
1550                      (ly:music-property m 'symbol)))
1551               ((OverrideProperty)
1552                (cons* 'push
1553                       (ly:music-property m 'symbol)
1554                       (ly:music-property m 'grob-value)
1555                       (cond
1556                        ((ly:music-property m 'grob-property #f) => list)
1557                        (else
1558                         (ly:music-property m 'grob-property-path)))))
1559               ((RevertProperty)
1560                (cons* 'pop
1561                       (ly:music-property m 'symbol)
1562                       (cond
1563                        ((ly:music-property m 'grob-property #f) => list)
1564                        (else
1565                         (ly:music-property m 'grob-property-path)))))))
1566            (case (ly:music-property m 'name)
1567              ((ApplyContext)
1568               (ly:add-context-mod mods
1569                                   (list 'apply
1570                                         (ly:music-property m 'procedure))))
1571              ((ContextSpeccedMusic)
1572               (if (or (not ctx)
1573                       (eq? ctx (ly:music-property m 'context-type)))
1574                   (musicop (ly:music-property m 'element))))
1575              (else
1576               (let ((callback (ly:music-property m 'elements-callback)))
1577                 (if (procedure? callback)
1578                     (for-each musicop (callback m))))))))
1579      (musicop music)
1580      mods))
1581
1582 shape =
1583 #(define-music-function (offsets item)
1584    (list? symbol-list-or-music?)
1585    (_i "Offset control-points of @var{item} by @var{offsets}.  The
1586 argument is a list of number pairs or list of such lists.  Each
1587 element of a pair represents an offset to one of the coordinates of a
1588 control-point.  If @var{item} is a string, the result is
1589 @code{\\once\\override} for the specified grob type.  If @var{item} is
1590 a music expression, the result is the same music expression with an
1591 appropriate tweak applied.")
1592    (define (shape-curve grob)
1593      (let* ((orig (ly:grob-original grob))
1594             (siblings (if (ly:spanner? grob)
1595                           (ly:spanner-broken-into orig) '()))
1596             (total-found (length siblings))
1597             (function (assoc-get 'control-points
1598                                  (reverse (ly:grob-basic-properties grob))))
1599             (coords (function grob)))
1600
1601        (define (offset-control-points offsets)
1602          (if (null? offsets)
1603              coords
1604              (map
1605                (lambda (x y) (coord-translate x y))
1606                coords offsets)))
1607
1608        (define (helper sibs offs)
1609          (if (pair? offs)
1610              (if (eq? (car sibs) grob)
1611                  (offset-control-points (car offs))
1612                  (helper (cdr sibs) (cdr offs)))
1613              coords))
1614
1615        ;; we work with lists of lists
1616        (if (or (null? offsets)
1617                (not (list? (car offsets))))
1618            (set! offsets (list offsets)))
1619
1620        (if (>= total-found 2)
1621            (helper siblings offsets)
1622            (offset-control-points (car offsets)))))
1623    (once (propertyTweak 'control-points shape-curve item)))
1624
1625 shiftDurations =
1626 #(define-music-function (dur dots arg)
1627    (integer? integer? ly:music?)
1628    (_i "Change the duration of @var{arg} by adding @var{dur} to the
1629 @code{durlog} of @var{arg} and @var{dots} to the @code{dots} of @var{arg}.")
1630
1631    (shift-duration-log arg dur dots))
1632
1633 single =
1634 #(define-music-function (overrides music)
1635    (ly:music? ly:music?)
1636    (_i "Convert @var{overrides} to tweaks and apply them to @var{music}.
1637 This does not convert @code{\\revert}, @code{\\set} or @code{\\unset}.")
1638    (set! (ly:music-property music 'tweaks)
1639          (fold-some-music
1640           (lambda (m) (eq? (ly:music-property m 'name)
1641                            'OverrideProperty))
1642           (lambda (m tweaks)
1643             (let ((p (cond
1644                       ((ly:music-property m 'grob-property #f) => list)
1645                       (else
1646                        (ly:music-property m 'grob-property-path)))))
1647               (acons (cons (ly:music-property m 'symbol) ;grob name
1648                            (if (pair? (cdr p))
1649                                p ;grob property path
1650                                (car p))) ;grob property
1651                      (ly:music-property m 'grob-value)
1652                      tweaks)))
1653           (ly:music-property music 'tweaks)
1654           overrides))
1655    music)
1656
1657 skip =
1658 #(define-music-function (dur) (ly:duration?)
1659   (_i "Skip forward by @var{dur}.")
1660   (make-music 'SkipMusic
1661               'duration dur))
1662
1663
1664 slashedGrace =
1665 #(def-grace-function startSlashedGraceMusic stopSlashedGraceMusic
1666    (_i "Create slashed graces (slashes through stems, but no slur) from
1667 the following music expression"))
1668
1669 spacingTweaks =
1670 #(define-music-function (parameters) (list?)
1671    (_i "Set the system stretch, by reading the 'system-stretch property of
1672 the `parameters' assoc list.")
1673    (overrideProperty
1674     '(Score NonMusicalPaperColumn line-break-system-details)
1675     (list (cons 'alignment-extra-space (cdr (assoc 'system-stretch parameters)))
1676           (cons 'system-Y-extent (cdr (assoc 'system-Y-extent parameters))))))
1677
1678 styledNoteHeads =
1679 #(define-music-function (style heads music)
1680    (symbol? symbol-list-or-symbol? ly:music?)
1681    (_i "Set @var{heads} in @var{music} to @var{style}.")
1682    (style-note-heads heads style music))
1683
1684 tag =
1685 #(define-music-function (tags music) (symbol-list-or-symbol? ly:music?)
1686    (_i "Tag the following @var{music} with @var{tags} and return the
1687 result, by adding the single symbol or symbol list @var{tags} to the
1688 @code{tags} property of @var{music}.")
1689
1690    (set!
1691     (ly:music-property music 'tags)
1692     ((if (symbol? tags) cons append)
1693      tags
1694      (ly:music-property music 'tags)))
1695    music)
1696
1697 tagGroup =
1698 #(define-void-function (tags) (symbol-list?)
1699    (_i "Define a tag group comprising the symbols in the symbol list
1700 @var{tags}.  Tag groups must not overlap.")
1701    (let ((err (define-tag-group tags)))
1702      (if err (ly:parser-error err (*location*)))))
1703
1704 temporary =
1705 #(define-music-function (music)
1706    (ly:music?)
1707    (_i "Make any @code{\\override} in @var{music} replace an existing
1708 grob property value only temporarily, restoring the old value when a
1709 corresponding @code{\\revert} is executed.  This is achieved by
1710 clearing the @samp{pop-first} property normally set on
1711 @code{\\override}s.
1712
1713 An @code{\\override}/@/@code{\\revert} sequence created by using
1714 @code{\\temporary} and @code{\\undo} on the same music containing
1715 overrides will cancel out perfectly or cause a@tie{}warning.
1716
1717 Non-property-related music is ignored, warnings are generated for any
1718 property-changing music that isn't an @code{\\override}.")
1719    (define warned #f)
1720    (for-some-music
1721     (lambda (m)
1722       (and (or (music-is-of-type? m 'layout-instruction-event)
1723                (music-is-of-type? m 'context-specification)
1724                (music-is-of-type? m 'apply-context)
1725                (music-is-of-type? m 'time-signature-music))
1726            (case (ly:music-property m 'name)
1727              ((OverrideProperty)
1728               (if (ly:music-property m 'pop-first #f)
1729                   (set! (ly:music-property m 'pop-first) '()))
1730               (if (ly:music-property m 'once #f)
1731                   (set! (ly:music-property m 'once) '()))
1732               #t)
1733              ((ContextSpeccedMusic)
1734               #f)
1735              (else
1736               (if (not warned)
1737                   (begin
1738                     (ly:input-warning (*location*) (_ "Cannot make ~a revertible")
1739                                       (ly:music-property m 'name))
1740                     (set! warned #t)))
1741               #t))))
1742     music)
1743    music)
1744
1745 time =
1746 #(define-music-function (beat-structure fraction)
1747    ((number-list? '()) fraction?)
1748    (_i "Set @var{fraction} as time signature, with optional
1749 number list @var{beat-structure} before it.")
1750   (make-music 'TimeSignatureMusic
1751               'numerator (car fraction)
1752               'denominator (cdr fraction)
1753               'beat-structure beat-structure))
1754
1755 times =
1756 #(define-music-function (fraction music)
1757    (fraction? ly:music?)
1758    (_i "Scale @var{music} in time by @var{fraction}.")
1759   (make-music 'TimeScaledMusic
1760               'element (ly:music-compress music (ly:make-moment (car fraction) (cdr fraction)))
1761               'numerator (car fraction)
1762               'denominator (cdr fraction)))
1763
1764 transpose =
1765 #(define-music-function
1766    (from to music)
1767    (ly:pitch? ly:pitch? ly:music?)
1768
1769    (_i "Transpose @var{music} from pitch @var{from} to pitch @var{to}.")
1770    (make-music 'TransposedMusic
1771                'element (ly:music-transpose music (ly:pitch-diff to from))))
1772
1773 transposedCueDuring =
1774 #(define-music-function
1775    (what dir pitch main-music)
1776    (string? ly:dir? ly:pitch? ly:music?)
1777
1778    (_i "Insert notes from the part @var{what} into a voice called @code{cue},
1779 using the transposition defined by @var{pitch}.  This happens
1780 simultaneously with @var{main-music}, which is usually a rest.  The
1781 argument @var{dir} determines whether the cue notes should be notated
1782 as a first or second voice.")
1783
1784    (make-music 'QuoteMusic
1785                'element main-music
1786                'quoted-context-type 'CueVoice
1787                'quoted-context-id "cue"
1788                'quoted-music-name what
1789                'quoted-voice-direction dir
1790                ;; following is inverse of instrumentTransposition for
1791                ;; historical reasons
1792                'quoted-transposition pitch))
1793
1794 transposition =
1795 #(define-music-function (pitch) (ly:pitch?)
1796    (_i "Set instrument transposition")
1797
1798    (context-spec-music
1799     (make-property-set 'instrumentTransposition pitch)
1800     'Staff))
1801
1802 tuplet =
1803 #(define-music-function (ratio tuplet-span music)
1804    (fraction? (ly:duration? '()) ly:music?)
1805    (_i "Scale the given @var{music} to tuplets.  @var{ratio} is a
1806 fraction that specifies how many notes are played in place of the
1807 nominal value: it will be @samp{3/2} for triplets, namely three notes
1808 being played in place of two.  If the optional duration
1809 @var{tuplet-span} is specified, it is used instead of
1810 @code{tupletSpannerDuration} for grouping the tuplets.
1811 For example,
1812 @example
1813 \\tuplet 3/2 4 @{ c8 c c c c c @}
1814 @end example
1815 will result in two groups of three tuplets, each group lasting for a
1816 quarter note.")
1817    (make-music 'TimeScaledMusic
1818                'element (ly:music-compress
1819                          music
1820                          (ly:make-moment (cdr ratio) (car ratio)))
1821                'numerator (cdr ratio)
1822                'denominator (car ratio)
1823                'duration tuplet-span))
1824
1825 tupletSpan =
1826 #(define-music-function (tuplet-span)
1827    ((ly:duration?))
1828    (_i "Set @code{tupletSpannerDuration}, the length into which
1829 @code{\\tuplet} without an explicit @samp{tuplet-span} argument of its
1830 own will group its tuplets, to the duration @var{tuplet-span}.  To
1831 revert to the default of not subdividing the contents of a @code{\\tuplet}
1832 command without explicit @samp{tuplet-span}, use
1833 @example
1834 \\tupletSpan \\default
1835 @end example
1836 ")
1837    (if tuplet-span
1838        #{ \set tupletSpannerDuration = #(ly:duration-length tuplet-span) #}
1839        #{ \unset tupletSpannerDuration #}))
1840
1841 tweak =
1842 #(define-music-function (prop value music)
1843    (symbol-list-or-symbol? scheme? ly:music?)
1844    (_i "Add a tweak to the following @var{music}.
1845 Layout objects created by @var{music} get their property @var{prop}
1846 set to @var{value}.  If @var{prop} has the form @samp{Grob.property}, like with
1847 @example
1848 \\tweak Accidental.color #red cis'
1849 @end example
1850 an indirectly created grob (@samp{Accidental} is caused by
1851 @samp{NoteHead}) can be tweaked; otherwise only directly created grobs
1852 are affected.
1853
1854 @var{prop} can contain additional elements in which case a nested
1855 property (inside of an alist) is tweaked.")
1856    (let ((p (check-grob-path prop (*location*)
1857                              #:start 1
1858                              #:default #t
1859                              #:min 2)))
1860      (cond ((not p))
1861            ;; p now contains at least two elements.  The first
1862            ;; element is #t when no grob has been explicitly
1863            ;; specified, otherwise it is a grob name.
1864            ((music-is-of-type? music 'context-specification)
1865             ;; This is essentially dealing with the case
1866             ;; \tweak color #red \propertyTweak font-size #3 NoteHead
1867             ;; namely when stacked tweaks end in a symbol list
1868             ;; rather than a music expression.
1869             ;;
1870             ;; We have a tweak here to convert into an override,
1871             ;; so we need to know the grob to apply it to.  That's
1872             ;; easy if we have a directed tweak, and otherwise we
1873             ;; need to find the symbol in the expression itself.
1874             (let* ((elt (ly:music-property music 'element))
1875                    (seq (if (music-is-of-type? elt 'sequential-music)
1876                             elt
1877                             (make-sequential-music (list elt))))
1878                    (elts (ly:music-property seq 'elements))
1879                    (symbol (if (symbol? (car p))
1880                                (car p)
1881                                (and (pair? elts)
1882                                     (ly:music-property (car elts)
1883                                                        'symbol)))))
1884               (if (symbol? symbol)
1885                   (begin
1886                     (set! (ly:music-property seq 'elements)
1887                           (cons (make-music 'OverrideProperty
1888                                             'symbol symbol
1889                                             'grob-property-path (cdr p)
1890                                             'pop-first #t
1891                                             'grob-value value
1892                                             'origin (*location*))
1893                                 elts))
1894                     (set! (ly:music-property music 'element) seq))
1895                   (begin
1896                     (ly:parser-error (_ "Cannot \\tweak")
1897                                      (*location*))
1898                     (ly:music-message music (_ "untweakable"))))))
1899            (else
1900             (set! (ly:music-property music 'tweaks)
1901                   (acons (cond ((pair? (cddr p)) p)
1902                                ((symbol? (car p))
1903                                 (cons (car p) (cadr p)))
1904                                (else (cadr p)))
1905                          value
1906                          (ly:music-property music 'tweaks)))))
1907      music))
1908
1909
1910 undo =
1911 #(define-music-function (music)
1912    (ly:music?)
1913    (_i "Convert @code{\\override} and @code{\\set} in @var{music} to
1914 @code{\\revert} and @code{\\unset}, respectively.  Any reverts and
1915 unsets already in @var{music} cause a warning.  Non-property-related music is ignored.")
1916    (define warned #f)
1917    (let loop
1918        ((music music))
1919      (let
1920          ((lst
1921            (fold-some-music
1922             (music-type-predicate '(layout-instruction-event
1923                                     context-specification
1924                                     apply-context
1925                                     time-signature-music))
1926             (lambda (m overrides)
1927               (case (ly:music-property m 'name)
1928                 ((OverrideProperty)
1929                  (cons
1930                   (make-music 'RevertProperty
1931                               'symbol (ly:music-property m 'symbol)
1932                               'grob-property-path
1933                               (cond
1934                                ((ly:music-property m 'grob-property #f) => list)
1935                                (else
1936                                 (ly:music-property m 'grob-property-path))))
1937                   overrides))
1938                 ((PropertySet)
1939                  (cons
1940                   (make-music 'PropertyUnset
1941                               'symbol (ly:music-property m 'symbol))
1942                   overrides))
1943                 ((ContextSpeccedMusic)
1944                  (cons
1945                   (make-music 'ContextSpeccedMusic
1946                               'element (loop (ly:music-property m 'element))
1947                               'context-type (ly:music-property m 'context-type))
1948                   overrides))
1949                 (else
1950                  (if (not warned)
1951                      (begin
1952                        (ly:input-warning (*location*) (_ "Cannot revert ~a")
1953                                          (ly:music-property m 'name))
1954                        (set! warned #t)))
1955                  overrides)))
1956             '()
1957             music)))
1958        (cond
1959         ((null? lst) (make-music 'Music))
1960         ((null? (cdr lst)) (car lst))
1961         (else (make-sequential-music lst))))))
1962
1963 unfoldRepeats =
1964 #(define-music-function (music) (ly:music?)
1965    (_i "Force any @code{\\repeat volta}, @code{\\repeat tremolo} or
1966 @code{\\repeat percent} commands in @var{music} to be interpreted
1967 as @code{\\repeat unfold}.")
1968    (unfold-repeats music))
1969
1970 void =
1971 #(define-void-function (arg) (scheme?)
1972    (_i "Accept a scheme argument, return a void expression.
1973 Use this if you want to have a scheme expression evaluated
1974 because of its side-effects, but its value ignored."))
1975
1976 withMusicProperty =
1977 #(define-music-function (sym val music)
1978    (symbol? scheme? ly:music?)
1979    (_i "Set @var{sym} to @var{val} in @var{music}.")
1980
1981    (set! (ly:music-property music sym) val)
1982    music)