lilypond-user
[Top][All Lists]
Advanced

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

Re: Help with function to output formatted \mark


From: Stefano Troncaro
Subject: Re: Help with function to output formatted \mark
Date: Fri, 16 Dec 2016 15:19:34 -0300

I achieved a working solution after I found out about lambda*.
I would like to improve on this, but at least I achieved the expected result.

The example:

\version "2.19.52"

%Useful definitions
#(define characters.thinSpace (ly:wide-char->utf-8 #x2009))
#(define characters.longDash (ly:wide-char->utf-8 #x2013))
#(define characters.curvyEqual "≈")

%Properties of the customMark
#(define customMark.parenthesized #t)
#(define customMark.tempoEqText "= ca.")
#(define customMark.separator (string-append characters.thinSpace characters.longDash characters.thinSpace))

#(define (ly:duration-or-false? obj)
   (if (or (ly:duration? obj) (and (boolean? obj) (not obj)))
       #t
       #f))

#(define (number-or-false? obj)
   (if (or (number? obj) (and (boolean? obj) (not obj)))
       #t
       #f))

createCustomMark =
#(define-music-function
    (text dur val1 val2)
    (markup? ly:duration-or-false? number-or-false? (number-or-false? #f))
  #{
    \mark \markup { \line { \upright { \fontsize #-2 {
       \larger { \bold { #text } }
       #(if (or dur val1 val2)
            #{
              \markup \concat { %\markup needed to avoid "unknown escaped string: `\concat'"
                #(if customMark.parenthesized "(")
                #(if dur
                     #{
                       \markup \fontsize #-3 { \general-align #Y #DOWN { \note #(ly:duration->string dur) #1 } }
                     #}
                     "") %needed to avoid "not a markup" error when dur is #f
                " "
                #customMark.tempoEqText
                #characters.thinSpace
                #(if val1
                     (number->string val1)
                     "") %needed to avoid "not a markup" error when val1 is #f
                #(if val2 
                     (string-append customMark.separator (number->string val2))
                     "") %needed to avoid "not a markup" error when val2 is #f
                #(if customMark.parenthesized ")")
              }
            #}
            "") %needed to avoid "not a markup" error when tempo is #f
     } } } }
  #})

customMark =
#(lambda* (text #:optional (dur #f) (val1 #f) (val2 #f))
   (createCustomMark text dur val1 val2))

allegro = #(customMark "Allegro." #{ 4 #} 120 125)
ceder = #(customMark "ceder...")
metromark = #(customMark "" #{ 4 #} 120)

\relative c' {
  \allegro c4 d e \ceder f \metromark
}

2016-12-16 13:44 GMT-03:00 Stefano Troncaro <address@hidden>:
I made some progress, although I'm sure there better and more elegant solution.

Example:

\version "2.19.52"

%Useful definitions
#(define characters.thinSpace (ly:wide-char->utf-8 #x2009))
#(define characters.longDash (ly:wide-char->utf-8 #x2013))
#(define characters.curvyEqual "≈")

%Properties of the customMark
#(define customMark.parenthesized #t)
#(define customMark.tempoEqText "= ca.")
#(define customMark.separator (string-append characters.thinSpace characters.longDash characters.thinSpace))

#(define (ly:duration-or-false? obj)
   (if (or (ly:duration? obj) (and (boolean? obj) (not obj)))
       #t
       #f))

#(define (number-or-false? obj)
   (if (or (number? obj) (and (boolean? obj) (not obj)))
       #t
       #f))


customMark =
#(define-music-function
    (text tempo dur val1 val2)
    (markup? boolean? ly:duration-or-false? number-or-false? number-or-false?)
  #{
    \mark \markup { \line { \upright { \fontsize #-2 {
       \larger { \bold { #text } }
       #(if tempo
            #{
              \markup \concat { %\markup needed to avoid "unknown escaped string: `\concat'"
                #(if customMark.parenthesized "(")
                #(if dur
                     #{
                       \markup \fontsize #-3 { \general-align #Y #DOWN { \note #(ly:duration->string dur) #1 } }
                     #}
                     "") %needed to avoid "not a markup" error when dur is #f
                " "
                #customMark.tempoEqText
                #characters.thinSpace
                #(if val1
                     (number->string val1)
                     "") %needed to avoid "not a markup" error when val1 is #f
                #(if val2 
                     (string-append customMark.separator (number->string val2))
                     "") %needed to avoid "not a markup" error when val2 is #f
                #(if customMark.parenthesized ")")
              }
            #}
            "") %needed to avoid "not a markup" error when tempo is #f
     } } } }
  #})


allegro = \customMark "Allegro." ##t 4 120 125
ceder = \customMark "ceder..." ##f ##f ##f ##f
metromark = \customMark "" ##t 4 120 ##f


\relative c' {
  \allegro c4 d e \ceder f \metromark
}

Now, I can't figure out how to achieve that the last 4 parameters of the function default to ##f, to avoid errors if I don't pass them.

Again, thanks in advance!
Stéfano

2016-12-16 4:17 GMT-03:00 Stefano Troncaro <address@hidden>:
Hello everyone,

I finally decided to start using Scheme functions. For learning purposes, I'm trying to write a function that will imitate the output from this snippet from the repository.

I achieved the look of the output but I can't seem to figure out how to make a function that accepts different types of parameters. Example:

\version "2.19.52"

%Properties of the customMark
#(define characters.thinSpace (ly:wide-char->utf-8 #x2009))
#(define customMark.parenthesized #t)
#(define customMark.tempoEqText "= ca.")

textandnotemark =
#(define-music-function
    (text dur val)
    (markup? ly:duration? number?)
  #{
    \mark \markup { \line { \upright { \fontsize #-2 {
       \larger { \bold { #text } }
       \concat {
         #(if customMark.parenthesized "(")
         \fontsize #-3 { \general-align #Y #DOWN { \note #(ly:duration->string dur) #1 } }
         " "
         #customMark.tempoEqText
         #characters.thinSpace
         #(number->string val)
         #(if customMark.parenthesized ")")
       }
     } } } }
  #})

allegro = \textandnotemark "Allegro." 4 120
%ceder = \textandnotemark "ceder..."
metromark = \textandnotemark "" 4 120

\relative c' {
  \allegro c4 d e f \metromark
}

The line that is commented near the end of the example represents the behavior that I'd like to achieve, that is, the case where there is only text. I thought it would be easy to do it by setting defaults, leaving the duration and value parameters blank, and managing the special case, but I can't figure out how to make it work.

Thanks in advance for your time!
Stéfano.



reply via email to

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