Re: TextSpanner usability improvements

2020-09-25 Thread Martín Rincón Botero
Dear all,

in case there are people like me interested in having a basic syntax for
inputting text spanners, I wrote three simple functions for that matter:
\textSpan, \textSpanArrow and \textSpanDoubleArrow. They replace in
practice following overrides with user input:

\override TextSpanner.bound-details.left.text
\override TextSpanner.bound-details.right.text
\override TextSpanner.style
\override TextSpanner.bound-details.right.arrow
\override TextSpanner.bound-details.left.arrow

The syntax of these three functions is:
\textSpan "text" #'linestyle "text", and are used in combination with
\startTextSpan and \stopTextSpan. Overrides and tweaks can still be used,
preferably after and not before, so that what you change is not changed
again by these functions.

\version "2.20.0"

textSpan = #(define-music-function
   (parser location leftmarkup style rightmarkup)
   (markup? symbol? markup?)
   #{
\override TextSpanner.bound-details.left.text = \markup { \upright
#leftmarkup }
\override TextSpanner.bound-details.right.text = \markup { \upright
#rightmarkup }
\override TextSpanner.bound-details.left-broken.text = ##f
\override TextSpanner.bound-details.right-broken.text = ##f
\override TextSpanner.style = #style
\override TextSpanner.bound-details.right.arrow = ##f
\override TextSpanner.bound-details.left.arrow = ##f
   #})

textSpanArrow = #(define-music-function
   (parser location leftmarkup style rightmarkup)
   (markup? symbol? markup?)
   #{
\override TextSpanner.style = #style
\override TextSpanner.bound-details.right.stencil-align-dir-y = #CENTER
\override TextSpanner.bound-details.left.stencil-align-dir-y = #CENTER
\override TextSpanner.bound-details.right.arrow = ##t
\override TextSpanner.bound-details.left.text = \markup { \upright
#leftmarkup }
\override TextSpanner.bound-details.right.text = \markup { \upright
#rightmarkup }
\override TextSpanner.bound-details.left-broken.text = ##f
\override TextSpanner.bound-details.right-broken.text = ##f
\override TextSpanner.dash-period = 1.0
   #})

textSpanDoubleArrow = #(define-music-function
   (parser location leftmarkup style rightmarkup)
   (markup? symbol? markup?)
   #{
\override TextSpanner.style = #style
\override TextSpanner.bound-details.right.stencil-align-dir-y = #CENTER
\override TextSpanner.bound-details.left.stencil-align-dir-y = #CENTER
\override TextSpanner.bound-details.right.arrow = ##t
\override TextSpanner.bound-details.left.arrow = ##t
\override TextSpanner.bound-details.left.text = \markup { \upright
#leftmarkup }
\override TextSpanner.bound-details.right.text = \markup { \upright
#rightmarkup }
\override TextSpanner.bound-details.left-broken.text = ##f
\override TextSpanner.bound-details.right-broken.text = ##f
\override TextSpanner.dash-period = 1.0
   #})

%EXAMPLE

\relative c' {
  \textSpan \markup { \bold "press." } #'trill \markup { \italic
\center-align "norm." }
  c1\startTextSpan
  c1
  c1\stopTextSpan
  \textSpanArrow "m. vib." #'dashed-line \markup { \center-align "senza
vib."}
  \break
  c1\startTextSpan
  c1
  c1\stopTextSpan
  \break
  \textSpanDoubleArrow \markup { \box "sul pont."} #'line "sul tasto"
  c1\startTextSpan
  c1
  c1
  c1\stopTextSpan
  \textSpan \markup {\italic "air"} #'zigzag " "
  c1\startTextSpan
  c4 c2.\stopTextSpan
}

[image: image.png]

Cheers,
Martín.




Am So., 20. Sept. 2020 um 18:57 Uhr schrieb Thomas Morley <
thomasmorle...@gmail.com>:

> Am So., 20. Sept. 2020 um 17:30 Uhr schrieb Xavier Scheuer
> :
> >
> > On Sun, 20 Sep 2020 at 13:03, Thomas Morley 
> wrote:
> > >
> > > 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.
> >
> > Hi,
> >
> > Great! Could you add this to issue 3176 (a proof of concept is not yet a
> proper solution, but is anyway better than nothing, especially for a 7
> years old issue)?
> > https://gitlab.com/lilypond/lilypond/-/issues/3176
> >
> > Thank you!
> >
> > Cheers,
> > Xavier
> >
> > --
> > Xavier Scheuer 
> >
>
> Done, with a slightly improved and commented code:
> https://gitlab.com/lilypond/lilypond/-/issues/3176#note_415526421
>
> Cheers,
>   Harm
>


-- 
www.martinrinconbotero.com


Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-20 Thread Thomas Morley
Am So., 20. Sept. 2020 um 17:30 Uhr schrieb Xavier Scheuer
:
>
> On Sun, 20 Sep 2020 at 13:03, Thomas Morley  wrote:
> >
> > 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.
>
> Hi,
>
> Great! Could you add this to issue 3176 (a proof of concept is not yet a 
> proper solution, but is anyway better than nothing, especially for a 7 years 
> old issue)?
> https://gitlab.com/lilypond/lilypond/-/issues/3176
>
> Thank you!
>
> Cheers,
> Xavier
>
> --
> Xavier Scheuer 
>

Done, with a slightly improved and commented code:
https://gitlab.com/lilypond/lilypond/-/issues/3176#note_415526421

Cheers,
  Harm



Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-20 Thread Xavier Scheuer
On Sun, 20 Sep 2020 at 13:03, Thomas Morley 
wrote:
>
> 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.

Hi,

Great! Could you add this to issue 3176 (a proof of concept is not yet a
proper solution, but is anyway better than nothing, especially for a 7
years old issue)?
https://gitlab.com/lilypond/lilypond/-/issues/3176

Thank you!

Cheers,
Xavier

-- 
Xavier Scheuer 


Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-20 Thread Martín Rincón Botero
Hi Thomas,

thank you for your interest in this very constructive discussion with Aaron!
> 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!?

Exactly, me neither. Forcing the default to be empty text without giving the 
user the chance to give input right there where the music is, is almost as 
undesirable as having “left text” and “right text” as defaults that you have to 
manually override.
> 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.

In principle, I would support this as well.
> 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.

Wow! I can’t wait to start playing with this! I’ll certainly report later, 
perhaps in a different thread, my observations. Thank you!

Best regards,
Martín.
On 20. Sep 2020, 13:02 +0200, Thomas Morley , wrote:
>
> That


Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-20 Thread Thomas Morley
Am So., 20. Sept. 2020 um 12:05 Uhr schrieb Martín Rincón Botero
:
>
> 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 , 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 symbolspanner-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

Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-20 Thread Martín Rincón Botero
> 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 , wrote:
>
> existing


Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-19 Thread Aaron Hill

On 2020-09-19 12:31 am, Martín Rincón Botero wrote:

[ . . . ]


I was going to comment on your reply in greater detail, but I realized 
it would not be terribly productive.  In short, you and I simply 
disagree on what is satisfactory for syntax.  And that is not a bad 
thing.  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.


That said, \with is a powerful construct that need not be relegated to 
just context modification.  Also, this Kool-Aid(tm) is really quite 
refreshing!




Yes, the script I started writing and that you splendidly finished is
a workaround, not a solution. I’m not a programmer, so the day I can
actually make a pull request for issues like these might never come.
It would be great if such spanners can be implemented!


It is good to have the "non-programmer" perspective.  Mind you, I would 
argue your use of LilyPond and interest in Scheme means you have already 
begun your journey as a programmer.  (:



-- Aaron Hill



Re: TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-19 Thread Martín Rincón Botero
> I am uncertain what you mean by "proper" markup syntax.

Sorry, I meant syntax for markup tagging.
> while interesting, is invalid syntax and surely not proper. Perhaps
> you simply meant something that *looks* like it could be valid LilyPond.

how can a proposed syntax (for which functions have to be written yet) as 
example be invalid? It surely has to look like it could be valid Lilypond!
> Including all of these as
> parameters to a function could make the function unwieldy to use when
> one only needs to specify a few values. Optional arguments help to some
> degree, but they aren't perfect especially when there is ambiguity of
> types.

At no point is my suggestion to “all” of these parameters in a function. My 
suggestion is to have a basic function with “sensible” defaults. They can 
always be tweaked or overridden by the user as desired. That’s what \override 
and \tweak are for.
> And users of TextSpanners should invest in creating
> their own wrappers for commonly used items.

No they shouldn’t. They have to if they want to have a legible code with a 
proper markup tagging.
> b'4 a' g'2\startTextSpan \with { left-text = "rit."
>  to-barline = ##t } |
>  f'4 g'8 a' g'2 | a'1\stopTextSpan }

I also was thinking of the better possibility that \startTextSpan can take 
arguments. The \with function is not meant for data input but for changing 
context properties. And if we’re starting to put text where it actually belongs 
in the music, certainly saying “left-text” for the \startTextSpan function is 
redundant. If \startTextSpan accepts text, \stopTextSpan should accept the 
right part of the text, so that it appears in the correct place in the music. A 
basic (hypothetical) c1\startTextSpan "left" c1 c1\stopTextSpan "right" would 
be a massive improvement in readability. If this function could stop being 
“misused” for tempo variations (if we had tempo spanners), then I suppose the 
italics by default could go away (I can’t think of other reason why they have 
to be italics by default!)
> That approach would better preserve the semantics of the underlying
> elements. Consuming a \tempo command only to produce a \markup that
> *looks* like a MetronomeMark but is not one leads to issues as you found
> with MIDI. The Tempo_performer cannot do what it needs to do as it does
> not understand what the \markup means. That is not to mention that the
> use of \tempo occurs at the wrong moment in the music. Such a proposed
> MetronomeSpanner would terminate with an actual \tempo command on either
> end at the correct moments. And the Tempo_performer could be improved
> to understand how to interpolate tempos that are connected by spanners.

Yes, the script I started writing and that you splendidly finished is a 
workaround, not a solution. I’m not a programmer, so the day I can actually 
make a pull request for issues like these might never come. It would be great 
if such spanners can be implemented!
> I wonder if the parser's \etc could support defining new functions that
> borrow the syntax from built-in ones:

That would be nice as well :-).
On 19. Sep 2020, 07:01 +0200, Aaron Hill , wrote:
>
> I am uncertain what you mean by "proper" markup syntax.


TextSpanner usability improvements (was Re: Scheme predicative types)

2020-09-18 Thread Aaron Hill

On 2020-09-18 2:06 pm, Martín Rincón Botero wrote:

[...] There are two
unsatisfactory problems for usability involved from my point of view. 
One

is the impossibility to use proper markup syntax for text spanners.


I am uncertain what you mean by "proper" markup syntax.  Even though 
they are called "TextSpanners", the text can be any markup? value:



{ b'4 -\tweak bound-details.left.text \markup \box ?
  -\tweak bound-details.right.text \markup \circle !
  -\tweak font-series #'bold
  -\tweak font-shape #'upright
  \startTextSpan
  a' g'2 | f'4 g'8 a' g'2 | a'1\stopTextSpan }


Your proposed...


\markupSpan { "sul pont." \arrow "sul tasto" }


...while interesting, is invalid syntax and surely not proper.  Perhaps 
you simply meant something that *looks* like it could be valid LilyPond.




[...] In the case of
text spanners, the default has no musical use: a dashed line with no 
text
on either side. The syntax of a text spanner has the serious omission 
of
starting something without user input (\startTextSpan starts what? The 
user

should have an "interface" to give an initial input.


Consider a \textSpan function that has you specify the left and right 
text.  What happens when you only need left-side text?  Is it 
satisfactory for a user to have to say \textSpan "left" ""?  Next, there 
are options for padding and whether the side of the spanner terminates 
in an arrow.  What happens when you need to specify the padding on one 
side and the arrow-type on the other?  Including all of these as 
parameters to a function could make the function unwieldy to use when 
one only needs to specify a few values.  Optional arguments help to some 
degree, but they aren't perfect especially when there is ambiguity of 
types.


The existing interface for TextSpanners requires that one manually 
\override or \tweak properties so that you only specify what you need.  
This may seem cumbersome when adjusting many things, but it is at least 
very clear what is going on.  You certainly don't have to remember which 
argument is which.  And users of TextSpanners should invest in creating 
their own wrappers for commonly used items.  Consider something like 
this:



startRitSpan =
  -\tweak bound-details.left.text "rit."
  -\tweak to-barline ##t
  \startTextSpan

{ b'4 a' g'2\startRitSpan |
  f'4 g'8 a' g'2 | a'1\stopTextSpan }


The result is something that is more succinct to use within the actual 
music, uncluttered by \overrides and \tweaks.  And being reusable 
assists in keeping the overall score consistent.  (It is mildly annoying 
though to have to use \stopTextSpan, but it is probably better than 
polluting the namespace with a whole host of \stop*Span aliases that all 
do the same thing.)


While the above is some defense of the existing interface, there could 
be ways to improve the experience.  For instance, imagine this:



{ b'4 a' g'2\startTextSpan \with { left-text = "rit."
   to-barline = ##t } |
  f'4 g'8 a' g'2 | a'1\stopTextSpan }


I do wonder if my obsession with ly:context-mod? goes too far, but I 
keep finding that the \with {} construct is a great alternative to 
variable argument lists.  There is never any confusion as properties are 
well-named; plus, the construct is quite extensible.




[...] The second issue is the mentioned 2013
issue. Lilypond lacks the possibility of using text spanners not only 
with

a \tempo syntax (which thanks to your script is very well solved now!),
something that makes the "music" in the code more legible (because 
there is
proper markup of musical events) but also to format the whole thing as 
a

\tempo marking in the score (tempo indications are not attached to the
staff but to the system, and horizontally metronome marks are not 
attached
to the first note of the measure but to the time signature above which 
they

are centered, that's why I included \halign properties in the script as
workaround).


That would point to TextSpanners not being the right fit/tool for the 
job.  What we perhaps need is something like a MetronomeSpanner and 
possibly a RehearsalSpanner--connecting MetronomeMarks and 
RehearsalMarks, respectively.  And then we need a way to attach the 
spanner to \tempos or \marks in an equivalent manner as you attach 
TextSpanners to notes.


That approach would better preserve the semantics of the underlying 
elements.  Consuming a \tempo command only to produce a \markup that 
*looks* like a MetronomeMark but is not one leads to issues as you found 
with MIDI.  The Tempo_performer cannot do what it needs to do as it does 
not understand what the \markup means.  That is not to mention that the 
use of \tempo occurs at the wrong moment in the music.  Such a proposed 
MetronomeSpanner would terminate with an actual \tempo command on either 
end at the correct moments.  And the Tempo_performer could be improved 
to understand how to interpolate tempos that are conne