Jump to content

Separating key cancellations from key signature changes: Difference between revisions

From LilyPond wiki
m Replace version="2.24.0" with version="2.24" now that the LilyWiki extension supports auto-selecting the latest release in a stable series
mNo edit summary
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
By default, the accidentals used for key cancellations are placed adjacent to those for key signature changes. This behavior can be changed by overriding the <code>break-align-orders</code> property of the <code>BreakAlignment</code> grob.
By default, the accidentals used for key cancellations are placed adjacent to those for key signature changes. This behavior can be changed by overriding the <code>break-align-orders</code> property of the <code>BreakAlignment</code> grob.


The value of <code>break-align-orders</code> is a vector of length 3, with quoted lists of breakable items as elements. Each list describes the default order of prefatory matter at the end, in the middle, and at the beginning of a line, respectively. We are only interested in changing the behaviour in the middle of a line.
The value of <code>break-align-orders</code> is a vector of length&nbsp;3, with quoted lists of breakable items as elements. Each list describes the default order of prefatory matter at the end, in the middle, and at the beginning of a line, respectively. We are only interested in changing the behaviour in the middle of a line.


If you look up the definition of <code>break-align-orders</code> in LilyPond's Internal Reference (see the [https://lilypond.org/doc/v2.22/Documentation/internals/breakalignment <code>BreakAlignment</code>] grob), you get the following order in the second element:
If you look up the definition of <code>break-align-orders</code> in LilyPond's Internal Reference (see the [https://lilypond.org/doc/v2.24/Documentation/internals/breakalignment <code>BreakAlignment</code>] grob), you get the following order in the second element:


<pre>...
<pre>...
Line 10: Line 10:
key-signature
key-signature
...</pre>
...</pre>
We want to change that, moving <code>key-cancellation</code> before <code>staff-bar</code>. To make this happen we use the <code>grob-transformer</code> function, which gives us access to the original vector as the second argument of the lambda function, here called <code>orig</code> (we don't need the first argument, <code>grob</code>). We return a new vector, with unchanged first and last elements. For the middle element, we first remove <code>key-cancellation</code> from the list, then adding it again before <code>staff-bar</code>.


<lilypond version="2.24" full>
We want to change that, moving <code>key-cancellation</code> before <code>staff-bar</code>. To make this happen we use the <code>grob-transformer</code> function, which gives us access to the original vector as the second argument of the lambda function, here called <var>orig</var> (we don't need the first argument, <var>grob</var>). We return a new vector, with unchanged first and last elements. For the middle element, we first remove <code>key-cancellation</code> from the list, then adding it again before <code>staff-bar</code>.
 
<lilypond version="2.24">
%LSR based on
%LSR based on
%LSR https://stackoverflow.com/questions/40964806/scheme-inserting-a-number-in-a-list
%LSR https://stackoverflow.com/questions/40964806/scheme-inserting-a-number-in-a-list
Line 53: Line 54:
   \cancellationFirst
   \cancellationFirst
   \music }
   \music }
\paper { tagline = ##f }
</lilypond>
</lilypond>


[[Category:Pitches]]
[[Category:Pitches]]
[[Category:Pitches]]
[[Category:Scheme]]
[[Category:Tweaks and overrides]]
[[Category:Tweaks and overrides]]
[[Category:Included in the official documentation]]
[[Category:Included in the official documentation]]
[[Category:Snippet]]

Latest revision as of 14:26, 29 November 2025

By default, the accidentals used for key cancellations are placed adjacent to those for key signature changes. This behavior can be changed by overriding the break-align-orders property of the BreakAlignment grob.

The value of break-align-orders is a vector of length 3, with quoted lists of breakable items as elements. Each list describes the default order of prefatory matter at the end, in the middle, and at the beginning of a line, respectively. We are only interested in changing the behaviour in the middle of a line.

If you look up the definition of break-align-orders in LilyPond's Internal Reference (see the BreakAlignment grob), you get the following order in the second element:

...
staff-bar
key-cancellation
key-signature
...

We want to change that, moving key-cancellation before staff-bar. To make this happen we use the grob-transformer function, which gives us access to the original vector as the second argument of the lambda function, here called orig (we don't need the first argument, grob). We return a new vector, with unchanged first and last elements. For the middle element, we first remove key-cancellation from the list, then adding it again before staff-bar.

\version "2.24"

%LSR based on
%LSR https://stackoverflow.com/questions/40964806/scheme-inserting-a-number-in-a-list

#(define (insert-before where what lst)
   (cond
    ((null? lst)           ; If the list is empty,
     (list what))          ; return a single-element list.
    ((eq? where (car lst)) ; If we find symbol `where`,
     (cons what lst))      ; insert `what` before curr. position.
    (else                  ; Otherwise keep building the list by
     (cons (car lst)       ; adding the current element and
                           ; recursing with the next element.
           (insert-before where what (cdr lst))))))

cancellationFirst =
\override Score.BreakAlignment.break-align-orders =
#(grob-transformer
  'break-align-orders
  (lambda (grob orig)
    (let* ((middle (vector-ref orig 1))
           (middle (delq 'key-cancellation middle))
           (middle (insert-before
                    'staff-bar 'key-cancellation middle)))
      (vector
       ;; end of line
       (vector-ref orig 0)
       ;; middle of line
       middle
       ;; beginning of line
       (vector-ref orig 2)))))

music = { \key es \major d'1 \bar "||"
          \key a \major d'1 }

{ <>^\markup "default"
  \music }

{ <>^\markup "cancellation first"
  \cancellationFirst
  \music }