Am So., 20. Sept. 2020 um 12:05 Uhr schrieb Martín Rincón Botero
<martinrinconbot...@gmail.com>:
>
> In short, you and I simply
>
> disagree on what is satisfactory for syntax.
>
>
> Well, it seems we already agreed on one satisfactory syntax with the way you 
> finished the script in the other thread, so I suppose it’s not impossible to 
> agree on something ;-).
>
> We just come to LilyPond from two different perspectives. Folks
>
> like me will try to make the best of the existing system, and folks like
>
> you will contribute to improving its syntactic elegance.
>
>
> I hadn’t thought about it that way. I certainly give a lot of importance to 
> syntax. Perhaps I should try to contribute in that territory somehow. Not a 
> being a Scheme wizard limits my powers though.
>
> That said, \with is a powerful construct that need not be relegated to
>
> just context modification.
>
>
> I suppose the \with construct could be extended to uses it doesn’t have right 
> now. But I guess one would need to understand first why isn’t that 
> construction so often required in the first place.
>
>  It is good to have the "non-programmer" perspective.
>
>
> I’m glad that’s the case. Thank you for being so helpful with non-programmers 
> like me! :-).
>
> Best regards,
> Martín.
> On 19. Sep 2020, 17:41 +0200, Aaron Hill <lilyp...@hillvisions.com>, wrote:
>
>
> existing

Hi Martin,

in general I'm more with Aaron.
P.e., I have no clue which default text one could think of for
TextSpanner's left/right-text!?
Otoh, I'd wish we'd have a LilyPond-data-structure to assign a list of
key/value pairs in ly-syntax to a variable. Right now we can do so at
top-level, in layout, paper and \with.

That said, find attached a TempoSpanner-coding.
I'm not sure it's the best approach at all. For sure there's wide room
for improvements.
Probably the best one could say: it's a proof of concept.

Cheers,
  Harm
\version "2.20.0"

#(define-event-class 'tempo-span-event 'span-event)

#(define (add-grob-definition grob-name grob-entry)
   (let* ((meta-entry   (assoc-get 'meta grob-entry))
          (class        (assoc-get 'class meta-entry))
          (ifaces-entry (assoc-get 'interfaces meta-entry)))
     (set-object-property! grob-name 'translation-type? ly:grob-properties?)
     (set-object-property! grob-name 'is-grob? #t)
     (set! ifaces-entry (append (case class
                                  ((Item) '(item-interface))
                                  ((Spanner) '(spanner-interface))
                                  ((Paper_column) '((item-interface
                                                     paper-column-interface)))
                                  ((System) '((system-interface
                                               spanner-interface)))
                                  (else '(unknown-interface)))
                                ifaces-entry))
     (set! ifaces-entry (uniq-list (sort ifaces-entry symbol<?)))
     (set! ifaces-entry (cons 'grob-interface ifaces-entry))
     (set! meta-entry (assoc-set! meta-entry 'name grob-name))
     (set! meta-entry (assoc-set! meta-entry 'interfaces
                                  ifaces-entry))
     (set! grob-entry (assoc-set! grob-entry 'meta meta-entry))
     (set! all-grob-descriptions
           (cons (cons grob-name grob-entry)
                 all-grob-descriptions))))
                 
#(define tempo-text->spanner-text
  (lambda (grob)
    (let* ((bound-left (ly:spanner-bound grob LEFT))
           (bound-right (ly:spanner-bound grob RIGHT))
           (bound-left-ext (ly:grob-extent bound-left bound-left X))
           (bound-left-center (interval-center bound-left-ext))
           (bound-right-ext (ly:grob-extent bound-right bound-right X))
           (bound-right-center (interval-center bound-right-ext))
           (bound-details (ly:grob-property grob 'bound-details))
           (details-right (assoc-get 'right bound-details))
           (details-left (assoc-get 'left bound-details))
           (text-padding-left (assoc-get 'text-padding details-left))
           (text-padding-right (assoc-get 'text-padding details-right))
           (left-bound-text (ly:grob-property bound-left 'text))
           (right-bound-text (ly:grob-property bound-right 'text)))
           
     (ly:grob-set-nested-property! grob '(bound-details left text) 
       #{ \markup { #left-bound-text \hspace #text-padding-left } #})
     (ly:grob-set-nested-property! grob '(bound-details right text) 
       #{ \markup { \hspace #text-padding-right #right-bound-text } #})
       
     (ly:grob-set-nested-property! grob '(bound-details left padding) 
       (-  bound-left-center))
     (ly:grob-set-nested-property! grob '(bound-details right padding) 
       (+ text-padding-right bound-right-center))
       
     (ly:side-position-interface::move-to-extremal-staff grob))))

#(add-grob-definition
  'TempoSpanner
  `((after-line-breaking . ,tempo-text->spanner-text)
    (bound-details . ((left . ((Y . 0)
                               (padding . 0.25)
                               (text-padding . 0.4)
                               (stencil-offset . (0 . -0.5))
                               ))
                      (right . ((Y . 0)
                                (padding . 0.25)
                                (stencil-offset . (0 . -0.5))
                                (text-padding . 0.4)
                                ))
                      ))
    (dash-fraction . 0.4)
    (dash-period . 2.0)
    (direction . ,UP)
    (font-shape . upright)
    (left-bound-info . ,ly:line-spanner::calc-left-bound-info)
    (outside-staff-priority . 350)
    (padding . 0.8)
    (right-bound-info . ,ly:line-spanner::calc-right-bound-info)
    (staff-padding . 0.8)
    (stencil . ,ly:line-spanner::print)
    (style . dashed-line)
    (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
    (meta . ((class . Spanner)
             (interfaces . (font-interface
                            line-interface
                            line-spanner-interface
                            outside-staff-interface
                            side-position-interface))))))

#(define scheme-event-spanner-types
   '(
     (TempoSpanEvent
      . ((description . "Used to signal where scheme text spanner brackets
start and stop.")
         (types . (tempo-span-event span-event event))
         ))
     ))

#(set!
  scheme-event-spanner-types
  (map (lambda (x)
         (set-object-property! (car x)
                               'music-description
                               (cdr (assq 'description (cdr x))))
         (let ((lst (cdr x)))
           (set! lst (assoc-set! lst 'name (car x)))
           (set! lst (assq-remove! lst 'description))
           (hashq-set! music-name-to-property-table (car x) lst)
           (cons (car x) lst)))
       scheme-event-spanner-types))

#(set! music-descriptions
       (append scheme-event-spanner-types music-descriptions))

#(set! music-descriptions
       (sort music-descriptions alist<?))

#(define (axis-offset-symbol axis)
   (if (eqv? axis X) 'X-offset 'Y-offset))

#(define (set-axis! grob axis)
  (if (not (number? (ly:grob-property grob 'side-axis)))
      (begin
        (set! (ly:grob-property grob 'side-axis) axis)
        (ly:grob-chain-callback
         grob
         (if (eqv? axis X)
             ly:side-position-interface::x-aligned-side
             side-position-interface::y-aligned-side)
         (axis-offset-symbol axis)))))
        
tempoSpannerEngraver =
#(lambda (context)
   (let ((span '())
         (finished '())
         (mm-start #f)
         (mm-stop #f)
         (bound-left #f)
         (bound-right #f))
     (make-engraver
      (acknowledgers 
        ((metronome-mark-interface engraver grob source-engraver)
          (let* ((details (ly:grob-property grob 'details))
                 (start-tempo-span (assoc-get 'start-tempo-span details #f))
                 (stop-tempo-span (assoc-get 'stop-tempo-span details #f)))
          (if start-tempo-span (set! mm-start grob))
          (if stop-tempo-span (set! mm-stop grob)))))
          
      ((process-music trans)
       (if mm-stop
           (if (null? span)
               (ly:warning 
      "You're trying to end a scheme text spanner but you haven't started one.")
               (begin (set! finished span)
                      (ly:engraver-announce-end-grob trans finished mm-stop)
                      (set! span '())
                      (set! bound-right mm-stop)
                      (set! mm-stop #f))))
       (if mm-start
           (begin
             (set! span (ly:engraver-make-grob trans 'TempoSpanner '()))
             (set-axis! span Y)
             (set! bound-left mm-start)
             (set! mm-start #f))))
             
      ((stop-translation-timestep trans)
       (if (and (ly:spanner? span) (ly:grob? bound-left))
           (begin
             (ly:spanner-set-bound! span LEFT bound-left)
             (ly:grob-set-property! bound-left 'stencil '())
             (set! bound-left #f)))
       (if (and (ly:spanner? finished) (ly:grob? bound-right))
           (begin 
             (ly:spanner-set-bound! finished RIGHT bound-right)
             (set! finished '())
             (ly:grob-set-property! bound-right 'stencil '())
             (set! bound-right #f)
             (set! mm-stop #f))))
             
      ((finalize trans)
       (if (ly:spanner? finished)
           (begin
             (if (null? (ly:spanner-bound finished RIGHT))
                 (ly:spanner-set-bound! finished RIGHT
                   (ly:context-property context 'currentMusicalColumn)))
             (set! finished '())))
       (if (ly:spanner? span)
           (begin
             (ly:warning "I think there's a dangling scheme text spanner :-(")
             (ly:grob-suicide! span)
	         (set! span '())))))))


\layout {
  \context {
    \Global
    \grobdescriptions #all-grob-descriptions
  }
  \context {
    \Score
    \consists \tempoSpannerEngraver
  }
}

startTempoSpan = 
\once \override Score.MetronomeMark.details.start-tempo-span = ##t

stopTempoSpan =
\once \override Score.MetronomeMark.details.stop-tempo-span = ##t

%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%%%%%%%%

%#(ly:set-option 'debug-skylines #t)

\paper { ragged-right = ##f }

mus = {
  \tempo "Moderato"
  b1
  \startTempoSpan
  \tempo "accellerando"
  b1
  b
  \break
  
  \stopTempoSpan
  \tempo "Allegro" 4 = 120
  c' c' c'
  \tempo "Adagio"
  d'
  \startTempoSpan
  \tempo "rit."
  \override Score.TempoSpanner.bound-details.right.text-padding = 0
  c'
  \once \override Score.MetronomeMark.X-offset = 0
  \stopTempoSpan
  \tempo \markup \translate #'(2 . 0.5) \draw-line #'(0 . -0.5) 
  f'
}


\new Staff \mus
  
 <<
   \mus
   \mus
 >>

Reply via email to