lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scheme predicative types


From: Aaron Hill
Subject: Re: Scheme predicative types
Date: Fri, 18 Sep 2020 07:26:23 -0700
User-agent: Roundcube Webmail/1.4.2

On 2020-09-18 4:40 am, Martín Rincón Botero wrote:
Thank you very much, Aaron! The \markup \null construction is something
that I will have to study carefully in the next few days to fully grasp it. I made some adjustments to the formatting, so that it matches the default
\tempo formatting of Lilypond, especially when using a tempo range
(Lilypond uses – instead of -, and leaves a space before and after the
hyphen, so your added \concat is not required here ;-)), and I made all
\tempo text bold by default (as Lilypond does). However, your example made me compare it with Lilypond's formatting and there's still one issue even after fixing the other small details: When the user writes \tempo "Adagio" 4 = 70, he expects the tempo unit and metronome count in parenthesis after the given text. Here I'm absolutely limited by my Scheme ignorance on how to achieve that (somehow combining several conditions and adding \markup {#text \concat { "(" #tempo-unit } = \concat { #metronome-count ")" } ?).

Looking at the internal format-metronome-markup function, it uses half spaces (U+2009) and an en dash (U+2013).

Regardless, I will leave you with my final contribution of a "cleaned up" version with some logic and usage updates. In particular, I reordered the arguments to enable default values for the alignments. And the main refactoring uses a different approach to assembling the markup, which makes handling the parentheses simpler.

%%%%
\version "2.20.0"

tempoTextSpan =
#(define-music-function
  (left-halign left-text right-halign tempo)
  ((number? LEFT) markup? (number? LEFT) ly:music?)

  (define (tempo-property prop)
    (if (ly:prob? tempo)
        (ly:prob-property tempo prop #f)))

  ;; Verify tempo argument contains one tempo-change-event.
  (let ((events (extract-typed-music tempo 'tempo-change-event)))
    (if (eq? 1 (length events))
        (set! tempo (first events))
        (begin
          (ly:music-error tempo
            "Argument must specify a single \\tempo indication.")
          (set! tempo #f))))

  (let ((tempo-text (tempo-property 'text))
        (tempo-unit (tempo-property 'tempo-unit))
        (metronome-count (tempo-property 'metronome-count))
        (tempo-markup #f))

    (if (ly:duration? tempo-unit)
       (set! tempo-markup
         #{
           \markup {
             \general-align #Y #DOWN
             \smaller
             \note #(ly:duration->string tempo-unit) #UP
             =
             #(cond
               ((number-pair? metronome-count)
                #{
                  \markup \concat {
                    #(format #f "~d" (car metronome-count))
                    \char ##x2009 \char ##x2013 \char ##x2009
                    #(format #f "~d" (cdr metronome-count))
                  }
                #})
               ((number? metronome-count)
                #{ \markup #(format #f "~d" metronome-count) #})
               (else (make-null-markup)))
           }
         #}))
    (if (markup? tempo-text)
      (set! tempo-markup
        #{
          \markup {
            \bold #tempo-text
            #(if (markup? tempo-markup)
                 #{ \markup \concat { ( #tempo-markup ) } #}
                 (make-null-markup))
          }
        #}))

    #{
      \once {
        \override TextSpanner.bound-details.left-broken.text = ##f
        \override TextSpanner.bound-details.right-broken.text = ##f
        \override TextSpanner.bound-details.left.text =
          \markup \abs-fontsize #11
                  \halign #left-halign #left-text
        \override TextSpanner.bound-details.right.text =
          \markup \abs-fontsize #11 \normal-text
                  \halign #right-halign #tempo-markup
      }
    #}))

{
  \tempoTextSpan "accel." #RIGHT \tempo 2 = 50-55
  g'4\startTextSpan 4 4 4 | 2 2 | 1\stopTextSpan | R1
  \tempoTextSpan #RIGHT "rall." #CENTER \tempo "Adagio" 4 = 60
  g'4\startTextSpan 4 4 4 | 2 2 | 1\stopTextSpan | R1
  \tempoTextSpan "rit." #-0.5 \tempo \markup \circle \bold "!"
  g'4\startTextSpan 4 4 4 | 2 2 | 1\stopTextSpan \bar "|."
}

%% Uncomment to test argument validation.
% \tempoTextSpan "missing \\tempo" { }
% \tempoTextSpan "too many \\tempos" { \tempo "" \tempo "" }
%%%%


Oh! Right! Then I guess one solution would be to name the function
\tempoSpan instead, with a "dummy" variable (for the sake of syntax)
startTempoSpan = \startTextSpan and a variable stopTempoSpan, that would have to call the previous obtained values of tempoSpan (that I can't re-use because they're a markup and not a number anymore? Or because I don't know
how to call information obtained in other variables? Or both? GUILLE
complains of an Unbound variable: tempo-unit and Unbound variable:
metronome-count) and would add something like stopTempoSpan = \stopTextSpan
\once \omit Score.MetronomeMark \tempo #tempo-unit = #metronome-count.

You could use context properties to persist the relevant information; or, if you were feeling more adventurous, you could build a custom engraver/performer to do the work.

But if I can be honest, this approach is starting to feel awkward and potentially circuitous. Initially, I had no idea what you intended to do with the information from the \tempo command. Now, it is as if all you need is a normal MetronomeMark aligned to the end of a TextSpanner. After all, reusing is preferred to reinventing.

So while you could continue to develop the function above, perhaps time would be better spent solving the underlying issues that necessitated creating this function in the first place. Though, that discussion would likely merit its own thread.


-- Aaron Hill

Attachment: tempo-text-span.cropped.png
Description: PNG image


reply via email to

[Prev in Thread] Current Thread [Next in Thread]