From 5c4b80afe97acbe20199a3aa71a0d63172112f23 Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Tue, 23 Oct 2012 07:52:45 +0200 Subject: [PATCH] Create \temporary for doing overrides without pop-first set Normal overrides change the top of the current property stack rather than pushing to it, by having the pop-first property set in the music. \temporary will remove this property from its argument's overrides. For property-changing music that is not an override, a warning will be generated. Calling \temporary \override and \revert in succession on the same property will have a net effect of zero. Similarly, pairing \temporary and \undo on the same music containing overrides will have a net effect of zero. In more complex arrangements, \revert will revert to the state before the last (matching) \temporary override of the same property. Properties are maintained conceptually using one stack per property per grob per context. Using \push/\pop instead of \temporary/\undo was deemed unsuitable for a musician-accessible user interface. --- ly/music-functions-init.ly | 56 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index 4fa31929d4..1fcdeedce7 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -1242,6 +1242,47 @@ tag = (ly:music-property arg 'tags))) arg) +temporary = +#(define-music-function (parser location music) + (ly:music?) + (_i "Make any @code{\\override} in @var{music} replace an existing +grob property value only temporarily, restoring the old value when a +corresponding @code{\\revert} is executed. This is achieved by +clearing the @samp{pop-first} property normally set on +@code{\\override}s. + +An @code{\\override}/@/@code{\\revert} sequence created by using +@code{\\temporary} and @code{\\undo} on the same music containing +overrides will cancel out perfectly or cause a@tie{}warning. + +Non-property-related music is ignored, warnings are generated for any +property-changing music that isn't an @code{\\override}.") + (define warned #f) + (for-some-music + (lambda (m) + (and (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)) + (case (ly:music-property m 'name) + ((OverrideProperty) + (if (ly:music-property m 'pop-first #f) + (set! (ly:music-property m 'pop-first) '())) + (if (ly:music-property m 'once #f) + (set! (ly:music-property m 'once) '())) + #t) + ((ContextSpeccedMusic) + #f) + (else + (if (not warned) + (begin + (ly:input-warning location (_ "Cannot make ~a revertible") + (ly:music-property m 'name)) + (set! warned #t))) + #t)))) + music) + music) + time = #(define-music-function (parser location beat-structure fraction) ((number-list? '()) fraction?) @@ -1326,14 +1367,17 @@ undo = (ly:music?) (_i "Convert @code{\\override} and @code{\\set} in @var{music} to @code{\\revert} and @code{\\unset}, respectively. Any reverts and -unsets already in @var{music} are ignored and not converted.") +unsets already in @var{music} cause a warning. Non-property-related music is ignored.") + (define warned #f) (let loop ((music 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 'context-specification) + (music-is-of-type? m 'apply-context) + (music-is-of-type? m 'time-signature-music))) (lambda (m overrides) (case (ly:music-property m 'name) ((OverrideProperty) @@ -1357,7 +1401,13 @@ unsets already in @var{music} are ignored and not converted.") 'element (loop (ly:music-property m 'element)) 'context-type (ly:music-property m 'context-type)) overrides)) - (else overrides))) + (else + (if (not warned) + (begin + (ly:input-warning location (_ "Cannot revert ~a") + (ly:music-property m 'name)) + (set! warned #t))) + overrides))) '() music))) (cond -- 2.39.5