%%%% You should have received a copy of the GNU General Public License
%%%% along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
-\version "2.19.22"
+\version "2.19.25"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define-void-function (name music) (string? ly:music?)
(_i "Define @var{music} as a quotable music expression named
@var{name}")
- (add-quotable (*parser*) name music))
+ (add-quotable name music))
%% keep these two together
afterGraceFraction = #(cons 6 8)
#(define-music-function (main grace) (ly:music? ly:music?)
(_i "Create @var{grace} note(s) after a @var{main} music expression.")
(let ((main-length (ly:music-length main))
- (fraction (ly:parser-lookup (*parser*) 'afterGraceFraction)))
+ (fraction (ly:parser-lookup 'afterGraceFraction)))
(make-simultaneous-music
(list
main
(begin
(ly:music-warning item (_ "not a spanner"))
item))
- (let* ((p (check-grob-path item (*parser*) (*location*)
+ (let* ((p (check-grob-path item (*location*)
#:default 'Bottom
#:min 2
#:max 2))
(member 'spanner-interface
(assoc-get 'interfaces
(assoc-get 'meta description))))
- #{
- \override #item . #property =
- #(value-for-spanner-piece arg)
- #}
+ (propertyOverride (append item (if (symbol? property)
+ (list property)
+ property))
+ (value-for-spanner-piece arg))
(begin
(ly:input-warning (*location*) (_ "not a spanner name, `~a'") name)
(make-music 'Music))))))
(func music))
applyOutput =
-#(define-music-function (ctx proc) (symbol? procedure?)
- (_i "Apply function @code{proc} to every layout object in context @code{ctx}")
- (make-music 'ApplyOutputEvent
- 'procedure proc
- 'context-type ctx))
+#(define-music-function (target proc) (symbol-list-or-symbol? procedure?)
+ (_i "Apply function @code{proc} to every layout object matched by
+@var{target} which takes the form @code{Context} or @code{Context.Grob}.")
+ (let ((p (check-grob-path target (*location*) #:max 2)))
+ (if p
+ (make-music 'ApplyOutputEvent
+ 'procedure proc
+ 'context-type (car p)
+ (if (pair? (cdr p))
+ (list (cons 'symbol (cadr p)))
+ '()))
+ (make-music 'Music))))
appoggiatura =
#(def-grace-function startAppoggiaturaMusic stopAppoggiaturaMusic
(make-grob-property-override 'Beam 'positions (check-slope-callbacks comp)))
autochange =
-#(define-music-function (music) (ly:music?)
- (_i "Make voices that switch between staves automatically")
- (make-autochange-music (*parser*) music))
-
-
+#(define-music-function (pitch clef-1 clef-2 music)
+ ((ly:pitch? (ly:make-pitch 0 0)) (ly:context-mod?)(ly:context-mod?) ly:music?)
+ (_i "Make voices that switch between staves automatically. As an option the
+pitch where to switch staves may be specified. The clefs for the staves are
+optional as well. Setting clefs works only for implicitly instantiated
+staves.")
+ (let ;; keep the contexts alive for the full duration
+ ((skip (make-skip-music (make-duration-of-length
+ (ly:music-length music)))))
+ #{
+ <<
+ \context Staff = "up" $(or clef-1 #{ \with { \clef "treble" } #})
+ <<
+ #(make-autochange-music pitch music)
+ \new Voice { #skip }
+ >>
+ \context Staff = "down" $(or clef-2 #{ \with { \clef "bass" } #})
+ \new Voice { #skip }
+ >>
+ #}))
balloonGrobText =
#(define-music-function (grob-name offset text)
bookOutputName =
#(define-void-function (newfilename) (string?)
(_i "Direct output for the current book block to @var{newfilename}.")
- (set! (paper-variable (*parser*) #f 'output-filename) newfilename))
+ (set! (paper-variable #f 'output-filename) newfilename))
bookOutputSuffix =
#(define-void-function (newsuffix) (string?)
(_i "Set the output filename suffix for the current book block to
@var{newsuffix}.")
- (set! (paper-variable (*parser*) #f 'output-suffix) newsuffix))
+ (set! (paper-variable #f 'output-suffix) newsuffix))
%% \breathe is defined as a music function rather than an event identifier to
%% ensure it gets useful input location information: as an event identifier,
to @var{port}, defaulting to the console.")
(let ((port (or port (current-output-port))))
(newline port)
- (display-lily-music music (*parser*) port))
+ (display-lily-music music port))
music)
displayMusic =
(_i "Compatibility function wrapping @code{EventChord} around
isolated rhythmic events occuring since version 2.15.28, after
expanding repeat chords @samp{q}.")
- (event-chord-wrap! music (*parser*)))
+ (event-chord-wrap! music))
featherDurations=
#(define-music-function (factor argument) (ly:moment? ly:music?)
If both are null, just generate @code{KeyChangeEvent}.")
(cond ((null? tonic) (make-music 'KeyChangeEvent))
((null? pitch-alist)
- (ly:parser-error (*parser*) (_ "second argument must be pitch list")
+ (ly:parser-error (_ "second argument must be pitch list")
(*location*))
(make-music 'SequentialMusic 'void #t))
(else
language =
#(define-void-function (language) (string?)
(_i "Set note names for language @var{language}.")
- (note-names-language (*parser*) language))
+ (note-names-language language))
languageSaveAndChange =
#(define-void-function (language) (string?)
(_i "Store the previous pitchnames alist, and set a new one.")
(set! previous-pitchnames pitchnames)
- (note-names-language (*parser*) language))
+ (note-names-language language))
languageRestore =
#(define-void-function () ()
(if previous-pitchnames
(begin
(set! pitchnames previous-pitchnames)
- (ly:parser-set-note-names (*parser*) pitchnames))
+ (ly:parser-set-note-names pitchnames))
(ly:input-warning (*location*) (_ "No other language was defined previously. Ignoring."))))
mark =
#(define-music-function
- (label) ((scheme? '()))
+ (label) ((number-or-markup?))
"Make the music for the \\mark command."
(let* ((set (and (integer? label)
(context-spec-music (make-property-set 'rehearsalMark label)
(if set
(make-sequential-music (list set ev))
(begin
- (set! (ly:music-property ev 'label) label)
+ (if label (set! (ly:music-property ev 'label) label))
ev))))
musicMap =
(let ((prop-path (check-grob-path
(if (symbol? property)
(list property)
- property)
- (*parser*) (*location*)
+ property) (*location*)
#:start 1 #:default #t #:min 2 #:max 2)))
(if prop-path
; If the head of the grob property path is a symbol--i.e.,
(append item
(if (symbol? property)
(list property)
- property))
- (*parser*) (*location*)
+ property)) (*location*)
#:default 'Bottom #:min 3 #:max 3)))
(if prop-path
- #{
- \override #prop-path = #(offsetter (third prop-path) offsets)
- #}
+ (propertyOverride prop-path (offsetter (third prop-path) offsets))
(make-music 'Music)))))
omit =
(_i "Set the grob property specified by @var{grob-property-path} to
@var{value}. @var{grob-property-path} is a symbol list of the form
@code{Context.GrobName.property} or @code{GrobName.property}, possibly
-with subproperties given as well.")
- (let ((p (check-grob-path grob-property-path (*parser*) (*location*)
+with subproperties given as well.
+
+As opposed to @code{\\override} which overrides the context-dependent
+defaults with which a grob is created, this command uses
+@code{Output_property_engraver} at the grob acknowledge stage. This
+may be necessary for overriding values set after the initial grob
+creation.")
+ (let ((p (check-grob-path grob-property-path (*location*)
#:default 'Bottom
#:min 3)))
(if p
(and (or split-elt split-elts)
(map
(lambda (e es)
- (apply music-clone music
- (append
- ;; reassigning the origin of the parent only
- ;; makes sense if the first expression in the
- ;; result is from a distributed origin
- (let ((origin
- (if (ly:music? elt)
- (and (ly:music? e) (ly:music-property e 'origin #f))
- (and (pair? es) (ly:music-property (car es) 'origin #f)))))
- (if origin (list 'origin origin) '()))
- (if (ly:music? e) (list 'element e) '())
- (if (pair? es) (list 'elements es) '()))))
+ (let ((m (ly:music-deep-copy music
+ ;;; reassigning the origin of the parent only
+ ;;; makes sense if the first expression in the
+ ;;; result is from a distributed origin
+ (or (and (ly:music? e) e)
+ (and (pair? es) (car es))))))
+ (if (ly:music? e)
+ (set! (ly:music-property m 'element) e))
+ (if (pair? es)
+ (set! (ly:music-property m 'elements) es))
+ m))
(or split-elt (circular-list #f))
(or split-elts (circular-list #f))))))
(let ((voices (recurse-and-split music)))
;;
;; bind voice identifiers to the voices
(for-each (lambda (voice-id voice)
- (ly:parser-define! (*parser*) voice-id voice))
+ (ly:parser-define! voice-id voice))
voice-ids voices)
(ly:music-warning music
(_ "ignoring parallel music without barchecks")))))
(set! (ly:music-property arg 'parenthesize) #t))
arg)
-#(define (make-directed-part-combine-music
- parser direction chord-range part1 part2
+#(define (make-directed-part-combine-music direction chord-range part1 part2
one-context-settings
two-context-settings
shared-context-settings)
- (let* ((pc-music (make-part-combine-music
- parser (list part1 part2) direction chord-range))
+ (let* ((pc-music (make-music 'PartCombineMusic))
+ (m1 (context-spec-music (make-non-relative-music part1) 'Voice "one"))
+ (m2 (context-spec-music (make-non-relative-music part2) 'Voice "two"))
+ (listener (ly:parser-lookup 'partCombineListener))
+ (evs2 (recording-group-emulate m2 listener))
+ (evs1 (recording-group-emulate m1 listener))
+ (split-list
+ (if (and (assoc "one" evs1) (assoc "two" evs2))
+ (determine-split-list (reverse! (assoc-get "one" evs1) '())
+ (reverse! (assoc-get "two" evs2) '())
+ chord-range)
+ '()))
(L1 (ly:music-length part1))
(L2 (ly:music-length part2))
;; keep the contexts alive for the full duration
(skip (make-skip-music (make-duration-of-length
(if (ly:moment<? L1 L2) L2 L1)))))
+
+ (set! (ly:music-property pc-music 'elements)
+ (list (make-music
+ 'PartCombinePartMusic
+ 'element m1
+ 'context-change-list
+ (make-part-combine-context-changes
+ default-part-combine-context-change-state-machine-one
+ split-list))
+ (make-music
+ 'PartCombinePartMusic
+ 'element m2
+ 'context-change-list
+ (make-part-combine-context-changes
+ default-part-combine-context-change-state-machine-two
+ split-list))))
+
+ (set! (ly:music-property pc-music 'direction) direction)
+
#{ \context Staff <<
\context Voice = "one" \with #one-context-settings { #skip }
\context Voice = "two" \with #two-context-settings { #skip }
\context NullVoice = "null" { #skip }
#pc-music
#(make-part-combine-marks
- default-part-combine-mark-state-machine
- (ly:music-property pc-music 'split-list))
+ default-part-combine-mark-state-machine split-list)
>> #} ))
partcombine =
and @var{part2} are combined into one voice where appropriate.
Optional @var{chord-range} sets the distance in steps between notes
that may be combined into a chord or unison.")
- (make-directed-part-combine-music (*parser*) #f chord-range part1 part2
+ (make-directed-part-combine-music #f chord-range part1 part2
#{ \with { \voiceOne \override DynamicLineSpanner.direction = #UP } #}
#{ \with { \voiceTwo \override DynamicLineSpanner.direction = #DOWN } #}
#{ #} ))
((number-pair? '(0 . 8)) ly:music? ly:music?)
(_i "Take the music in @var{part1} and @var{part2} and typeset so
that they share a staff with stems directed upward.")
- (make-directed-part-combine-music (*parser*) UP chord-range part1 part2
+ (make-directed-part-combine-music UP chord-range part1 part2
#{ \with { \voiceOne \override DynamicLineSpanner.direction = #UP } #}
#{ \with { \voiceThree \override DynamicLineSpanner.direction = #UP } #}
#{ \with { \voiceOne \override DynamicLineSpanner.direction = #UP } #} ))
((number-pair? '(0 . 8)) ly:music? ly:music?)
(_i "Take the music in @var{part1} and @var{part2} and typeset so
that they share a staff with stems directed downward.")
- (make-directed-part-combine-music (*parser*) DOWN chord-range part1 part2
+ (make-directed-part-combine-music DOWN chord-range part1 part2
#{ \with { \voiceFour \override DynamicLineSpanner.direction = #DOWN } #}
#{ \with { \voiceTwo \override DynamicLineSpanner.direction = #DOWN } #}
#{ \with { \voiceTwo \override DynamicLineSpanner.direction = #DOWN } #} ))
trill-events)))))
main-note))
+propertyOverride =
+#(define-music-function (grob-property-path value)
+ (symbol-list? scheme?)
+ (_i "Set the grob property specified by @var{grob-property-path} to
+@var{value}. @var{grob-property-path} is a symbol list of the form
+@code{Context.GrobName.property} or @code{GrobName.property}, possibly
+with subproperties given as well. This music function is mostly intended
+for use from Scheme as a substitute for the built-in @code{\\override}
+command.")
+ (let ((p (check-grob-path grob-property-path (*location*)
+ #:default 'Bottom
+ #:min 3)))
+ (if p
+ (context-spec-music
+ (make-music 'OverrideProperty
+ 'symbol (cadr p)
+ 'origin (*location*)
+ 'grob-value value
+ 'grob-property-path (cddr p)
+ 'pop-first #t)
+ (car p))
+ (make-music 'Music))))
+
+propertyRevert =
+#(define-music-function (grob-property-path)
+ (symbol-list?)
+ (_i "Revert the grob property specified by @var{grob-property-path} to
+its previous value. @var{grob-property-path} is a symbol list of the form
+@code{Context.GrobName.property} or @code{GrobName.property}, possibly
+with subproperties given as well. This music function is mostly intended
+for use from Scheme as a substitute for the built-in @code{\\revert}
+command.")
+ (let ((p (check-grob-path grob-property-path (*location*)
+ #:default 'Bottom
+ #:min 3)))
+ (if p
+ (context-spec-music
+ (make-music 'RevertProperty
+ 'symbol (cadr p)
+ 'origin (*location*)
+ 'grob-property-path (cddr p))
+ (car p))
+ (make-music 'Music))))
+
+propertySet =
+#(define-music-function (property-path value)
+ (symbol-list-or-symbol? scheme?)
+ (_i "Set the context property specified by @var{property-path} to
+@var{value}. This music function is mostly intended for use from
+Scheme as a substitute for the built-in @code{\\set} command.")
+ (let ((p (check-context-path property-path (*location*))))
+ (if p
+ (context-spec-music
+ (make-music 'PropertySet
+ 'symbol (cadr p)
+ 'value value
+ 'origin (*location*))
+ (car p))
+ (make-music 'Music))))
+
+propertyUnset =
+#(define-music-function (property-path)
+ (symbol-list-or-symbol?)
+ (_i "Unset the context property specified by @var{property-path}.
+This music function is mostly intended for use from Scheme as a
+substitute for the built-in @code{\\unset} command.")
+ (let ((p (check-context-path property-path (*location*))))
+ (if p
+ (context-spec-music
+ (make-music 'PropertyUnset
+ 'symbol (cadr p)
+ 'origin (*location*))
+ (car p))
+ (make-music 'Music))))
+
pushToTag =
#(define-music-function (tag more music)
(symbol? ly:music? ly:music?)
'element main-music
'quoted-music-name what))
+
relative =
#(define-music-function (pitch music)
((ly:pitch?) ly:music?)
(_i "Define a tag group comprising the symbols in the symbol list
@var{tags}. Tag groups must not overlap.")
(let ((err (define-tag-group tags)))
- (if err (ly:parser-error (*parser*) err (*location*)))))
+ (if err (ly:parser-error err (*location*)))))
temporary =
#(define-music-function (music)
@var{prop} can contain additional elements in which case a nested
property (inside of an alist) is tweaked.")
(if (ly:music? item)
- (let ((p (check-grob-path prop (*parser*) (*location*)
+ (let ((p (check-grob-path prop (*location*)
#:start 1
#:default #t
#:min 2)))
- (if p
- (set! (ly:music-property item 'tweaks)
- (acons (cond ((pair? (cddr p)) p)
- ((symbol? (car p))
- (cons (car p) (cadr p)))
- (else (cadr p)))
- value
- (ly:music-property item 'tweaks))))
+ (cond ((not p))
+ ;; p now contains at least two elements. The first
+ ;; element is #t when no grob has been explicitly
+ ;; specified, otherwise it is a grob name.
+ ((music-is-of-type? item 'context-specification)
+ ;; This is essentially dealing with the case
+ ;; \tweak color #red \tweak font-size #3 NoteHead
+ ;; namely when stacked tweaks end in a symbol list
+ ;; rather than a music expression.
+ ;;
+ ;; We have a tweak here to convert into an override,
+ ;; so we need to know the grob to apply it to. That's
+ ;; easy if we have a directed tweak, and otherwise we
+ ;; need to find the symbol in the expression itself.
+ (let* ((elt (ly:music-property item 'element))
+ (seq (if (music-is-of-type? elt 'sequential-music)
+ elt
+ (make-sequential-music (list elt))))
+ (elts (ly:music-property seq 'elements))
+ (symbol (if (symbol? (car p))
+ (car p)
+ (and (pair? elts)
+ (ly:music-property (car elts)
+ 'symbol)))))
+ (if (symbol? symbol)
+ (begin
+ (set! (ly:music-property seq 'elements)
+ (cons (make-music 'OverrideProperty
+ 'symbol symbol
+ 'grob-property-path (cdr p)
+ 'pop-first #t
+ 'grob-value value
+ 'origin (*location*))
+ elts))
+ (set! (ly:music-property item 'element) seq))
+ (begin
+ (ly:parser-error (_ "Cannot \\tweak")
+ (*location*))
+ (ly:music-message item (_ "untweakable"))))))
+ (else
+ (set! (ly:music-property item 'tweaks)
+ (acons (cond ((pair? (cddr p)) p)
+ ((symbol? (car p))
+ (cons (car p) (cadr p)))
+ (else (cadr p)))
+ value
+ (ly:music-property item 'tweaks)))))
item)
- ;; We could just throw this at \override and let it sort this
- ;; out on its own, but this way we should get better error
- ;; diagnostics.
- (let ((p (check-grob-path
- (append item (if (symbol? prop) (list prop) prop))
- (*parser*) (*location*)
- #:default 'Bottom #:min 3)))
- (if p
- #{ \override #p = #value #}
- (make-music 'Music)))))
+ (propertyOverride (append item (if (symbol? prop) (list prop) prop)) value)))
undo =
#(define-music-function (music)
(let
((lst
(fold-some-music
- (lambda (m) (or (music-is-of-type? m 'layout-instruction-event)
- (music-is-of-type? m 'context-specification)
- (music-is-of-type? m 'apply-context)
- (music-is-of-type? m 'time-signature-music)))
+ (music-type-predicate '(layout-instruction-event
+ context-specification
+ apply-context
+ time-signature-music))
(lambda (m overrides)
(case (ly:music-property m 'name)
((OverrideProperty)