On 2024-03-25 4:13 am, Jean Abou Samra wrote:
No, this doesn't exist OOTB. It could be implemented with a
Scheme engraver, but that would probably be overkill, unless
for some reason it's really important for what you're trying
to do?


Here's a simple non-engraver way to potentially get close:

%%%%
\version "2.25.13"

#(define context-stack '())

#(define (context-stack-find property)
  (ly:assoc-get property context-stack '()))

#(define (context-stack-push! property value)
  (set! context-stack
    (assoc-set! context-stack property
      (cons value (context-stack-find property)))))

#(define (context-stack-pop! property)
  (let ((stack (context-stack-find property)))
    (if (null? stack) '()
        (let ((value (car stack)) (rest (cdr stack)))
          (set! context-stack
            (if (null? rest)
              (assoc-remove! context-stack property)
              (assoc-set! context-stack property rest)))
          value))))

push =
#(define-music-function
  (property value)
  (symbol? scheme?)
  (define (proc ctxt)
    (let ((value (ly:context-property ctxt property '())))
      (or (null? value)
        (context-stack-push! property value)))
    (ly:context-set-property! ctxt property value)
    ;; (format #t "~a\n" context-stack)
  )
  #{ \applyContext #proc #})

pop =
#(define-music-function
  (property)
  (symbol?)
  (define (proc ctxt)
    (let ((value (context-stack-pop! property)))
      (if (null? value)
        (ly:context-unset-property ctxt property)
        (ly:context-set-property! ctxt property value)))
    ;; (format #t "~a\n" context-stack)
  )
  #{ \applyContext #proc #})

{
  \repeat unfold 8 b'8
  %% This example involves a property
  %% that already has a value set...
  \push autoBeaming ##f
  \repeat unfold 8 b'8
  \pop autoBeaming
  \repeat unfold 8 b'8
}

{
  \repeat unfold 2 { <a' c''>4( <g' b'>) }
  %% This example involves a property
  %% that was unset initially...
  \push doubleSlurs ##t
  \repeat unfold 2 { <a' c''>4( <g' b'>) }
  \pop doubleSlurs
  \repeat unfold 2 { <a' c''>4( <g' b'>) }
}
%%%%

It is probably missing some edge case handling, and certainly the `context-stack` should itself be stored within the context rather than just some arbitrary global variable. Another issue would be not handling the extended \set syntax as in, say, `\set Score.skipBars = ##t`. The property argument would need to become a `key-list?` with the appropriate handling to redirect to another named context.


-- Aaron Hill

Reply via email to