Abjad / abjad

Abjad is a Python API for building LilyPond files. Use Abjad to make PDFs of music notation.
https://abjad.github.io
GNU General Public License v3.0
234 stars 41 forks source link

Advance lexical position of \tweaks in LilyPond output #1556

Closed trevorbaca closed 11 months ago

trevorbaca commented 11 months ago

This change only applies to code that uses abjad.tweak().

Consider the following text spanner example in Abjad 3.18:

voice = abjad.Voice("c'4 d' e' f'")
start_text_span = abjad.StartTextSpan(
    left_text=abjad.Markup(r"\upright pont."),
    right_text=abjad.Markup(r"\markup \upright tasto"),
    style="dashed-line-with-arrow",
)
bundle = abjad.bundle(start_text_span, r"- \tweak staff-padding 2.5")
bundle = abjad.bundle(bundle, r"- \tweak dash-fraction 0.75")
abjad.attach(bundle, voice[0])
stop_text_span = abjad.StopTextSpan()
abjad.attach(stop_text_span, voice[-1])
score = abjad.Score([voice])
abjad.setting(score).proportionalNotationDuration = "#(ly:make-moment 1 16)"
lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', score])

The output is as expected. Note that the text spanner's dash-fraction appears to be 0.25:

starting-example

To change the text spanner's dash-fraction from 0.25 to 0.75, it should be enough to tweak abjad.StartTextSpan:

bundle = abjad.bundle(
    start_text_span,
    r"- \tweak staff-padding 2.5",
    r"- \tweak dash-fraction 0.75",
)

But this does nothing:

starting-example

Why?

Here's the LilyPond code that Abjad 3.18 creates:

string = abjad.lilypond(lilypond_file)
print(string)
\version "2.25.6"
\language "english"
\include "abjad.ily"
\new Score
\with
{
    proportionalNotationDuration = #(ly:make-moment 1 16)
}
<<
    \new Voice
    {
        c'4
        - \tweak dash-fraction 0.75
        - \tweak staff-padding 2.5
        - \abjad-dashed-line-with-arrow
        - \tweak bound-details.left.text \markup \concat { \upright pont. \hspace #0.5 }
        - \tweak bound-details.right.text \markup \upright tasto
        \startTextSpan
        d'4
        e'4
        f'4
        \stopTextSpan
    }
>>

Note that - \tweak dash-fraction 0.75 appears lexically early in the output: it is in the first tweak in a stack of six tweaks.

Then note that the - \abjad-dashed-line-with-arrow function is the source of the dash-fraction 0.25 setting; here's the definition of abjad-dashed-line-with-arrow in abjad/scm/abjad-text-spanner-line-styles.ily:

abjad-dashed-line-with-arrow = #(
    define-music-function
    (parser location music)
    (ly:music?)
    #{
    - \tweak Y-extent ##f
    - \tweak arrow-width 0.25
    - \tweak bound-details.left-broken.text ##f
    - \tweak bound-details.left.stencil-align-dir-y #center
    - \tweak bound-details.right-broken.arrow ##t
    - \tweak bound-details.right-broken.padding 0
    - \tweak bound-details.right-broken.text ##f
    - \tweak bound-details.right.arrow ##t
    - \tweak bound-details.right.padding 0.5
    - \tweak bound-details.right.stencil-align-dir-y #center
    - \tweak dash-fraction 0.25
    - \tweak dash-period 1.5
    - \tweak to-barline ##t
    $music
    #}
    )

This means that LilyPond first interprets - \tweak dash-fraction 0.75 and then overwrites this value with - \tweak dash-fraction 0.25. The result is that it isn't possible to tweak dash-fraction -- or any of the other dozen properties defined in abjad-dashed-line-with-arrow -- when using abjad-dashed-line-with-arrow.

The solution is to change the lexical position at which - \tweak dash-fraction 0.75 appears in LilyPond output. Abjad 3.19 does this:

voice = abjad.Voice("c'4 d' e' f'")
start_text_span = abjad.StartTextSpan(
    left_text=abjad.Markup(r"\upright pont."),
    right_text=abjad.Markup(r"\markup \upright tasto"),
    style="dashed-line-with-arrow",
)
bundle = abjad.bundle(
    start_text_span,
    r"- \tweak staff-padding 2.5",
    r"- \tweak dash-fraction 0.75",
)
abjad.attach(bundle, voice[0])
stop_text_span = abjad.StopTextSpan()
abjad.attach(stop_text_span, voice[-1])
score = abjad.Score([voice])
abjad.setting(score).proportionalNotationDuration = "#(ly:make-moment 1 16)"
lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', score])
string = abjad.lilypond(lilypond_file)
print(string)
\version "2.25.6"
\language "english"
\include "abjad.ily"
\new Score
\with
{
    proportionalNotationDuration = #(ly:make-moment 1 16)
}
<<
    \new Voice
    {
        c'4
        - \tweak staff-padding 2.5
        - \abjad-dashed-line-with-arrow
        - \tweak bound-details.left.text \markup \concat { \upright pont. \hspace #0.5 }
        - \tweak bound-details.right.text \markup \upright tasto
        - \tweak dash-fraction 0.75
        \startTextSpan
        d'4
        e'4
        f'4
        \stopTextSpan
    }
>>

Which makes it possible to tweak dash-fraction with abjad-dashed-line-with-arrow for the first time:

dash-fraction-0-75